uniapp+vant weapp实现课程表小程序_课程表功能的实现

课程表功能的实现

思路

课程表的实现,我想了很久,在没有现成组件库的情况下实现,我主要是用了vant weapp的宫格和单选框来实现,主要的难点有以下两个方面:

1.节数与天数和grid内单选框索引的转换

返回值给我一个包含课程节数和天数的对象数组,我把它转换成一个包含unit(5节课*7天的对应的数字来定位)的对象数组

2.单选框样式的魔改

单选框直接使用radio的插槽来贴图来适应样式需求

<van-radio-group :value="unit" @change="addClass">
				<van-grid :border="false" :column-num="7" :clickable="true">
					<van-grid-item v-for="value in 35" :key="value" use-slot custom-class="editCourse">
						<van-button type="primary" color="#006600" v-show="map[value]!==-1?true:false"
							@click="editCourse(value)"
							custom-style="padding-left:5rpx;line-height:35rpx;padding-right:5rpx;padding-top:5rpx;height:203rpx;margin: 0 auto;width:90rpx;border-radius: 10rpx;font-size:25rpx!important;font-weight:bold">
							<div>{{InfoMap[value].courseName}}</div>
						</van-button>
						<van-radio use-icon-slot :value="unit" :name="value" v-show="map[value]!==-1?false:true">
							<image style="margin-top:10rpx;height:190rpx;width:90rpx;" slot="icon"
								:src="unit===value?icon.choosed:icon.unChoosed" />
						</van-radio>

					</van-grid-item>
				</van-grid>
			</van-radio-group>

这样就看不出来是单选框了
uniapp+vant weapp实现课程表小程序_课程表功能的实现

温馨提示:尽量用原生

其他主要是布局和样式,没啥好说的.吐槽一句,vant组件库的插槽不是真的放在组件里面,而是悬浮在它上面,有时候会出现错位的情况.
所以能用原生尽量用原生,组件样式带原生样式,样式穿透和!important都不起作用,不太好把握(主要是我太菜了,css好难)


源码

Table.vue:

<template>
	<view>
		<bar :nav="setNav" />
		<van-popup :show="chooseWeek" @close="onCloseChooseWeek" position="bottom" custom-class="height:50%">
			<van-picker show-toolbar title="请选择现在的周数" :columns="weeks" @cancel="cancelChooseWeek" @confirm="confirmWeek"
				:loading="loadingTable" />
		</van-popup>
		<van-row>
			<van-col span="22" offset="2">
				<van-grid :border="false" :column-num="7" :clickable="true">
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周一
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周二
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周三
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周四
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周五
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周六
						</van-tag>
					</van-grid-item>
					<van-grid-item use-slot custom-class="week">
						<van-tag type="primary" color="#006600" custom-class="weekTag">
							周日
						</van-tag>
					</van-grid-item>
				</van-grid>
			</van-col>
		</van-row>
		<van-row>
			<van-col span="2">
				<van-grid :border="false" :column-num="1" :clickable="true">
					<van-grid-item use-slot v-for="value in 5" :key="value" custom-class="courseNum">
						<div class="course">
							<van-button type="primary" color="#006600" block custom-class="courseNumBtn">
								{{value+1}}
							</van-button>
						</div>
					</van-grid-item>
				</van-grid>
			</van-col>
			<van-radio-group :value="unit" @change="addClass">
				<van-grid :border="false" :column-num="7" :clickable="true">
					<van-grid-item v-for="value in 35" :key="value" use-slot custom-class="editCourse">
						<van-button type="primary" color="#006600" v-show="map[value]!==-1?true:false"
							@click="editCourse(value)"
							custom-style="padding-left:5rpx;line-height:35rpx;padding-right:5rpx;padding-top:5rpx;height:203rpx;margin: 0 auto;width:90rpx;border-radius: 10rpx;font-size:25rpx!important;font-weight:bold">
							<div>{{InfoMap[value].courseName}}</div>
						</van-button>
						<van-radio use-icon-slot :value="unit" :name="value" v-show="map[value]!==-1?false:true">
							<image style="margin-top:10rpx;height:190rpx;width:90rpx;" slot="icon"
								:src="unit===value?icon.choosed:icon.unChoosed" />
						</van-radio>

					</van-grid-item>
				</van-grid>
			</van-radio-group>
			<van-notify id="van-notify" />
		</van-row>
	</view>
</template>
<script>
	import bar from '../../components/bar.vue';
	import Notify from '../../wxcomponents/vant/dist/notify/notify';
	export default {
		components: {
			bar
		},
		data() {
			return {
				loadingTable: false,
				courseMap: [],
				map: [],
				InfoMap: [],
				weeks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
				unit: null,
				showBtn: false,
				chooseWeek: false,
				week: 1,
				icon: {
					unChoosed: "/static/Btn/addBtn.png",
					choosed: "/static/Btn/addBtn_HL.png"
				},
				setNav: {
					'bg': '#006600',
					'color': "#fff",
					'isdisPlayNavTitle': true,
					'navTitle': '课表'
				},
				windowHeight: null,
				weekHeight: null,
				courseHeight: null,
				btnHeight: null
			}
		},
		mounted() {
			let token = ""
			token = wx.getStorageSync('token')
			if (token !== "") {
				this.loadDefaultData()
			} else {
				this.login()
			}
		},
		onLoad() {
			uni.$on('choose', (chooseWeek) => {
				this.chooseWeek = chooseWeek
			})
		},
		onShow() {
			this.loadDefaultData()
		},
		onUnload() {
			uni.$off('choose')
		},
		methods: {
			login() {
				let self = this
				wx.login({
					success(res) {
						wx.request({
							url: getApp().globalData.baseURL + "/login",
							data: {
								"code": res.code
							},
							success(res) {
								if (res.data.code === 1) {
									wx.setStorageSync('openid', res.data.data.openid)
									wx.setStorageSync('token', res.data.data.token)
									self.loadDefaultData()
								} else {
									Notify({
										type: 'danger',
										message: '获取用户信息失败,请重试'
									});
								}

							},
							fail(err) {
								Notify({
									type: 'danger',
									message: '连接服务器失败'
								});
							}
						})
					},
					fail(err) {
						Notify({
							type: 'danger',
							message: '获取用户登录态失败'
						});
					}
				})
			},

			editCourse(value) {

				var Info = this.InfoMap[value]
				uni.$on('Send', () => {
					uni.$emit('courseInfo', Info)
				})
				uni.navigateTo({
					url: "../courseInfo/courseInfo"
				})
			},
			// 关闭选择周数弹出层
			onCloseChooseWeek() {
				this.chooseWeek = false
			},
			cancelChooseWeek(e) {
				this.chooseWeek = false
			},
			// 计算并得到一个包含课程信息的数组
			getMap(data) {
				var map = new Array()
				for (let i = 0; i < data.length; i++) {
					map[i] = {
						unit: (data[i].jieshu - 1) * 7 + data[i].day - 1,
						courseName: data[i].courseName,
						teacher: data[i].teacher,
						classroom: data[i].classroom,
						weeks: data[i].weeks
					}
				}
				this.courseMap = map
			},
			resetMap(courseMap) {
				// 拿到一个排序的数组
				var map = new Array()
				for (let i = 0; i < courseMap.length; i++) {
					map[i] = courseMap[i].unit
				}
				var compare = function(x, y) {
					if (x < y) {
						return -1;
					} else if (x > y) {
						return 1;
					} else {
						return 0;
					}
				}
				map.sort(compare)
				var Map = new Array(35).fill(-1)
				for (let i = 0; i < map.length; i++) {
					Map[map[i]] = map[i]
				}
				this.map = Map
			},
			getInfoMap(courseMap) {
				var map = new Array()

				function compare(prop) {
					return function(x, y) {
						var v1 = x[prop];
						var v2 = y[prop];
						return v1 - v2
					}
				}
				map = courseMap.sort(compare('unit'))
				// console.log(map)
				var Map = new Array(35).fill({})
				for (let i = 0; i < map.length; i++) {
					Map[map[i].unit] = {
						unit: map[i].unit,
						teacher: map[i].teacher,
						classroom: map[i].classroom,
						courseName: map[i].courseName,
						weeks: map[i].weeks
					}
				}
				this.InfoMap = Map

			},
			loadDefaultData() {
				let self = this
				uni.request({
					url: getApp().globalData.baseURL + "/course/selectByOpenidAndWeeks",
					data: {
						"openid": wx.getStorageSync('openid'),
						"week": `${this.week}`
					},
					header: {
						"token": wx.getStorageSync('token')
					},
					success: (res) => {
						self.loadingTable = false
						if (res.data.code == 1) {
							self.getMap(res.data.data)
							self.resetMap(self.courseMap)
							self.getInfoMap(self.courseMap)
						} else if (res.data.code == 0) {
							Notify({
								type: 'warning',
								message: '您尚未登录,无法获取课表哦',
								top: 64
							});
						} else {
							Notify({
								type: 'danger',
								message: '获取课表失败',
								top: 64
							});
						}
						this.chooseWeek = false
					},
					fail: (err) => {
						self.loadingTable = false
						Notify({
							type: 'danger',
							message: '获取课表失败,请检查您的网络连接',
							top: 64
						});
						this.chooseWeek = false
					},

				})
			},
			confirmWeek(e) {
				this.week = e.detail.value
				this.loadingTable = true
				let self = this
				uni.request({
					url: getApp().globalData.baseURL + "/course/selectByOpenidAndWeeks",
					data: {
						"openid": wx.getStorageSync('openid'),
						"week": `${this.week}`
					},
					header: {
						"token": wx.getStorageSync('token')
					},
					success: (res) => {
						self.loadingTable = false
						if (res.data.code == 1) {
							self.getMap(res.data.data)
							self.resetMap(self.courseMap)
							self.getInfoMap(self.courseMap)
							Notify({
								type: 'success',
								message: '获取课表成功!',
								top: 64
							});
						} else if (res.data.code == 0) {
							Notify({
								type: 'warning',
								message: '您尚未登录,无法获取课表哦',
								top: 64
							});
						} else {
							Notify({
								type: 'danger',
								message: '获取课表失败',
								top: 64
							});
						}
						this.chooseWeek = false
						console.log(res.data)
					},
					fail: (err) => {
						self.loadingTable = false
						Notify({
							type: 'danger',
							message: '获取课表失败,请检查您的网络连接',
							top: 64
						});
						this.chooseWeek = false
					},

				})
			},
			// 添加课程
			addClass(e) {
				this.unit = e.detail
				uni.navigateTo({
					url: "../addCourse/addCourse"
				})
				uni.$on('send', () => {
					uni.$emit('update', {
						msg: this.unit
					})
				})

			}
		}
	}
</script>
<style>
	.month {
		/* height: 60rpx; */
		font-size: 32rpx;
	}

	.week {
		height: 60rpx;
		text-align: center;
	}

	.courseNum {
		height: 210rpx;

		text-align: center;
	}

	.courseNumBtn {
		height: 203rpx !important;
		width: 20rpx !important;
		border-radius: 10rpx !important;
	}

	.editCourse {
		height: 210rpx;
	}

	.weekTag {
		width: 60rpx;
		height: 50rpx;
		text-align: center;
		font-weight: bold;
	}

	.course {
		width: 100rpx;
		margin-right: 20rpx;
	}
</style>

自定义顶部导航栏组件:

<template>
	<view>
		<view class="header"
			:style="{'height':titleBarHeight,'padding-top':statusBarHeight,'background-color': nav.bg}">
			<text class="iconfont header-back " :style="{'border':nav.color}" v-if="nav.isdisPlayNavTitle"
				@click="popChooseWeek">
				&#xe61e;
			</text>
			<view class="header-title ">{{nav.navTitle}}</view>

		</view>
		<view :style="{'height':titleBarHeight,'padding-top':statusBarHeight}"></view>
	</view>
</template>
<script>
	export default {
		props: ["nav"],
		data() {
			return {
				chooseWeek: false,
				statusBarHeight: 0,
				titleBarHeight: 0,
			}
		},
		created() {
			var that = this;
			uni.getSystemInfo({
				success: function(res) {
					if (res.model.indexOf('iPhone') !== -1) {
						that.titleBarHeight = 44 + 'px';
					} else {
						that.titleBarHeight = 48 + 'px';
					}
					that.statusBarHeight = res.statusBarHeight + 'px'
				},

			})
		},
		methods: {
			// 弹出选择周数框
			popChooseWeek() {
				this.chooseWeek = true
				uni.$emit('choose', this.chooseWeek)
			}
		}
	}
</script>

<style>
	.header {
		display: flex;
		align-items: center;
		top: 0;
		position: fixed;
		width: 100%;
		z-index: 100;
		left: 0;
	}

	.header .header-title {
		position: absolute;
		left: 50%;
		font-size: 31rpx;
		transform: translateX(-50%);
		color: #fff
	}

	.header-back {
		position: absolute;
		left: 15upx;
		font-size: 30upx;
		padding: 10upx;
		border-radius: 50%;
	}

	@font-face {
		font-family: 'iconfont';
		/* Project id 2568587 */
		src: url('//at.alicdn.com/t/font_2568587_gslu7gcw01.woff2?t=1621863393001') format('woff2'),
			url('//at.alicdn.com/t/font_2568587_gslu7gcw01.woff?t=1621863393001') format('woff'),
			url('//at.alicdn.com/t/font_2568587_gslu7gcw01.ttf?t=1621863393001') format('truetype');
	}

	.iconfont {
		font-family: "iconfont" !important;
		font-size: 25px !important;
		color: #fff !important
	}

	.weight {
		font-weight: bold;
	}
</style>

效果:uniapp+vant weapp实现课程表小程序_课程表功能的实现

上一篇:2021-09-17 工作记录-vue-用vant实现下拉刷新


下一篇:vant-ui 按需引入