Browse Source

zhi_neng_ke_fu

lhl 18 hours ago
parent
commit
5214a359c2
79 changed files with 3817 additions and 920 deletions
  1. 322 277
      App.vue
  2. 6 0
      api/index.js
  3. 82 0
      api/kf.js
  4. 29 0
      api/signing.js
  5. 23 0
      api/user.js
  6. 30 0
      config/tabbar.js
  7. 1 1
      manifest.json
  8. 88 48
      pages.json
  9. 2 2
      pages/eduction/detail.vue
  10. 15 6
      pages/index/detail.vue
  11. 75 14
      pages/index/index.vue
  12. 8 2
      pages/index/listModel.vue
  13. 169 0
      pages/index/store.vue
  14. 27 0
      pages/index/webview.vue
  15. 32 2
      pages/modelData/modeltemplate/model_1.vue
  16. 33 10
      pages/modelData/modeltemplate/model_2.vue
  17. 43 2
      pages/modelData/modeltemplate/model_3.vue
  18. 34 19
      pages/modelData/modeltemplate/model_5.vue
  19. 40 33
      pages/public/artDetail.vue
  20. 121 118
      pages/public/artDetailTab.vue
  21. 5 0
      pages/public/login.vue
  22. 6 1
      pages/public/loginMethods.vue
  23. 6 1
      pages/public/phoneLogin.vue
  24. 17 7
      pages/public/wxLogin.vue
  25. 165 142
      pages/set/kf/index.vue
  26. 257 0
      pages/set/kf/list.vue
  27. 6 1
      pages/set/lng.vue
  28. 6 1
      pages/set/phone.vue
  29. 6 1
      pages/set/userinfo.vue
  30. 3 2
      pages/user/forum/index.vue
  31. 27 5
      pages/user/jf/bill.vue
  32. 14 1
      pages/user/jf/detail.vue
  33. 83 2
      pages/user/jf/jfcz.vue
  34. 202 11
      pages/user/jf/orderDetail.vue
  35. 24 6
      pages/user/jf/rechange.vue
  36. 6 1
      pages/user/jf/success.vue
  37. 284 91
      pages/user/model/model.vue
  38. 4 1
      pages/user/model/modelList.vue
  39. 1 1
      pages/user/model/modelQr.vue
  40. 66 6
      pages/user/model/modelrz.vue
  41. 1 1
      pages/user/myteam.vue
  42. 6 1
      pages/user/realName/realNameAuthentication.vue
  43. 120 36
      pages/user/signing/mySig.vue
  44. 87 40
      pages/user/signing/signing.vue
  45. 145 26
      pages/userhome/user.vue
  46. 100 0
      pages/znkf/index.vue
  47. BIN
      static/error/emptyCart.png
  48. BIN
      static/error/emptyItem.png
  49. BIN
      static/error/emptyList.png
  50. BIN
      static/error/emptyMyCart.png
  51. BIN
      static/error/emptyNotice.png
  52. BIN
      static/error/emptyOrder.png
  53. BIN
      static/error/errorImage.jpg
  54. BIN
      static/error/shopErroe.png
  55. BIN
      static/icon/close.png
  56. BIN
      static/icon/jfsc.png
  57. BIN
      static/icon/kff.png
  58. BIN
      static/icon/kfzx.png
  59. BIN
      static/icon/ok.png
  60. BIN
      static/image/ht.png
  61. BIN
      static/image/logo.png
  62. BIN
      static/image/modelQshare.png
  63. BIN
      static/image/qy.png
  64. BIN
      static/image/qybanner.jpg
  65. BIN
      static/image/qyweichat.jpg
  66. BIN
      static/image/teimImg.jpg
  67. BIN
      static/image/zx.png
  68. BIN
      static/img/b0c1028581f40a90b2454abfde489f9.png
  69. BIN
      static/img/e0caee5ee096efb49bed156878b1db1.png
  70. BIN
      static/img/phb.png
  71. BIN
      static/img/tg-bg.png
  72. BIN
      static/tabBar/tab-xxjl-current.png
  73. BIN
      static/tabBar/tab-xxjl.png
  74. 4 0
      store/index.js
  75. 76 0
      uni_modules/m-tabbar/changelog.md
  76. 516 0
      uni_modules/m-tabbar/components/m-tabbar/m-tabbar.vue
  77. 81 0
      uni_modules/m-tabbar/package.json
  78. 312 0
      uni_modules/m-tabbar/readme.md
  79. 1 1
      utils/request.js

+ 322 - 277
App.vue

@@ -1,300 +1,345 @@
 <script>
-/**
- * vuex管理登陆状态,具体可以参考官方登陆模板示例
- */
-import { mapMutations } from 'vuex';
-// #ifdef H5
-import { weixindata, setRouter } from './utils/wxAuthorized';
-// #endif
-// #ifdef APP-PLUS
-import { getUpApp } from './utils/upApp.js';
-// #endif
-export default {
-	data() {
-		return {
-			/* 保存微信信息 */
-			appData: {}
-		};
-	},
-	methods: {
-		...mapMutations('user', ['setUserInfo', 'login', 'hasLogin']),
-		...mapMutations('shop', ['setShopInfo','setShopAction']),
-		...mapMutations(['setFirstUse']),
-		// #ifdef MP
-		...mapMutations(['setSystem']),
-		// #endif
-	},
-	onLaunch: function(urlObj) {
-		const that = this;
-		// #ifdef MP
-		uni.getSystemInfo({
-			success(re) {
-				that.setSystem(re.osName)
-			}
-		})
-		// #endif
-		const obj = this;
-		// 加载缓存中的用户信息
-		const userInfo = uni.getStorageSync('userInfo') || '';
-		// 判断是否拥有用户信息
-		if (userInfo) {
-			//更新登陆状态
-			uni.getStorage({
-				key: 'userInfo',
-				success: res => {
-					obj.setUserInfo(res.data);
-					obj.login();
-				},fail(res) {
-					console.log(res,'res.data');
+	/**
+	 * vuex管理登陆状态,具体可以参考官方登陆模板示例
+	 */
+	import {
+		mapMutations
+	} from 'vuex';
+	// #ifdef H5
+	import {
+		weixindata,
+		setRouter
+	} from './utils/wxAuthorized';
+	// #endif
+	// #ifdef APP-PLUS
+	import {
+		getUpApp
+	} from './utils/upApp.js';
+	// #endif
+	export default {
+		data() {
+			return {
+				/* 保存微信信息 */
+				appData: {}
+			};
+		},
+		methods: {
+			...mapMutations('user', ['setUserInfo', 'login', 'hasLogin']),
+			...mapMutations('shop', ['setShopInfo', 'setShopAction']),
+			...mapMutations(['setFirstUse','openOpen']),
+			// #ifdef MP
+			...mapMutations(['setSystem']),
+			// #endif
+		},
+		onLaunch: function(urlObj) {
+			const that = this;
+			// #ifdef MP
+			uni.getSystemInfo({
+				success(re) {
+					that.setSystem(re.osName)
 				}
-				
-			});
+			})
+			// #endif
+			const obj = this;
+			// 加载缓存中的用户信息
+			const userInfo = uni.getStorageSync('userInfo') || '';
+			// 判断是否拥有用户信息
+			if (userInfo) {
+				//更新登陆状态
+				uni.getStorage({
+					key: 'userInfo',
+					success: res => {
+						obj.setUserInfo(res.data);
+						obj.login();
+					},
+					fail(res) {
+						console.log(res, 'res.data');
+					}
+
+				});
+			}
+
+			// 获取当前位置附近商店数据
+			const shopDetail = uni.getStorageSync('shopDetail') || '';
+			if (shopDetail) {
+				uni.getStorage({
+					key: 'shopDetail',
+					success: res => {
+						obj.setShopInfo(res.data);
+					}
+				});
+			}
+			// 获取商家用户数据
+			const shopDetailAction = uni.getStorageSync('shopDetailAction') || '';
+			if (shopDetailAction) {
+				uni.getStorage({
+					key: 'shopDetailAction',
+					success: res => {
+						obj.setShopAction(res.data);
+					}
+				});
+			}
+			// 获取是否已经在如果引导图
+			const guideMap = uni.getStorageSync('guideMap') || false;
+			// 判断是否已经加载过数据
+			if (guideMap) {
+				this.setFirstUse(true)
+			}
+			// #ifdef H5
+			// 保存路由对象
+			setRouter(this.$router);
+			//判断是否已经缓存浏览器
+			let bool = uni.getStorageSync('weichatBrowser') || '';
+			if (bool === '') {
+				//判断是否为微信浏览
+				bool = navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger';
+				// 保存当前是否为微信内核浏览器
+				uni.setStorageSync('weichatBrowser', bool);
+			}
+			if (bool) {
+				// 加载微信信息
+				weixindata();
+			}
+			// #endif
+			// #ifdef APP-PLUS
+			// 判断是否升级
+			getUpApp();
+			// 获取当前运行系统
+			let system = uni.getStorageSync('platform') || '';
+			if (!system) {
+				uni.setStorage({
+					key: 'platform',
+					data: uni.getSystemInfoSync().platform
+				});
+			}
+			// #endif
+		},
+		onShow: function() {
+			const appBaseInfo = wx.getAccountInfoSync()
+			if (appBaseInfo.miniProgram.envVersion == 'release') {
+				// release  develop
+				console.log('open++++++++++++');
+				this.openOpen(true)
+			} else {
+				this.openOpen(false)
+			}
+			// 加载拦截
+		},
+		onHide: function() {}
+	};
+</script>
+
+<style lang="scss">
+	/*全局公共样式和字体图标*/
+	@import '/static/css/cmy.css';
+
+	view,
+	scroll-view,
+	swiper,
+	swiper-item,
+	cover-view,
+	cover-image,
+	icon,
+	text,
+	rich-text,
+	progress,
+	button,
+	checkbox,
+	form,
+	input,
+	label,
+	radio,
+	slider,
+	switch,
+	textarea,
+	navigator,
+	audio,
+	camera,
+	image,
+	video {
+		box-sizing: border-box;
+	}
+
+	/* 骨架屏替代方案 */
+	.Skeleton {
+		background: #f3f3f3;
+		padding: 20rpx 0;
+		border-radius: 8rpx;
+	}
+
+	/* 图片载入替代方案 */
+	.image-wrapper {
+		font-size: 0;
+		background: #f3f3f3;
+		border-radius: 4px;
+
+		image {
+			width: 100%;
+			height: 100%;
+			transition: 0.6s;
+			opacity: 0;
+
+			&.loaded {
+				opacity: 1;
+			}
 		}
-		
-		// 获取当前位置附近商店数据
-		const shopDetail = uni.getStorageSync('shopDetail') ||'';
-		if(shopDetail){
-			uni.getStorage({
-				key: 'shopDetail',
-				success: res => {
-					obj.setShopInfo(res.data);
-				}
-			});
+	}
+
+	// 设置富文本中图片最大宽度
+	uni-rich-text img {
+		max-width: 100% !important;
+	}
+
+	/*边框*/
+	.b-b:after,
+	.b-t:after {
+		position: absolute;
+		z-index: 3;
+		left: 0;
+		right: 0;
+		height: 0;
+		content: '';
+		transform: scaleY(0.5);
+		border-bottom: 1px solid $border-color-base;
+	}
+
+	.b-b:after {
+		bottom: 0;
+	}
+
+	.b-t:after {
+		top: 0;
+	}
+
+	/* input 样式 */
+	.input-placeholder {
+		color: #999999;
+	}
+
+	.placeholder {
+		color: #999999;
+	}
+
+	// 边距样式
+	@for $i from 1 to 5 {
+		.margin-l-#{$i * 10} {
+			margin-left: $i * 10rpx !important;
 		}
-		// 获取商家用户数据
-		const shopDetailAction = uni.getStorageSync('shopDetailAction') ||'';
-		if(shopDetailAction){
-			uni.getStorage({
-				key: 'shopDetailAction',
-				success: res => {
-					obj.setShopAction(res.data);
-				}
-			});
+
+		.margin-r-#{$i * 10} {
+			margin-right: $i * 10rpx !important;
 		}
-		// 获取是否已经在如果引导图
-		const guideMap = uni.getStorageSync('guideMap') ||false;
-		// 判断是否已经加载过数据
-		if(guideMap){
-			this.setFirstUse(true)
+
+		.margin-t-#{$i * 10} {
+			margin-top: $i * 10rpx !important;
 		}
-		// #ifdef H5
-		// 保存路由对象
-		setRouter(this.$router);
-		//判断是否已经缓存浏览器
-		let bool = uni.getStorageSync('weichatBrowser') || '';
-		if (bool === '') {
-			//判断是否为微信浏览
-			bool = navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger';
-			// 保存当前是否为微信内核浏览器
-			uni.setStorageSync('weichatBrowser', bool);
+
+		.margin-b-#{$i * 10} {
+			margin-bottom: $i * 10rpx !important;
 		}
-		if (bool) {
-			// 加载微信信息
-			weixindata();
+
+		.margin-#{$i * 10} {
+			margin: $i * 10rpx !important;
 		}
-		// #endif
-		// #ifdef APP-PLUS
-		// 判断是否升级
-		getUpApp();
-		// 获取当前运行系统
-		let system = uni.getStorageSync('platform') || '';
-		if (!system) {
-			uni.setStorage({
-				key: 'platform',
-				data: uni.getSystemInfoSync().platform
-			});
+
+		.margin-v-#{$i * 10} {
+			margin-top: $i * 10rpx !important;
+			margin-bottom: $i * 10rpx !important;
 		}
-		// #endif
-	},
-	onShow: function() {
-		// 加载拦截
-	},
-	onHide: function() {
-	}
-};
-</script>
 
-<style lang="scss">
-/*全局公共样式和字体图标*/
-@import '/static/css/cmy.css';
-view,
-scroll-view,
-swiper,
-swiper-item,
-cover-view,
-cover-image,
-icon,
-text,
-rich-text,
-progress,
-button,
-checkbox,
-form,
-input,
-label,
-radio,
-slider,
-switch,
-textarea,
-navigator,
-audio,
-camera,
-image,
-video {
-	box-sizing: border-box;
-}
-/* 骨架屏替代方案 */
-.Skeleton {
-	background: #f3f3f3;
-	padding: 20rpx 0;
-	border-radius: 8rpx;
-}
-
-/* 图片载入替代方案 */
-.image-wrapper {
-	font-size: 0;
-	background: #f3f3f3;
-	border-radius: 4px;
-	image {
-		width: 100%;
-		height: 100%;
-		transition: 0.6s;
-		opacity: 0;
-		&.loaded {
-			opacity: 1;
+		.margin-c-#{$i * 10} {
+			margin-left: $i * 10rpx !important;
+			margin-right: $i * 10rpx !important;
+		}
+
+		.padding-l-#{$i * 10} {
+			padding-left: $i * 10rpx !important;
+		}
+
+		.padding-r-#{$i * 10} {
+			padding-right: $i * 10rpx !important;
+		}
+
+		.padding-t-#{$i * 10} {
+			padding-top: $i * 10rpx !important;
+		}
+
+		.padding-b-#{$i * 10} {
+			padding-bottom: $i * 10rpx !important;
+		}
+
+		.padding-#{$i * 10} {
+			padding: $i * 10rpx !important;
+		}
+
+		.padding-v-#{$i * 10} {
+			padding-top: $i * 10rpx !important;
+			padding-bottom: $i * 10rpx !important;
+		}
+
+		.padding-c-#{$i * 10} {
+			padding-left: $i * 10rpx !important;
+			padding-right: $i * 10rpx !important;
 		}
 	}
-}
-
-// 设置富文本中图片最大宽度
-uni-rich-text img {
-	max-width: 100% !important;
-}
-/*边框*/
-.b-b:after,
-.b-t:after {
-	position: absolute;
-	z-index: 3;
-	left: 0;
-	right: 0;
-	height: 0;
-	content: '';
-	transform: scaleY(0.5);
-	border-bottom: 1px solid $border-color-base;
-}
-
-.b-b:after {
-	bottom: 0;
-}
-
-.b-t:after {
-	top: 0;
-}
-
-/* input 样式 */
-.input-placeholder {
-	color: #999999;
-}
-
-.placeholder {
-	color: #999999;
-}
-// 边距样式
-@for $i from 1 to 5 {
-	.margin-l-#{$i * 10} {
-		margin-left: $i * 10rpx !important;
-	}
-	.margin-r-#{$i * 10} {
-		margin-right: $i * 10rpx !important;
-	}
-	.margin-t-#{$i * 10} {
-		margin-top: $i * 10rpx !important;
-	}
-	.margin-b-#{$i * 10} {
-		margin-bottom: $i * 10rpx !important;
+
+	// 字体大小
+	.font-size-sm {
+		font-size: $font-sm;
 	}
-	.margin-#{$i * 10} {
-		margin: $i * 10rpx !important;
+
+	.font-size-base {
+		font-size: $font-base;
 	}
-	.margin-v-#{$i * 10} {
-		margin-top: $i * 10rpx !important;
-		margin-bottom: $i * 10rpx !important;
+
+	.font-size-lg {
+		font-size: $font-lg;
 	}
-	.margin-c-#{$i * 10} {
-		margin-left: $i * 10rpx !important;
-		margin-right: $i * 10rpx !important;
+
+	// 字体颜色
+	.font-color-yellow {
+		color: $color-yellow !important;
 	}
-	.padding-l-#{$i * 10} {
-		padding-left: $i * 10rpx !important;
+
+	.font-color-gray {
+		color: $color-gray !important;
 	}
-	.padding-r-#{$i * 10} {
-		padding-right: $i * 10rpx !important;
+
+	.font-color-red {
+		color: $color-red !important;
 	}
-	.padding-t-#{$i * 10} {
-		padding-top: $i * 10rpx !important;
+
+	.font-color-greed {
+		color: $color-green !important;
 	}
-	.padding-b-#{$i * 10} {
-		padding-bottom: $i * 10rpx !important;
+
+	// 边框颜色
+	.border-color-yellow {
+		border: 1rpx solid $color-yellow;
 	}
-	.padding-#{$i * 10} {
-		padding: $i * 10rpx !important;
+
+	// 基础按钮
+	.base-buttom {
+		background-color: $base-color;
+		font-size: 32rpx;
+		padding: 30rpx;
+		color: #FFFFFF;
+		margin: 0 30rpx;
+		border-radius: 10rpx;
+		margin-top: 100rpx;
+		text-align: center;
+		z-index: 95;
 	}
-	.padding-v-#{$i * 10} {
-		padding-top: $i * 10rpx !important;
-		padding-bottom: $i * 10rpx !important;
+
+	// 修改默认背景颜色
+	uni-page-wrapper {
+		background-color: $page-color-base;
 	}
-	.padding-c-#{$i * 10} {
-		padding-left: $i * 10rpx !important;
-		padding-right: $i * 10rpx !important;
+
+	page {
+		background-color: $page-color-base;
+		// 设置默认字体
+		font-family: PingFang SC, STHeitiSC-Light, Helvetica-Light, arial, sans-serif, Droid Sans Fallback;
+		min-height: 100%;
 	}
-}
-// 字体大小
-.font-size-sm {
-	font-size: $font-sm;
-}
-.font-size-base {
-	font-size: $font-base;
-}
-.font-size-lg {
-	font-size: $font-lg;
-}
-// 字体颜色
-.font-color-yellow {
-	color: $color-yellow !important;
-}
-.font-color-gray {
-	color: $color-gray !important;
-}
-.font-color-red {
-	color: $color-red !important;
-}
-.font-color-greed {
-	color: $color-green !important;
-}
-// 边框颜色
-.border-color-yellow {
-	border: 1rpx solid $color-yellow;
-}
-// 基础按钮
-.base-buttom {
-	background-color: $base-color;
-	font-size: 32rpx;
-	padding: 30rpx;
-	color: #FFFFFF;
-	margin: 0 30rpx;
-	border-radius: 10rpx;
-	margin-top: 100rpx;
-	text-align: center;
-	z-index: 95;
-}
-// 修改默认背景颜色
-uni-page-wrapper {
-	background-color: $page-color-base;
-}
-page {
-	background-color: $page-color-base;
-	// 设置默认字体
-	font-family: PingFang SC, STHeitiSC-Light, Helvetica-Light, arial, sans-serif, Droid Sans Fallback;
-	min-height: 100%;
-}
-</style>
+</style>

+ 6 - 0
api/index.js

@@ -85,6 +85,12 @@ export function getArtDetail(data) {
 		data
 	});
 }
+export function getArtList(data) {
+	return request({
+		url: '/api/pub/getArtList?cid=' + data,
+		method: 'get'
+	});
+}
 
 export function getKcList(data) {
 	return request({

+ 82 - 0
api/kf.js

@@ -0,0 +1,82 @@
+import request from '@/utils/request'
+/**
+ * 发送
+ * @param {Object} data
+ * @param {number} data.to_user_id
+ * @param {number} data.content
+ * @param {number} data.type
+ * @param {number} data.form_type
+ */
+export function send(data) {
+	return request({
+		url: '/api/chat/send',
+		method: 'post',
+		data
+	});
+}
+
+/**
+ * 标记消息已读
+ * @param {Object} data
+ * @param {number} data.form_user_id
+ */
+export function markRead(data) {
+	return request({
+		url: '/api/chat/markRead',
+		method: 'post',
+		data
+	});
+}
+
+/**
+ *  获取未读消息数
+ * @param {Object} data
+ * @param {number} data.form_user_id
+ */
+export function getUnreadCount(data) {
+	return request({
+		url: '/api/chat/unreadCount',
+		method: 'post',
+		data
+	});
+}
+
+/**
+ * 获取会话列表
+ */
+export function getSessionList() {
+	return request({
+		url: '/api/chat/sessionList',
+		method: 'get',
+	});
+}
+
+/**
+ * 记录
+ * @param {Object} data
+ * @param {number} data.to_user_id
+ * @param {number} data.page
+ * @param {number} data.limit
+ */
+export function getRecordList(data) {
+	return request({
+		url: '/api/chat/recordList',
+		method: 'get',
+		data
+	});
+}
+
+
+/**
+ * 建立连接扣次数
+ * @param {Object} data
+ * @param {number} data.to_user_id 
+ */
+export function initSession(data) {
+	return request({
+		url: '/api/chat/initSession',
+		method: 'post',
+		data
+	});
+}
+

+ 29 - 0
api/signing.js

@@ -9,6 +9,25 @@ export function createSigning(data) {
 	});
 }
 
+//修改合同
+export function changeSigning(data) {
+	return request({
+		url: '/api/user/modifyContract',
+		method: 'post',
+		data
+	});
+}
+
+// 审核修改
+export function passChange(data) {
+	// /api/user/confirmModifyContract 
+	return request({
+		url: '/api/user/confirmModifyContract',
+		method: 'post',
+		data
+	});
+}
+
 //获取签约列表
 export function getContractList(data) {
 	return request({
@@ -18,6 +37,16 @@ export function getContractList(data) {
 	});
 }
 
+//修改列表
+export function getChangeList(data) {
+	// /api/user/getModifyList
+	return request({
+		url: '/api/user/getModifyList',
+		method: 'get',
+		data
+	});
+}
+
 //甲方签约
 export function Jcheck(data) {
 	return request({

+ 23 - 0
api/user.js

@@ -1,5 +1,14 @@
 import request from '@/utils/request'
 
+///api/user/getOpenId
+export function getOpenId(data) {
+	return request({
+		url: '/api/user/getOpenId',
+		method: 'get',
+		data
+	});
+}
+
 // 订单统计信息
 export function orderData(data) {
 	return request({
@@ -508,4 +517,18 @@ export function buyChatCount(data) {
 		method: 'post',
 		data
 	})
+}
+
+/**
+ * @param {object} data 
+ * @param {string} data.order_id
+ * 查询物流
+ */
+export function express(data) {
+	console.log(data,'data');
+	return request({
+		url: '/api/shop/express',
+		method: 'post',
+		data
+	})
 }

+ 30 - 0
config/tabbar.js

@@ -0,0 +1,30 @@
+export default {
+    color: "#161616",
+    selectedColor: "#F65486",
+    borderStyle: "black",
+    backgroundColor: "#ffffff",
+    list: [{
+				"pagePath": "pages/index/index",
+				"iconPath": "static/tabBar/tab-home.png",
+				"selectedIconPath": "static/tabBar/tab-home-current.png",
+				"text": "首页"
+			},
+			{
+				"pagePath": "pages/index/store",
+				"iconPath": "/static/tabBar/kc.png",
+				"selectedIconPath": "static/tabBar/kcaction.png",
+				"text": "积分商城"
+			},
+			{
+				"pagePath": "pages/znkf/index",
+				"iconPath": "static/tabBar/tab-xxjl.png",
+				"selectedIconPath": "static/tabBar/tab-xxjl-current.png",
+				"text": "智能客服"
+			},
+			{
+				"pagePath": "pages/userhome/user",
+				"iconPath": "static/tabBar/tab-my.png",
+				"selectedIconPath": "static/tabBar/tab-my-current.png",
+				"text": "我的"
+			}]
+}

+ 1 - 1
manifest.json

@@ -1,6 +1,6 @@
 {
     "name" : "母婴界严选",
-    "appid" : "__UNI__DCA211F",
+    "appid" : "__UNI__A91D60B",
     "description" : "",
     "versionName" : "1.0.19",
     "versionCode" : 122,

+ 88 - 48
pages.json

@@ -15,6 +15,12 @@
 				"navigationBarTitleText": "母婴界严选"
 			}
 		},
+		{
+			"path": "pages/index/webview",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
 		{
 			"path": "pages/index/detail",
 			"style": {
@@ -51,6 +57,14 @@
 			"style": {
 				"navigationBarTitleText": "服务人员搜索"
 			}
+		},
+		{
+			"path": "pages/index/store",
+			"style": {
+				"navigationBarTitleText": "积分商城",
+				"navigationBarTextStyle": "white",
+				"navigationBarBackgroundColor": "#ff629f"
+			}
 		}
 		// {
 		// 	"path": "pages/forum/index",
@@ -71,6 +85,29 @@
 			"name": "model_index",
 			"pages": []
 		},
+		{
+			"root": "pages/znkf",
+			"name": "znkf",
+			"pages": [{
+				"path": "index",
+				"style": {
+					"navigationBarBackgroundColor": "#ff629f",
+					"navigationBarTextStyle": "white",
+					"navigationBarTitleText": "智能客服",
+					"mp-weixin": {
+						"usingComponents": {
+							"chat": "plugin://chatbot/chat"
+						}
+					}
+				}
+			}],
+			"plugins" : {
+			    "chatbot" : {
+			        "version" : "1.5.4",
+			        "provider" : "wx8c631f7e9f2465e1"
+			    }
+			}
+		},
 		{
 			"root": "pages/user",
 			"name": "user",
@@ -261,21 +298,19 @@
 					"style": {
 						"navigationBarTitleText": "商品详情"
 					}
-				}
-				,
+				},
 				{
 					"path": "jf/rechange",
 					"style": {
-						"navigationBarTitleText": "次数购买"
-					}
-				}
-				,
-				{
-					"path": "jf/store",
-					"style": {
-						"navigationBarTitleText": "积分商城"
+						"navigationBarTitleText": ""
 					}
 				},
+				// {
+				// 	"path": "jf/store",
+				// 	"style": {
+				// 		"navigationBarTitleText": "积分商城"
+				// 	}
+				// },
 				{
 					"path": "jf/addres",
 					"style": {
@@ -375,6 +410,12 @@
 					"style": {
 						"navigationBarTitleText": ""
 					}
+				},
+				{
+					"path": "kf/list",
+					"style": {
+						"navigationBarTitleText": ""
+					}
 				}
 			]
 		}, {
@@ -472,14 +513,13 @@
 					"style": {
 						"navigationBarTitleText": "数字名片制作"
 					}
+				},
+				{
+					"path": "artDetailTab",
+					"style": {
+						"navigationBarTitleText": ""
+					}
 				}
-				// ,
-				// {
-				// 	"path": "artDetailTab",
-				// 	"style": {
-				// 		"navigationBarTitleText": ""
-				// 	}
-				// }
 			]
 		}, {
 			"root": "pages/eduction",
@@ -506,37 +546,37 @@
 		"navigationBarBackgroundColor": "#FFFFFF",
 		"backgroundColor": "#f8f8f8"
 	},
-	"tabBar": {
-		"color": "#666666",
-		"selectedColor": "#F65486",
-		"borderStyle": "black",
-		"backgroundColor": "#ffffff",
-		"list": [{
-				"pagePath": "pages/index/index",
-				"iconPath": "static/tabBar/tab-home.png",
-				"selectedIconPath": "static/tabBar/tab-home-current.png",
-				"text": "首页"
-			},
-			// {
-			// 	"pagePath": "pages/category/category",
-			// 	"iconPath": "static/tabBar/tab-cate.png",
-			// 	"selectedIconPath": "static/tabBar/tab-cate-current.png",
-			// 	"text": "分类"
-			// },
-			{
-				"pagePath": "pages/index/detail",
-				"iconPath": "static/tabBar/tab-xxjl.png",
-				"selectedIconPath": "static/tabBar/tab-xxjl-current.png",
-				"text": "学习交流群"
-			},
-			{
-				"pagePath": "pages/userhome/user",
-				"iconPath": "static/tabBar/tab-my.png",
-				"selectedIconPath": "static/tabBar/tab-my-current.png",
-				"text": "我的"
-			}
-		]
-	},
+	// "tabBar": {
+	// 	"color": "#666666",
+	// 	"selectedColor": "#F65486",
+	// 	"borderStyle": "black",
+	// 	"backgroundColor": "#ffffff",
+	// 	"list": [{
+	// 			"pagePath": "pages/index/index",
+	// 			"iconPath": "static/tabBar/tab-home.png",
+	// 			"selectedIconPath": "static/tabBar/tab-home-current.png",
+	// 			"text": "首页"
+	// 		},
+	// 		{
+	// 			"pagePath": "pages/index/store",
+	// 			"iconPath": "/static/tabBar/kc.png",
+	// 			"selectedIconPath": "static/tabBar/kcaction.png",
+	// 			"text": "积分商城"
+	// 		},
+	// 		// {
+	// 		// 	"pagePath": "pages/index/znkf",
+	// 		// 	"iconPath": "static/tabBar/tab-xxjl.png",
+	// 		// 	"selectedIconPath": "static/tabBar/tab-xxjl-current.png",
+	// 		// 	"text": "智能客服"
+	// 		// },
+	// 		{
+	// 			"pagePath": "pages/userhome/user",
+	// 			"iconPath": "static/tabBar/tab-my.png",
+	// 			"selectedIconPath": "static/tabBar/tab-my-current.png",
+	// 			"text": "我的"
+	// 		}
+	// 	]
+	// },
 	"condition": { //模式配置,仅开发期间生效
 		"current": 0, //当前激活的模式(list 的索引项)
 		"list": [{

+ 2 - 2
pages/eduction/detail.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="content">
+	<view class="content" v-if="isOpen">
 		<view class="video-wrap">
 			<video :src="could_play?chooseCourse.course_sp:''" id="videoId" class="top-video" :poster="topimg"
 				v-if="chooseCourse.course_sp"></video>
@@ -165,7 +165,7 @@
 		},
 		computed: {
 			// #ifdef MP
-			...mapState(['systeam']),
+			...mapState(['systeam','isOpen']),
 			// #endif
 			videoContext() {
 				return uni.createVideoContext('videoId', this)

+ 15 - 6
pages/index/detail.vue

@@ -1,13 +1,13 @@
 <template>
-	<view class="content ">
+	<view class="content "  v-if="isOpen">
 		<view class="flex-center">
-		<image class="bannerImg" src="../../static/image/qybanner.jpg" mode="widthFix"></image>
+		<image class="bannerImg" src="https://api.myjie.cn/static/img/qybanner.jpg" mode="widthFix"></image>
 		</view>
 		<view class="flex">
-			<image class="qun" src="../../static/image/teimImg.jpg" mode="widthFix"></image>
+			<image class="qun" src="https://api.myjie.cn/static/img/teimImg.jpg" mode="widthFix"></image>
 		</view>
 		<view class="flex-center">
-		<image class="shareImg" show-menu-by-longpress src="../../static/image/qyweichat.jpg" mode="scaleToFill"></image>
+		<image class="shareImg" show-menu-by-longpress src="https://api.myjie.cn/static/img/qyweichat.jpg" mode="scaleToFill"></image>
 		</view>
 		<view class="buttom">
 			长按二维码识别加入群聊
@@ -67,20 +67,29 @@
 	export default {
 		data() {
 			return {
-				
+				is_open: false
 			};
 		},
 		onLoad(opt) {
 			
+			
 		},
 		onShow() {
-			
+			const appBaseInfo = wx.getAccountInfoSync()
+			if(appBaseInfo.miniProgram.envVersion == 'release') {
+				this.is_open = true
+			}else {
+				this.is_open = false
+			}
 		},
 		onReachBottom() {
 
 		},
 		methods: {
 			
+		},
+		computed: {
+			...mapState(['isOpen'])
 		}
 	};
 </script>

+ 75 - 14
pages/index/index.vue

@@ -1,12 +1,12 @@
 <template>
 	<view class="indexBox">
-		<view class="topSearchBox" @click="navTo('./search')">
+		<view class="topSearchBox" @click="navTo('/pages/index/listModel?type=2&timetype=&servicePrice=&work_type_id=&service_area=&is_china=')">
 			<view class="search flex">
 				<text>搜索附近的服务人员</text><uni-icons type="search" size="30rpx" color="#FFFFFF"></uni-icons>
 			</view>
 		</view>
 		<swiper class="top-swiper" autoplay="true" duration="400" interval="5000" @change="swiperChange">
-			<swiper-item :key='ind' v-for="(item,ind) in imagelist" class="carousel-item" @click="openXcx(item.url)">
+			<swiper-item :key='ind' v-for="(item,ind) in imagelist" class="carousel-item" @click="openXcx(item)">
 				<image class="imageitem" :src="item.img" />
 			</swiper-item>
 		</swiper>
@@ -60,11 +60,12 @@
 				</view>
 			</view>
 			<view class="flex">
-				<view class="banner" @click="navTo('/pages/public/video')">
+				<!-- @click="navTo('/pages/public/video')" -->
+				<view class="banner" @click="navTo('/pages/public/artDetailTab?cid=4')">
 					<image v-if="baseURL" :src="baseURL+'/static/img/indexLeft.png'" mode="widthFix"></image>
 				</view>
 				<!-- <view class="banner" @click="navTo('/pages/user/model/phb')"> -->
-				<view class="banner" @click="navTo('/pages/index/search')">
+				<view class="banner" @click="navTo('/pages/index/listModel?type=2&timetype=&servicePrice=&work_type_id=&service_area=&is_china=')">
 					<image v-if="baseURL" :src="baseURL+'/static/img/indexRight.png'" mode="widthFix"></image>
 				</view>
 			</view>
@@ -104,13 +105,18 @@
 			</view>
 			<cmy-mys-list :list='zxList'></cmy-mys-list>
 		</view>
+		<view class="footer" v-if="loading == 'loading'">
+			<uni-icons type="spinner-cycle"></uni-icons>加载中
+		</view>
 		<view class="footer">
-			仅显示50条
+			仅显示1000条
 		</view>
+		<m-tabbar fixed fill current="0" :tabbar="tabbar"></m-tabbar>
 	</view>
 </template>
 
 <script>
+	import TabbarConfig from '@/config/tabbar.js'
 	import {
 		mapState,
 		mapMutations
@@ -130,6 +136,7 @@
 	export default {
 		data() {
 			return {
+				 tabbar: TabbarConfig,
 				// 通知列表
 				textList: [],
 				//轮播图
@@ -148,6 +155,9 @@
 				rmList: [],
 				jxList: [], //精选列表
 				zxList: [],
+				page: 1,
+				limit: 20,
+				loading: 'more'
 			};
 		},
 		computed: {
@@ -177,6 +187,9 @@
 		onShow() {
 			this.loadIndexs();
 			this.getWorkerList()
+			this.getNewWorkerList('re');
+		},
+		onReachBottom() {
 			this.getNewWorkerList();
 		},
 		// #ifdef MP
@@ -213,12 +226,44 @@
 		// #endif
 		methods: {
 			// 打开小程序
-			openXcx(url) {
+			openXcx(item) {
 				// #ifdef MP
-				wx.navigateToMiniProgram({
-					appId: "wx3fa16889ff680ac8",
-					path: url,
-				})
+				let data = JSON.parse(item.data)
+				if(data.length > 0) {
+					console.log(data);
+					if(data[0].wxcode) {
+						wx.navigateToMiniProgram({
+							appId: data[0].wxcode,
+							path: item.url
+						})
+					}else {
+						uni.navigateTo({
+							url:item.url,
+							fail(e) {
+								console.log(e);
+								uni.switchTab({
+									url:item.url
+								})
+							}
+						})
+					}
+					
+				}else {
+					uni.navigateTo({
+						url:item.url,
+						fail(e) {
+							console.log(e);
+							uni.switchTab({
+								url:item.url
+							})
+						}
+					})
+				}
+				
+				// wx.navigateToMiniProgram({
+				// 	appId: "wx3fa16889ff680ac8",
+				// 	path: url,
+				// })
 				// #endif
 			},
 			getWorkerList() {
@@ -247,11 +292,19 @@
 				}
 			},
 			// 最新名片
-			getNewWorkerList() {
+			getNewWorkerList(type) {
+				let that = this;
+				if(type == 're') {
+					that.page = 1
+					that.zxList = []
+					that.loading = 'more'
+				}
+				if(that.loading == 'loading' || that.loading == 'noMore')return;
+				that.loading = 'loading'
 				try {
 					getNewWorkerList({
-						page: 1,
-						pageSize: 50,
+						page: that.page,
+						pageSize: that.limit,
 					}).then(res => {
 						let arr = []
 						res.data.list.forEach(item => {
@@ -265,10 +318,18 @@
 								arr.push(item)
 							}
 						})
-						this.zxList = arr
+						this.zxList = this.zxList.concat(arr)
+						if(res.data.list.length == that.limit && that.page < 50) {
+							that.loading = 'more'
+							that.page++
+						}else {
+							that.loading = 'noMore'
+						}
+						
 					})
 				} catch (e) {
 					//TODO handle the exception
+					that.loading = 'more'
 					console.log(e);
 				}
 

+ 8 - 2
pages/index/listModel.vue

@@ -3,6 +3,7 @@
 		<map name="" :longitude="longitude" :latitude="latitude" class="map-wrap" :markers="markers"></map>
 		<view class="itemTip flex" @click="$refs.popup.open()">
 			<uni-icons type="bars" size="40rpx"></uni-icons>
+			筛选
 		</view>
 		<!-- <scroll-view scroll-x="true" class="topSearch">
 			<view class="itemBox flex">
@@ -18,7 +19,7 @@
 		</scroll-view> -->
 		<scroll-view scroll-y="true" :style="{'height':height}" class="scroll-wrap" @scrolltolower="getKcList">
 			<!-- <cmy-mys-list :list='navList[currentIndex].list'></cmy-mys-list> -->
-			<view class="js" v-for="item in navList[currentIndex].list" @click="clickList(item)">
+			<view class="js" v-for="item in navList[currentIndex].list" @click="lookMore(item)" v-if="item.uid != 96 && item.uid != 4393">
 				<view class="js-left">
 					
 				</view>
@@ -33,7 +34,7 @@
 						</view>
 					</view>
 				</view>
-				<view class="js-more">
+				<view class="js-more"  @click.stop="clickList(item)">
 					查看简历 >
 				</view>
 			</view>
@@ -246,6 +247,10 @@
 
 		},
 		methods: {
+			lookMore(item) {
+				this.latitude = item.latitude
+				this.longitude = item.longitude
+			},
 			clickList(item) {
 				const url = '/pages/user/model/model?uid=' + item.uid + '&mtype=' + item.show_template_id + '&type=2'
 				uni.navigateTo({
@@ -363,6 +368,7 @@
 	}
 	.scroll-wrap{
 		padding: 30rpx;
+		background-color: #fff;
 	}
 	.alertBox{
 		line-height: 1;

+ 169 - 0
pages/index/store.vue

@@ -0,0 +1,169 @@
+<template>
+	<view class="content">
+		<view class="goods-list">
+			<view class="goods-item" v-for="(item, index) in goodsList" :key="index" @click="addCart(item)">
+				<image :src="item.image" mode="aspectFill" class="goods-image"></image>
+				<view class="goods-name clamp">{{item.store_name}}</view>
+				<view class="goods-info">
+					<text class="goods-points">{{item.price}} 积分</text>
+					<image src="/static/icon/cart.png" mode="widthFix" class="add-cart" ></image>
+				</view>
+			</view>
+		</view>
+	<m-tabbar fixed fill current="1" :tabbar="tabbar"></m-tabbar>
+		</view>
+	</template>
+	<script>
+		import TabbarConfig from '@/config/tabbar.js'
+	import { getProductList  } from '@/api/good.js'
+	export default {
+		data() {
+			return {
+				tabbar: TabbarConfig,
+				page: 1,
+				limit: 20,
+				list: [],
+				loaded: false,
+				status: 'more',
+				goodsList: []
+			};
+		},
+		methods: {
+			// 返回
+			getProductList() {
+				let that = this
+				if(that.status == 'noMore' || that.status == 'loading') return;
+				that.status = 'loading'
+				getProductList({
+					page: that.page,
+					pageSize: that.limit,
+				}).then(res => {
+					let list = res.data.list
+					that.goodsList = that.goodsList.concat(list)
+					if(that.limit == list.length) {
+						that.status = 'more'
+					}else {
+						that.status = 'noMore'
+					}
+					that.loaded = true
+				})
+			},
+			// 添加到购物车
+			addCart(item) {
+				uni.navigateTo({
+					url:'/pages/user/jf/detail?id=' + item.id
+				})
+			}
+		},
+		onLoad() {
+			this.getProductList()
+		},
+		onReachBottom() {
+			this.getProductList()
+		}
+	};
+</script>
+
+<style lang="scss">
+	page {
+		height: 100%;
+		background-color: #F5F5F5;
+	}
+
+	.content {
+		min-height: 100%;
+	}
+
+	.header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 0 30rpx;
+		height: 80rpx;
+		background-color: #FF4444;
+		
+		.back {
+			width: 40rpx;
+			height: 40rpx;
+			
+			image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+		
+		.title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #FFFFFF;
+		}
+		
+		.right {
+			width: 40rpx;
+		}
+	}
+
+
+
+	.goods-list {
+		display: flex;
+		flex-wrap: wrap;
+		padding: 0 15rpx;
+		justify-content: space-between;
+		padding-top: 20rpx;
+		.goods-item {
+			width: 350rpx;
+			// margin: 1%;
+			background-color: #FFFFFF;
+			border-radius: 15rpx;
+			overflow: hidden;
+			margin-bottom: 20rpx;
+			.goods-image {
+				width: 350rpx;
+				height: 300rpx;
+			}
+			
+			.goods-name {
+				width: 330rpx;
+				padding: 15rpx ;
+				font-size: 26rpx;
+				color: #333333;
+				line-height: 36rpx;
+				height: 72rpx;
+				// overflow: hidden;
+				// text-overflow: ellipsis;
+				// display: -webkit-box;
+				// -webkit-line-clamp: 2;
+				// -webkit-box-orient: vertical;
+			}
+			
+			.goods-info {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				padding: 0 15rpx 15rpx;
+				
+				.goods-points {
+					font-size: 26rpx;
+					font-weight: bold;
+					color: #FF4444;
+				}
+				
+				.add-cart {
+					width: 40rpx;
+					height: 40rpx;
+					background-color: #FF4444;
+					border-radius: 50%;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					
+					.cart-icon {
+						width: 24rpx;
+						height: 24rpx;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 27 - 0
pages/index/webview.vue

@@ -0,0 +1,27 @@
+<template>
+	<view>
+		<web-view :webview-styles="webviewStyles" :src="wsrc"></web-view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				wsrc: '',
+				webviewStyles: {
+					progress: {
+						color: '#ff629f'
+					}
+				}
+			}
+		},
+		onLoad(opt) {
+			this.wsrc = opt.targetUrl
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 32 - 2
pages/modelData/modeltemplate/model_1.vue

@@ -61,7 +61,7 @@
 							<view class="info-item-b">
 								服务次数: {{cardInfo.service_count || '0'}}
 							</view>
-							<view class="info-item-q flex" style="align-items: flex-start;" v-if="honorList.length > 0">
+							<!-- <view class="info-item-q flex" style="align-items: flex-start;" v-if="honorList.length > 0">
 								<text style="flex-shrink: 0;">荣誉信息:</text>
 								<view class="fwdz flex" >
 									<view v-for="(fwitem,fwindex) in honorList" :key="fwindex">
@@ -69,7 +69,7 @@
 									</view>
 								</view>
 								
-							</view>
+							</view> -->
 							<view class="info-item-q flex" style="align-items: flex-start;">
 								<text style="flex-shrink: 0;">服务地区:</text>
 								<view class="fwdz flex" v-if="cardInfo.is_china == 1">
@@ -93,6 +93,21 @@
 					<view class="" style="height: 80rpx;"></view>
 				</view>
 			</view>
+			<!-- 我的荣誉 -->
+			<view class="m-card" v-if="honorList.length > 0">
+				<image v-if="baseURL" :src="baseURL + '/resource/model/model1/card-bg.png'"  class="card-bg"></image>
+				<view class="card-tit flex">
+					<image v-if="baseURL" :src="baseURL + '/resource/model/model1/m5.png'"  class="tit-logo"></image>荣誉信息
+				</view>
+				<view class="flex" style="flex-wrap: wrap;justify-content: center; padding-bottom: 20rpx;">
+					<view class="honor " v-for="item in honorList">
+						<image :src="item.icon" mode="heightFix" class="honor-icon"></image>
+						<view class="honor-name">
+							{{item.name}}
+						</view>
+					</view>
+				</view>
+			</view>
 			<!-- 自我评价 -->
 			<view class="hua4">
 				<view class="hua3">
@@ -659,4 +674,19 @@
 		color: #F46C85;
 		
 	}
+	
+	.honor {
+		width: 33.3%;
+		&-icon {
+			// width: 5;
+			display: block;
+			height: 200rpx;
+			margin: 20rpx auto;
+		}
+		&-name {
+			text-align: center;
+			font-size: 30rpx;
+			color: #000;
+		}
+	}
 </style>

+ 33 - 10
pages/modelData/modeltemplate/model_2.vue

@@ -45,7 +45,7 @@
 								从业:{{(cardInfo.work_year + '年')|| '暂无'}}
 							</view>
 							<view class="info-item-b">
-								星座:{{cardInfo.constellation.replace('座','') || '暂无'}}
+								星座:{{cardInfo.constellation || '暂无'}}
 							</view>
 							<!-- <view class="info-item-b">
 								职业: {{cardInfo.user_work_type_title || '暂无'}}
@@ -82,14 +82,6 @@
 									</view>
 								</view>
 							</view>
-							<view class="info-item-q flex" style="align-items: flex-start;" v-if="honorList.length > 0">
-								<text style="flex-shrink: 0;">荣誉信息:</text>
-								<view class="fwdz flex" >
-									<view :key='fwindex' v-for="(fwitem,fwindex) in honorList">
-										{{fwitem.name}}{{fwindex ==(honorList.length -1) ?'': '、'  }}
-									</view>
-								</view>
-							</view>
 							<view class="info-item-q flex" style="align-items: flex-start;height: 110rpx;">
 								<text style="flex-shrink: 0;">服务价格: </text>
 								<view class="gzt">
@@ -111,7 +103,24 @@
 				</view>
 			</view>	
 			</view>
-			
+			<view class="hua4">
+				<view >
+					<view class="m-card">
+						<view class="card-tit flex">
+							<image class="image" v-if="baseURL" :src="baseURL + '/resource/icon/model2/ryxx.png'"  ></image>
+						</view>
+						<view class="flex" style="flex-wrap: wrap;justify-content: center;">
+							<view class="honor " v-for="item in honorList">
+								<image :src="item.icon" mode="heightFix" class="honor-icon"></image>
+								<view class="honor-name">
+									{{item.name}}
+								</view>
+							</view>
+						</view>
+						
+					</view>
+				</view>
+			</view>
 			<!-- 自我评价 -->
 			<view class="hua4">
 				<view >
@@ -729,4 +738,18 @@
 		color: #202e4f;
 		
 	}
+	.honor {
+		width: 33.3%;
+		&-icon {
+			// width: 5;
+			display: block;
+			height: 200rpx;
+			margin: 20rpx auto;
+		}
+		&-name {
+			text-align: center;
+			font-size: 30rpx;
+			color: #000;
+		}
+	}
 </style>

+ 43 - 2
pages/modelData/modeltemplate/model_3.vue

@@ -95,7 +95,7 @@
 					</view>
 				</view>
 			</view>
-			<view class="list-item padding-l-30 margin-b-30 flex-start" v-if="honorList.length > 0">
+			<!-- <view class="list-item padding-l-30 margin-b-30 flex-start" v-if="honorList.length > 0">
 				<view class="fwdqTop">
 					荣誉信息:
 				</view>
@@ -106,7 +106,7 @@
 						</view>
 					</view>
 				</view>
-			</view>
+			</view> -->
 			<view class="info-item-q flex-start ">
 				<text class="flex-shrink-false">服务价格: </text>
 				<view class="gzt">
@@ -126,6 +126,33 @@
 					v-if="cardInfo.is_type_audit == 1&&baseURL"></image>
 			</view>
 		</view>
+		<view class="content-text">
+			<view class="flex margin-b-20">
+				<view class="name">
+					荣誉信息
+				</view>
+				<image v-if="baseURL" class="icon" :src="baseURL + '/resource/model/model3/tap13.png'" mode="widthFix"></image>
+			</view>
+			<view class="flex" style="justify-content: center;flex-wrap: wrap;">
+				<view class="honor" v-for="(fwitem,fwindex) in honorList">
+					<image :src="fwitem.icon" mode="heightFix" class="honor-icon"></image>
+					<view class="honor-name">
+						{{fwitem.name}}
+					</view>
+				</view>
+			</view>
+			
+			<!-- <view class="flex">
+				<view></view>
+				<image v-if="baseURL" class="line" :src="baseURL + '/resource/model/model3/tap11.png'" mode="widthFix"></image>
+			</view>
+			<view class="text margin-t-20">
+				<rich-text :nodes="cardInfo.service_intro_content"></rich-text>
+			</view>
+			<view class="img-list flex">
+				<image class="image"  @click="$emit('openImage',siiitem)" :src="siiitem" mode="scaleToFill" :key='ind' v-for="(siiitem,ind) in cardInfo.service_intro_imgs"></image>
+			</view> -->
+		</view>
 		<view class="content-text">
 			<view class="flex margin-b-20">
 				<view class="name">
@@ -702,4 +729,18 @@
 	.fwdqTop {
 		align-self: flex-start;
 	}
+	.honor {
+		width: 33.3%;
+		&-icon {
+			// width: 5;
+			display: block;
+			height: 200rpx;
+			margin: 20rpx auto;
+		}
+		&-name {
+			text-align: center;
+			font-size: 30rpx;
+			color: #2682c7;
+		}
+	}
 </style>

+ 34 - 19
pages/modelData/modeltemplate/model_5.vue

@@ -65,18 +65,7 @@
 				</view>
 				
 				<view class="position-relative">
-					<view class="typeTitleImg flex-center" v-if="honorList.length > 0">
-						<image :src="`${baseURL}/resource/model/model5/honor.png`" mode="scaleToFill" class="typeImage">
-						</image>
-					</view>
-					<view class="" style="padding: 30rpx 0;">
-						<view class="honor flex" v-for="item in honorList">
-							<image :src="item.icon" mode="" class="honor-icon"></image>
-							<view class="honor-name">
-								{{item.name}}
-							</view>
-						</view>
-					</view>
+					
 					
 					<view class="typeTitleImg flex-center">
 						<image :src="`${baseURL}/resource/user/user5/text1.png`" mode="scaleToFill" class="typeImage">
@@ -105,6 +94,18 @@
 						</text>
 					</view>
 					<image :src="`${baseURL}/resource/user/user5/img2.png`" mode="scaleToFill" class="typeLeftLogo"></image>
+					<view class="typeTitleImg flex-center" v-if="honorList.length > 0">
+						<image :src="`${baseURL}/resource/model/model5/honor.png`" mode="scaleToFill" class="typeImage">
+						</image>
+					</view>
+					<view class="flex" style="padding: 30rpx 0;flex-wrap: wrap;justify-content: center;">
+						<view class="honor " v-for="item in honorList">
+							<image :src="item.icon" mode="heightFix" class="honor-icon"></image>
+							<view class="honor-name">
+								{{item.name}}
+							</view>
+						</view>
+					</view>
 				</view>
 			</view>
 			<view class="footerBox">
@@ -393,18 +394,32 @@
 			height: 1000rpx;
 		}
 	}
+	// .honor {
+	// 	justify-content: center;
+	// 	margin-bottom: 20rpx;
+	// 	&-icon {
+	// 		width: 40rpx;
+	// 		height: 40rpx;
+	// 		margin-right: 15rpx;
+	// 	}
+	// 	&-name {
+	// 		color: #0DF6F3;
+	// 		font-size: 30rpx;
+			
+	// 	}
+	// }
 	.honor {
-		justify-content: center;
-		margin-bottom: 20rpx;
+		width: 33.3%;
 		&-icon {
-			width: 40rpx;
-			height: 40rpx;
-			margin-right: 15rpx;
+			// width: 5;
+			display: block;
+			height: 200rpx;
+			margin: 20rpx auto;
 		}
 		&-name {
-			color: #0DF6F3;
+			text-align: center;
 			font-size: 30rpx;
-			
+			color: #CBA892;
 		}
 	}
 </style>

+ 40 - 33
pages/public/artDetail.vue

@@ -2,10 +2,11 @@
 	<view class="center">
 <!-- 		<view class="title clamp">{{ item.title }}</view>
 		<view class="time">{{ item.add_time }}</view> -->
-		<view class="main" v-for="(ls, index) in item.content" :key="index">
+		<!-- <view class="main" v-for="(ls, index) in item.content" :key="index">
 			<mp-html v-if="ls.type == 'rich-text'" :content="ls.value"></mp-html>
 			<video v-if="ls.type == 'video' && ls.value" :src="ls.value" style="width:100%;height: 300px" frameborder="0"></video>
-		</view>
+		</view> -->
+		<mp-html  :content="item.content"></mp-html>
 	</view>
 </template>
 
@@ -53,7 +54,8 @@ export default {
 		loadData() {
 			getArtDetail({id:this.id}).then(({ data }) => {
 				let content = data.list[0]
-				content.content = content.content.replace(/<img/g, '<img class="rich-img"').replace(/<p>\s*<img/g, '<p class="pHeight"><img').replace(/<div/g, '<div style="max-width: 50% !important;"');
+				content.content = content.content.replace(/<img/g, '<img class="rich-img"').replace(/<p>\s*<img/g, '<p class="pHeight"><img');
+				// .replace(/<div/g, '<div style="max-width: 50% !important;"')
 				content.content = this.getVideo(content.content);
 				this.item = content;
 				uni.setNavigationBarTitle({
@@ -63,36 +65,41 @@ export default {
 		},
 		// 富文本视频解析
 		getVideo(data) {
-			let videoList = [];
-			let videoReg = /<video.*?(?:>|\/>)/gi; //匹配到字符串中的 video 标签
-			let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; //匹配到字符串中的 video 标签 的路径
-			let arr = data.match(videoReg) || []; // arr 为包含所有video标签的数组
-			let articleList = data.split('</video>'); // 把字符串  从视频标签分成数组
-			arr.forEach((item, index) => {
-				var src = item.match(srcReg);
-				videoList.push(src[1]); //所要显示的字符串中 所有的video 标签 的路径
-			});
-			let needArticleList = [];
-			articleList.forEach((item, index) => {
-				if (item != '' && item != undefined) {
-					//  常见的标签渲染
-					if((index+1)%2==0){
-						item =  item + '</video>';
-					}
-					needArticleList.push({
-						type: 'rich-text',
-						value:item
-					});
-				}
-				let articleListLength = articleList.length; // 插入到原有video 标签位置
-				if (index < articleListLength && videoList[index] != undefined) {
-					needArticleList.push({
-						type: 'video',
-						value: videoList[index]
-					});
-				}
-			});
-			return needArticleList;
+			// let videoList = [];
+			// let videoReg = /<video.*?(?:>|\/>)/gi; //匹配到字符串中的 video 标签
+			// let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; //匹配到字符串中的 video 标签 的路径
+			// let arr = data.match(videoReg) || []; // arr 为包含所有video标签的数组
+			// let articleList = data.split('</video>'); // 把字符串  从视频标签分成数组
+			// arr.forEach((item, index) => {
+			// 	var src = item.match(srcReg);
+			// 	videoList.push(src[1]); //所要显示的字符串中 所有的video 标签 的路径
+			// });
+			// let needArticleList = [];
+			// articleList.forEach((item, index) => {
+			// 	if (item != '' && item != undefined) {
+			// 		//  常见的标签渲染
+			// 		if((index+1)%2==0){
+			// 			item =  item + '</video>';
+			// 		}
+			// 		needArticleList.push({
+			// 			type: 'rich-text',
+			// 			value:item
+			// 		});
+			// 	}
+			// 	let articleListLength = articleList.length; // 插入到原有video 标签位置
+			// 	if (index < articleListLength && videoList[index] != undefined) {
+			// 		needArticleList.push({
+			// 			type: 'video',
+			// 			value: videoList[index]
+			// 		});
+			// 	}
+			// });
+			// return needArticleList;
+			if (!data) return data;
+			const regex = /<video([^>]*)>\s*<source\s+src="([^"]+)"[^>]*\/>\s*<\/video>/gi;
+			data = data.replace(regex, '<video$1 src="$2"></video>').replace(/<video/g, '<video autoplay loop style="width: 100%"');
+			console.log(data);
+			return data
 		}
 	}
 };

+ 121 - 118
pages/public/artDetailTab.vue

@@ -1,138 +1,141 @@
 <template>
 	<view class="center">
-<!-- 		<view class="title clamp">{{ item.title }}</view>
-		<view class="time">{{ item.add_time }}</view> -->
-		<view class="main" v-for="(ls, index) in item.content" :key="index">
-			<view v-if="ls.type == 'rich-text'" v-html="ls.value" class="main"></view>
-			<video v-if="ls.type == 'video' && ls.value" :src="ls.value" style="width:100%;height: 300px" frameborder="0"></video>
+		<view class="art" v-for="item in list" @click="navto('/pages/public/artDetail?id=' + item.id)">
+			<image :src="item.cover" class="art-img" mode="aspectFill"></image>
+			<view class="art-info">
+				<view class="art-info-title clamp">
+					{{item.title}}
+				</view>
+				<view class="art-info-synopsis">
+					{{item.synopsis || ''}}
+				</view>
+			</view>
 		</view>
 	</view>
 </template>
 
 <script>
-import { getArtDetail } from '@/api/index.js'
-export default {
-	data() {
-		return {
-			id: '',
-			item: {
-				content:[]
-			}
-		};
-	},
-	onLoad(option) {
-		this.id = option.id;
-		this.loadData();
-	},
-	onShareAppMessage(options) {
-		// 设置菜单中的转发按钮触发转发事件时的转发内容
-		let pages = getCurrentPages(); //获取加载的页面
-		let currentPage = pages[pages.length - 1]; //获取当前页面的对象
-		let url = currentPage.route; //当前页面url
-		let item = currentPage.options; //如果要获取url中所带的参数可以查看options
-		let shareObj = {
-			title: '母婴界数字名片', // 默认是小程序的名称(可以写slogan等)
-			path: url + '?id=' + item.id, // 默认是当前页面,必须是以‘/’开头的完整路径
-			imageUrl: '',
-			success: function(res) {
-				// 转发成功之后的回调
-				if (res.errMsg == 'shareAppMessage:ok') {}
-			},
-			fail: function() {
-				// 转发失败之后的回调
-				if (res.errMsg == 'shareAppMessage:fail cancel') {
-					// 用户取消转发
-				} else if (res.errMsg == 'shareAppMessage:fail') {
-					// 转发失败,其中 detail message 为详细失败信息
-				}
-			}
-		};
-		return shareObj;
-	},
-	methods: {
-		loadData() {
-			getArtDetail({id:this.id}).then(({ data }) => {
-				let content = data.list[0]
-				content.content = content.content.replace(/<img/g, '<img class="rich-img"').replace(/<p>\s*<img/g, '<p class="pHeight"><img').replace(/<div/g, '<div style="max-width: 50% !important;"');
-				content.content = this.getVideo(content.content);
-				this.item = content;
-				uni.setNavigationBarTitle({
-					title: this.item.title
-				})
-			});
+	import {
+		getArtList
+	} from '@/api/index.js'
+	export default {
+		data() {
+			return {
+				cid: '',
+				list: '',
+				page: 1,
+				limit: 100
+			};
+		},
+		onLoad(option) {
+			this.cid = option.cid;
+			this.loadData();
 		},
-		// 富文本视频解析
-		getVideo(data) {
-			let videoList = [];
-			let videoReg = /<video.*?(?:>|\/>)/gi; //匹配到字符串中的 video 标签
-			let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; //匹配到字符串中的 video 标签 的路径
-			let arr = data.match(videoReg) || []; // arr 为包含所有video标签的数组
-			let articleList = data.split('</video>'); // 把字符串  从视频标签分成数组
-			arr.forEach((item, index) => {
-				var src = item.match(srcReg);
-				videoList.push(src[1]); //所要显示的字符串中 所有的video 标签 的路径
-			});
-			let needArticleList = [];
-			articleList.forEach((item, index) => {
-				if (item != '' && item != undefined) {
-					//  常见的标签渲染
-					if((index+1)%2==0){
-						item =  item + '</video>';
+		onShareAppMessage(options) {
+			// 设置菜单中的转发按钮触发转发事件时的转发内容
+			let that = this
+			let shareObj = {
+				title: '母婴界数字名片', // 默认是小程序的名称(可以写slogan等)
+				path: url + '?cid=' + that.cid, // 默认是当前页面,必须是以‘/’开头的完整路径
+				imageUrl: '',
+				success: function(res) {
+					// 转发成功之后的回调
+					if (res.errMsg == 'shareAppMessage:ok') {}
+				},
+				fail: function() {
+					// 转发失败之后的回调
+					if (res.errMsg == 'shareAppMessage:fail cancel') {
+						// 用户取消转发
+					} else if (res.errMsg == 'shareAppMessage:fail') {
+						// 转发失败,其中 detail message 为详细失败信息
 					}
-					needArticleList.push({
-						type: 'rich-text',
-						value:item
-					});
 				}
-				let articleListLength = articleList.length; // 插入到原有video 标签位置
-				if (index < articleListLength && videoList[index] != undefined) {
-					needArticleList.push({
-						type: 'video',
-						value: videoList[index]
-					});
-				}
-			});
-			return needArticleList;
+			};
+			return shareObj;
+		},
+		methods: {
+			navto(url) {
+				uni.navigateTo({
+					url,
+					fail() {
+						uni.switchTab({
+							url
+						})
+					}
+				})
+			},
+			loadData() {
+				getArtList(this.cid).then(res => {
+					this.list = res.data.list
+					if(this.list.length == 1) {
+						uni.redirectTo({
+							url:'/pages/public/artDetail?id=' + this.list[0].id
+						})
+					}
+				});
+			},
 		}
-	}
-};
+	};
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 	page {
-		background-color: #fff;
+		background-color: #f5f5f5;
 		min-height: 100%;
 		height: auto;
 	}
-.center {
-	min-height: 100%;
-	height: auto;
-	background: #ffffff;
-	padding: 30rpx 24rpx 0;
-}
-.title {
-	font-size: 32rpx;
-	font-family: PingFang SC;
-	font-weight: bold;
-	color: #333333;
-}
-.time {
-	font-size: 24rpx;
-	font-family: PingFangSC;
-	font-weight: 500;
-	color: #999999;
-	margin-top: 40rpx;
-}
-.main {
-	margin-top: 60rpx;
-}
-/deep/ .main {
-	.rich-img {
-		width: 100% !important;
+
+	.center {
+		min-height: 100%;
 		height: auto;
+		background: #f5f5f5;
+		padding: 30rpx 24rpx 30rpx;
+	}
+
+	.art {
+		display: flex;
+		background-color: #ffffff;
+		border-radius: 20rpx;
+		overflow: hidden;
+		margin-bottom: 24rpx;
+		box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
+	}
+
+	.art-img {
+		width: 240rpx;
+		height: 240rpx;
+		flex-shrink: 0;
+	}
+
+	.art-info {
+		flex: 1;
+		padding: 20rpx 24rpx;
+		display: flex;
+		flex-direction: column;
+	}
+
+	.art-info-title {
+		font-size: 30rpx;
+		font-weight: bold;
+		color: #333333;
+		line-height: 40rpx;
+		width: 400rpx;
+		
+		margin-bottom: 12rpx;
 	}
-	* {
-		max-width: 100% !important;
+
+	.art-info-synopsis {
+		font-size: 26rpx;
+		color: #999999;
+		line-height: 36rpx;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		overflow: hidden;
+		flex: 1;
+	}
+
+	/deep/ .rich-img {
+		width: 750rpx;
 	}
-}
-</style>
+</style>

+ 5 - 0
pages/public/login.vue

@@ -178,6 +178,11 @@
 								fail(e) {
 									uni.switchTab({
 										url: '/pages/index/index',
+										fail() {
+											uni.navigateTo({
+												url:'/pages/index/index'
+											})
+										}
 									});
 								}
 							})

+ 6 - 1
pages/public/loginMethods.vue

@@ -129,7 +129,12 @@
 												obj.setUserInfo(e.data);
 												//成功跳转首页
 												uni.switchTab({
-													url: '/pages/index/index'
+													url: '/pages/index/index',
+													fail() {
+														uni.navigateTo({
+															url:'/pages/index/index'
+														})
+													}
 												});
 											});
 			

+ 6 - 1
pages/public/phoneLogin.vue

@@ -154,7 +154,12 @@
 						obj.setUserInfo(e.data);
 						//成功跳转首页
 						uni.switchTab({
-							url: '/pages/index/index'
+							url: '/pages/index/index',
+							fail() {
+								uni.navigateTo({
+									url:'/pages/index/index'
+								})
+							}
 						});
 					});
 				}).catch((e) => {

+ 17 - 7
pages/public/wxLogin.vue

@@ -129,7 +129,12 @@
 			outUser() {
 				this.logout();
 				uni.switchTab({
-					url: '/pages/index/index'
+					url: '/pages/index/index',
+					fail() {
+						uni.navigateTo({
+							url:'/pages/index/index'
+						})
+					}
 				})
 			},
 			getLoginCode() {
@@ -214,20 +219,25 @@
 			ToIndex() {
 				let ur = uni.getStorageSync('present') || '/pages/index/index';
 				// 用于处理缓存bug
-				if (ur == 'pages/product/product') {
+				if (ur == '/pages/public/wxLogin') {
 					ur = '/pages/index/index';
 				}
 				uni.switchTab({
 					url: ur,
 					fail(e) {
-						uni.navigateTo({
-							url: ur,
-							fail(e) {
+						uni.redirectTo({
+							url:ur,
+							fail() {
 								uni.navigateTo({
-									url: '/pages/index/index'
+									url: ur,
+									fail(e) {
+										uni.navigateTo({
+											url: '/pages/index/index'
+										});
+									}
 								});
 							}
-						});
+						})
 					}
 				});
 				// uni.switchTab({

+ 165 - 142
pages/set/kf/index.vue

@@ -2,10 +2,10 @@
 	<view class="chat-container">
 		<view class="header">
 			<text class="title">{{name || '在线客服'}}</text>
-			<view class="status">
+			<!-- <view class="status">
 				<text class="status-dot" :class="{ 'online': isConnected }"></text>
-				<text class="status-text">{{ isConnected ? '已连接' : '连接中...' }}</text>
-			</view>
+				<text class="status-text">{{ isConnected ? '已连接' : '连接中...' }}</text> 
+			</view> -->
 		</view>
 		
 		<scroll-view 
@@ -15,33 +15,36 @@
 			:scroll-with-animation="true"
 		>
 			<view class="message-item" v-for="(msg, index) in messages" :key="index" :id="'msg-' + index">
-				<view v-if="msg.type === 'text'" class="message-bubble" :class="msg.from === 'me' ? 'right' : 'left'">
+				<view v-if="msg.type === 6" class="system-message">
+					<text>{{ showTime(msg.create_time)}}</text>
+				</view>
+				<view v-if="msg.type === 1" class="message-bubble" :class="msg.is_mine ? 'right' : 'left'">
 					<view class="avatar">
-						<image v-if="msg.from === 'me' && userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
-						<view v-else :class="msg.from === 'me' ? 'my-avatar' : 'service-avatar'">
-							<text>{{ msg.from === 'me' ? '我' : '客' }}</text>
-						</view>
+						<image v-if="msg.is_mine && userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
+						<image v-if="!msg.is_mine && avatar" :src="avatar" mode="scaleToFill"></image>
+						<!-- <view v-else :class="msg.is_mine ? 'my-avatar' : 'service-avatar'">
+							<text>{{ msg.is_mine ? '我' : '客' }}</text>
+						</view> -->
 					</view>
 					<view class="bubble-content">
 						<text>{{ msg.content }}</text>
 					</view>
 				</view>
 				
-				<view v-else-if="msg.type === 'image'" class="message-bubble" :class="msg.from === 'me' ? 'right' : 'left'">
+				<view v-else-if="msg.type === 3" class="message-bubble" :class="msg.is_mine ? 'right' : 'left'">
 					<view class="avatar">
-						<image v-if="msg.from === 'me' && userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
-						<view v-else :class="msg.from === 'me' ? 'my-avatar' : 'service-avatar'">
-							<text>{{ msg.from === 'me' ? '我' : '客' }}</text>
-						</view>
+						<image v-if="msg.is_mine && userInfo.avatar" :src="userInfo.avatar" mode="scaleToFill"></image>
+						<image v-if="!msg.is_mine && avatar" :src="avatar" mode=""></image>
+						<!-- <view v-else :class="msg.is_mine ? 'my-avatar' : 'service-avatar'">
+							<text>{{ msg.is_mine ? '我' : '客' }}</text>
+						</view> -->
 					</view>
 					<view class="bubble-image" @click="previewImage(msg.content)">
 						<image :src="msg.content" mode="widthFix" @tap="previewImage(msg.content)"></image>
 					</view>
 				</view>
 				
-				<view v-else-if="msg.type === 'system'" class="system-message">
-					<text>{{ msg.content }}</text>
-				</view>
+				
 			</view>
 		</scroll-view>
 		
@@ -54,6 +57,7 @@
 					placeholder="请输入消息..." 
 					placeholder-class="placeholder"
 					@confirm="sendText"
+					maxlength="1000"
 				/>
 			</view>
 			<view class="action-buttons">
@@ -75,10 +79,12 @@
 	import {
 		upload
 	} from '@/api/set.js';
+	import { send, getRecordList } from '@/api/kf.js'
 	
 	export default {
 		data() {
 			return {
+				to_uid: '',
 				name: '',
 				socketTask: null,
 				isConnected: false,
@@ -87,79 +93,89 @@
 				messages: [],
 				inputText: '',
 				scrollToView: '',
-				wsUrl: 'ws://api.myje.cn:2345'
+				wsUrl: 'wss://api.myje.cn',
+				page: 1,
+				limit: 1000,
+				pollingTimer: null,
+				pollingInterval: 3000,
+				lastMessageId: 0,
+				avatar: ''
 			}
 		},
 		onLoad(opt) {
-			this.addSystemMessage('正在连接服务器...');
-			this.name = opt.name
-			this.connectWebSocket(opt.to_uid);
+			this.name = decodeURI(opt.name)
+			this.to_uid = opt.to_uid
+			this.avatar = uni.getStorageSync('avt')
+			console.log(this.avatar);
+			
+			this.getRecordList()
+			this.startPolling()
+			// this.connectWebSocket();
 		},
 		onUnload() {
-			this.closeWebSocket();
+			// this.closeWebSocket();
+			this.stopPolling();
+		},
+		onHide() {
+			this.stopPolling();
 		},
 		computed: {
 			...mapState('user', ['userInfo'])
 		},
 		methods: {
-			connectWebSocket(to_uid) {
-				const token = uni.getStorageSync('token') || '';
-				const wsUrl =`${this.wsUrl}?token=${token}` + '&type=user&from=3&to_uid=' + to_uid;
+			showTime(time) {
+				const date = new Date(time * 1000);
+				const today = new Date();
+				const isToday = date.toDateString() === today.toDateString();
 				
-				this.socketTask = uni.connectSocket({
-					url: wsUrl,
-					success: () => {
-						console.log('WebSocket连接请求成功');
-					},
-					fail: (err) => {
-						console.log('WebSocket连接失败', err);
-						this.handleReconnect();
-					}
-				});
+				const month = String(date.getMonth() + 1).padStart(2, '0');
+				const day = String(date.getDate()).padStart(2, '0');
+				const hours = String(date.getHours()).padStart(2, '0');
+				const minutes = String(date.getMinutes()).padStart(2, '0');
 				
-				this.socketTask.onOpen(() => {
-					console.log('WebSocket连接成功');
-					this.isConnected = true;
-					this.reconnectCount = 0;
-					this.addSystemMessage('已连接到服务器');
-				});
-				
-				this.socketTask.onMessage((res) => {
-					this.handleMessage(res.data);
-				});
-				
-				this.socketTask.onClose(() => {
-					console.log('WebSocket连接关闭');
-					this.isConnected = false;
-					this.handleReconnect();
-				});
-				
-				this.socketTask.onError((err) => {
-					console.log('WebSocket错误', err);
-					this.isConnected = false;
-					this.addSystemMessage('连接发生错误');
-				});
-			},
-			
-			handleReconnect() {
-				if (this.reconnectCount < this.maxReconnect) {
-					this.reconnectCount++;
-					this.addSystemMessage(`正在重连... (${this.reconnectCount}/${this.maxReconnect})`);
-					setTimeout(() => {
-						this.connectWebSocket();
-					}, 2000);
+				if (isToday) {
+					return `${hours}:${minutes}`;
 				} else {
-					this.addSystemMessage('连接失败,请稍后重试');
+					return `${month}-${day} ${hours}:${minutes}`;
 				}
 			},
-			
-			closeWebSocket() {
-				if (this.socketTask) {
-					this.socketTask.close();
-					this.socketTask = null;
-				}
+			getRecordList() {
+				let that = this
+				getRecordList({
+					to_user_id: that.to_uid,
+					page: that.page,
+					limit: that.limit
+				}).then(res => {
+					const originalList = res.data.list;
+					
+					if (originalList.length > 0) {
+						that.lastMessageId = originalList[originalList.length - 1].create_time;
+						const processedList = [{type: 6, create_time: originalList[0].create_time}];
+						for (let i = 0; i < originalList.length; i++) {
+							processedList.push(originalList[i]);
+							
+							if (i < originalList.length - 1) {
+								const currentTime = originalList[i].create_time;
+								const nextTime = originalList[i + 1].create_time;
+								const diff = Math.abs(nextTime - currentTime);
+								
+								if (diff >= 3600) {
+									processedList.push({
+										type: 6,
+										create_time: nextTime
+									});
+								}
+							}
+						}
+						that.messages = processedList;
+					}
+					
+					
+					
+					
+					that.scrollToBottom()
+				})
 			},
-			
 			handleMessage(data) {
 				try {
 					const message = typeof data === 'string' ? JSON.parse(data) : data;
@@ -172,100 +188,107 @@
 					});
 				}
 			},
-			
 			addMessage(msg) {
 				this.messages.push({
-					from: msg.from || 'service',
-					type: msg.type || 'text',
+					is_mine: msg.is_mine || true,
+					type: msg.type || 1,
 					content: msg.content,
-					time: new Date().getTime()
+					create_time: msg.create_time
 				});
+				this.lastMessageId = msg.create_time
+				// console.log(this.messages,'this.messages');
 				this.scrollToBottom();
 			},
-			
-			addSystemMessage(content) {
-				this.messages.push({
-					type: 'system',
-					content: content,
-					time: new Date().getTime()
+			startPolling() {
+				this.stopPolling();
+				this.pollingTimer = setInterval(() => {
+					this.pollNewMessages();
+				}, this.pollingInterval);
+			},
+			stopPolling() {
+				if (this.pollingTimer) {
+					clearInterval(this.pollingTimer);
+					this.pollingTimer = null;
+				}
+			},
+			pollNewMessages() {
+				let that = this;
+				getRecordList({
+					to_user_id: that.to_uid,
+					page: 1,
+					limit: that.limit
+				}).then(res => {
+					const newMessages = res.data.list;
+					console.log(newMessages,'newMessages');
+					if (newMessages.length > 0) {
+						const latestId =  newMessages[newMessages.length - 1].create_time;
+						console.log(latestId,'latestId','that.lastMessageId',that.lastMessageId,newMessages[0]);
+						if (latestId > that.lastMessageId) {
+							for (let i = 0; i < newMessages.length; i++) {
+								const msgId = newMessages[i].create_time;
+								console.log(msgId,that.lastMessageId);
+								if (msgId > that.lastMessageId) {
+									that.messages.push(newMessages[i]);
+								}
+							}
+							that.lastMessageId = latestId;
+							console.log(that.lastMessageId);
+							that.scrollToBottom();
+						}
+					}
+				}).catch(err => {
+					console.log('轮询获取消息失败', err);
 				});
-				this.scrollToBottom();
 			},
-			
 			sendText() {
+				let that = this
 				if (!this.inputText.trim()) {
 					return;
 				}
-				
 				const text = this.inputText.trim();
-				
-				if (!this.isConnected) {
-					uni.showToast({
-						title: '连接未就绪',
-						icon: 'none'
+				send({
+					to_user_id: that.to_uid,
+					content: text,
+					type: 1,
+					form_type: 2
+				}).then(res => {
+					let time = new Date(res.data.create_time).getTime() / 1000
+					this.addMessage({
+						is_mine: true,
+						type: 1,
+						content: text,
+						create_time:time 
 					});
-					return;
-				}
-				
-				const message = {
-					type: 'text',
-					content: text
-				};
+					this.inputText = '';
+				})
 				
-				this.socketTask.send({
-					data: JSON.stringify(message),
-					success: () => {
-						this.addMessage({
-							from: 'me',
-							type: 'text',
-							content: text
-						});
-						this.inputText = '';
-					},
-					fail: () => {
-						uni.showToast({
-							title: '发送失败',
-							icon: 'none'
-						});
-					}
-				});
 			},
 			
 			sendImage() {
-				if (!this.isConnected) {
-					uni.showToast({
-						title: '连接未就绪',
-						icon: 'none'
-					});
-					return;
-				}
-				
+				let that = this
 				upload({
 					filename: ''
 				}).then(data => {
 					const imageUrl = data[0].img;
-					
 					const message = {
 						type: 'image',
 						content: imageUrl
 					};
+					send({
+						to_user_id: that.to_uid,
+						content: imageUrl,
+						type: 3,
+						form_type: 2
+					}).then(res => {
+						let time = new Date(res.data.create_time).getTime() / 1000
+						this.addMessage({
+							is_mine: true,
+							type: 3,
+							content: imageUrl,
+							create_time: time
+						});
+					})
 					
-					this.socketTask.send({
-						data: JSON.stringify(message),
-						success: () => {
-							this.addMessage({
-								from: 'me',
-								type: 'image',
-								content: imageUrl
-							});
-						},
-						fail: () => {
-							uni.showToast({
-								title: '发送失败',
-								icon: 'none'
-							});
-						}
-					});
 				}).catch(err => {
 					console.log('上传图片失败', err);
 				});
@@ -300,7 +323,7 @@
 	
 	.header {
 		display: flex;
-		justify-content: space-between;
+		justify-content: center;
 		align-items: center;
 		padding: 20rpx 30rpx;
 		background-color: #FFFFFF;
@@ -436,7 +459,7 @@
 			text {
 				font-size: $font-sm;
 				color: $font-color-light;
-				background-color: rgba(0, 0, 0, 0.06);
+				// background-color: rgba(0, 0, 0, 0.06);
 				padding: 8rpx 20rpx;
 				border-radius: 20rpx;
 			}

+ 257 - 0
pages/set/kf/list.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="chat-list-container" v-if="isOpen == 1">
+		<view class="flex" style="background-color: #fff;margin-bottom: 20rpx;" v-if="Number(chatConfig.balance) > 0">
+			<view class="remain">
+				<text class="label">我的剩余次数:</text>
+				<text class="count">{{chatConfig.balance}}</text>
+			</view>
+		</view>
+		<view class="chat-list">
+			<view class="chat-item" v-for="(item, index) in chatList" :key="index" @click="goChat(item)">
+				<view class="avatar">
+					<image v-if="item.avatar" :src="item.avatar" mode="aspectFill"></image>
+					<view v-else class="default-avatar">
+						<text>{{ item.nickname.charAt(0) }}</text>
+					</view>
+				</view>
+				<view class="info">
+					<text class="name">{{ item.nickname }}</text>
+					<text class="last-message"
+						v-if="item.last_message.indexOf('https://') == -1">{{ item.last_message }}</text>
+					<text class="last-message" v-else>[图片]</text>
+				</view>
+				<view class="right">
+					<text class="time">{{ showTime(item.last_message_time)}}</text>
+					<view v-if="item.unread_count > 0" class="unread-badge">
+						<text>{{ item.unread_count > 99 ? '99+' : item.unread_count }}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		getSessionList
+	} from '@/api/kf.js'
+	import { getChatConfig } from '@/api/user.js'
+	import { mapState} from 'vuex'
+	export default {
+		data() {
+			return {
+				chatConfig: {
+					balance: 0,
+					price: 0
+				},
+				chatList: [],
+				pollingTimer: null,
+				pollingInterval: 5000
+			}
+		},
+		computed: {
+			...mapState(['isOpen'])
+		},
+		methods: {
+			navto(url) {
+				uni.navigateTo({
+					url
+				})
+			},
+			getChatConfig() {
+				getChatConfig().then(res => {
+					this.chatConfig = res.data
+				})
+			},
+			startPolling() {
+			    this.stopPolling();
+			    this.pollingTimer = setInterval(() => {
+			        this.getSessionList();
+			    }, this.pollingInterval);
+			},
+			stopPolling() {
+			    if (this.pollingTimer) {
+			        clearInterval(this.pollingTimer);
+			        this.pollingTimer = null;
+			    }
+			},
+			goChat(item) {
+				uni.setStorageSync('avt', item.avatar)
+				uni.navigateTo({
+					url: `/pages/set/kf/index?to_uid=${item.user_id}&name=${encodeURIComponent(item.nickname)}`
+				});
+			},
+			getSessionList() {
+				getSessionList().then(res => {
+					this.chatList = res.data.list
+				})
+			},
+			showTime(time='') {
+				if (!time) return '';
+				time = time.replace(/-/g,'/')
+				const date = new Date(time);
+				const today = new Date();
+				const isToday = date.toDateString() === today.toDateString();
+
+				const month = String(date.getMonth() + 1).padStart(2, '0');
+				const day = String(date.getDate()).padStart(2, '0');
+				const hours = String(date.getHours()).padStart(2, '0');
+				const minutes = String(date.getMinutes()).padStart(2, '0');
+
+				if (isToday) {
+					return `${hours}:${minutes}`;
+				} else {
+					return `${month}-${day}`;
+				}
+			}
+		},
+		onShow() {
+		    this.getSessionList();
+		    this.startPolling();
+			this.getChatConfig()
+		},
+		onHide() {
+		    this.stopPolling();
+		},
+		onUnload() {
+		    this.stopPolling();
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F5F5F5;
+	}
+
+	.chat-list-container {
+		// padding: 20rpx;
+	}
+
+	.chat-list {
+		background-color: #FFFFFF;
+		border-radius: 16rpx;
+		overflow: hidden;
+	}
+
+	.chat-item {
+		display: flex;
+		align-items: center;
+		padding: 24rpx;
+		border-bottom: 1px solid #F0F0F0;
+
+		&:last-child {
+			border-bottom: none;
+		}
+
+		&:active {
+			background-color: #F8F8F8;
+		}
+	}
+
+	.avatar {
+		width: 100rpx;
+		height: 100rpx;
+		margin-right: 20rpx;
+		border-radius: 12rpx;
+		overflow: hidden;
+		background-color: #EEEEEE;
+
+		image {
+			width: 100%;
+			height: 100%;
+		}
+
+		.default-avatar {
+			width: 100%;
+			height: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			background: linear-gradient(135deg, #FF6B6B, #FFE66D);
+
+			text {
+				font-size: 36rpx;
+				color: #FFFFFF;
+				font-weight: bold;
+			}
+		}
+	}
+
+	.info {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+
+		.name {
+			font-size: 28rpx;
+			color: #333333;
+			font-weight: bold;
+			margin-bottom: 8rpx;
+		}
+
+		.last-message {
+			font-size: 24rpx;
+			color: #999999;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			white-space: nowrap;
+		}
+
+		.last-message {
+			height: 40;
+		}
+	}
+
+	.right {
+		display: flex;
+		flex-direction: column;
+		align-items: flex-end;
+
+		.time {
+			font-size: 22rpx;
+			color: #CCCCCC;
+			margin-bottom: 8rpx;
+		}
+
+		.unread-badge {
+			min-width: 36rpx;
+			height: 36rpx;
+			background-color: #FF5722;
+			border-radius: 18rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			padding: 0 10rpx;
+
+			text {
+				font-size: 20rpx;
+				color: #FFFFFF;
+				font-weight: bold;
+			}
+		}
+	}
+	
+	.remain {
+		padding: 30rpx;
+		
+		.label {
+			font-size: 28rpx;
+			color: #666666;
+		}
+		.labels {
+			font-size: 28rpx;
+			background-color:  #f55586;
+			color: #fff;
+			padding: 15rpx 20rpx;
+			border-radius:15rpx;
+		}
+		
+		.count {
+			font-size: 28rpx;
+			font-weight: bold;
+			color: #f55586;
+			margin-left: 10rpx;
+		}
+	}
+</style>

+ 6 - 1
pages/set/lng.vue

@@ -60,7 +60,12 @@
 					this.$api.msg('修改成功');
 					setTimeout(() => {
 						uni.switchTab({
-							url: '/pages/userhome/user'
+							url: '/pages/userhome/user',
+							fail() {
+								uni.navigateTo({
+									url:'/pages/userhome/user'
+								})
+							}
 						});
 					}, 1000);
 				})

+ 6 - 1
pages/set/phone.vue

@@ -123,7 +123,12 @@
 						setTimeout(function() {
 							obj.loding = false;
 							uni.switchTab({
-								url: '/pages/userhome/user'
+								url: '/pages/userhome/user',
+								fail() {
+									uni.navigateTo({
+										url:'/pages/userhome/user'
+									})
+								}
 							});
 						}, 1000);
 					})

+ 6 - 1
pages/set/userinfo.vue

@@ -77,7 +77,12 @@
 						this.$api.msg('修改成功');
 						setTimeout(() => {
 							uni.switchTab({
-								url: '/pages/userhome/user'
+								url: '/pages/userhome/user',
+								fail() {
+									uni.navigateTo({
+										url:'/pages/userhome/user'
+									})
+								}
 							});
 						}, 1000);
 					})

+ 3 - 2
pages/user/forum/index.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="content">
-		<view class="post-list" v-if="is_show == 1">
+		<view class="post-list" v-if="isOpen == 1">
 			<view class="post-item" v-for="(post, index) in postList" :key="index">
 				<view class="post-header">
 					<image :src="post.author_avatar" mode="aspectFill" class="avatar"></image>
@@ -34,7 +34,7 @@
 			</view>
 		</view>
 		<empty v-else></empty>
-		<view class="publish-btn" @click="publish" v-if="userInfo.permission == 1 && is_show == 1">
+		<view class="publish-btn" @click="publish" v-if="userInfo.permission == 1 && isOpen == 1">
 			<image src="../../../static/icon/fabu.png" mode="widthFix" class="publish-icon"></image>
 			<text class="publish-text">我要发布</text>
 		</view>
@@ -66,6 +66,7 @@
 		},
 		computed: {
 			...mapState('user', ['userInfo', 'hasLogin']),
+			...mapState(['isOpen']),
 		},
 		// #ifdef MP
 		onShareAppMessage() {

+ 27 - 5
pages/user/jf/bill.vue

@@ -4,16 +4,20 @@
 			<view class="status_bar">
 			</view>
 			<view class="content-bg">
-				<image src="/static/img/tg-bg.png" mode=""></image>
+				<image src="https://api.myjie.cn/static/img/tg-bg.png" mode=""></image>
 			</view>
 			<view class="money-box">
 				<view class="money">{{ userInfo.score|| '0' }}</view>
 				<view>我的积分</view>
 			</view>
 			<view class="money-box flex" style="padding:20rpx;" >
-				<view style="flex-grow: 1;text-align: left;" @click="navto('/pages/user/jf/store')">积分商城</view>
+				<!-- 积分商城 -->
+				<view style="flex-grow: 1;text-align: left;" @click="navto('/pages/index/store')"></view>
 				<view style="flex-grow: 1;text-align: right;" @click="navto('/pages/user/jf/jfcz')">充值积分</view>
 			</view>
+			<!-- <view class="money-box flex" style="padding:20rpx;" >
+				<view style="flex-grow: 1;text-align: left;" @click="navto('/pages/user/jf/rechange')">聊天次数:{{count}}</view>
+			</view> -->
 		</view>
 		<view class="nav flex">
 			<view class="nav-item" v-for="(item,index) in navList" @click="navClick(index)"
@@ -51,7 +55,8 @@
 	import {
 		getChildList,
 		getJfBill,
-		getUserInfo
+		getUserInfo,
+		getChatConfig
 	} from '@/api/user.js'
 	export default {
 		onReady(res) {
@@ -69,6 +74,7 @@
 		},
 		data() {
 			return {
+				count: 0,
 				current: 0,
 				navList: [
 					{
@@ -101,9 +107,15 @@
 		onShow() {
 			this.loadData();
 			this.getUserInfo()
+			// this.getChatConfig()
 		},
 		methods: {
 			...mapMutations('user',['setUserInfo']),
+			getChatConfig() {
+				getChatConfig().then(res => {
+					this.count = res.data.balance
+				})
+			},
 			getUserInfo() {
 				getUserInfo().then(res => {
 					this.setUserInfo(res.data)
@@ -116,7 +128,12 @@
 			// 页面跳转
 			navto(e) {
 				uni.navigateTo({
-					url: e
+					url: e,
+					fail() {
+						uni.switchTab({
+							url: e
+						})
+					}
 				});
 			},
 			//获取收入支出信息
@@ -166,7 +183,12 @@
 			// 点击返回 我的页面
 			toBack() {
 				uni.switchTab({
-					url: '/pages/user/user'
+					url: '/pages/userhome/user',
+					fail() {
+						uni.navigateTo({
+							url:'/pages/userhome/user'
+						})
+					}
 				});
 			}
 		}

+ 14 - 1
pages/user/jf/detail.vue

@@ -195,10 +195,23 @@
 			confirmExchange() {
 				if (!this.selectedAddress) {
 					// 提示用户选择地址
-					console.log('请选择收货地址');
+					// console.log();
+					this.$api.msg('请选择收货地址')
 					return;
 				}
 				let that = this;
+				if(this.userInfo.score < this.totalPoints) {
+					return uni.showModal({
+						title:'您当前积分不足,是否立即充值?',
+						complete(e) {
+							if(e.confirm) {
+								uni.navigateTo({
+									url:'/pages/user/jf/jfcz'
+								})
+							}
+						}
+					})
+				}
 				addToCart({
 					product_id: that.id,
 					cart_num: that.quantity,

+ 83 - 2
pages/user/jf/jfcz.vue

@@ -7,7 +7,7 @@
 	
 		<view class="listBox">
 			<view class="list flex">
-				<view @click="changePoints(index)" :class="{action:index==actionIndex}" class="item flex" 
+				<view @click="changePoints(index)" :class="{action:index==actionIndex && !isCustom}" class="item flex" 
 					v-for="(item,index) in pointsList">
 					<image class="icon" src="/static/icon/jf.png" mode="widthFix"></image>
 					<view class="info">
@@ -16,7 +16,22 @@
 					</view>
 				</view>
 			</view>
-			
+			<view class="custom-item" :class="{action:isCustom}" @click="selectCustom">
+				<view class="custom-input-wrap">
+					<input 
+						type="digit" 
+						class="custom-input" 
+						placeholder="自定义积分" 
+						:value="customPoints"
+						@input="inputCustom"
+						:focus="isCustom"
+					/>
+					<text class="input-unit">积分</text>
+				</view>
+				<view class="custom-info" v-if="customPoints">
+					<text>约 ¥{{customMoney}} 元</text>
+				</view>
+			</view>
 			<view class="amount">
 				<text class="label">应付金额(活动随机立减0.10~1.00元)</text>
 				<text class="value">¥{{payMoney}}元</text>
@@ -59,6 +74,8 @@
 					{ points: 0, price: 200 }
 				],
 				reduction: 0.1, //活动立减金额
+				customPoints: '', //自定义积分
+				isCustom: false //是否选择自定义
 			};
 		},
 		onShow() {
@@ -66,9 +83,15 @@
 		},
 		computed: {
 			payMoney() {
+				if (this.isCustom && this.customPoints) {
+					return (parseFloat(this.customPoints) / this.bl).toFixed(2)
+				}
 				const selected = this.pointsList[this.actionIndex];
 				return selected.price
 			},
+			customMoney() {
+				return this.isCustom && this.customPoints ? (parseFloat(this.customPoints) / this.bl).toFixed(2) : '0.00'
+			},
 			...mapState('user', ['userInfo', 'orderInfo', 'hasLogin']),
 		},
 		methods: {
@@ -95,6 +118,15 @@
 			// 选择积分选项
 			changePoints(ind) {
 				this.actionIndex = ind;
+				this.isCustom = false;
+			},
+			// 选择自定义积分
+			selectCustom() {
+				this.isCustom = true;
+			},
+			// 输入自定义积分
+			inputCustom(e) {
+				this.customPoints = e.detail.value;
 			},
 			// 选择支付方式
 			selectPayment(type) {
@@ -274,6 +306,55 @@
 		}
 	}
 
+	.custom-item {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		height: 120rpx;
+		background-color: #F5F5F5;
+		border-radius: 15rpx;
+		padding: 20rpx;
+		margin-top: 20rpx;
+		border: 2rpx solid transparent;
+		
+		&.action {
+			background-color: #FFF0F0;
+			border: 2rpx solid #f65486;
+		}
+		
+		.custom-input-wrap {
+			display: flex;
+			align-items: center;
+			
+			.custom-input {
+				width: 200rpx;
+				height: 60rpx;
+				font-size: 30rpx;
+				text-align: center;
+				background-color: #FFFFFF;
+				border-radius: 10rpx;
+				padding: 0 20rpx;
+				border: 1rpx solid #DDDDDD;
+			}
+			
+			.input-unit {
+				font-size: 28rpx;
+				color: #666666;
+				margin-left: 10rpx;
+			}
+		}
+		
+		.custom-info {
+			margin-top: 10rpx;
+			
+			text {
+				font-size: 24rpx;
+				color: #f65486;
+			}
+		}
+	}
+
 	.amount {
 		margin-top: 30rpx;
 		padding-top: 30rpx;

+ 202 - 11
pages/user/jf/orderDetail.vue

@@ -124,13 +124,13 @@
 					@click="cancelOrder">
 					<text>取消订单</text>
 				</view>
-				<!-- <view 
+				<view 
 					class="action-btn btn-primary" 
-					v-if="order.status === 1" 
-					@click="payOrder"
+					@click="lookWl"
+					v-if="order.status === 2"
 				>
-					<text>立即支付</text>
-				</view> -->
+					<text>查看物流</text>
+				</view>
 				<view class="action-btn btn-primary" v-if="order.status === 2" @click="confirmReceipt">
 					<text>确认收货</text>
 				</view>
@@ -142,6 +142,38 @@
 				</view> -->
 			</view>
 		</view>
+		<uni-popup ref="wlpopup" type="center">
+			<view class="wl-popup">
+				<view class="wl-header">
+					<text class="wl-title">物流信息</text>
+					<view class="wl-close" @click="closeWl">×</view>
+				</view>
+				<view class="wl-content">
+					<view class="express-info" v-if="logistics.express_type">
+						<text class="express-label">快递公司:</text>
+						<text class="express-value">{{logistics.express_type}}</text>
+					</view>
+					<view class="wl-empty" v-if="logistics.items.length === 0">
+						<text>暂无物流信息</text>
+					</view>
+					<view class="wl-timeline" v-else>
+						<view 
+							class="wl-item" 
+							v-for="(item, index) in logistics.items" 
+							:key="index"
+							:class="{active: index === 0}"
+						>
+							<view class="wl-dot"></view>
+							<view class="wl-line" v-if="index < logistics.items.length - 1"></view>
+							<view class="wl-info">
+								<text class="wl-status">{{item.status}}</text>
+								<text class="wl-time">{{item.time}}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</uni-popup>
 	</view>
 </template>
 
@@ -151,7 +183,8 @@
 	} from 'vuex'
 	import {
 		getOrderDetail,
-		cancelOrder
+		cancelOrder,
+		express
 	} from '@/api/user.js'
 	export default {
 		data() {
@@ -170,7 +203,11 @@
 					address: null,
 					items: []
 				},
-				timeline: []
+				timeline: [],
+				logistics: {
+					express_type: '',
+					items: []
+				}
 			}
 		},
 		computed: {
@@ -186,6 +223,17 @@
 			}
 		},
 		methods: {
+			lookWl(item) {
+				express({
+					order_id: this.orderId
+				}).then(res => {
+					if (res.data) {
+						this.logistics.express_type = res.data.express_type || ''
+						this.logistics.items = res.data.list || []
+					}
+					this.$refs.wlpopup.open()
+				})
+			},
 			cancelOrder() {
 				uni.showModal({
 					title: '提示',
@@ -308,6 +356,9 @@
 			},
 			goBack() {
 				uni.navigateBack()
+			},
+			closeWl() {
+				this.$refs.wlpopup.close()
 			}
 		},
 		onLoad(options) {
@@ -321,13 +372,11 @@
 <style lang="scss">
 	page {
 		background-color: #F5F5F5;
-		min-height: 100vh;
-		padding-bottom: 120rpx;
 	}
 
 	.order-detail-container {
-		min-height: 100vh;
 		background-color: #F5F5F5;
+		padding-top: 20rpx;
 	}
 
 	.status-bar {
@@ -401,7 +450,7 @@
 
 	.order-card {
 		background-color: #FFFFFF;
-		margin: 20rpx;
+		margin:0 20rpx 20rpx;
 		border-radius: 15rpx;
 		overflow: hidden;
 		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
@@ -751,4 +800,146 @@
 			}
 		}
 	}
+
+	.wl-popup {
+		width: 650rpx;
+		background-color: #FFFFFF;
+		border-radius: 20rpx;
+		overflow: hidden;
+	}
+
+	.wl-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding: 30rpx;
+		border-bottom: 1rpx solid #F0F0F0;
+
+		.wl-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333333;
+		}
+
+		.wl-close {
+			font-size: 40rpx;
+			color: #999999;
+			width: 60rpx;
+			height: 60rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+
+	.wl-content {
+		padding: 30rpx;
+		max-height: 700rpx;
+		overflow-y: auto;
+	}
+
+	.express-info {
+		display: flex;
+		align-items: center;
+		padding: 20rpx 0;
+		border-bottom: 1rpx solid #F5F5F5;
+		margin-bottom: 20rpx;
+
+		.express-label {
+			font-size: 26rpx;
+			color: #999999;
+		}
+
+		.express-value {
+			font-size: 28rpx;
+			color: #333333;
+			font-weight: 500;
+		}
+	}
+
+	.wl-empty {
+		padding: 60rpx 0;
+		text-align: center;
+
+		text {
+			font-size: 28rpx;
+			color: #999999;
+		}
+	}
+
+	.wl-timeline {
+		position: relative;
+		padding-left: 30rpx;
+	}
+
+	.wl-item {
+		position: relative;
+		padding-bottom: 30rpx;
+
+		&:last-child {
+			padding-bottom: 0;
+
+			.wl-line {
+				display: none;
+			}
+		}
+
+		.wl-dot {
+			position: absolute;
+			left: -30rpx;
+			top: 8rpx;
+			width: 16rpx;
+			height: 16rpx;
+			border-radius: 50%;
+			background-color: #DDDDDD;
+			border: 3rpx solid #FFFFFF;
+			box-shadow: 0 0 0 2rpx #EEEEEE;
+		}
+
+		.wl-line {
+			position: absolute;
+			left: -24rpx;
+			top: 30rpx;
+			width: 2rpx;
+			height: calc(100% - 10rpx);
+			background-color: #EEEEEE;
+		}
+
+		.wl-info {
+			display: flex;
+			flex-direction: column;
+
+			.wl-status {
+				font-size: 26rpx;
+				color: #999999;
+				margin-bottom: 8rpx;
+				line-height: 36rpx;
+			}
+
+			.wl-time {
+				font-size: 22rpx;
+				color: #CCCCCC;
+			}
+		}
+
+		&.active {
+			.wl-dot {
+				background-color: #FF4444;
+				box-shadow: 0 0 0 2rpx rgba(255, 68, 68, 0.2);
+			}
+
+			.wl-status {
+				color: #333333;
+				font-weight: 500;
+			}
+
+			.wl-time {
+				color: #999999;
+			}
+
+			.wl-line {
+				background-color: #FF4444;
+			}
+		}
+	}
 </style>

+ 24 - 6
pages/user/jf/rechange.vue

@@ -1,13 +1,13 @@
 <template>
-	<view class="content">
+	<view class="content" v-if="isOpen == 1">
 		<view class="flex" style="background-color: #fff;">
 			<view class="remain">
 				<text class="label">我的剩余次数:</text>
 				<text class="count">{{chatConfig.balance}}</text>
 			</view>
-			<view class="remain">
+			<!-- <view class="remain">
 				<text class="labels">我的订单</text>
-			</view>
+			</view> -->
 		</view>
 		<view class="listBox">
 			<view class="custom">
@@ -44,9 +44,13 @@
 <script>
 	import { mapState,mapMutations } from 'vuex'
 	import { getChatConfig, buyChatCount,getUserInfo } from '@/api/user.js'
+	import {
+		share
+	} from '@/api/wx';
 	export default {
 		data() {
 			return {
+				is_open: 0,
 				chatConfig: {
 					balance: 0,
 					price: 0
@@ -59,15 +63,29 @@
 		},
 		computed: {
 			...mapState('user', ['userInfo']),
+			...mapState(['isOpen']),
 			estimatedPoints() {
 				return this.count * this.chatConfig.price;
 			}
 		},
 		onLoad() {
 			this.getChatConfig()
+			this.getShow()
 		},
 		methods: {
 			...mapMutations('user',['setUserInfo']),
+			getShow() {
+				share({}).then(({
+					data
+				}) => {
+					this.is_open = data.is_show
+					if(this.is_open == 1) {
+						uni.setNavigationBarTitle({
+							title:'次数充值'
+						})
+					}
+				});
+			},
 			getUserInfo() {
 				getUserInfo().then(res => {
 					this.setUserInfo(res.data)
@@ -118,9 +136,9 @@
 								that.getChatConfig()
 								that.getUserInfo()
 								// 购买成功后返回
-								// setTimeout(() => {
-								// 	this.navBack();
-								// }, 1500);
+								setTimeout(() => {
+									uni.navigateBack()
+								}, 1500);
 							})
 						}
 					},

+ 6 - 1
pages/user/jf/success.vue

@@ -56,7 +56,12 @@
 		methods: {
 			goBack() {
 				uni.switchTab({
-					url:'/pages/index/index'
+					url:'/pages/index/index',
+					fail() {
+						uni.navigateTo({
+							url:'/pages/index/index'
+						})
+					}
 				})
 			},
 			viewOrder() {

+ 284 - 91
pages/user/model/model.vue

@@ -58,7 +58,7 @@
 					模板预览
 				</view>
 				<view v-if="systeam!='ios'" class="by-now" @click="gobuy">
-					立即使用
+					{{!isBuy?'立即购买': (!isBase ? '设为默认': '默认模板')}}
 				</view>
 			</view>
 		</block>
@@ -66,7 +66,7 @@
 			结束预览
 		</view>
 
-		<view class="rightIcon">
+		<view class="rightIcon" v-if="isOpen">
 			<view class="Dz" @click="onDz(1)">
 				<uni-icons class="icon" :color="userTemplate.is_like==0?'#FFF':'#FEB8C6'" size='80rpx'
 					type="hand-up-filled"></uni-icons>
@@ -90,8 +90,7 @@
 			</view>
 			<!--  -->
 			<view class="Dz" @click="showDk(userTemplate.check_num)">
-				<uni-icons class="icon" color="#FFF" size='80rpx'
-					type="calendar-filled"></uni-icons>
+				<uni-icons class="icon" color="#FFF" size='80rpx' type="calendar-filled"></uni-icons>
 			</view>
 			<view class="ScNum">
 				{{userTemplate.check_num||0}}
@@ -99,12 +98,23 @@
 		</view>
 		<image src="/static/image/qy.png" mode="widthFix" class="qianyue" @click="goQy"
 			v-if="!userInfo.uid || (userInfo.uid && userInfo.uid != uid)"></image>
-		<image src="/static/image/qy.png" mode="widthFix" class="qianyues" @click="goZx"
-			v-if="!userInfo.uid || (userInfo.uid && userInfo.uid != uid)"></image>
+		<image src="/static/image/ht.png" mode="widthFix" class="qianyue" @click="goHt"
+			v-if="userInfo.uid && userInfo.uid == uid"></image>
+			<!-- v-if="isOpen" -->
+		<view class="qianyues" v-if="isOpen">
+			<image src="/static/image/zx.png" mode="widthFix" class="qianyues" @click="goZx"
+				v-if="!userInfo.uid || (userInfo.uid && userInfo.uid != uid)"></image>
+			<view class="unread" v-if="unreadCount > 0">
+				{{unreadCount > 99 ? '99+': unreadCount}}
+			</view>
+		</view>
+
 	</view>
 </template>
 
 <script>
+	import model from '@/pages/modelData/index.vue';
+
 	import {
 		mapState,
 		mapMutations
@@ -114,23 +124,42 @@
 		getCommonUserCardInfo,
 		getShowTemplateItem,
 		subShowTemplateOrder,
-		likeAndBookmark
+		likeAndBookmark,
+		userShowTemplateList,
+		setShowTemplate
 	} from '@/api/model.js'
 	import {
 		getUser,
-		getHonor
+		getHonor,
+		getChatConfig,
+		buyChatCount
 	} from '@/api/user.js';
 	import {
 		saveUrl,
 		interceptor
 	} from '@/utils/loginUtils.js';
-	import model from '@/pages/modelData/index.vue';
+	import {
+		getUnreadCount,
+		initSession,
+		getSessionList
+	} from '@/api/kf.js'
+	import {
+		share
+	} from '@/api/wx';
 	export default {
 		components: {
 			model
 		},
 		data() {
 			return {
+				price: 0,
+				isBase: false,
+				isBuy: false,
+				tList: [],
+				balance: 0,
+				is_open: 0,
+				chatList: [],
+				unreadCount: 0,
 				honor_list: [],
 				mtype: 1, //modelid
 				shareId: '', //保存分享uid
@@ -151,7 +180,6 @@
 		},
 		onLoad(opt) {
 			const that = this;
-			that.getHonor(opt.uid)
 			// #ifndef MP
 			if (opt.spread) {
 				// 存储其他邀请人
@@ -176,6 +204,7 @@
 					data: arr[0]
 				});
 				this.getCommonUserCardInfo(arr[0]);
+				that.getHonor(arr[0])
 				this.uid = arr[0];
 				return
 			}
@@ -191,6 +220,7 @@
 				if (this.userInfo.uid) {
 					this.getCommonUserCardInfo(this.userInfo.uid);
 					this.uid = this.userInfo.uid;
+					that.getHonor(this.userInfo.uid)
 				}
 				this.getShowTemplateItem();
 				return
@@ -209,6 +239,7 @@
 				this.isLook = 2;
 				this.shareId = opt.uid;
 				this.getCommonUserCardInfo(opt.uid);
+				that.getHonor(opt.uid)
 				this.uid = opt.uid;
 				return
 			} else
@@ -218,6 +249,7 @@
 				this.isLook = 2;
 				this.shareId = this.userInfo.uid;
 				this.getCommonUserCardInfo(this.userInfo.uid);
+				that.getHonor(this.userInfo.uid)
 				this.uid = this.userInfo.uid;
 				return
 			}
@@ -242,15 +274,23 @@
 
 		},
 		computed: {
-			...mapState(['baseURL']),
+			...mapState(['baseURL', 'isOpen']),
 			...mapState('user', ['userInfo', 'hasLogin']),
 			// #ifdef MP
 			...mapState(['systeam']),
 			// #endif
 		},
 		onShow() {
-
-			// this.getUser()
+			this.getShow()
+			if (this.hasLogin) {
+				this.getSessionList()
+				this.getUnreadCount()
+				this.getChatConfig()
+			}else {
+				if(this.isOpen) {
+					this.getUser()
+				}
+			}
 		},
 		// #ifdef MP
 		onShareAppMessage(options) {
@@ -289,34 +329,135 @@
 			let currentPage = pages[pages.length - 2]; //获取当前页面的对象
 			if (currentPage.route == 'pages/public/wxLogin') {
 				uni.switchTab({
-					url: '/pages/index/index'
+					url: '/pages/index/index',
+					fail() {
+						uni.navigateTo({
+							url:'/pages/index/index'
+						})
+					}
 				})
 			}
 		},
 		methods: {
 			...mapMutations('user', ['setUserInfo']),
+			getChatConfig() {
+				getChatConfig().then(res => {
+					this.balance = res.data.balance
+					this.price = Number(res.data.price)
+				})
+			},
+			goHt() {
+				uni.navigateTo({
+					url: '/pages/user/signing/mySig'
+				})
+			},
+			getShow() {
+				share({}).then(({
+					data
+				}) => {
+					this.is_open = data.is_show
+				});
+			},
+			getSessionList() {
+				getSessionList().then(res => {
+					this.chatList = res.data.list.map(item => {
+						return Number(item.user_id)
+					})
+				})
+			},
+			getUnreadCount() {
+				getUnreadCount({
+					form_user_id: this.uid
+				}).then(res => {
+					this.unreadCount = res.data.count
+					console.log(this.unreadCount, res.data.count);
+				})
+			},
 			goZx() {
 				let that = this
-				uni.showModal({
-					title:'温馨提示',
-					content:'建立聊天将消耗一次聊天次数,是否立即聊天?',
-					complete(e) {
-						if(e.confirm) {
-							uni.navigateTo({
-								url:'/pages/set/kf/index?to_uid=' + that.uid + '&name=' + that.userTemplate.name
+
+				if (this.chatList.includes(Number(that.uid))) {
+					uni.setStorageSync('avt', that.userTemplate.avatar)
+					uni.navigateTo({
+						url: '/pages/set/kf/index?to_uid=' + that.uid + '&name=' + that.userTemplate.name
+					})
+				} else {
+					//没有聊天次数
+					if (this.balance == 0) {
+						// 判断积分是否足够
+						if(Number(that.userInfo.score) < that.price) {
+							uni.showModal({
+								title: '温馨提示',
+								content: '您当前积分不足' + that.price + ',是否立即充值?',
+								complete(e) {
+									if(e.confirm) {
+										uni.navigateTo({
+											url:'/pages/user/jf/jfcz'
+										})
+									}
+								}
+							})
+						}else {
+							uni.showModal({
+								title: '温馨提示',
+								content: '建立聊天将消耗' + that.price + '积分,是否立即聊天?',
+								complete(e) {
+									if(e.confirm) {
+										// 买一次聊天
+										buyChatCount({
+											chat_num: 1
+										}).then(res => {
+											initSession({
+												to_user_id: that.uid
+											}).then(res => {
+												uni.setStorageSync('avt', that.userTemplate.avatar)
+												uni.navigateTo({
+													url: '/pages/set/kf/index?to_uid=' + that.uid +
+														'&name=' +
+														that.userTemplate.name
+												})
+											})
+										})
+									}
+									
+								}
 							})
 						}
+						
+					} else {
+						uni.showModal({
+							title: '温馨提示',
+							content: '建立聊天将消耗一次聊天次数,是否立即聊天?',
+							complete(e) {
+								if (e.confirm) {
+									initSession({
+										to_user_id: that.uid
+									}).then(res => {
+										uni.setStorageSync('avt', that.userTemplate.avatar)
+										uni.navigateTo({
+											url: '/pages/set/kf/index?to_uid=' + that.uid +
+												'&name=' +
+												that.userTemplate.name
+										})
+									})
+
+								}
+							}
+						})
 					}
-				})
+
+				}
+
+
 			},
-			showDk(num=0) {
+			showDk(num = 0) {
 				this.$api.msg('总打卡' + num + '次')
 			},
 			getHonor(uid) {
 				getHonor({
 					uid
 				}).then(res => {
-					console.log(res,'res');
+					console.log(res, 'res');
 					this.honor_list = res.data.honor_list
 				})
 			},
@@ -429,80 +570,117 @@
 					} else {
 						that.cardInfo = {}
 					}
+					this.userShowTemplateList()
 				}).catch((e) => {})
 			},
-			gobuy() {
+			userShowTemplateList() {
 				let that = this
-				subShowTemplateOrder({
-					id: that.mtype,
-					pay_type: that.payType
+				userShowTemplateList({
+					page: 1,
+					limit: 20
 				}).then(res => {
-					if (res.data.status == 1) {
-						uni.showModal({
-							title: '提示',
-							content: '支付成功!',
-							cancelText: '关闭',
-							confirmText: '查看模板',
-							success: res => {
-								if (res.confirm) {
-									uni.reLaunch({
-										url: '/pages/user/model/model?mtype=' +
-											that.mtype,
-									});
+					console.log(res);
+					this.tList = res.data.list
+					if (this.tList.length > 0) {
+						this.tList.forEach(item => {
+							if (item.show_template_id == that.mtype) {
+								that.isBuy = true
+								if (item.is_default == 1) {
+									that.isBase = true
 								}
-							},
-							fail: () => {},
-							complete: () => {}
-						});
-					} else {
-						let da = res.data.jsApiParameters;
-						let data = {
-							appId: da.appId,
-							// #ifdef H5
-							timestamp: da.timeStamp,
-							// #endif
-							// #ifdef MP
-							timeStamp: da.timeStamp + '',
-							// #endif
-							nonceStr: da.nonceStr,
-							package: da.package,
-							signType: da.signType,
-							paySign: da.paySign,
-							success: function(res) {
-								// obj.paySuccessTo();
-								// alert('支付成功')
-								uni.showModal({
-									title: '提示',
-									content: '支付成功!',
-									cancelText: '关闭',
-									confirmText: '查看模板',
-									success: res => {
-										if (res.confirm) {
-											uni.reLaunch({
-												url: '/pages/user/model/model?mtype=' +
-													that.mtype,
-											});
-										}
-									},
-									fail: () => {},
-									complete: () => {}
-								});
-							},
-							fail: (err) => {
-								console.log(err)
-								// alert('支付失败')
-								// uni.navigateTo({
-								// 	url: '/pages/order/order?state=0'
-								// });
 							}
-						};
-						if (that.payType == 'wxpay') {
-							wx.requestPayment(data)
-						}
+						})
 					}
 
 				})
 			},
+			gobuy() {
+				let that = this
+				if (that.isBuy) {
+					if (that.isBase) return;
+					setShowTemplate({
+						show_template_id: that.mtype
+					}).then(res => {
+						uni.showToast({
+							title: res.msg
+						})
+						that.isBase = true
+					})
+				} else {
+					subShowTemplateOrder({
+						id: that.mtype,
+						pay_type: that.payType
+					}).then(res => {
+						if (res.data.status == 1) {
+							that.userShowTemplateList()
+							uni.showModal({
+								title: '提示',
+								content: '支付成功!',
+								cancelText: '关闭',
+								confirmText: '查看模板',
+								success: res => {
+									if (res.confirm) {
+										uni.reLaunch({
+											url: '/pages/user/model/model?mtype=' +
+												that.mtype,
+										});
+									}
+								},
+								fail: () => {},
+								complete: () => {}
+							});
+						} else {
+							let da = res.data.jsApiParameters;
+							let data = {
+								appId: da.appId,
+								// #ifdef H5
+								timestamp: da.timeStamp,
+								// #endif
+								// #ifdef MP
+								timeStamp: da.timeStamp + '',
+								// #endif
+								nonceStr: da.nonceStr,
+								package: da.package,
+								signType: da.signType,
+								paySign: da.paySign,
+								success: function(res) {
+									// obj.paySuccessTo();
+									// alert('支付成功')
+									that.userShowTemplateList()
+									uni.showModal({
+										title: '提示',
+										content: '支付成功!',
+										cancelText: '关闭',
+										confirmText: '查看模板',
+										success: res => {
+											if (res.confirm) {
+												uni.reLaunch({
+													url: '/pages/user/model/model?mtype=' +
+														that.mtype,
+												});
+											}
+										},
+										fail: () => {},
+										complete: () => {}
+									});
+								},
+								fail: (err) => {
+									console.log(err)
+									// alert('支付失败')
+									// uni.navigateTo({
+									// 	url: '/pages/order/order?state=0'
+									// });
+								}
+							};
+							if (that.payType == 'wxpay') {
+								wx.requestPayment(data)
+							}
+						}
+
+					})
+				}
+
+			},
 			// 获取模板详情
 			getShowTemplateItem() {
 				let that = this
@@ -694,15 +872,30 @@
 		right: 20rpx;
 		// top:300rpx;
 		bottom: 0;
-		top: 500rpx;
+		top: 450rpx;
 	}
+
 	.qianyues {
 		width: 98rpx;
 		height: 108rpx;
 		position: fixed;
 		right: 20rpx;
 		// top:300rpx;
-		bottom: 0;
-		top: 380rpx;
+		bottom: 200rpx;
+		// top: 380rpx;
+	}
+
+	.unread {
+		$with: 50rpx;
+		position: absolute;
+		width: $with;
+		height: $with;
+		text-align: center;
+		line-height: $with;
+		top: -25rpx;
+		right: -10rpx;
+		border-radius: 50%;
+		background-color: #f65486;
+		color: #fff;
 	}
 </style>

+ 4 - 1
pages/user/model/modelList.vue

@@ -10,7 +10,7 @@
 						<view class="list-title clamp">
 							{{item.title}}
 						</view>
-						<view class="list-money flex flex-start">
+						<view class="list-money flex flex-start" v-if="isOpen == 1">
 							<view class="money">
 								¥{{item.price}}
 							</view>
@@ -51,6 +51,9 @@
 				},
 			};
 		},
+		computed: {
+			...mapState(['isOpen'])
+		},
 		onLoad: function(option) {
 			if(option.isrecommend){
 				uni.setNavigationBarTitle({

+ 1 - 1
pages/user/model/modelQr.vue

@@ -191,7 +191,7 @@
 				getWxmpShowQrcode({
 					id: obj.modelid
 				}).then(res => {
-					obj.bgimg = "/static/image/modelQshare.png"
+					obj.bgimg = "https://api.myjie.cn/static/img/modelQshare.png"
 					obj.qrcode = res.data.qrcode
 					uni.hideLoading();
 					obj.createPoster()

+ 66 - 6
pages/user/model/modelrz.vue

@@ -192,6 +192,7 @@
 								placeholder-class="placeholder" />
 						</view>
 					</view>
+
 					<view class="flex listItem">
 						<view class="flex titleBox">
 							<text class="title">服务区域</text>
@@ -205,6 +206,14 @@
 							</picker>
 						</view>
 					</view>
+					<view class="flex listItem" @click="chooseLng">
+						<view class="flex titleBox">
+							<text class="font-color-red font-size-sm">✲</text><text class="title">定位地址</text>
+						</view>
+						<view class="right flex">
+							<text>{{updata.latitude ? (updata.latitude + ','+updata.longitude): '请选择定位'}}</text>
+						</view>
+					</view>
 					<view class="flex listItem" v-if="actionAreaType==1">
 						<view class="flex titleBox">
 							<text class="font-color-red font-size-sm">✲</text><text class="title">服务区域</text>
@@ -261,12 +270,12 @@
 					<view class="con_image" v-for="(item,ind) in updata.imageList">
 						<image class="img" v-if="modelid==7" @click="upImage('imageList',3,ind)" :src="item"></image>
 						<image class="img" v-else @click="navCroper(400,400,'tab',ind)" :src="item"></image>
-						
+
 						<image @click="updata.imageList.splice(ind,1)" class="tip"
 							src="../../../static/icon/goodsExit.png" mode="scaleToFill"></image>
 					</view>
 					<view class="con_image">
-						<image class="img" v-if="modelid==7"  @click="upImage('imageList',2)"
+						<image class="img" v-if="modelid==7" @click="upImage('imageList',2)"
 							src="../../../static/image/upImg.png"></image>
 						<image class="img" v-else @click="navCroper(400,400,'all')"
 							src="../../../static/image/upImg.png"></image>
@@ -360,12 +369,18 @@
 
 	import pickerAddress from '@/components/wangding-pickerAddress/wangding-pickerAddress.vue';
 
+	import {
+		addLng
+	} from '@/api/set.js'
+
 	export default {
 		components: {
 			pickerAddress
 		},
 		data() {
 			return {
+				latitude: '',
+				longitude: '',
 				// showModelType:false,//默认类型
 				// 初始化数据失败
 				dataInitError: false,
@@ -405,6 +420,8 @@
 					service_imgs: [], //服务展示
 					model_imgs: [], //服务展示
 					no: '',
+					latitude: '',
+					longitude: ''
 				},
 				typeList: [], //服务类型
 				timeTypeList: [], //时间类型
@@ -474,6 +491,29 @@
 			...mapState(['baseURL']),
 		},
 		methods: {
+			chooseLng() {
+				let that = this
+				uni.chooseLocation({
+					success(res) {
+						that.updata.latitude = res.latitude
+						that.updata.longitude = res.longitude
+						uni.setStorageSync('latitude', res.latitude)
+						uni.setStorageSync('longitude', res.longitude)
+						addLng({
+							latitude: res.latitude,
+							longitude: res.longitude
+						}).then(res => {
+							// this.$api.msg('修改成功');
+
+						}).catch(err => {
+							console.log(err);
+						})
+					},
+					fail(err) { // 失败回调
+						console.error('选择位置失败:', err)
+					},
+				})
+			},
 			changeMyask({
 				detail
 			}) {
@@ -690,8 +730,16 @@
 									no: res.no,
 									service_count: res.service_count,
 									weight: res.weight * 1,
-									height: res.height
+									height: res.height,
+									latitude: res.latitude || '',
+									longitude: res.longitude || '',
 								})
+								let longitude = uni.getStorageSync('longitude') || ''
+								let latitude = uni.getStorageSync('latitude') || ''
+								if (latitude && longitude) {
+									that.updata.longitude = longitude
+									that.updata.latitude = latitude
+								}
 								if (that.modelid != 6) {
 									that.editorCtx.setContents({
 										html: res.service_intro_content
@@ -821,9 +869,9 @@
 			upImage(name, type, ind) {
 				const that = this;
 				that.onImg(1).then((res) => {
-					console.log(res.tempFilePath,'res');
+					console.log(res.tempFilePath, 'res');
 					that.upLoad(res.tempFilePath).then((urldata) => {
-						console.log(urldata,'urldata');
+						console.log(urldata, 'urldata');
 						if (type == 1) {
 							that.updata[name] = urldata.img
 						} else if (type == 2) {
@@ -954,7 +1002,11 @@
 									uni.switchTab({
 										url: "/pages/userhome/user",
 										fail(re) {
-											console.log(re)
+
+											uni.navigateTo({
+												url: '/pages/userhome/user'
+											})
+
 										}
 									})
 								}, 1000
@@ -1061,6 +1113,14 @@
 						});
 						return false
 					}
+					if (!that.updata.latitude) {
+						uni.showModal({
+							title: '错误',
+							content: '请选择定位',
+							showCancel: false,
+						});
+						return false
+					}
 				} else if (that.updata.modelType == 1) {
 					if (that.updata.model_imgs.length == 0) {
 						uni.showModal({

+ 1 - 1
pages/user/myteam.vue

@@ -11,7 +11,7 @@
 				<view class="header">我的推广</view>
 			</view> -->
 			<view class="content-bg">
-				<image src="../../static/img/tg-bg.png" mode=""></image>
+				<image src="https://api.myjie.cn/static/img/tg-bg.png" mode=""></image>
 			</view>
 			<view class="money-box">
 				<view class="money">{{ all|| '0' }}</view>

+ 6 - 1
pages/user/realName/realNameAuthentication.vue

@@ -303,7 +303,12 @@
 								showCancel: false,
 								complete: () => {
 									uni.switchTab({
-										url: '/pages/userhome/user'
+										url: '/pages/userhome/user',
+										fail() {
+											uni.navigateTo({
+												url:'/pages/userhome/user'
+											})
+										}
 									})
 								}
 							});

+ 120 - 36
pages/user/signing/mySig.vue

@@ -10,10 +10,14 @@
 			<view>
 
 				<view class="sig" v-for="item in navList[current].list" @click="check(item)">
-					<view class="sig-status"
+					<view class="sig-status" v-if="current != 3"
 						:style="{backgroundColor: item.status == 1 ? '#ff6e15': ( item.status == 2 ? '#31c98f': '#fd4664')}">
 						{{showStatus(item)}}
 					</view>
+					<view class="sig-status" v-else
+						:style="{backgroundColor: item.confirm == 0 ? '#ff6e15': ( item.confirm == 1 ? '#31c98f': '#fd4664')}">
+						{{item.confirm == 0 ?'待乙方确认': item.confirm == 1 ? '已同意': '已拒绝'}}
+					</view>
 					<view class="sig-tit">
 						服务预约
 					</view>
@@ -70,7 +74,11 @@
 						<text class="sig-info-tit">结束时间</text><text
 							class="sig-info-val">{{item.end_time | showTime}}</text>
 					</view>
-					<view class="sig-btn">
+					<view class="sig-btn" v-if="current != 3">
+						<view v-if="userInfo.uid == item.uid && item.status != 2 && item.status != 0"
+							class="sig-btn-base" @click="changeY(item)">
+							修改合同
+						</view>
 						<!-- 甲方签约 -->
 						<signInput v-if="!item.uid_img && userInfo.uid == item.uid && item.status == 0"
 							:ref="'sign' + index" :canvasId="'twoDrowCanvas' + index" :type="1"
@@ -86,7 +94,8 @@
 						</view>
 						<!-- <view class="sig-btn-base" -->
 						<!-- userInfo.uid == item.uid &&  -->
-						<view class="sig-btn-base" v-if="userInfo.uid == item.uid && item.status == 1 && !item.comment" @click="pj(item)">
+						<view class="sig-btn-base" v-if="userInfo.uid == item.uid && item.status != 0 && !item.comment"
+							@click="pj(item)">
 							评价
 						</view>
 						<view class="sig-btn-base" v-if="userInfo.uid == item.to_uid && item.status == 1"
@@ -108,6 +117,15 @@
 							取消
 						</view>
 					</view>
+					<view class="sig-btn" v-else>
+						<view v-if="userInfo.uid == item.to_uid && item.confirm == 0"
+							class="sig-btn-base" @click="passA(item,1)">
+							同意修改
+						</view>
+						<view class="sig-btn-base sig-btn-cancel" v-if="userInfo.uid == item.to_uid && item.confirm == 0" @click="passA(item,-1)">
+							拒绝修改
+						</view>
+					</view>
 				</view>
 				<empty v-if="navList[current].list.length == 0 && navList[current].loaded"></empty>
 				<uni-load-more v-else :status="navList[current].loading"></uni-load-more>
@@ -245,12 +263,12 @@
 				<textarea name="" id="" cols="30" rows="10" v-model="checkItem.comment.content" maxlength="200"
 					class="pj-wrap" disabled></textarea>
 				<view class="image-list flex">
-					<image mode="" v-for="item,index in checkItem.comment.imgs"  class="pj-img"
-						:src="item" @click="lookImg(item)"></image>
+					<image mode="" v-for="item,index in checkItem.comment.imgs" class="pj-img" :src="item"
+						@click="lookImg(item)"></image>
 				</view>
 			</view>
 		</uni-popup>
-		
+
 	</view>
 
 </template>
@@ -265,12 +283,13 @@
 		mapState
 	} from "vuex"
 	import {
+		getChangeList,
 		getContractList,
 		Jcheck,
 		tjCheck,
 		cancelSig,
 		goPj,
-
+		passChange
 	} from '@/api/signing.js'
 	import {
 		getHdDetail
@@ -334,6 +353,15 @@
 						page: 1,
 						limit: 10,
 						loaded: false
+					},
+					{
+						tit: '修改申请',
+						status: 3,
+						list: [],
+						loading: 'more',
+						page: 1,
+						limit: 10,
+						loaded: false
 					}
 				]
 			}
@@ -361,10 +389,34 @@
 			}
 		},
 		methods: {
+			passA(item,index) {
+				let that = this
+				uni.showModal({
+					title: '温馨提醒',
+					content:index == 1 ? '确认通过本次合同修改?': '确认拒绝本次合同修改',
+					complete(res) {
+						if (res.confirm) {
+							passChange({
+								id: item.id,
+								type: index
+							}).then(res => {
+								that.$api.msg(index == 1 ? '已同意': '已拒绝')
+								this.getList('re')
+							})
+						}
+					}
+				});
+			},
+			changeY(item) {
+				uni.setStorageSync('signing', item)
+				uni.navigateTo({
+					url: '/pages/user/signing/signing?id=' + item.to_uid + '&isChange=1'
+				})
+			},
 			lookImg(url) {
 				uni.previewImage({
 					urls: [url],
-					current:url
+					current: url
 				})
 			},
 			imgsub(index) {
@@ -557,9 +609,9 @@
 			lookPj(item) {
 				this.checkItem = item
 				if (this.checkItem.comment && this.checkItem.comment.imgs) {
-					console.log(this.checkItem.comment.imgs,typeof(this.checkItem.comment.imgs));
-					if(typeof(this.checkItem.comment.imgs) == 'string') {
-						
+					console.log(this.checkItem.comment.imgs, typeof(this.checkItem.comment.imgs));
+					if (typeof(this.checkItem.comment.imgs) == 'string') {
+
 						this.checkItem.comment.imgs = this.checkItem.comment.imgs.split(',')
 					}
 				}
@@ -596,7 +648,7 @@
 			openY(item) {
 				this.checkItem = item
 				if (this.checkItem.comment && this.checkItem.comment.imgs) {
-					if(typeof(this.checkItem.comment.imgs) == 'string') {
+					if (typeof(this.checkItem.comment.imgs) == 'string') {
 						this.checkItem.comment.imgs = this.checkItem.comment.imgs.split(',')
 					}
 				}
@@ -735,33 +787,64 @@
 				if (type == 'tab' && item.loaded) return;
 				if (item.loading == 'noMore' || item.loading == 'loading') return;
 				item.loading = 'loading'
-				getContractList({
-					page: item.page,
-					limit: item.limit,
-					status: item.status,
-					uid: that.userInfo.uid
-				}).then(res => {
-					let arr = res.data.list.map(item => {
-						if (item.content) {
-							try {
-								item.content = JSON.parse(JSON.parse(item.content))
-							} catch (error) {
-								item.content = JSON.parse(item.content)
-								//TODO handle the exception
+				if (item.status == 3) {
+					///  /api/user/getModifyList
+					getChangeList({
+						page: item.page,
+						limit: item.limit,
+						uid: that.userInfo.uid	
+					}).then(res => {
+						let arr = res.data.list.map(item => {
+							if (item.content) {
+								try {
+									item.content = JSON.parse(JSON.parse(item.content))
+								} catch (error) {
+									item.content = JSON.parse(item.content)
+									//TODO handle the exception
+								}
 							}
+							return item
+						})
+						console.log(arr);
+						item.list = item.list.concat(arr)
+						item.page++
+						if (arr.length == item.limit) {
+							item.loading = 'more'
+						} else {
+							item.loading = 'noMore'
 						}
-						return item
+						item.loaded = true
 					})
-					console.log(arr);
-					item.list = item.list.concat(arr)
-					item.page++
-					if (arr.length == item.limit) {
-						item.loading = 'more'
-					} else {
-						item.loading = 'noMore'
-					}
-					item.loaded = true
-				})
+				} else {
+					getContractList({
+						page: item.page,
+						limit: item.limit,
+						status: item.status,
+						uid: that.userInfo.uid
+					}).then(res => {
+						let arr = res.data.list.map(item => {
+							if (item.content) {
+								try {
+									item.content = JSON.parse(JSON.parse(item.content))
+								} catch (error) {
+									item.content = JSON.parse(item.content)
+									//TODO handle the exception
+								}
+							}
+							return item
+						})
+						console.log(arr);
+						item.list = item.list.concat(arr)
+						item.page++
+						if (arr.length == item.limit) {
+							item.loading = 'more'
+						} else {
+							item.loading = 'noMore'
+						}
+						item.loaded = true
+					})
+				}
+
 			}
 		},
 		onLoad() {
@@ -887,6 +970,7 @@
 				font-size: 26rpx;
 				color: #999;
 			}
+
 			&-cancels {
 				background: #fff;
 				border: 2rpx solid #FC4564;

+ 87 - 40
pages/user/signing/signing.vue

@@ -4,12 +4,14 @@
 			选择合同
 		</view>
 		<view class="ht-title flex">
-			<picker @change="bindPickerChange" :value="0" :range="htList" range-key="title">
+			<picker @change="bindPickerChange" :value="0" :range="htList" range-key="title" v-if="isChange == 0">
 				<view class="clamp">
 					{{htDetail.title}}
 				</view>
 			</picker>
-
+			<view class="clamp" v-else>
+				{{htDetail.title}}
+			</view>
 			<view class="look" @click="lookMore">
 				查看
 			</view>
@@ -142,7 +144,7 @@
 		</view> -->
 		<view class="base-buttom flex">
 			<view class="updata flex flex-center" :class="{ 'bg-gray': loding }" @click="loding ? '' : confirm()">
-				提交
+				{{isChange == 1 ? '修改': '提交'}}
 			</view>
 		</view>
 		<!-- <uni-popup ref="popup" type="center">
@@ -185,7 +187,8 @@
 	} from "vuex"
 
 	import {
-		createSigning
+		createSigning,
+		changeSigning
 	} from '@/api/signing.js'
 	import pickerAddress from '@/components/wangding-pickerAddress/wangding-pickerAddress.vue';
 
@@ -196,6 +199,7 @@
 		},
 		data() {
 			return {
+				isChange: 0,
 				htList: [],
 				loding: false,
 				fujia: '',
@@ -224,12 +228,20 @@
 				type: 0,
 				htDetail: {},
 				jsonAr: [],
-				jsonBr: []
+				jsonBr: [],
+				signing: {}
 			};
 		},
 		onLoad(options) {
 			this.getHtModel()
 			const that = this;
+			if (options.isChange == 1) {
+				this.isChange = 1
+				this.signing = uni.getStorageSync('signing')
+				uni.setNavigationBarTitle({
+					title: '修改合同'
+				})
+			}
 			if (options.id) {
 				this.uid = options.id
 				this.getCommonUserCardInfo()
@@ -239,6 +251,7 @@
 			if (options.type) {
 				this.type == options.type
 			}
+
 		},
 		computed: {
 			// #ifdef H5
@@ -273,14 +286,19 @@
 					id: hid
 				}).then(res => {
 					this.htDetail = res.data
-					this.jsonAr = this.htDetail.content.jsonAr.map(item => {
-						item.value = ''
-						return item
-					})
-					this.jsonBr = this.htDetail.content.jsonBr.map(item => {
-						item.value = ''
-						return item
-					})
+					if (this.isChange == 1) {
+						this.jsonAr = this.signing.content.jsonAr
+						this.jsonBr = this.signing.content.jsonBr
+					} else {
+						this.jsonAr = this.htDetail.content.jsonAr.map(item => {
+							item.value = ''
+							return item
+						})
+						this.jsonBr = this.htDetail.content.jsonBr.map(item => {
+							item.value = ''
+							return item
+						})
+					}
 					this.setBInfo()
 					// this.htDetail = res.data
 				})
@@ -370,7 +388,13 @@
 					uid: this.uid
 				}).then(res => {
 					this.partyB = res.data
-					this.getHtList()
+					if (this.isChange == 1) {
+						console.log(this.signing, 'signingsigningsigningsigning');
+						this.getHdDetail(this.signing.content.id)
+					} else {
+
+						this.getHtList()
+					}
 				})
 			},
 			confirm(e) {
@@ -381,36 +405,58 @@
 				let start_time_item = this.jsonAr.find(item => item.code == 'start_time')
 				let end_time_item = this.jsonAr.find(item => item.code == 'end_time')
 				that.loding = true;
-				createSigning({
-						id: 0,
-						to_name: that.partyB.name,
-						// name: that.partyA.name,
-						uid: that.userInfo.uid,
-						// phone: that.partyA.mobile,
-						// address: that.partyA.address,
-						// card: that.partyA.idcard,
-						to_uid: that.uid,
-						// price: that.contract.money,
-						// deposit: that.contract.deposit,
-						// balance: that.contract.balance,
-						// period: that.contract.day,
-						start_time: start_time_item.value,
-						end_time: end_time_item.value,
-						// mark: that.fujia,
-						latitude: that.partyA.latitude,
-						longitude: that.partyA.longitude,
-						template_id: that.htDetail.id,
-						content: JSON.stringify({
-							id: that.htDetail.id,
-							title: that.htDetail.title,
-							jsonAr: that.jsonAr,
-							jsonBr: that.jsonBr
-						})
+				let pdata = {
+					to_name: that.partyB.name,
+					// name: that.partyA.name,
+					uid: that.userInfo.uid,
+					// phone: that.partyA.mobile,
+					// address: that.partyA.address,
+					// card: that.partyA.idcard,
+					to_uid: that.uid,
+					// price: that.contract.money,
+					// deposit: that.contract.deposit,
+					// balance: that.contract.balance,
+					// period: that.contract.day,
+					start_time: start_time_item.value,
+					end_time: end_time_item.value,
+					// mark: that.fujia,
+					latitude: that.partyA.latitude,
+					longitude: that.partyA.longitude,
+					template_id: that.htDetail.id,
+					content: JSON.stringify({
+						id: that.htDetail.id,
+						title: that.htDetail.title,
+						jsonAr: that.jsonAr,
+						jsonBr: that.jsonBr
 					})
+				}
+				let pfun = createSigning
+				if (that.isChange == 1) {
+					pdata.cr_id = that.signing.id
+					pfun = changeSigning
+				} else {
+					pdata.id = 0
+				}
+				pfun(pdata)
 					.then((e) => {
+						if(that.isChange == 1) {
+							uni.showModal({
+								title: '温馨提醒',
+								content:'修改请求已发送,等待对方确认',
+								confirmText:'返回',
+								complete(res) {
+									if (res.confirm) {
+										uni.navigateTo({
+											url: '/pages/user/signing/mySig'
+										})
+									}
+								}
+							});
+						}else {
+							
 						uni.showModal({
 							title: '温馨提醒',
-							content: '成功创建合同,是否立即签约',
+							content:'成功创建合同,是否立即签约',
 							complete(res) {
 								if (res.confirm) {
 									uni.navigateTo({
@@ -419,6 +465,7 @@
 								}
 							}
 						});
+						}
 						that.loding = false;
 					})
 					.catch(err => {

+ 145 - 26
pages/userhome/user.vue

@@ -86,8 +86,7 @@
 								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
 							</view>
 						</view> -->
-						<view v-if="is_open == 1" class="flex listItem" @click="navTo('/pages/user/forum/index')"
-							>
+						<view v-if="isOpen == 1" class="flex listItem" @click="navTo('/pages/user/forum/index')">
 							<view class="flex titleBox">
 								<image class="listIconImg" src="../../static/icon/forum.png" mode="widthFix"></image>
 								<text class="title">论坛</text>
@@ -97,8 +96,29 @@
 								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
 							</view>
 						</view>
-						<view class="flex listItem" @click="navTo('/pages/user/jf/bill')"
-							>
+						<view v-if="isOpen == 1" class="flex listItem" @click="navTo('/pages/set/kf/list')">
+							<view class="flex titleBox">
+								<image class="listIconImg" src="../../static/icon/kff.png" mode="widthFix"></image>
+								<text class="title">咨询列表</text>
+								<text class="tips" v-if="unread">({{unread}}条消息未读)</text>
+							</view>
+							<view class="right flex">
+								<text></text>
+								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
+							</view>
+						</view>
+						<!-- <view v-if="is_open == 1" class="flex listItem" @click="navTo('/pages/user/jf/store')">
+							<view class="flex titleBox">
+								<image class="listIconImg" src="../../static/icon/jfsc.png" mode="widthFix"></image>
+								<text class="title">积分商城</text>
+								<text class="tips"></text>
+							</view>
+							<view class="right flex">
+								<text></text>
+								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
+							</view>
+						</view> -->
+						<view class="flex listItem" @click="navTo('/pages/user/jf/bill')">
 							<view class="flex titleBox">
 								<image class="listIconImg" src="../../static/icon/myjf.png" mode="widthFix"></image>
 								<text class="title">我的积分</text>
@@ -108,8 +128,7 @@
 								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
 							</view>
 						</view>
-						<view class="flex listItem" @click="navTo('/pages/user/model/phb')"
-							>
+						<view class="flex listItem" @click="navTo('/pages/user/model/phb')">
 							<view class="flex titleBox">
 								<image class="listIconImg" src="../../static/icon/guanjun.png" mode="widthFix"></image>
 								<text class="title">人气排行</text>
@@ -211,6 +230,16 @@
 								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
 							</view>
 						</view>
+						<button hover-class="none" class="flex listItem" @click="navTo('/pages/index/detail')" v-if="isOpen">
+							<view class="flex titleBox">
+								<image class="listIconImg" src="../../static/icon/kfzx.png" mode="widthFix"></image>
+								<text class="title">学习交流群</text>
+							</view>
+							<view class="right flex">
+								<text></text>
+								<image class="img" src="../../static/icon/next1.png" mode="widthFix"></image>
+							</view>
+						</button>
 						<!-- #ifdef MP -->
 						<button hover-class="none" class="flex listItem" @click="openEnterpriseWechat">
 							<view class="flex titleBox">
@@ -273,16 +302,33 @@
 				</view>
 			</view>
 		</scroll-view>
-		<uni-popup ref="popup" type="center">
-			<swiper class="alertBox" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
-				<swiper-item v-for="ls in ggList">
-					<image @click="openXcx(ls)" class="alertImage" :src="ls.img" mode="scaleToFill"></image>
-				</swiper-item>
-			</swiper>
+		<uni-popup ref="popup" type="center" :maskClick="false">
+			<view class="show-bg">
+				<swiper class="alertBox" :indicator-dots="false" :autoplay="true" :interval="3000" :duration="1000"
+					:style="{'height': iHeight}">
+					<swiper-item v-for="ls in ggList" :style="{'height': iHeight}">
+						<image @click="openXcx(ls)" class="alertImage" :src="ls.img" mode="widthFix">
+						</image>
+					</swiper-item>
+				</swiper>
+				<image src="/static/icon/close.png" mode="" class="close-icon" @click="$refs.popup.close()"></image>
+				<!-- <view class="show-btn-wrap flex">
+					<view class="show-btn">
+						关闭
+					</view>
+					<view class="show-btn">
+						立即跳转
+					</view>
+				</view> -->
+				
+			</view>
+			
 		</uni-popup>
+		<m-tabbar fixed fill current="3" :tabbar="tabbar"></m-tabbar>
 	</view>
 </template>
 <script>
+	import TabbarConfig from '@/config/tabbar.js'
 	import {
 		mapState,
 		mapMutations
@@ -309,9 +355,15 @@
 	import {
 		getBannerList
 	} from '@/api/model.js';
+	import {
+		getSessionList
+	} from '@/api/kf.js'
 	export default {
 		data() {
 			return {
+				tabbar: TabbarConfig,
+				iHeight: '480rpx',
+				unread: 0,
 				is_open: 0,
 				user: {
 					avatar: '', //头像
@@ -324,7 +376,7 @@
 		},
 		computed: {
 			...mapState('user', ['userInfo', 'orderInfo', 'hasLogin']),
-			...mapState(['baseURL', 'urlFile']),
+			...mapState(['baseURL', 'urlFile','isOpen']),
 			...mapState(['fx']),
 			// #ifdef MP
 			...mapState(['systeam']),
@@ -347,18 +399,16 @@
 			if (!this.showGG && this.hasLogin && this.ggList.length > 0) {
 				this.showGG = true;
 				this.$nextTick(() => {
-					this.$refs.popup.open()
+					// this.$refs.popup.open()
 				})
 			}
 		},
 		methods: {
 			...mapMutations('user', ['setUserInfo']),
 			getShow() {
-				console.log('zhel');
 				share({}).then(({
 					data
 				}) => {
-					
 					this.is_open = data.is_show
 				});
 			},
@@ -369,8 +419,8 @@
 				});
 				wx.openCustomerServiceChat({
 					corpId: 'wwaff436832bc11deb', // 必填:企业微信的corpId,从企业微信管理后台获取
-					extInfo:{
-						url:'https://work.weixin.qq.com/kfid/kfc2e05cbe1de7cb887'
+					extInfo: {
+						url: 'https://work.weixin.qq.com/kfid/kfc2e05cbe1de7cb887'
 					},
 					success: (res) => {
 						uni.hideLoading();
@@ -394,11 +444,13 @@
 			},
 			// #endif
 			getGG() {
+				let that = this
 				getBannerList({
 					page_id: 73
 				}).then(
 					(res) => {
-						this.ggList = res.data.list.map((re) => {
+
+						that.ggList = res.data.list.map((re) => {
 							if (re.data.length > 0) {
 								const json = JSON.parse(re.data)
 								for (var i = 0; i < json.length; i++) {
@@ -409,7 +461,28 @@
 							}
 							return re
 						})
-						console.log(this.ggList)
+						let show = uni.getStorageSync('show') || 0
+						if (show != that.ggList[0].id) {
+							const appBaseInfo = wx.getAccountInfoSync()
+							
+							uni.getImageInfo({
+								src: that.ggList[0].img, // 图片路径或base64字符串(如果是base64字符串则不需要src)
+								success: (imageInfo) => {
+									that.iHeight = 480 / imageInfo.width * imageInfo.height + 'rpx'
+									if(appBaseInfo.miniProgram.envVersion == 'release') {
+										that.$refs.popup.open()
+										uni.setStorageSync('show', that.ggList[0].id)
+									}
+								},
+								fail(err) {
+									console.log(err, '时报');
+								}
+							});
+
+
+						} else {
+							// uni.setStorageSync('show',that.ggList[0].id)
+						}
 					}
 				).catch(
 					(res) => {
@@ -417,6 +490,9 @@
 					}
 				)
 			},
+			loadImage(e) {
+				console.log(e);
+			},
 			// 打开小程序
 			openXcx(item) {
 				// #ifdef MP
@@ -430,7 +506,12 @@
 						this.$refs.popup.close()
 					} else {
 						uni.navigateTo({
-							url: item.url
+							url: item.url,
+							fail() {
+								uni.switchTab({
+									url: item.url,
+								})
+							}
 						})
 					}
 				}
@@ -516,11 +597,19 @@
 				getUser({}).then((e) => {
 					this.user = e.data;
 					this.setUserInfo(e.data)
-
+					this.getSessionList()
 				}).catch((e) => {
 					console.log(e, 'sj');
 				})
 			},
+			getSessionList() {
+				this.unread = 0
+				getSessionList().then(res => {
+					res.data.list.forEach(item => {
+						this.unread += Number(item.unread_count)
+					})
+				})
+			},
 			changeTab() {
 				this.$emit('tab', true)
 			},
@@ -738,13 +827,43 @@
 
 	.alertBox {
 
-		width: 479rpx;
-		height: 832rpx;
+		width: 480rpx;
+		// height: 832rpx;
 
 		.alertImage {
 			border-radius: 20rpx;
-			width: 479rpx;
-			height: 832rpx;
+			width: 480rpx;
 		}
 	}
+
+	.tips {
+		font-size: 24rpx;
+		color: #999;
+	}
+	.show-btn-wrap {
+		padding: 20rpx;
+		
+	}
+	.show-btn {
+		background-color: #f65486;
+		color: #fff;
+		width: 200rpx;
+		height: 80rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		border-radius: 40rpx;
+	}
+	.show-bg {
+		position: relative;
+	}
+	.close-icon {
+		width: 60rpx;
+		height: 60rpx;
+		position: absolute;
+		bottom: -80rpx;
+		left: 0;
+		right: 0;
+		margin: auto;
+	}
 </style>

+ 100 - 0
pages/znkf/index.vue

@@ -0,0 +1,100 @@
+<template>
+	<view style="height: 100vh;" class="hhh">
+		<chat @queryCallback="queryCallback" @openWebview="handleOpenWebview" @openMiniProgram="handleOpenMiniProgram" >
+		</chat>
+		<!-- <m-tabbar fixed fill current="2" :tabbar="tabbar"></m-tabbar> -->
+	</view>
+</template>
+
+<script>
+	import TabbarConfig from '@/config/tabbar.js'
+	import {
+		mapState,
+		mapMutations
+	} from 'vuex';
+	import {
+		getOpenId
+	} from '@/api/user.js'
+	export default {
+		data() {
+			return {
+				tabbar: TabbarConfig,
+				openId: ''
+			}
+		},
+		computed: {
+			...mapState('user', ['userInfo', 'orderInfo', 'hasLogin']),
+		},
+		methods: {
+			inst() {
+				let that = this
+				var plugin = requirePlugin("chatbot");
+				plugin.init({
+					appid: "s2y2Lv65jK14ksQwYWa0WmMGqddGn4", //微信对话开放平台小程序插件appid
+					openid: that.openId, // 小程序用户的openid,必填项
+					userHeader: that.userInfo.avatar, // 用户头像,不传会弹出登录框
+					userName: that.userInfo.nickname, // 用户昵称,不传会弹出登录框
+					anonymous: false, // 是否允许匿名用户登录,版本1.2.9后生效, 默认为false,设为true时,未传递userName、userHeader两个字段时将弹出登录框
+					// guideList: ['你好', '如何退款', '订单查询'], // 底部快捷提问
+					// guideCardHeight: 0,
+					success: () => {
+						console.log( '成功');
+					}, //非必填
+					fail: (error) => {
+						console.log('失败:',error);
+					}, //非必填
+				});
+				// uni.navigateTo({
+				// 	url:'plugin://chatbot/chat'
+				// })
+			},
+			getUserInfo() {
+				getOpenId().then(res => {
+					this.openId = res.data.open_id
+					this.inst()
+				})
+			},
+			// 机器人问答回调
+			queryCallback(e) {
+				console.log('用户提问回调', e.detail)
+			},
+			// 机器人回复中点击H5链接
+			handleOpenWebview(e) {
+				const url = encodeURIComponent(e.detail.weburl)
+				uni.navigateTo({
+					url: `/pages/index/webview?targetUrl=${url}`
+				})
+			},
+			// 机器人回复跳转其他小程序
+			handleOpenMiniProgram(e) {
+				const {
+					appid,
+					pagepath
+				} = e.detail
+				uni.navigateToMiniProgram({
+					appId: appid,
+					path: pagepath
+				})
+			}
+		},
+		onShow() {
+			let that = this
+			wx.login({
+				success(res) {
+					console.log(res,'wxlogin');
+					that.getUserInfo()
+				}
+			})
+		},
+		onReady() {
+			// this.getUserInfo()
+			// getOpenId
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.hhh {
+		height: calc(100vh - 44px);
+	}
+</style>

BIN
static/error/emptyCart.png


BIN
static/error/emptyItem.png


BIN
static/error/emptyList.png


BIN
static/error/emptyMyCart.png


BIN
static/error/emptyNotice.png


BIN
static/error/emptyOrder.png


BIN
static/error/errorImage.jpg


BIN
static/error/shopErroe.png


BIN
static/icon/close.png


BIN
static/icon/jfsc.png


BIN
static/icon/kff.png


BIN
static/icon/kfzx.png


BIN
static/icon/ok.png


BIN
static/image/ht.png


BIN
static/image/logo.png


BIN
static/image/modelQshare.png


BIN
static/image/qy.png


BIN
static/image/qybanner.jpg


BIN
static/image/qyweichat.jpg


BIN
static/image/teimImg.jpg


BIN
static/image/zx.png


BIN
static/img/b0c1028581f40a90b2454abfde489f9.png


BIN
static/img/e0caee5ee096efb49bed156878b1db1.png


BIN
static/img/phb.png


BIN
static/img/tg-bg.png


BIN
static/tabBar/tab-xxjl-current.png


BIN
static/tabBar/tab-xxjl.png


+ 4 - 0
store/index.js

@@ -6,6 +6,7 @@ Vue.use(Vuex)
 
 const store = new Vuex.Store({
 	state: {
+		isOpen: 0,
 		// baseURL:"http://yrh.liuniu946.com",//'http://eb.shuibo.net',//请求地址配置 
 		baseURL:'https://api.myjie.cn',//请求地址配置 
 		// baseURL:'http://dp.frp.shuibo.net',//请求地址配置 
@@ -25,6 +26,9 @@ const store = new Vuex.Store({
 		// #endif
 	},
 	mutations: {
+		openOpen(state, provider) {
+			state.isOpen = provider
+		},
 		// #ifdef MP
 		setSystem(state, provider){
 			state.systeam = provider;

+ 76 - 0
uni_modules/m-tabbar/changelog.md

@@ -0,0 +1,76 @@
+## 2.0.0(2023-11-14)
+1、新增切换拦截返回当前点击index
+2、新增自动读取主页面配置功能
+3、优化部分代码结构实现
+注意:代码重构优化,2.0.0版本不支持老版本兼容
+## 1.3.3(2023-02-27)
+修复openType类型为navigateTo时,页面返回,重新点击不响应问题
+## 1.3.2(2023-02-27)
+修改占位空间点击事件遮挡问题
+## 1.3.1(2023-02-27)
+1、新增页面打开方式,可以自定义每个tabbarItem的点击打开方式
+2、新增tabbarHeight参数,方便你直接使用参数控制tabbar高度
+## 1.3.0(2023-02-21)
+新增ref方法若干,优化使用说明文档
+## 1.2.9(2023-02-21)
+修改safe计算,使用原生css,抛弃原始计算耗时能力
+## 1.2.8(2023-02-20)
+修正文档使用说明
+## 1.2.7(2023-02-20)
+1、新增角标显示
+2、新增setTabBarBadge,reLoad方法
+## 1.2.6(2023-02-13)
+修复判断safebottom底部安全距离数值写死问题
+## 1.2.5(2023-01-12)
+1、修复默认初始高度闪烁问题,不在使用计算,直接默认
+2、修复上个版本遗留current选中问题
+3、修复safeBottom底部判断错误问题
+4、更新使用说明文档
+## 1.2.4(2023-01-09)
+新增文档说明,增加示例项目页面
+## 1.2.3(2022-12-14)
+修复外部不跳转页面修改current,组件不响应bug
+## 1.2.2(2022-12-14)
+新增click事件,click事件会优先于任何事件
+## 1.2.1(2022-12-09)
+修改文档使用说明,路由拦截有平台兼容性,暂时无法解决,平台原生不支持
+## 1.2.0(2022-12-09)
+新增插槽,可以自定义凸起导航,优化文档使用说明
+## 1.1.9(2022-12-06)
+修复iconPath图片路径为网络路径判断错误问题
+## 1.1.7(2022-12-01)
+优化部分机器计算错误问题
+## 1.1.6(2022-12-01)
+修改高度计算错误问题
+## 1.1.5(2022-12-01)
+修复各别设备上高度计算有误问题
+## 1.1.4(2022-11-25)
+修复vue2版本在微信小程序上不支持:style传入参数bug,优化参数错误逻辑
+## 1.1.3(2022-11-24)
+修复native模式borderStyle样式丢失问题
+## 1.1.2(2022-11-24)
+修改描述文档说明,修改插件描述信息
+## 1.1.1(2022-11-24)
+优化使用说明文档
+## 1.1.0(2022-11-24)
+极度简化native模式,页面只需要引入组件即可,任何操作都不需要
+## 1.0.9(2022-11-24)
+修复native模式下,fill忘记计算高度.
+## 1.0.8(2022-11-24)
+优化native模式,简化参数数量,使用更简单
+## 1.0.7(2022-11-24)
+新增native配置,可以兼容原生tabbar,新增beforeChange,可自行根据要求自己兼容路由守卫
+## 1.0.6(2022-11-23)
+修改文档描述错误
+## 1.0.5(2022-11-23)
+修复fill高度遗漏安全距离问题,文档使用说明优化更新
+## 1.0.4(2022-11-23)
+优化配置选项,提取当前选中项,新增fixed配置
+## 1.0.3(2022-11-14)
+添加上阴影效果,修复由于去除了上线条,造成如果内容如果是白色,tabbar会和内容高度重合的问题
+## 1.0.2(2022-11-14)
+修改说明文档,更加详细备注说明
+## 1.0.1(2022-11-14)
+新增当前选中项class名,方便用户直接样式覆盖
+## 1.0.0(2022-11-14)
+第一个自定义tabbar版本

+ 516 - 0
uni_modules/m-tabbar/components/m-tabbar/m-tabbar.vue

@@ -0,0 +1,516 @@
+<template>
+	<view class="m-tabbar-box" :style="tabbarBoxStyle" v-if="isShowTabBar">
+		<view class="m-tabbar__fill" v-if="fill || native" :class="{'m-tabbar__safe': (safeBottom || native)}"
+			:style="tabbarFillStyle" />
+		<view id="m-tabbar" class="m-tabbar"
+			:class="{'fixed': (fixed || native), 'm-tabbar__safe': (safeBottom || native)}" :style="tabbarStyle">
+			<view class="m-tabbar__border" v-if="borderStyle === 'black'" />
+			<!-- tabbar border -->
+			<view class="m-tabbar__flex">
+				<view class="m-tabbar__item" @click="_tabChange(index)" v-for="(item, index) in tabbarList" :key="index"
+					:class="{
+						'm-tabbar__item__active': index === currentIndex,
+					}">
+					<slot :name="`tabbar_index_${index}`">
+						<view class="m-tabbar__icon">
+							<view class="m-tabbar__badge" v-if="item.dot">{{item.dot}}</view>
+							<image :src="currentIndex === index ? item.selectedIconPath : item.iconPath"
+								class="m-tabbar__icon_img" />
+						</view>
+						<view class="m-tabbar__label"
+							:style="{'color': index === currentIndex ? tabbarConfig.selectedColor : tabbarConfig.color }">
+							{{ item.text }}
+						</view>
+					</slot>
+				</view>
+				<!-- tabbar item -->
+			</view>
+			<!-- tabbar item box -->
+		</view>
+		<!-- tabbar block -->
+	</view>
+	<!-- tabbar box -->
+</template>
+
+<script>
+	// style转为string
+	const obj2strStyle = (obj) => {
+		let style = ''
+		for (let key in obj) {
+			style += `${key}:${obj[key]};`
+		}
+		return style
+	}
+
+	// 自动填充路径
+	const padFirstSymbol = (str, smb) => {
+		if (str.startsWith(smb) || str.startsWith('http')) {
+			return str
+		}
+		return `/${str}`
+	}
+
+	// 替换原生路径问题
+	const replaceTabbarList = (list) => {
+		if (!list.length > 0) {
+			return []
+		}
+		return list.map(item => {
+			if (item.iconPath) {
+				item.iconPath = padFirstSymbol(item.iconPath, '/')
+			}
+			if (item.pagePath) {
+				item.pagePath = padFirstSymbol(item.pagePath, '/')
+			}
+			if (item.selectedIconPath) {
+				item.selectedIconPath = padFirstSymbol(item.selectedIconPath, '/')
+			}
+			return item
+		})
+	}
+
+	// 设置缓存,方便重复调用方法
+	const setTabbarStorage = (key, value, name) => {
+		try {
+			uni.setStorageSync(`mTab_${key}_${name}`, value)
+		} catch (e) {
+			console.error(e)
+		}
+	}
+
+	// 读取缓存
+	const getTabbarStorage = (key, name) => {
+		try {
+			const value = uni.getStorageSync(`mTab_${key}_${name}`)
+			if (value) {
+				return value
+			}
+			return ''
+		} catch (e) {
+			console.error(e)
+		}
+	}
+
+
+	import PageConfig from '@/pages.json'
+
+	export default {
+		emits: ['change', 'click'],
+		props: {
+			// 使用原生配置自动生成
+			native: {
+				type: Boolean,
+				default: false
+			},
+			// 当前选择下标,默认0开始
+			current: {
+				type: [Number, String],
+				default: 0
+			},
+			// tabbar配置项
+			tabbar: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			// 是否固定在底部
+			fixed: {
+				type: Boolean,
+				default: false
+			},
+			// 是否自动填充底部
+			fill: {
+				type: Boolean,
+				default: false
+			},
+			// 显示层级
+			zIndex: {
+				type: [Number, String],
+				default: 9999
+			},
+			// 是否自动规避底部安全距离
+			safeBottom: {
+				type: Boolean,
+				default: true
+			},
+			// 切换时拦截事件(有兼容性,部分平台不支持)
+			beforeChange: {
+				type: Function,
+				default: null
+			},
+			// 自定义tabbar高度,单位rpx
+			tabbarHeight: {
+				type: [Number, String],
+				default: 100
+			},
+			// 自定义tabbar的name,方便读取默认tabbar
+			name: {
+				type: String,
+				default: 'custom'
+			}
+		},
+		data() {
+			return {
+				isShowTabBar: false, //是否显示导航
+				currentIndex: 0, //当前值
+				beforeData: {}, //切换前值
+				initTabbarConfig: {},
+				isReload: false //uni不支持computed的get set,使用reload无感重置刷新
+			}
+		},
+		watch: {
+			current(val) {
+				this.currentIndex = val * 1
+			}
+		},
+		computed: {
+			tabbarConfig() {
+				const {
+					isReload,
+					native,
+					initTabbarConfig: tabbar
+				} = this
+				if(isReload){}
+				// 如果是native模式,直接读取执行
+				if (native) {
+					if (!tabbar) {
+						console.error('Native mode, Pages.json no tabbar config')
+						return {
+							borderStyle: 'black',
+							list: []
+						}
+					}
+					return tabbar
+				}
+				// 如果没有配置tabbar,会尝试在缓存读取
+				if (!tabbar.color) {
+					return this._getDefaultTabbar()
+				}
+				return tabbar
+			},
+			tabbarList() {
+				const {
+					isReload,
+					tabbarConfig: {
+						list
+					}
+				} = this
+				if(isReload){}
+				if (!list) {
+					console.error('No tabbar config')
+					return []
+				}
+				return replaceTabbarList(list)
+			},
+			borderStyle() {
+				const {
+					isReload,
+					borderStyle
+				} = this.tabbarConfig
+				if(isReload){}
+				return borderStyle
+			},
+			tabbarBoxStyle() {
+				const {
+					isReload,
+					zIndex
+				} = this
+				if(isReload){}
+				return obj2strStyle({
+					'z-index': zIndex,
+				})
+			},
+			tabbarFillStyle() {
+				const {
+					isReload,
+					tabbarHeight
+				} = this
+				if(isReload){}
+				return obj2strStyle({
+					'height': `${tabbarHeight}rpx`
+				})
+			},
+			tabbarStyle() {
+				const {
+					isReload,
+					tabbarHeight,
+					tabbarConfig: {
+						backgroundColor
+					}
+				} = this
+				if(isReload){}
+				return obj2strStyle({
+					'height': `${tabbarHeight}rpx`,
+					'background-color': backgroundColor || '#fff',
+				})
+			},
+			tabbarItemStyle() {
+				const {
+					isReload,
+					currentIndex,
+					tabbarConfig: {
+						color,
+						selectedColor
+					}
+				} = this
+				if(isReload){}
+				return obj2strStyle({
+					'color': currentIndex ? selectedColor : color
+				})
+			}
+		},
+		created() {
+			const {
+				tabbar,
+				native
+			} = this
+			const pageTabbar = PageConfig.tabBar
+			this.initTabbarConfig = native ? pageTabbar : tabbar
+			console.log(this.name)
+			this._initTabbar()
+		},
+		methods: {
+			_initTabbar() {
+				const {
+					current,
+					fill,
+					native,
+					tabbarList
+				} = this
+				this.currentIndex = current * 1
+				if (native && tabbarList.length > 0) {
+					const currentPage = `/${getCurrentPages()[0].route}`
+					const currentIndex = tabbarList.findIndex(item => item.pagePath === currentPage)
+					this.currentIndex = currentIndex
+					uni.hideTabBar()
+				}
+				setTimeout(() => {
+					this.isShowTabBar = true
+				})
+				this._setTabbarStorage('tabbarConfig')
+			},
+			_setTabbarStorage(key){
+				setTabbarStorage(key, this.tabbarConfig, this.name)
+				this._setReload()
+			},
+			_getDefaultTabbar() {
+				return getTabbarStorage('tabbarConfig', this.name)
+			},
+			_checkMaxIndex(index) {
+				const {
+					tabbarConfig: {
+						list
+					}
+				} = this
+				if (list.length < 1) {
+					return false
+				}
+				if (!list[index]) {
+					console.error('Max tabbar index')
+					return false
+				}
+				return true
+			},
+			_setReload(){
+				this.isReload = true
+				setTimeout(()=>{
+					this.isReload = false
+				})
+			},
+			setTabBarBadge(obj) {
+				const {
+					index,
+					text
+				} = obj
+				if (this._checkMaxIndex(index)) {
+					this.tabbarConfig.list[index].dot = text
+					this._setTabbarStorage('tabbarConfig')
+				}
+			},
+			setTabBarItem(obj) {
+				const {
+					index,
+					text,
+					pagePath: newPagePath,
+					iconPath,
+					selectedIconPath
+				} = obj
+				const {
+					pagePath: oldPagePath
+				} = this.tabbarConfig.list[index]
+				if (this._checkMaxIndex(index)) {
+					this.tabbarConfig.list[index] = {
+						pagePath: newPagePath ? newPagePath : oldPagePath,
+						text,
+						iconPath,
+						selectedIconPath
+					}
+					this._setTabbarStorage('tabbarConfig')
+				}
+			},
+			showTabBar() {
+				this.isShowTabBar = true
+			},
+			hideTabBar() {
+				this.isShowTabBar = false
+			},
+			reload(){
+				this.initTabbarConfig = this._getDefaultTabbar()
+			},
+			_tabChange(index) {
+				const {
+					currentIndex
+				} = this
+				this.$emit('click', index)
+				if (index === currentIndex) {
+					return
+				}
+				this.beforeData = {
+					newIndex: index,
+					oldIndex: currentIndex,
+					next: this.jumpPage
+				}
+				if (this.beforeChange) {
+					this.beforeChange(this._jumpPage, index)
+				} else {
+					this._jumpPage()
+				}
+			},
+			_jumpPage() {
+				const {
+					native,
+					beforeData: {
+						newIndex: index
+					},
+					tabbarList: list
+				} = this
+				const {
+					pagePath: url,
+					openType
+				} = list[index]
+				if (url) {
+					if (native) {
+						uni.switchTab({
+							url
+						})
+					} else {
+						if (openType !== 'navigate') {
+							this.currentIndex = index
+						}
+						switch (openType) {
+							case 'navigate':
+								uni.navigateTo({
+									url
+								})
+								break;
+							case 'redirect':
+								uni.redirectTo({
+									url
+								})
+								break;
+							case 'reLaunch':
+								uni.reLaunch({
+									url
+								})
+								break;
+							case 'switchTab':
+								uni.switchTab({
+									url
+								})
+								break;
+							case 'navigateBack':
+								uni.navigateBack({
+									delta: 1
+								})
+								break;
+							default:
+								uni.reLaunch({
+									url
+								})
+						}
+					}
+				}
+				this.$emit('change', index)
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.m-tabbar-box {
+		position: relative;
+		z-index: 9999;
+	}
+
+	.m-tabbar {
+		position: relative;
+
+		&.fixed {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 100vw;
+		}
+
+		&__safe {
+			padding-bottom: env(safe-area-inset-bottom);
+		}
+	}
+
+	.m-tabbar__fill {
+		pointer-events: none;
+		opacity: 0;
+	}
+
+	.m-tabbar__flex {
+		display: flex;
+		flex-direction: row;
+	}
+
+	.m-tabbar__border {
+		background-color: rgba(0, 0, 0, 0.33);
+		width: 100%;
+		height: 1rpx;
+		transform: scaleY(0.5);
+	}
+
+	.m-tabbar__item {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		flex: 1;
+		padding: 4px 0 2px;
+	}
+
+	.m-tabbar__icon {
+		width: 48rpx;
+		height: 48rpx;
+		margin-bottom: 6rpx;
+		position: relative;
+
+		&_img {
+			display: block;
+			width: 100%;
+			height: 100%;
+		}
+
+		.m-tabbar__badge {
+			color: #fff;
+			background-color: #f00;
+			border-radius: 20rpx;
+			font-size: 22rpx;
+			position: absolute;
+			right: -25rpx;
+			left: 40rpx;
+			padding: 2rpx 0;
+			width: 100%;
+			text-align: center;
+			white-space: nowrap;
+		}
+	}
+
+	.m-tabbar__label {
+		font-size: 24rpx;
+	}
+</style>

+ 81 - 0
uni_modules/m-tabbar/package.json

@@ -0,0 +1,81 @@
+{
+  "id": "m-tabbar",
+  "displayName": "自定义tabbar、tabbar路由守卫、零配置tabbar、凸起导航",
+  "version": "2.0.0",
+  "description": "自定义tabbar,超高还原原生配置模式,一行代码自定义导航,自带tabbar路由守卫功能",
+  "keywords": [
+    "自定义tabbar,tabbar,自定义标签栏,tabbar路由守卫,零配置tabbar,路由守卫、凸起导航"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.5.4"
+  },
+  "dcloudext": {
+    "type": "component-vue",
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y",
+          "钉钉": "y",
+          "快手": "y",
+          "飞书": "y",
+          "京东": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        }
+      }
+    }
+  }
+}

+ 312 - 0
uni_modules/m-tabbar/readme.md

@@ -0,0 +1,312 @@
+# m-tabbar自定义
+
+
+## 使用说明,注意事项(必看)
+
+# 我配套上传了一个案例包,强烈建议下载阅读体验使用
+
+---
+
+> 1、自定义tabbar的情况下,不建议在一个页面内通过几个组件,用v-if切换去模拟各个页面,会存在各种不可控bug
+
+> 闪烁的话,可以使用一个页面,多个组件,如果是`if切换组件`的话,就是一个页面控制多个组件显示隐藏来实现。 如果组件封装的有问题,会出现组件之间的协调问题,请看情况使用。 还有一些原生的交互没有办法达到预期,会影响到原生体验。 比如下拉刷新,滚动加载更多,切换tabbar后滚动位置不能固定等
+
+>2、在pages.json中正常定义tabbar配置和字段,使用`native`模式,组件会自动加载pages.json配置项,并自动判断当前选中项,并自动隐藏原生的tabbar, 但是有个闪烁问题,暂时无解,如果你有好的方案,欢迎指正
+
+> 3、如果出现tabbar不显示,但是控制台无任何报错信息,应该就是样式布局影响了,请自行排查
+
+> 4、因为是自定义导航,所以原生方法是不支持的,只能通过 ref 可以获取到 tabbar 实例并调用插件的实例方法,详细请看页面最下方
+
+
+---
+# 快速使用
+
+## 方式一、Native模式使用
+
+```
+// native模式,无需配置其他项
+<m-tabbar native></m-tabbar>
+```
+在各个tabbar页面引入tabbar组件,传入属性`native`,`native`模式下无需任何配置
+
+组件会默认自动通过`uni.hideTabBar()`隐藏系统tabbar
+
+
+## 方式二、页面使用(current默认从0开始)(强烈推荐)
+
+```
+// 普通页面模式
+<m-tabbar fixed fill current="1" :tabbar="tabbar"></m-tabbar>
+```
+
+配置选项和`uniapp`的配置完全相同,直接复制过来, 默认传入`pagePath`后,直接使用`reLaunch`跳转
+插件支持扩展`openType`参数,用户可根据自己情况自行扩展页面打开方式,详细看下方配置
+
+> 闪烁的话,可以使用一个页面,多个组件,如果是`if切换组件`的话,就是一个页面控制多个组件显示隐藏来实现。 如果组件封装的有问题,会出现组件之间的协调问题,请看情况使用。 还有一些原生的交互没有办法达到预期,会影响到原生体验。 比如下拉刷新,滚动加载更多,切换tabbar后滚动位置不能固定等
+
+### 1、提取tabbar配置(2.0.0版本支持自动读取配置,主页面配置,内页可以不配置)
+
+新建文件config/tabbar.js(默认你有config目录,根据自己情况而定)
+```
+export default {
+	color: "#161616",
+	selectedColor: "#161616",
+	borderStyle: "black",
+	backgroundColor: "#ffffff",
+	list: [{
+		pagePath: "/pages/index/index",
+		iconPath: "/static/tabbar/index.png",
+		selectedIconPath: "/static/tabbar/index_active.png",
+		text: "首页",
+		openType: 'navigate',  //新版本新增,页面被打开方式,默认为reLaunch
+		dot: 1 //新版本新增参数,详细看页面最下方使用说明
+	}, {
+		pagePath: "/pages/shop/index",
+		iconPath: "/static/tabbar/shop.png",
+		selectedIconPath: "/static/tabbar/shop_active.png",
+		text: "门店"
+	}, {
+		pagePath: "/pages/my/index",
+		iconPath: "/static/tabbar/my.png",
+		selectedIconPath: "/static/tabbar/my_active.png",
+		text: "我的"
+	}]
+}
+```
+
+### 2、引入tabbar (2.0.0版本支持自动读取配置,主页面配置,内页可以不引入)
+#### VUE2引入
+```
+import TabbarConfig from '@/config/tabbar.js'
+export default {
+	data(){
+		return {
+			tabbar: TabbarConfig
+		}
+	},
+	onLoad(){
+		// 没有开启native模式下,使用reLaunch跳转,会存在首页标志,需要隐藏
+		#ifdef MP-JD || MP-WEIXIN
+		uni.hideHomeButton()
+		#endif
+	}
+}
+```
+
+####  VUE3 setup引入
+```
+import TabbarConfig from '@/config/tabbar.js'
+import { reactive } from 'vue'
+
+// 没有开启native模式下,使用reLaunch跳转,会存在首页标志,需要隐藏
+#ifdef MP-JD || MP-WEIXIN
+uni.hideHomeButton()
+#endif
+
+const tabbar = reactive(TabbarConfig)
+```
+
+### 3、页面使用
+```
+<m-tabbar fixed fill current="1" :tabbar="tabbar"></m-tabbar>
+```
+
+## 高级用法(beforeChange)(路由守卫)
+
+有些特殊需求,我们在点击一个tabbar其他一项的时候,可能需要判断权限是否可以进入,那么我们在切换前做一下路由拦截`beforeChange`,如果达到自己的预期,就进行跳转
+
+> uniapp 微信小程序不支持$listeners,只能使用prop方式传入, 部分平台不支持prop传入方法,有平台限制,详细请看(问题解答)[https://ask.dcloud.net.cn/question/70659]
+
+### 页面使用传入beforeChange
+
+```
+// native模式,无需传入 fixed fill
+<m-tabbar native :beforeChange="onBeforeChange"></m-tabbar>
+
+// 普通页面模式
+<m-tabbar fixed fill current="1" :tabbar="tabbar" :beforeChange="onBeforeChange"></m-tabbar>
+```
+
+### 进行事件判断监听
+
+函数必选参数 next,当判断逻辑执行完毕后,满足条件的情况下执行 `next()`
+
+```
+methods: {
+	onBeforeChange(next, index){
+    //index为当前点击的是第几项,0开始
+		console.log('before page2 switch')
+		setTimeout(()=>{
+			console.log('switch page2 end')
+			next()
+		}, 1000)
+	}
+}
+```
+
+## 自定义凸起导航(插槽使用)
+
+```
+<m-tabbar native>
+	<template v-slot:tabbar_index_1> //插槽详细看文档,样式你自己写
+		<view class="custom_style">
+			<view class="custom_style_icon">+</view>
+		</view>
+	</template>
+</m-tabbar>
+<style lang="scss">
+	.custom_style{
+		color: #fff;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		font-size: 24rpx;
+		&_icon{
+			background-color: #15357A;
+			font-size: 80rpx;
+			width: 120rpx;
+			height: 120rpx;
+			border-radius: 100%;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin-top: -40rpx;
+		}
+	}
+</style>
+```
+
+### 属性说明(Native模式)
+
+| 属性名       | 类型          | 默认值 | 必填 | 说明                                                                                                                                                                  |
+| ------------ | ------------- | ------ | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| zIndex       | Number,String | 999    | 否   | 当前处于z-index层级                                                                                                                                                   |
+| native       | Boolean       | false  | 否   | native模式,当前页面是系统原生tabbar页面(pages.json里面配置了tabBar)                                                                                                  |
+| beforeChange | Function      | null   | 否   | 导航切换前事件hooks,用于判断点击tabbar的时候,可以先执行自己定义的事件,达到预期后在跳转(类似router的路由守卫),方法需要调用next参数回调,部分平台不支持,存在兼容性 |
+| tabbarHeight | Number,String | 100    | 否   | 默认tabbar高度,有些时候你可能想控制tabbar高度(没啥用,如果非要更改,布局有影响,请使用样式覆盖)                                                                       |
+| name             |     string          |   custom      |  否     |     用于内部调用页面时,自动读取前一个页面的配置,无需二次配置     |
+
+### 属性说明(普通模式)
+
+| 属性名       | 类型          | 默认值 | 必填 | 说明                                                                                                                                                                  |
+| ------------ | ------------- | ------ | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| current      | Number,String | 0      | 是   | 默认选中第几项,0开始                                                                                                                                                  |
+| tabbar       | Object        | {}     | 是   | tabbar配置项(新增dot参数,详细看下方使用说明)                                                                                                                          |
+| fixed        | Boolean       | false  | 否   | 是否定位在底部                                                                                                                                                        |
+| fill         | Boolean       | false  | 否   | 是否填充底部高度(如果开启fixed后,会出现tabbar遮盖内容问题,开启此属性,会自动填充高度,可单独使用)                                                                 |
+| safeBottom   | Boolean       | true   | 否   | 是否自动规避iphoneX\XR等底部安全距离                                                                                                                                  |
+| zIndex       | Number,String | 999    | 否   | 当前处于z-index层级                                                                                                                                                   |
+| beforeChange | Function      | null   | 否   | 导航切换前事件hooks,用于判断点击tabbar的时候,可以先执行自己定义的事件,达到预期后在跳转(类似router的路由守卫),方法需要调用next参数回调,部分平台不支持,存在兼容性 |
+| tabbarHeight | Number,String | 100    | 否   | 默认tabbar高度,有些时候你可能想控制tabbar高度(没啥用,如果非要更改,布局有影响,请使用样式覆盖)                                                                       |
+| name             |     string          |   custom      |  否     |     用于内部调用页面时,自动读取前一个页面的配置,无需二次配置     |
+
+### openType对应值(默认reLaunch跳转)
+
+| 方法名 | 返回值说明 |
+| ------- | ------- | 
+|  navigate       |  [对应navigateTo](https://uniapp.dcloud.io/api/router?id=navigateto)    | 
+|  redirect       |  [对应redirectTo](https://uniapp.dcloud.io/api/router?id=redirectto)    |  
+|  reLaunch       |  [对应reLaunch](https://uniapp.dcloud.io/api/router?id=relaunch)    |  
+|  switchTab       |  [对应switchTab](https://uniapp.dcloud.io/api/router?id=switchtab) 注意此方法需要你有原生tabbar,比如内页使用了自定义导航,想回tabbar的指定页面    |  
+|  navigateBack       |  [对应navigateBack](https://uniapp.dcloud.io/api/router?id=navigateback) 只能后退一步   |  
+
+### 方法说明
+
+| 方法名 | 返回值说明 |
+| ------- | ------- | 
+|  click       |  当前选中index,无论什么情况下都会先触发click事件,方便自由定制更多方法    | 
+|  change       |  当前选中index(beforeChange会在change之前执行,只有执行next才会返回)    | 
+
+### 插槽 (注意Vue3存在跨断不兼容问题)
+
+| 插槽名 | 返回值说明 |
+| ------- | ------- | 
+|  tabbar_index_{index}       |  插槽名字为tabbar_index_你要变化的index, 可以做到任意控制自己的导航,比如中心凸起,比如你想让第一个变化,index就是0,比如你tabbarList里面有5个item,你想让中间的凸起,那么index就是2,取下标   | 
+
+### 方法 (通过 ref 可以获取到 tabbar 实例并调用实例方法)
+
+> 注意,由于是使用了自定义,所以原生的方法是不能使用的,只能通过 ref 可以获取到 tabbar 实例并调用实例方法,目前只有下面4个方法,而且方法是没有`success,fail,complete`回掉的,考虑到跨平台型,如果原生方法有平台差异,插件也是不考虑支持的
+
+| 事件名 | 参数 |  参数说明|
+| ------- | ------- | ------- | 
+|  setTabBarBadge   |   object  |  [为 tabBar 某一项的右上角添加文本](https://uniapp.dcloud.io/api/ui/tabbar?id=settabbarbadge)  |
+|  setTabBarItem   |   object  |  [动态设置 tabBar 某一项的内容](https://uniapp.dcloud.io/api/ui/tabbar?id=settabbaritem)  |
+|  reload      |    无  |  有特殊情况下,你可能需要调用重新载入tabbar配置,比如在内页进行了配置更新,返回前一个页面,自动读取前一个页面的配置  |
+|  showTabBar      |    无  |  显示tabbar,默认显示,无动画效果  |
+|  hideTabBar      |    无  |  隐藏tabbar,无动画效果  |
+
+
+```
+//页面调用组件添加ref
+<m-tabbar ref="tabbar" native></m-tabbar>
+// setTabBarBadge ,为 tabBar 某一项的右上角添加文本
+this.$refs.tabbar.setTabBarBadge({
+  index: 0,
+  text: '10'
+})
+
+//setTabBarItem 动态设置 tabBar 某一项的内容
+this.$refs.tabbar.setTabBarBadge({
+  index: 0,
+  text: 'text',
+  pagePath: 'newPagePath', 
+ //插件新增pagePath,注意native模式下,如果更改了pagePath,可能存在选中项自动选中失败问题
+  iconPath: '/path/to/iconPath',
+  selectedIconPath: '/path/to/selectedIconPath'
+})
+
+//如果直接在onload或者onshow等组件还在加载中的特殊情况下,由于加载比较慢,
+// 方法可能会失效,建议放在nextTick函数里面
+this.$nextTick(()=>{
+	this.$refs.tabbar.setTabBarBadge({
+	  index: 0,
+	  text: '10'
+	})
+})
+//reload重载整个组件
+this.$nextTick(()=>{
+				this.$refs.tabbar.reload()
+})
+```
+
+tabbarConfig参数新增dot配置项,可以单独配置每一项的右上角角标,可传入任意类型,不显示为空即可或者不填写, 默认为红色,如果想更改样式,请使用样式覆盖`m-tabbar__badge`
+```
+list: [{
+		pagePath: "/pages/index/index",
+		iconPath: "/static/tabbar/index.png",
+		selectedIconPath: "/static/tabbar/index_active.png",
+		text: "首页",
+		dot: 1
+	}, {
+		pagePath: "/pages/shop/index",
+		iconPath: "/static/tabbar/shop.png",
+		selectedIconPath: "/static/tabbar/shop_active.png",
+		text: "门店",
+		dot: ''
+	}, {
+		pagePath: "/pages/my/index",
+		iconPath: "/static/tabbar/my.png",
+		selectedIconPath: "/static/tabbar/my_active.png",
+		text: "我的",
+		dot: ''
+	}]
+```
+
+
+### 目前已知问题
+
+- 1、在全局加样式 filter: grayscale(1) 后,tabbar组件的fixed样式失效,排版在页面最底部(无法修复)
+- 2、微信小程序native模式首次进入的时候,底部tabbar会闪动一下(无法修复) 建议全局页面做一个延迟加载效果,等全部加载完成后,在显示
+
+
+### 插件写的时候,没办法照顾到所有平台,欢迎点评指正,如有问题欢迎给我留言
+
+#### 例如:
+```
+设备:iphone13 
+系统: ios13 
+使用环境平台: 微信小程序、app
+使用vue版本 :vue3
+问题描述: 提示什么什么错误
+```

+ 1 - 1
utils/request.js

@@ -29,7 +29,7 @@ service.interceptors.response(
 						}
 					})
 				} else {
-					if (res.msg != '系统出现异常') {
+					if (res.msg != '系统出现异常' && res.msg != '用户UID不能为空') {
 						uni.showToast({
 							title: res.msg,
 							duration: 1500,