caiyuqin 4 hónapja
szülő
commit
8eb584d753

+ 13 - 1
common/router/modules/routes.js

@@ -693,6 +693,18 @@ const routes = [{
 		meta: {
 			title: '我的团长',
 		},
-	}
+	},
+	{
+		//注意:path必须跟pages.json中的地址对应,最前面别忘了加'/'哦
+		path: '/pages/message/message',
+		name: 'message',
+		meta: {},
+	},
+	{
+		//注意:path必须跟pages.json中的地址对应,最前面别忘了加'/'哦
+		path: '/pages/message/details',
+		name: 'details',
+		meta: {},
+	},
 ]
 export default routes

+ 19 - 6
pages.json

@@ -456,6 +456,18 @@
 			"path": "pages/groupMeal/users/team-member",
 			"style": {}
 		},
+		{
+			"path": "pages/message/message",
+			"style": {
+				"navigationBarTitleText": "消息"
+			}
+		},
+		{
+			"path": "pages/message/details",
+			"style": {
+				"navigationBarTitleText": "消息详情"
+			}
+		},
 
 
 		// 广告---------------
@@ -499,18 +511,19 @@
 				"iconPath": "static/tabbar/index_tab.png",
 				"selectedIconPath": "static/tabbar/index_select_tab.png"
 			},
+			{ 
+				"text": "消息",
+				"pagePath": "pages/message/message",
+				"iconPath": "static/tabbar/msg_tab.png",
+				"selectedIconPath": "static/tabbar/msg_select_tab.png"
+			},
 			{
 				"text": "订单",
 				"pagePath": "pages/order/index",
 				"iconPath": "static/tabbar/order_tab.png",
 				"selectedIconPath": "static/tabbar/order_select_tab.png"
 			}
-			// { 
-			// 	"text": "消息",
-			// 	"pagePath": "pages/message/message",
-			// 	"iconPath": "static/tabbar/msg_tab.png",
-			// 	"selectedIconPath": "static/tabbar/msg_select_tab.png"
-			// },
+			
 			// {
 			// 	"text": "设置",
 			// 	"pagePath": "pages/my/my",

+ 187 - 0
pages/message/details.vue

@@ -0,0 +1,187 @@
+<template>
+  <view class="page-container">
+    <!-- 自定义导航栏 -->
+    <u-navbar :title="options.categoryName || '消息通知'" bgColor="#fff" :autoBack="true" :placeholder="true">
+    </u-navbar>
+
+    <view class="main-box">
+      <!-- 列表 -->
+      <view class="msg-list-card">
+        <ListScrollView ref="listScroll" :api="api" :init="initParams" :pageSize="20">
+          <template v-slot:list="{ data }">
+            <view class="msg-item" v-for="(item, i) in data" :key="i" @click="onDetail(item)">
+              <view class="msg-header-row">
+                <view class="title-with-dot">
+                  <text class="msg-title">{{ item.titleName }}</text>
+                  <view v-if="item.status === '0'" class="msg-dot"></view>
+                </view>
+              </view>
+              <view class="msg-divider"></view>
+              <view class="msg-desc">{{ item.content }}</view>
+              <view class="msg-time">{{ item.createTimeDisplay }}</view>
+            </view>
+          </template>
+        </ListScrollView>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import ListScrollView from '@/components/list-scroll-view/index.vue';
+import throttleUtil from '@/utils/public.js';
+import { USER_INFO } from "@/common/util/constants"
+export default {
+  components: {
+    ListScrollView
+  },
+  data() {
+    return {
+      api: {
+        url: '/localUserNotice/localUserNotice/getPageListNew',
+        method: 'POST',
+      },
+      initParams: {
+        userType: 1,
+        category: null
+      },
+      indexOption: null,
+      merchantId: null
+    };
+  },
+  onLoad(options) {
+    // 接收参数
+    if (options) {
+      this.initParams.category = options.category
+
+    }
+    this.initData()
+  },
+  methods: {
+    async initData() {
+      this.merchantId = uni.getStorageSync(USER_INFO).merchantId;
+      let res = await this.$http.get("/merchant/localMerchantInfo/queryAppInfoById?id=" + this.merchantId)
+      if (res.data.success) {
+        this.indexOption = res.data.result
+      }
+    },
+    // 点击消息详情
+    onDetail: throttleUtil.throttles(async function (item) {
+      if (item.status === '0') {
+        this.$http.post("/localUserNotice/localUserNotice/edit", {
+          id: item.id,
+          status: '1'
+        }).then(res => {
+          item.status = '1';
+        })
+      }
+      this.navigateToDetail(item);
+    }, 500), 
+    // 跳转详情页面
+    navigateToDetail(item) {
+      const queryString = encodeURIComponent(JSON.stringify(this.indexOption))
+      let routeMap = {
+        // 消息类
+        'S1': `/pages/login/settled?params=${queryString}`, //店铺信息审核结果
+        'S2': `/pages/store/brandMessage?params=${queryString}`, //品牌信息审核结果
+        'S3': `/pages/store/advertising?params=${queryString}`, //广告素材审核结果
+        'S4': `/pages/store/headPhoto?params=${queryString}`, //商户照片审核结果
+        'S5': '/pages/store/businessQua?params=${queryString}', //经营资质审核结果
+        'S6': '/pages/product/index?type=0', // 商品审核结果通过
+        'S7': '/pages/product/index?type=3', // 商品审核结果不通过
+        'S8': '/pages/store/settings', //店铺设置页面 
+        'O1': ``, //核销成功 不跳转
+        'O4': `/pages/groupMeal/goods/list`, //拼团成功
+      };
+
+      if (item.type === 'O2' || item.type === 'O3') {
+        const isService = item.isService == 1;
+        const url = isService
+          ? `/pages/order/serviceOrder/orderDetail?taskId=${item.businessId}&checkType=${item.checkType}&rightsId=''`
+          : `/pages/order/record?orderId=${item.businessId}`;
+        uni.navigateTo({ url });
+        return;
+      }
+      if (item.type === 'O5') {
+        const app = getApp();
+        app.globalData.currentIndex = 1
+        app.globalData.tabIndex = 1
+        uni.switchTab({
+          url: `/pages/order/index`//待接单提醒
+        })
+      }
+      if (routeMap[item.type]) {
+        uni.navigateTo({
+          url: routeMap[item.type]
+        });
+      }
+    },
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background: #f8f8fa;
+
+  .main-box {
+    flex: 1;
+    margin: 30rpx;
+    border-radius: 16rpx;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+  }
+}
+
+.msg-list-card {
+  flex: 1;
+  overflow: hidden;
+  background-color: #f8f8fa;
+
+  .msg-item {
+    background: #ffffff;
+    border-radius: 17rpx;
+    padding: 20rpx;
+    margin-bottom: 25rpx;
+    .msg-header-row {
+      margin-bottom: 16rpx;
+      .title-with-dot {
+        display: flex;
+        align-items: center;
+        .msg-title {
+          font-size: 28rpx;
+          font-weight: 500;
+          color: #333;
+        }
+        .msg-dot {
+          width: 13rpx;
+          height: 13rpx;
+          background: #ff004e;
+          border-radius: 50%;
+          margin-left: 10rpx;
+        }
+      }
+    }
+    .msg-divider {
+      width: 100%;
+      height: 1rpx;
+      background: #eeeeee;
+      margin-bottom: 16rpx;
+    }
+    .msg-desc {
+      font-size: 24rpx;
+      color: #666;
+      line-height: 1.5;
+      margin-bottom: 12rpx;
+    }
+    .msg-time {
+      font-size: 24rpx;
+      color: #666;
+    }
+  }
+}
+</style>

+ 124 - 0
pages/message/message.vue

@@ -0,0 +1,124 @@
+<template>
+  <view class="msg-container">
+    <u-navbar title="消息" :autoBack="true" :placeholder="true"></u-navbar>
+    <view class="msg-list">
+      <view class="msg-item" v-for="(item, idx) in msgList" :key="idx" @click="toNotification(item)">
+        <view class="msg-header-row">
+          <view class="msg-icon-container">
+            <image :src="`/static/message/${categoryIcons[item.category] || 'system'}.png`" class="icon-img"></image>
+          </view>
+          <view class="title-with-dot">
+            <text class="msg-title">{{ item.categoryName }}</text>
+            <view v-if="item.status === '0'" class="msg-dot"></view>
+          </view>
+          <text class="msg-time">{{ item.createTimeDisplay }}</text>
+        </view>
+        <view class="msg-divider"></view>
+        <text class="msg-desc">{{ item.content }}</text>
+      </view>
+    </view>
+    <u-empty text="暂无消息" mode="list" v-if="!msgList.length"></u-empty>
+  </view>
+</template>
+
+<script>
+
+
+export default {
+  data() {
+    return {
+      msgList: [],
+      categoryIcons: {
+        '1': 'market',
+        '2': 'order',
+        '3': 'system'
+      }
+    }
+  },
+  async onShow() {
+    this.getMsgList();
+  },
+  methods: {
+    // 获取消息
+    async getMsgList() {
+      this.$http.get("/localUserNotice/localUserNotice/getListNew", {
+        params: {
+          userType: 1
+        }
+      }).then(res => {
+        this.msgList = res.data.result || [];
+      })
+    },
+    // 跳转到通知二级页
+    toNotification(item) {
+      let str = this.$u.queryParams(item);
+      uni.navigateTo({
+        url: `/pages/message/details?${str}`
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.msg-list {
+  padding: 25rpx;
+  .msg-item {
+    background: #fff;
+    border-radius: 17rpx;
+    padding: 20rpx 20rpx 16rpx 20rpx;
+    margin-bottom: 25rpx;
+    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
+    .msg-header-row {
+      display: flex;
+      align-items: center;
+      margin-bottom: 16rpx;
+      .msg-icon-container {
+        margin-right: 16rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .icon-img {
+          width: 36rpx;
+          height: 42rpx;
+        }
+      }
+      .title-with-dot {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        .msg-title {
+          font-size: 28rpx;
+          font-weight: 500;
+          color: #333;
+        }
+        .msg-dot {
+          width: 13rpx;
+          height: 13rpx;
+          background: #ff004e;
+          border-radius: 50%;
+          margin-left: 10rpx;
+        }
+      }
+      .msg-time {
+        font-size: 25rpx;
+        color: #666666;
+        margin-left: 16rpx;
+      }
+    }
+    .msg-divider {
+      width: 100%;
+      height: 1rpx;
+      background: #eeeeee;
+      margin-bottom: 16rpx;
+    }
+    .msg-desc {
+      font-size: 24rpx;
+      color: #666;
+      line-height: 1.5;
+    }
+  }
+}
+</style>
+
+

+ 5 - 0
pages/order/index.vue

@@ -1005,6 +1005,11 @@
 					that.getserviceList(page)
 				}
 			})
+			const app = getApp();
+      this.currentIndex=app.globalData.currentIndex
+			this.tabIndex=app.globalData.tabIndex
+			app.globalData.currentIndex=''
+			app.globalData.tabIndex=''
 		},
 	}
 </script>

+ 3 - 1
pages/product/index.vue

@@ -26,7 +26,6 @@
 				<span class="cuIcon-search"></span>
 				<!-- <input @blur="InputBlur" :adjust-position="false" type="text" placeholder="请输入关键词" confirm-type="search"> -->
 				<u-input v-model="productName" />
-				</input>
 				<view class="search_btn" @click.stop="getProductList()">
 					<span></span>搜索
 				</view>
@@ -232,6 +231,9 @@ export default {
 			delistList: [] //下架商品集合
 		}
 	},
+	onLoad(option) {
+      this.currentIndex=option.type || 0
+		},
 	methods: {
 		//返回
 		back() {

+ 3 - 2
pages/store/settings.vue

@@ -4,7 +4,7 @@
 			<block slot="content">店铺设置</block>
 		</cu-custom> -->
 		<view class="top"></view>
-		<view class="head">
+		<!-- <view class="head">
 			<view class="handle">
 				<view class="head_left">
 					<span class="cuIcon-back" @click="back"></span>
@@ -13,7 +13,8 @@
 				<view class="head_right">
 				</view>
 			</view>
-		</view>
+		</view> -->
+		<u-navbar title="店铺设置" :autoBack="true" :placeholder="true"></u-navbar>
 		<view class="bg-fff" v-for="ele in ulList" :key="ele.name">
 			<view class=" cu-form-group" :style="ele.name == '基本信息' ? 'margin-top:0' : ''">
 				<view class="content ">

+ 3 - 1
plugin/colorui/main.css

@@ -3975,4 +3975,6 @@ scroll-view.cu-steps .cu-item {
 	display: flex;
 	align-items: center;
 	justify-content: space-between;
-}
+}
+
+

BIN
static/message/order.png


BIN
static/message/system.png


+ 11 - 1
style/zcm-main.css

@@ -1214,4 +1214,14 @@ body {
 
 .pr-5 {
 	padding-right: 50upx;
-}
+}
+
+::v-deep .uicon-nav-back{
+	color:#000 !important;
+	font-weight: bold !important;
+	}
+::v-deep .u-title{
+	color:#000 !important;
+	font-weight: 500;
+	font-size: 36rpx !important;
+}

+ 373 - 0
utils/public.js

@@ -0,0 +1,373 @@
+
+// 日期格式化原型扩展(单独维护)
+Date.prototype.Format = function (fmt) {
+	const o = {
+		"M+": this.getMonth() + 1, // 月份
+		"D+": this.getDate(), // 日
+		"h+": this.getHours(), // 小时
+		"m+": this.getMinutes(), // 分
+		"s+": this.getSeconds(), // 秒
+		"q+": Math.floor((this.getMonth() + 3) / 3), // 季度
+		"S": this.getMilliseconds() // 毫秒
+	};
+	if (/(Y+)/.test(fmt)) {
+		fmt = fmt.replace(
+			RegExp.$1,
+			(this.getFullYear() + "").substr(4 - RegExp.$1.length)
+		);
+	}
+	for (const k in o) {
+		if (new RegExp(`(${k})`).test(fmt)) {
+			fmt = fmt.replace(
+				RegExp.$1,
+				RegExp.$1.length === 1
+					? o[k]
+					: (`00${o[k]}`).substr((o[k] + "").length)
+			);
+		}
+	}
+	return fmt;
+};
+
+// 路由相关工具方法
+const routerUtil = {
+	navTo(url) {
+		if (!url) return;
+		uni.navigateTo({ url });
+	},
+
+	switchTo(url) {
+		uni.switchTab({ url });
+	},
+
+	reLaunchTo(url) {
+		uni.reLaunch({ url });
+	},
+
+	meRouter(option) {
+		const type = parseInt(option.jump || 0);
+		switch (type) {
+			case 1:
+				this.navTo(`/pages/activity/lifeDetail?id=${option.jump_address}`);
+				break;
+			case 2:
+				this.navTo(`/pages/activity/newsDetail?id=${option.jump_address}`);
+				break;
+			default:
+				break;
+		}
+	}
+};
+
+// 图片相关工具方法
+const imageUtil = {
+	showPic(arr, index) {
+		uni.previewImage({
+			indicator: "none",
+			current: index,
+			urls: arr
+		});
+	},
+
+	save(imgs) {
+		uni.downloadFile({
+			url: imgs,
+			success: res => {
+				if (res.statusCode === 200) {
+					uni.saveImageToPhotosAlbum({
+						filePath: res.tempFilePath,
+						success: () => this.$u.toast('保存下载成功'),
+						fail: () => this.$u.toast('保存失败,请稍后重试')
+					});
+				} else {
+					this.tools.toast('下载失败');
+				}
+			}
+		});
+	}
+};
+
+// 数据格式化工具方法
+const formatUtil = {
+	formatTime(time, pattern) {
+		// uview:  uni.$u.date('1585926095536', 'yyyy-mm')
+		// 过滤器: '1585926095536' | date('yyyy-mm')
+		const times = time * 1000;
+		let d = new Date(times).Format("YYYY-MM-DD hh:mm:ss");
+		if (pattern) {
+			d = new Date(times).Format(pattern);
+		}
+		return d.toLocaleString();
+	},
+	// 格式化距离
+	formatDistance(value) {
+		if (value == null) return '-';
+		const numValue = parseFloat(value);
+		if (isNaN(numValue)) return '无效距离';
+
+		if (numValue < 0.001) return '<1m';
+		if (numValue < 1) return `${Math.round(numValue * 1000)}m`;
+
+		return numValue % 1 === 0
+			? `${numValue}km`
+			: `${numValue.toFixed(2)}km`;
+	},
+	// 格式化销售数
+	formatSales(sales) {
+		if (typeof sales !== 'number' || !isFinite(sales)) return '0';
+		// 处理负数
+		sales = Math.max(0, Math.floor(sales));
+
+		if (sales < 100) return `${sales}`;
+		if (sales < 1000) return `${Math.floor(sales / 100) * 100}+`;
+		if (sales < 10000) return `${Math.floor(sales / 1000)}k+`;
+		return '1w+';
+	},
+	// 格式化评价星数
+	formatRating(val) {
+		if (val >= 4.5) return "超赞";
+		if (val >= 4.0) return "满意";
+		if (val >= 3.0) return "一般";
+		if (val >= 2.0) return "不满意";
+		return "非常差";
+	},
+	// 格式化数额差值
+	formatSubtract(num1, num2) {
+		const len1 = (num1.toString().split('.')[1] || '').length;
+		const len2 = (num2.toString().split('.')[1] || '').length;
+		const base = Math.pow(10, Math.max(len1, len2));
+		return (Math.round(num1 * base) - Math.round(num2 * base)) / base;
+	},
+};
+
+// 节流工具方法
+const throttleUtil = {
+	// 基础节流
+	throttle(func, wait = 500, immediate = false) {
+		let timeout = null;
+		return function (...args) {
+			if (timeout !== null) clearTimeout(timeout);
+
+			if (immediate) {
+				const callNow = !timeout;
+				timeout = setTimeout(() => {
+					timeout = null;
+				}, wait);
+				if (callNow) func && func.apply(this, args);
+			} else {
+				timeout = setTimeout(() => {
+					func && func.apply(this, args);
+				}, wait);
+			}
+		};
+	},
+	// 高级节流(带配置项)
+	throttles(func, delay, options = {}) {
+		let lastTime = 0;
+		let timer = null;
+		const { leading = true, trailing = true } = options;
+
+		return function (...args) {
+			const now = Date.now();
+			if (!lastTime && !leading) lastTime = now;
+
+			const remaining = delay - (now - lastTime);
+			if (remaining <= 0) {
+				if (timer) {
+					clearTimeout(timer);
+					timer = null;
+				}
+				lastTime = now;
+				func.apply(this, args);
+			} else if (!timer && trailing) {
+				timer = setTimeout(() => {
+					lastTime = !leading ? 0 : Date.now();
+					timer = null;
+					func.apply(this, args);
+				}, remaining);
+			}
+		};
+	}
+};
+
+// 其他工具方法
+const otherUtil = {
+	makePhoneCall(phone) {
+		if (phone) {
+			console.log(typeof phone, phone)
+			uni.makePhoneCall({ phoneNumber: phone });
+		}
+	},
+	// 以token判断是否登录
+	checkLogin(options = {}) {
+		const {
+			type,
+			modalText = '请登录账号后再操作',
+		} = options;
+
+		const token = uni.getStorageSync('token') || '';
+		const expireTime = uni.getStorageSync("expireTime");
+		const now = Date.now();
+		const isLogin = !!token && expireTime > now;
+		
+		// 后退参数
+		let str = uni.$u.queryParams({ isBack: 1 });
+		// 跳转路由
+		let path = `/packageF/pages/login/login${str}`;
+		// #ifdef MP-WEIXIN
+		path = `/packageF/pages/login/wxLogin${str}`;
+		// #endif
+
+		// 未登录时,根据 type 执行对应操作
+		if (!isLogin) {
+			switch (type) {
+				case 'reLaunch':
+					uni.reLaunch({
+						url: path,
+						success: () => {
+							console.log('未登录,已跳转至登录页');
+						}
+					});
+					break;
+
+				case 'navigate':
+					// 跳转登录页(带返回跳转,可返回原页面)
+					uni.navigateTo({
+						url: path,
+						success: () => {
+							console.log('未登录,已跳转至登录页');
+						}
+					});
+					break;
+			
+				case 'modal':
+					// 弹窗提示,确认后跳转登录页
+					uni.showModal({
+						title: '温馨提示',
+						content: modalText,
+						confirmText: '前往登录',
+						confirmColor: '#0879FF',
+						success: (res) => {
+							if (res.confirm) {
+								uni.navigateTo({ url: path });
+							}
+						}
+					});
+					break;
+			
+				// 默认:仅返回登录状态,不执行额外操作
+				default:
+					console.log('未登录,仅返回登录状态');
+					break;
+			}
+		}
+		return isLogin;
+	},
+
+	// 获取多级对象的长链
+	getProp(obj, path, defaultValue = '') {
+		const keys = path.split('.');
+		let result = obj;
+		for (const key of keys) {
+			if (result && typeof result === 'object' && key in result) {
+				result = result[key];
+			} else {
+				return defaultValue;
+			}
+		}
+		return result;
+	},
+	// 获取多图拼接的值
+	getSplitImg(e, index = 0) {
+		// 先处理原始数据:若e为空,返回空数组
+		if (!e || typeof e !== 'string') {
+		  	return [];
+		}
+	  
+		// 分割图片字符串为数组
+		const imgArr = e.split(',');
+	  
+		// 判断index是否为null/undefined(用户传空时),返回完整数组
+		if (index === null || index === undefined) {
+		  	return imgArr;
+		}
+	  
+		// 处理索引:确保是整数,且在有效范围内(0 <= index < 数组长度)
+		const validIndex = Math.floor(Number(index)); // 转为整数(避免传入字符串/小数)
+		if (isNaN(validIndex) || validIndex < 0 || validIndex >= imgArr.length) {
+		  	return ''; // 索引无效时,返回空字符串(避免显示错误图片)
+		}
+	  
+		// 返回指定索引的图片URL
+		return imgArr[validIndex];
+	},
+	//判断是安装了支付宝
+	isAlipayConfig() {
+		const params = {
+			pname: 'com.eg.android.AlipayGphone',
+			action: 'alipay://'
+		};
+		// 判断是否安装支付宝
+		if (!plus.runtime.isApplicationExist(params)) {
+			uni.$u.toast('未检测到支付宝,请安装后重试');
+			return false
+		}else{
+			return true
+		}
+	},
+	//判断是安装了微信
+	isWechatConfig() {
+		const params = {
+			pname: 'com.tencent.mm',
+			action: 'weixin://'
+		};
+		// 判断是否安装支付宝
+		if (!plus.runtime.isApplicationExist(params)) {
+			uni.$u.toast('未检测到微信,请安装后重试');
+			return false
+		}else{
+			return true
+		}
+	},
+
+	
+	
+	/* 
+	 会员部分使用
+	 */
+	// 转json
+	getConfigJson(item) {
+		// 先判断是否有值,避免null/undefined
+		if (!item || !item.configJson) {
+			return null;
+		}
+		// 防止JSON格式错误导致报错
+		try {
+			return JSON.parse(item.configJson);
+		} catch (e) {
+			console.error('解析configJson失败:', e);
+			return null;
+		}
+	},
+	// 获取 configJson 类型
+	getConfigType(item) {
+		const cfg = this.getConfigJson(item);
+		if (!cfg) return null;
+		return cfg;
+	},
+	// 安全取值,空时返回 ''
+	getConfigVal(item, key) {
+		const cfg = this.getConfigJson(item);
+		if (!cfg || cfg[key] == null || cfg[key] === '') return '';
+		return cfg[key];
+	},
+};
+
+// 组合导出
+export default {
+	...routerUtil,
+	...imageUtil,
+	...formatUtil,
+	...throttleUtil,
+	...otherUtil,
+};