xuqiaoying 3 éve
szülő
commit
4d9ef91780

+ 0 - 16
components/tabbar/TabBar.vue

@@ -1,16 +0,0 @@
-<template>
-    <view class="tab_bar">
-        <u-tabbar v-model="current" :list="list" :mid-button="true" :mid-button-size="60" class="tab_items"></u-tabbar>
-    </view>
-</template>
-
-<script>
-export default {
-    data() {
-        return {
-            current: 0,
-            list: this.$store.state.tabLists
-        }
-    },
-}
-</script>

+ 7 - 0
components/u-tabbar/style.scss

@@ -0,0 +1,7 @@
+// 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错
+@mixin vue-flex($direction: row) {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	flex-direction: $direction;
+	/* #endif */
+}

+ 334 - 0
components/u-tabbar/u-tabbar.vue

@@ -0,0 +1,334 @@
+<template>
+	<view v-if="show" class="u-tabbar" @touchmove.stop.prevent="() => {}">
+		<view class="u-tabbar__content safe-area-inset-bottom" :style="{
+			height: $u.addUnit(height),
+			backgroundColor: bgColor,
+		}" :class="{
+			'u-border-top': borderTop
+		}">
+			<view class="u-tabbar__content__item" v-for="(item, index) in list" :key="index" :class="{
+				'u-tabbar__content__circle': midButton &&item.midButton
+			}" @tap.stop="clickHandler(index)" :style="{
+				backgroundColor: bgColor
+			}">
+				<view :class="[
+					midButton && item.midButton ? 'u-tabbar__content__circle__button' : 'u-tabbar__content__item__button'
+				]">
+					<u-icon
+						:size="midButton && item.midButton ? midButtonSize : iconSize"
+						:name="elIconPath(index)"
+						img-mode="scaleToFill"
+						:color="elColor(index)"
+						:custom-prefix="item.customIcon ? 'custom-icon' : 'uicon'"
+					></u-icon>
+					<u-badge :count="item.count" :is-dot="item.isDot"
+						v-if="item.count || item.isDot"
+						:offset="[-2, getOffsetRight(item.count, item.isDot)]"
+					></u-badge>
+				</view>
+				<view class="u-tabbar__content__item__text" :style="{
+					color: elColor(index)
+				}">
+					<text class="u-line-1">{{item.text}}</text>
+				</view>
+			</view>
+			<view v-if="midButton" class="u-tabbar__content__circle__border" :class="{
+				'u-border': borderTop,
+			}" :style="{
+				backgroundColor: bgColor,
+				left: midButtonLeft
+			}">
+			</view>
+		</view>
+		<!-- 这里加上一个48rpx的高度,是为了增高有凸起按钮时的防塌陷高度(也即按钮凸出来部分的高度) -->
+		<view class="u-fixed-placeholder safe-area-inset-bottom" :style="{
+				height: `calc(${$u.addUnit(height)} + ${midButton ? 48 : 0}rpx)`,
+			}"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			// 显示与否
+			show: {
+				type: Boolean,
+				default: true
+			},
+			// 通过v-model绑定current值
+			value: {
+				type: [String, Number],
+				default: 0
+			},
+			// 整个tabbar的背景颜色
+			bgColor: {
+				type: String,
+				default: '#ffffff'
+			},
+			// tabbar的高度,默认50px,单位任意,如果为数值,则为rpx单位
+			height: {
+				type: [String, Number],
+				default: '50px'
+			},
+			// 非凸起图标的大小,单位任意,数值默认rpx
+			iconSize: {
+				type: [String, Number],
+				default: 40
+			},
+			// 凸起的图标的大小,单位任意,数值默认rpx
+			midButtonSize: {
+				type: [String, Number],
+				default: 90
+			},
+			// 激活时的演示,包括字体图标,提示文字等的演示
+			activeColor: {
+				type: String,
+				default: '#303133'
+			},
+			// 未激活时的颜色
+			inactiveColor: {
+				type: String,
+				default: '#606266'
+			},
+			// 是否显示中部的凸起按钮
+			midButton: {
+				type: Boolean,
+				default: false
+			},
+			// 配置参数
+			list: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			// 切换前的回调
+			beforeSwitch: {
+				type: Function,
+				default: null
+			},
+			// 是否显示顶部的横线
+			borderTop: {
+				type: Boolean,
+				default: true
+			},
+			// 是否隐藏原生tabbar
+			hideTabBar: {
+				type: Boolean,
+				default: true
+			},
+		},
+		data() {
+			return {
+				// 由于安卓太菜了,通过css居中凸起按钮的外层元素有误差,故通过js计算将其居中
+				midButtonLeft: '50%',
+				pageUrl: '', // 当前页面URL
+			}
+		},
+		created() {
+			// 是否隐藏原生tabbar
+			if(this.hideTabBar) uni.hideTabBar();
+			// 获取引入了u-tabbar页面的路由地址,该地址没有路径前面的"/"
+			let pages = getCurrentPages();
+			// 页面栈中的最后一个即为项为当前页面,route属性为页面路径
+			this.pageUrl = pages[pages.length - 1].route;
+		},
+		computed: {
+			elIconPath() {
+				return (index) => {
+					// 历遍u-tabbar的每一项item时,判断是否传入了pagePath参数,如果传入了
+					// 和data中的pageUrl参数对比,如果相等,即可判断当前的item对应当前的tabbar页面,设置高亮图标
+					// 采用这个方法,可以无需使用v-model绑定的value值
+					let pagePath = this.list[index].pagePath;
+					// 如果定义了pagePath属性,意味着使用系统自带tabbar方案,否则使用一个页面用几个组件模拟tabbar页面的方案
+					// 这两个方案对处理tabbar item的激活与否方式不一样
+					if(pagePath) {
+						if(pagePath == this.pageUrl || pagePath == '/' + this.pageUrl) {
+							return this.list[index].selectedIconPath;
+						} else {
+							return this.list[index].iconPath;
+						}
+					} else {
+						// 普通方案中,索引等于v-model值时,即为激活项
+						return index == this.value ? this.list[index].selectedIconPath : this.list[index].iconPath
+					}
+				}
+			},
+			elColor() {
+				return (index) => {
+					// 判断方法同理于elIconPath
+					let pagePath = this.list[index].pagePath;
+					if(pagePath) {
+						if(pagePath == this.pageUrl || pagePath == '/' + this.pageUrl) return this.activeColor;
+						else return this.inactiveColor;
+					} else {
+						return index == this.value ? this.activeColor : this.inactiveColor;
+					}
+				}
+			}
+		},
+		mounted() {
+			this.midButton && this.getMidButtonLeft();
+		},
+		methods: {
+			async clickHandler(index) {
+				if(this.beforeSwitch && typeof(this.beforeSwitch) === 'function') {
+					// 执行回调,同时传入索引当作参数
+					// 在微信,支付宝等环境(H5正常),会导致父组件定义的customBack()函数体中的this变成子组件的this
+					// 通过bind()方法,绑定父组件的this,让this.customBack()的this为父组件的上下文
+					let beforeSwitch = this.beforeSwitch.bind(this.$u.$parent.call(this))(index);
+					// 判断是否返回了promise
+					if (!!beforeSwitch && typeof beforeSwitch.then === 'function') {
+						await beforeSwitch.then(res => {
+							// promise返回成功,
+							this.switchTab(index);
+						}).catch(err => {
+
+						})
+					} else if(beforeSwitch === true) {
+						// 如果返回true
+						this.switchTab(index);
+					}
+				} else {
+					this.switchTab(index);
+				}
+			},
+			// 切换tab
+			switchTab(index) {
+				// 发出事件和修改v-model绑定的值
+				this.$emit('change', index);
+				// 如果有配置pagePath属性,使用uni.switchTab进行跳转
+				if(this.list[index].pagePath) {
+					uni.switchTab({
+						url: this.list[index].pagePath
+					})
+				} else {
+					// 如果配置了papgePath属性,将不会双向绑定v-model传入的value值
+					// 因为这个模式下,不再需要v-model绑定的value值了,而是通过getCurrentPages()适配
+					this.$emit('input', index);
+				}
+			},
+			// 计算角标的right值
+			getOffsetRight(count, isDot) {
+				// 点类型,count大于9(两位数),分别设置不同的right值,避免位置太挤
+				if(isDot) {
+					return -20;
+				} else if(count > 9) {
+					return -40;
+				} else {
+					return -30;
+				}
+			},
+			// 获取凸起按钮外层元素的left值,让其水平居中
+			getMidButtonLeft() {
+				let windowWidth = this.$u.sys().windowWidth;
+				// 由于安卓中css计算left: 50%的结果不准确,故用js计算
+				this.midButtonLeft = (windowWidth / 2) + 'px';
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	@import "./style.scss";
+	.u-fixed-placeholder {
+		/* #ifndef APP-NVUE */
+		box-sizing: content-box;
+		/* #endif */
+	}
+
+	.u-tabbar {
+
+		&__content {
+			@include vue-flex;
+			align-items: center;
+			position: relative;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 100%;
+			z-index: 998;
+			/* #ifndef APP-NVUE */
+			box-sizing: content-box;
+			/* #endif */
+
+			&__circle__border {
+				border-radius: 100%;
+				width: 110rpx;
+				height: 110rpx;
+				// top: -46rpx;
+				top: -20rpx;
+				position: absolute;
+				z-index: 4;
+				background-color: #ffffff;
+				// 由于安卓的无能,导致只有3个tabbar item时,此css计算方式有误差
+				// 故使用js计算的形式来定位,此处不注释,是因为js计算有延后,避免出现位置闪动
+				left: 50%;
+				transform: translateX(-50%);
+
+				&:after {
+					border-radius: 100px;
+				}
+			}
+
+			&__item {
+				flex: 1;
+				justify-content: center;
+				height: 100%;
+				padding: 12rpx 0;
+				@include vue-flex;
+				flex-direction: column;
+				align-items: center;
+				position: relative;
+
+				&__button {
+					position: absolute;
+					top: 14rpx;
+					left: 50%;
+					transform: translateX(-50%);
+				}
+
+				&__text {
+					color: $u-content-color;
+					font-size: 26rpx;
+					line-height: 28rpx;
+					position: absolute;
+					bottom: 14rpx;
+					left: 50%;
+					transform: translateX(-50%);
+					width: 100%;
+					text-align: center;
+				}
+			}
+
+			&__circle {
+				position: relative;
+				@include vue-flex;
+				flex-direction: column;
+				justify-content: space-between;
+				z-index: 10;
+				/* #ifndef APP-NVUE */
+				height: calc(100% - 1px);
+				/* #endif */
+
+				&__button {
+					// width: 90rpx;
+					// height: 90rpx;
+					width: 60rpx;
+					height: 60rpx;
+					border-radius: 100%;
+					@include vue-flex;
+					justify-content: center;
+					align-items: center;
+					position: absolute;
+					background-color: #ffffff;
+					// top: -40rpx;
+					top: -10rpx;
+					left: 50%;
+					z-index: 6;
+					transform: translateX(-50%);
+				}
+			}
+		}
+	}
+</style>

+ 10 - 10
pages.json

@@ -1031,34 +1031,34 @@
 		"borderStyle": "black",
 		"backgroundColor": "#fff",
 		"list": [{
-				"pagePath": "pages/index/index"
+				"pagePath": "pages/index/index",
 				// "iconPath": "static/nav1.png",
 				// "selectedIconPath": "static/nav1_on.png",
-				// "text": "首页"
+				"text": "首页"
 			},
 			{
-				"pagePath": "pages/course/index"
+				"pagePath": "pages/course/index",
 				// "iconPath": "static/nav2.png",
 				// "selectedIconPath": "static/nav2_on.png",
-				// "text": "选课"
+				"text": "选课"
 			},
             {
-				"pagePath": "pages/learn/index"
+				"pagePath": "pages/learn/index",
 				// "iconPath": "static/nav6.png",
 				// "selectedIconPath": "static/nav6_on.png",
-				// "text": "学习"
+				"text": "学习"
 			},
 			{
-				"pagePath": "pages/shopping/shoppingCart"
+				"pagePath": "pages/shopping/shoppingCart",
 				// "iconPath": "static/nav3.png",
 				// "selectedIconPath": "static/nav3_on.png",
-				// "text": "购物车"
+				"text": "购物车"
 			},
 			{
-				"pagePath": "pages/wd/index"
+				"pagePath": "pages/wd/index",
 				// "iconPath": "static/nav5.png",
 				// "selectedIconPath": "static/nav5_on.png",
-				// "text": "我的"
+				"text": "我的"
 			}
 		]
 	},

+ 15 - 6
pages/course/index.vue

@@ -10,7 +10,7 @@
 				<view class="bg_color"></view>
 				<view class="check_ck">
 					<view class="checked">
-						<view style="color: #666666;white-space: nowrap;width: 75%;overflow-x: hidden;">{{selObj.eName}}:{{selObj.pName}}-{{selObj.bName}}</view>
+						<view class="check_title">{{selObj.eName}}:{{selObj.pName}}-{{selObj.bName}}</view>
 						<view class="again_ck" @click="openLeft()">
 							<view style="color: #007AFF;font-size: 32rpx;">重新选择</view>
 							<u-icon name="list" color="#007AFF" size="40"></u-icon>
@@ -137,12 +137,12 @@
 			</view>
 		</view>
 
-		<tab-bar></tab-bar>
+		<tab-bar v-model="current" :list="tabbarlist" :mid-button="true" :mid-button-size="50" class="tab_items"></tab-bar>
 	</view>
 </template>
 
 <script>
-import TabBar from '../../components/tabbar/TabBar.vue';
+import TabBar from '@/components/u-tabbar/u-tabbar.vue';
 import { mapGetters } from 'vuex';
 export default {
 	components: {
@@ -205,7 +205,9 @@ export default {
 				eId:0,
 				bId:0,
 				pId:0,
-			}
+			},
+			current: 1,
+            tabbarlist: this.$store.state.tabLists
 		};
 	},
 	onPullDownRefresh(){
@@ -418,7 +420,14 @@ export default {
 	line-height: 108rpx;
 	border-bottom: 1rpx solid #EEEEEE;
 	font-size: 28rpx;
-	
+	.check_title {
+		font-size: 32rpx;
+		font-weight: 500;
+		color: #333;
+		white-space: nowrap;
+		width: 75%;
+		overflow-x: hidden;
+	}
 }
 .contents {
 	position: relative;
@@ -580,7 +589,7 @@ export default {
 	}
 	.listBox{
 		background-color: #EAEEF1;
-		padding: 24rpx 24rpx 100rpx 24rpx;
+		padding: 24rpx 24rpx 150rpx 24rpx;
 		position: relative;
 		// top: 235rpx;
 	}

+ 5 - 4
pages/index/index.vue

@@ -181,14 +181,14 @@
 			</view>
 		</view>
 
-		<tab-bar></tab-bar>
+		<tab-bar v-model="current" :list="tabbarlist" :mid-button="true" :mid-button-size="50" class="tab_items"></tab-bar>
 	</view>
 </template>
 
 <script>
 import { mapGetters, mapActions } from 'vuex';
 import { socket_url, version} from '@/common/request.js';
-import TabBar from '../../components/tabbar/TabBar.vue';
+import TabBar from '@/components/u-tabbar/u-tabbar.vue';
 export default {
 	components: { TabBar },
 	data() {
@@ -242,7 +242,9 @@ export default {
 			list1: [],
 			list2: [],
 			isLogin:false,
-			isOld:false
+			isOld:false,
+			current: 0,
+            tabbarlist: this.$store.state.tabLists
 		};
 	},
 	onPullDownRefresh() {},
@@ -288,7 +290,6 @@ export default {
 		this.appCommonConfig({
 			version
 		});
-		console.log('999999999999999')
 		if(this.$method.isLogin()){
 			this.$store.state.allowLoading = false;
 			this.$api.getinfoAttached().then(res => {

+ 4 - 2
pages/learn/index.vue

@@ -430,7 +430,7 @@
 			</view>
 		</u-modal>
 
-		<tab-bar></tab-bar>
+		<tab-bar v-model="current" :list="tabbarlist" :mid-button="true" :mid-button-size="50" class="tab_items"></tab-bar>
     </view>
 </template>
 
@@ -438,7 +438,7 @@
 var curTime = new Date().getTime() // 当前时间的时间戳
 import {mapGetters,mapActions} from 'vuex'
 import { WEBVIEW_URL } from '@/common/request.js'
-import TabBar from '../../components/tabbar/TabBar.vue'
+import TabBar from '@/components/u-tabbar/u-tabbar.vue';
 export default {
 	components: { TabBar },
     data() {
@@ -468,6 +468,8 @@ export default {
 			queitemIndex:'',
 			livingLists: [], // 直播列表
 			allLoading: false, // 加载样式
+			current: 2,
+            tabbarlist: this.$store.state.tabLists
         }
     },
 	filters: {

+ 7 - 4
pages/shopping/shoppingCart.vue

@@ -155,13 +155,13 @@
 			</view>
 		</view>
 
-		<tab-bar></tab-bar>
+		<tab-bar v-model="current" :list="tabbarlist" :mid-button="true" :mid-button-size="50" class="tab_items"></tab-bar>
 	</view>
 </template>
 
 <script>
 import { mapGetters } from 'vuex';
-import TabBar from '../../components/tabbar/TabBar.vue'
+import TabBar from '@/components/u-tabbar/u-tabbar.vue';
 export default {
 	components: { TabBar },
 	data() {
@@ -189,7 +189,9 @@ export default {
 			},
 			pAreaIndex: 0,
 			cAreaIndex: 0,
-			examIndex: 0
+			examIndex: 0,
+			current: 3,
+            tabbarlist: this.$store.state.tabLists
 		};
 	},
 	computed: { ...mapGetters(['userInfo','hideBuyState']) },
@@ -662,7 +664,7 @@ page {
 }
 .bottomBox {
 	position: fixed;
-	bottom: 100rpx;
+	bottom: 170rpx;
 	width: 100%;
 	left: 0;
 	height: 132rpx;
@@ -672,6 +674,7 @@ page {
 	align-items: center;
 	padding: 0 32rpx;
 	box-shadow: 0px -2px 6px 0px rgba(0,0,0,0.1000);
+	z-index: 9999;
 	.bottons_all {
 		// width: 674rpx;
 		// height: 104rpx;

+ 4 - 2
pages/wd/index.vue

@@ -133,14 +133,14 @@
 			<view class="slot-wrap"><image src="/static/logo.png" style="width: 178rpx;height: 31rpx;margin-left: 30rpx;"></image></view>
 		</u-navbar> -->
 
-		<tab-bar></tab-bar>
+		<tab-bar v-model="current" :list="tabbarlist" :mid-button="true" :mid-button-size="50" class="tab_items"></tab-bar>
 	</view>
 </template>
 
 <script>
 // import { websocket } from '@/common/socket.js';
 import { mapGetters } from 'vuex';
-import TabBar from '../../components/tabbar/TabBar.vue';
+import TabBar from '@/components/u-tabbar/u-tabbar.vue';
 export default {
 	components: {TabBar},
 	data() {
@@ -152,6 +152,8 @@ export default {
 			userNums: {},
 			total1:0,
 			total2:0,
+			current: 4,
+            tabbarlist: this.$store.state.tabLists
 		};
 	},
 	onLoad(option) {

+ 2 - 0
pages2/register/bind.vue

@@ -74,6 +74,8 @@ export default {
 									uni.navigateTo({
 										url: '/pages4/login/pcLoginSuccess'
 									})
+								} else {
+									this.$u.toast(res.data.msg)
 								}
 							})
 						} else { // 跳转到首页是原来的逻辑

+ 1 - 1
pages2/register/register.vue

@@ -399,7 +399,7 @@ export default {
 									title: '提示',
 									content: '注册成功',
 									showCancel:false,
-									success: function(resst) {
+									success: (resst) => {
 										// uni.navigateBack()
 										
 										that.$api.accountLogin({