Переглянути джерело

优化uview组件代码;
修改uview相关引入路径;

郭鹏飞 11 місяців тому
батько
коміт
69d2d30072

+ 1 - 1
App.vue

@@ -1,5 +1,5 @@
 <style lang="scss">
-		@import "uview-ui/index.scss";
+		@import "@/uni_modules/uview-ui/index.scss";
 </style>
 <script>
 	import Vue from 'vue'

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

@@ -605,7 +605,41 @@ const routes = [{
 		meta: {
 			title: '订单明细',
 		},
+	},
+	{
+		path: '/pages/groupMeal/users/index',
+		name: 'groupMealUsersIndex',
+		meta: {
+			title: '设置首页',
+		},
+	},
+	{
+		path: '/pages/groupMeal/users/settings',
+		name: 'groupMealUsersSettings',
+		meta: {
+			title: '团餐设置',
+		},
+	},
+	{
+		path: '/pages/groupMeal/users/withdrawal',
+		name: 'groupMealUsersWithdrawal',
+		meta: {
+			title: '提现',
+		},
+	},
+	{
+		path: '/pages/groupMeal/users/bankCard-list',
+		name: 'groupMealUsersBankCardList',
+		meta: {
+			title: '银行卡列表',
+		},
+	},
+	{
+		path: '/pages/groupMeal/users/bankCard-edit',
+		name: 'groupMealUsersBankCardEdit',
+		meta: {
+			title: '银行卡编辑',
+		},
 	}
-	
 ]
 export default routes

+ 1 - 1
main.js

@@ -1,5 +1,5 @@
 import Vue from 'vue'
-import uView from "uview-ui";
+import uView from "@/uni_modules/uview-ui";
 Vue.use(uView);
 import App from './App'
 import store from './store'

+ 20 - 0
pages.json

@@ -421,6 +421,26 @@
 		{
 			"path": "pages/groupMeal/orders/order-details",
 			"style": {}
+		},
+		{
+			"path": "pages/groupMeal/users/index",
+			"style": {}
+		},
+		{
+			"path": "pages/groupMeal/users/settings",
+			"style": {}
+		},
+		{
+			"path": "pages/groupMeal/users/withdrawal",
+			"style": {}
+		},
+		{
+			"path": "pages/groupMeal/users/bankCard-list",
+			"style": {}
+		},
+		{
+			"path": "pages/groupMeal/users/bankCard-edit",
+			"style": {}
 		}
 	],
 	"globalStyle": {

+ 171 - 134
pages/groupMeal/goods/form-step2.vue

@@ -2,85 +2,87 @@
 	<view class="page-container">
 		<u-navbar title="新建团餐" :autoBack="true" :placeholder="true"></u-navbar>
 		
-		<u-collapse ref="collapseRef"
-			:value="activeNames" 
-			@change="onCollapseChange">
-			<u-collapse-item
-				:class="{
-					active: activeNames == category.id
-				}"
-				v-for="(category, index) in dishCategories"
-				:key="category.id"
-				:name="category.id"
-				@click="onClick"
-			>
-				<view slot="title" class="collapse-title">
-					<text>{{ category.name }}</text>
-					<u-switch 
-						v-if="false"
-						size="20"
-						activeColor="#3c9cff"
-						:value="category.isActive" 
-						@change="onSwitchChange($event, category.id)" 
-					></u-switch>
-				</view>
-				
-				<view class="collapse-content">
-					<view class="dish-item" v-for="(dish, dishIndex) in category.items" :key="dish.id">
-						<view class="dish-header">
-							<view class="dish-title">
-								<u-image width="32rpx" height="32rpx" src="/static/icon/icon_edit.png"></u-image>
-								<text>{{ category.name }}{{ dishIndex + 1 }}</text>
+		<u-form :model="form" :rules="rules" ref="formRef" :error-type="['toast', 'border-bottom']">
+			<u-collapse ref="collapseRef"
+				:value="activeNames" 
+				@change="onCollapseChange">
+				<u-collapse-item
+					:class="{
+						active: activeNames == category.id
+					}"
+					v-for="(category, catIndex) in form.dishCategories"
+					:key="category.id"
+					:name="category.id"
+					@click="onClick"
+				>
+					<view slot="title" class="collapse-title">
+						<text>{{ category.name }}</text>
+						<u-switch 
+							v-if="false"
+							size="20"
+							activeColor="#3c9cff"
+							:value="category.isActive" 
+							@change="onSwitchChange($event, category.id)" 
+						></u-switch>
+					</view>
+					
+					<view class="collapse-content">
+						<view class="dish-item" v-for="(dish, dishIndex) in category.items" :key="dish.id">
+							<view class="dish-header">
+								<view class="dish-title">
+									<u-image width="32rpx" height="32rpx" src="/static/icon/icon_edit.png"></u-image>
+									<text>{{ category.name }}{{ dishIndex + 1 }}</text>
+								</view>
+								<view class="dish-actions">
+									<u-button v-if="dishIndex === category.items.length - 1" 
+										type="primary" size="mini"
+										hover-class="none"
+										:custom-style="{
+											color: '#2D88F4',
+											border: '1rpx solid #2D88F4',
+											background: 'rgba(45,136,244,0.1)',
+										}"		
+										@click="addDish(category.id)"
+									>
+										<view class="text">
+											<u-image width="32rpx" height="32rpx" src="/static/icon/icon_plus.png"></u-image>
+											<text>添加</text>
+										</view>
+									</u-button>
+									<u-button v-if="category.items.length > 1" 
+										type="error" size="mini"
+										hover-class="none"
+										:custom-style="{
+											color: '#FF6067',
+											border: '1rpx solid #FF6067',
+											background: 'rgba(255,96,103,0.1)',
+										}"	
+										@click="removeDish(category.id, dish.id)"
+									>
+										<view class="text">
+											<u-image width="32rpx" height="32rpx" src="/static/icon/icon_del.png"></u-image>
+											<text>删除</text>
+										</view>
+									</u-button>
+								</view>
 							</view>
-							<view class="dish-actions">
-								<u-button v-if="dishIndex === category.items.length - 1" 
-									type="primary" size="mini"
-									hover-class="none"
-									:custom-style="{
-										color: '#2D88F4',
-										border: '1rpx solid #2D88F4',
-										background: 'rgba(45,136,244,0.1)',
-									}"		
-									@click="addDish(category.id)"
-								>
-									<view class="text">
-										<u-image width="32rpx" height="32rpx" src="/static/icon/icon_plus.png"></u-image>
-										<text>添加</text>
-									</view>
-								</u-button>
-								<u-button v-if="category.items.length > 1" 
-									type="error" size="mini"
-									hover-class="none"
-									:custom-style="{
-										color: '#FF6067',
-										border: '1rpx solid #FF6067',
-										background: 'rgba(255,96,103,0.1)',
-									}"	
-									@click="removeDish(category.id, dish.id)"
-								>
-									<view class="text">
-										<u-image width="32rpx" height="32rpx" src="/static/icon/icon_del.png"></u-image>
-										<text>删除</text>
-									</view>
-								</u-button>
+							<view class="dish-form">
+								<u-form-item label="名称" :prop="`dishCategories.${catIndex}.items.${dishIndex}.name`" :required="isEdited(dish)">
+									<u-input v-model="dish.name" height="41" placeholder="请输入" inputAlign="right"></u-input>
+								</u-form-item>
+								<u-form-item label="价格" :prop="`dishCategories.${catIndex}.items.${dishIndex}.price`" :required="isEdited(dish)">
+									<u-input v-model="dish.price" type="digit" height="41" placeholder="输入金额" :clearable="false" inputAlign="right"></u-input>
+									<text slot="right" style="color: #333333;">元</text>
+								</u-form-item>
+								<u-form-item label="描述" :prop="`dishCategories.${catIndex}.items.${dishIndex}.description`" :required="isEdited(dish)">
+									<u-input v-model="dish.description" height="41" placeholder="请描述菜品的使用素材" inputAlign="right"></u-input>
+								</u-form-item>
 							</view>
 						</view>
-						<view class="dish-form">
-							<u-form-item label="名称">
-								<u-input v-model="dish.name" height="41" placeholder="请输入" inputAlign="right"></u-input>
-							</u-form-item>
-							<u-form-item label="价格">
-								<u-input v-model="dish.price" type="digit" height="41" placeholder="输入金额" :clearable="false" inputAlign="right"></u-input>
-								<text slot="right" style="color: #333333;">元</text>
-							</u-form-item>
-							<u-form-item label="描述" :borderBottom="false">
-								<u-input v-model="dish.description" height="41" placeholder="请描述菜品的使用素材" inputAlign="right"></u-input>
-							</u-form-item>
-						</view>
 					</view>
-				</view>
-			</u-collapse-item>
-		</u-collapse>
+				</u-collapse-item>
+			</u-collapse>
+		</u-form>
 
 		<view class="footer-bar">
 			<u-button 
@@ -113,61 +115,97 @@ let dishIdCounter = 100; // 简单的唯一ID生成器
 export default {
 	data() {
 		return {
-			// 模拟菜品分类和菜品数据
-			dishCategories: [
-				{
-					id: 1,
-					name: '荤菜',
-					isActive: false,
-					items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
-				},
-				{
-					id: 2,
-					name: '素菜',
-					isActive: false,
-					items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
-				},
-				{
-					id: 3,
-					name: '主食',
-					isActive: false,
-					items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
-				},
-				{
-					id: 4,
-					name: '汤',
-					isActive: false,
-					items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
-				},
-				{
-					id: 5,
-					name: '其他',
-					isActive: false,
-					items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
-				}
-			],
+			// 数据
+			form: {
+				dishCategories: [
+					{
+						id: 1,
+						name: '荤菜',
+						isActive: false,
+						items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
+					},
+					{
+						id: 2,
+						name: '素菜',
+						isActive: false,
+						items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
+					},
+					{
+						id: 3,
+						name: '主食',
+						isActive: false,
+						items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
+					},
+					{
+						id: 4,
+						name: '汤',
+						isActive: false,
+						items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
+					},
+					{
+						id: 5,
+						name: '其他',
+						isActive: false,
+						items: [{ id: dishIdCounter++, name: '', price: '', description: '' }]
+					}
+				],
+			},
+			rules: {},
 			activeNames: [1], // 控制折叠面板展开的name数组
 		};
 	},
+	watch: {
+		'form.dishCategories': {
+			handler() {
+				this.$nextTick(() => {
+					this.updateValidationRules();
+				});
+			},
+			deep: true
+		}
+	},
+	mounted() {
+		this.$nextTick(() => {
+			this.$refs.formRef.setRules(this.rules);
+		});
+	},
 	methods: {
+		// 判断一个菜品是否被编辑过
+		isEdited(dish) {
+			return !!(dish.name || dish.price || dish.description);
+		},
+		updateValidationRules() {
+			if (!this.$refs.formRef) return;
+			
+			const newRules = {};
+			this.form.dishCategories.forEach((category, catIndex) => {
+				category.items.forEach((dish, dishIndex) => {
+					if (this.isEdited(dish)) {
+						// 如果菜品的任一字段被填写,则所有字段都变为必填
+						const nameProp = `dishCategories.${catIndex}.items.${dishIndex}.name`;
+						const priceProp = `dishCategories.${catIndex}.items.${dishIndex}.price`;
+						const descProp = `dishCategories.${catIndex}.items.${dishIndex}.description`;
+						
+						newRules[nameProp] = [{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }];
+						newRules[priceProp] = [{ required: true, message: '请输入价格', trigger: ['blur', 'change'] }];
+						newRules[descProp] = [{ required: true, message: '请输入描述', trigger: ['blur', 'change'] }];
+					}
+				});
+			});
+			
+			this.rules = newRules;
+			this.$refs.formRef.setRules(this.rules);
+		},
 		// Switch开关状态变化
 		onSwitchChange(isActive, categoryId) {
-			const category = this.dishCategories.find(c => c.id === categoryId);
-			if (category) {
-				category.isActive = isActive;
-				
-				// 联动折叠面板
-				if (isActive) {
-					// 如果是打开,且当前未展开,则添加到activeNames
-					if (!this.activeNames.includes(categoryId)) {
-						this.activeNames.push(categoryId);
-					}
-				} else {
-					// 如果是关闭,从activeNames中移除
-					const index = this.activeNames.indexOf(categoryId);
-					if (index > -1) {
-						this.activeNames.splice(index, 1);
-					}
+			const index = this.activeNames.indexOf(categoryId);
+			if (isActive) {
+				if (index === -1) {
+					this.activeNames.push(categoryId);
+				}
+			} else {
+				if (index > -1) {
+					this.activeNames.splice(index, 1);
 				}
 			}
 		},
@@ -175,14 +213,10 @@ export default {
 		onCollapseChange(names) {
 			console.log(names)
 			this.activeNames = names;
-			// 反向联动Switch
-			// this.dishCategories.forEach(category => {
-			// 	category.isActive = names.includes(category.id);
-			// });
 		},
 		// 添加菜品
 		addDish(categoryId) {
-			const category = this.dishCategories.find(c => c.id === categoryId);
+			const category = this.form.dishCategories.find(c => c.id === categoryId);
 			if (category) {
 				category.items.push({
 					id: dishIdCounter++,
@@ -194,7 +228,7 @@ export default {
 		},
 		// 删除菜品
 		removeDish(categoryId, dishId) {
-			const category = this.dishCategories.find(c => c.id === categoryId);
+			const category = this.form.dishCategories.find(c => c.id === categoryId);
 			if (category && category.items.length > 1) {
 				const index = category.items.findIndex(d => d.id === dishId);
 				if (index > -1) {
@@ -208,9 +242,12 @@ export default {
 		},
 		// 提交审核
 		submit() {
-			const activeCategories = this.dishCategories.filter(c => c);
-			console.log('提交的数据:', activeCategories);
-			uni.showToast({ title: '提交成功', icon: 'success' });
+			this.$refs.formRef.validate().then(res => {
+				const activeCategories = this.form.dishCategories.filter(c => c.items.some(this.isDishEdited));
+				console.log('表单校验成功, 提交的数据:', activeCategories);
+			}).catch(errors => {
+				console.log('校验失败', errors);
+			});
 		}
 	}
 };
@@ -280,7 +317,7 @@ export default {
 				}
 			}
 			.dish-form {
-				padding: 0 16rpx;
+				padding: 6rpx 16rpx;
 				border-radius: 8rpx;
 				background: #F7F8FC;
 			}

+ 31 - 11
pages/groupMeal/goods/index.vue

@@ -2,12 +2,18 @@
 	<view class="page-container">
 		<u-navbar title="团餐活动" :autoBack="true" :placeholder="true"></u-navbar>
 		<image class="bg" src="/static/groupMeal/bg_baoming.png" mode="widthFix"></image>
+		<view class="content">
+			<view class="title">尊敬的餐饮行业合作伙伴:</view>
+			<view>当上班族的午餐需求突破千万单 / 日,当校园、企业、事业单位的团餐采购量逐年攀升,一个规模超万亿的黄金赛道正等你来开拓!为搭建优质团餐供需对接平台,现正式启动 2025 年度团餐合作商家招募,诚邀具备品质实力与服务能力的餐饮企业携手同行,共享市场红利。​</view>
+			<view class="title">为什么选择与我们合作?​</view>
+			<view>稳定订单保障:覆盖 200 + 企业、50 + 校园及事业单位客户,单月团餐需求总量超 10 万份,签约即享长期稳定订单,告别 “淡季焦虑”;​ 品牌曝光加持:通过官方平台、合作机构渠道及线下活动,为合作商家提供品牌宣传机会,助力提升区域知名度与客户信任度;​ 一站式运营支持:提供专业的团餐配送路线规划、食品安全溯源系统接入、客户反馈实时处理等服务,降低运营成本,提升服务效率;​ 灵活合作模式:可根据商家资质与能力,选择 “全品类供应”“特色餐品定制”“应急餐储备” 等多种合作形式,满足不同发展需求。 商家们踊跃报名参加吧!</view>
+		</view>
 		
 		<!-- 底部操作栏 -->
 		<view class="footer-bar">
 			<u-button
 				shape="circle"
-				@click="onSave"
+				@click="onSubmit"
 			>立即报名</u-button>
 		</view>
 	</view>
@@ -32,15 +38,11 @@ export default {
 	},
 	methods: {
 		// 按钮点击事件
-		onSave() {
-			let url = `/packageB/pages/activity/form?activityId=${this.query.activityId}`;
-			if (this.$p.checkLogin()) {
-				url = '/pages/login/login?isBack=1';
-				// #ifdef MP
-				url = '/pages/login/wxLogin?isBack=1';
-				// #endif
-			}
-			this.$p.navTo(url);
+		onSubmit() {
+			let url = `/pages/groupMeal/goods/list`;
+			uni.navigateTo({
+				url
+			});
 		},
 	}
 };
@@ -49,13 +51,31 @@ export default {
 <style lang="scss" scoped>
 .page-container {
 	min-height: 100vh;
-	padding-bottom: 120rpx;
 	background: #F7F8FC;
+	position: relative;
 
 	.bg {
 		width: 100vw;
 		height: 100vh;
 	}
+
+	.content {
+		font-weight: 400;
+		font-size: 26rpx;
+		color: #666666;
+		padding: 0 76rpx;
+		line-height: 1.5;
+		text-align: justify;
+		position: absolute;
+		top: 520rpx;
+		z-index: 1;
+		.title {
+			font-weight: 500;
+			font-size: 28rpx;
+			color: #444444;
+			padding: 12rpx 0;
+		}
+	}
 }
 
 .footer-bar {

+ 98 - 4
pages/groupMeal/goods/list.vue

@@ -53,8 +53,13 @@
 			</view>
 
 			<!-- 右侧商品列表 -->
-			<scroll-view scroll-y class="goods-scroll-view" :style="{ paddingBottom: isManaging ? '120rpx' : '0' }">
-				<view class="goods-category-section" v-for="category in filteredGoods" :key="category.id">
+			<scroll-view scroll-y class="goods-scroll-view" 
+				:style="{ paddingBottom: isManaging ? '120rpx' : '0' }"
+				:scroll-into-view="scrollIntoViewId"  
+				:scroll-with-animation="true"
+				@scroll="onScroll"  
+			>
+				<view class="goods-category-section" :id="category.scrollId" v-for="category in filteredGoods" :key="category.id">
 					<view class="category-title">{{ category.name }}</view>
 					<u-checkbox-group v-model="selectedGoods" placement="column">
 						<view class="goods-card" v-for="goods in category.items" :key="goods.id">
@@ -125,6 +130,10 @@ export default {
 			],
 			selectedGoods: [], // 已选中的商品ID
 			isAllSelected: false, // 用于全选checkbox的状态绑定
+			// 联动功能相关数据
+			scrollIntoViewId: '', // 滚动到指定视图的 ID
+			categoryOffsetTops: [], // 每个分类区域到 scroll-view 顶部的距离
+			isScrolling: false, // 标记是否正在进行点击滚动
 		};
 	},
 	computed: {
@@ -138,10 +147,16 @@ export default {
 					grouped.push({
 						id: index,
 						name: category.name,
-						items: items
+						items: items,
+						scrollId: `category_${index}` // 滚动目标 ID
 					});
 				}
 			});
+			// 每次 filteredGoods 数据变化后,重新计算 offset
+			this.$nextTick(() => {
+				// 确保在数据渲染完成后再计算
+				this.calculateCategoryOffsets();
+			});
 			return grouped;
 		}
 	},
@@ -160,6 +175,12 @@ export default {
 			this.currentStatusTab = e;
 			this.selectedGoods = []; // 切换Tab时清空选择
 			this.isAllSelected = false;
+			// 切换 Tab 后,重置左侧分类高亮到第一个
+			// this.currentCategoryTab = 0; 
+			// this.$nextTick(() => {
+			// 	// 确保在新数据渲染后,滚动到第一个分类
+			// 	this.scrollIntoViewId = this.filteredGoods[0]?.scrollId || '';
+			// });
 		},
 		onCategoryTabChange(index) {
 			this.currentCategoryTab = index;
@@ -190,7 +211,80 @@ export default {
 			}
 			console.log(`执行批量操作: ${action}`, this.selectedGoods);
 			uni.showToast({ title: '操作成功', icon: 'success' });
-		}
+		},
+		// 核心功能 1: 点击左侧二级分类,右侧商品列表滚动到对应位置
+		onCategoryTabChange(index) {
+			this.currentCategoryTab = index;
+			
+			// 1. 设置标记,在滚动动画期间忽略 onGoodsScroll,防止快速切换闪烁
+			this.isScrolling = true; 
+			
+			// 2. 找到对应的 scrollId 并设置给 scroll-view
+			const targetCategory = this.filteredGoods.find(c => c.id === index);
+			if (targetCategory) {
+				this.scrollIntoViewId = targetCategory.scrollId;
+			}
+			
+			// 3. 延迟清除标记,等待滚动动画结束 (通常 300ms)
+			setTimeout(() => {
+				this.isScrolling = false;
+			}, 300); 
+		},
+		// 核心功能 2: 滚动商品列表时,左侧二级分类高亮联动
+		onGoodsScroll(e) {
+			// 如果是点击左侧分类触发的滚动,则忽略联动
+			if (this.isScrolling) {
+				return;
+			}
+			
+			const scrollTop = e.detail.scrollTop;
+			const threshold = 10; // 切换阈值,避免刚好在边缘时闪烁
+
+			// 遍历所有分类的 offset,找到当前位于视图顶部的分类
+			for (let i = 0; i < this.categoryOffsetTops.length; i++) {
+				const current = this.categoryOffsetTops[i];
+				const next = this.categoryOffsetTops[i + 1];
+
+				// 检查条件:
+				// 1. 当前分类的 top 已经小于或等于 scrollTop (即分类标题已经经过视图顶部)
+				// 2. 并且 (如果存在下一个分类) 下一个分类的 top 还没有经过视图顶部
+				if (current.top <= scrollTop + threshold && (!next || next.top > scrollTop + threshold)) {
+					// 确保左侧分类的索引是正确的
+					if (this.currentCategoryTab !== current.id) {
+						 this.currentCategoryTab = current.id;
+					}
+					break; 
+				}
+			}
+		},
+		// 核心功能 3: 计算所有分类区块的顶部偏移量
+		calculateCategoryOffsets() {
+			if (this.filteredGoods.length === 0) {
+				this.categoryOffsetTops = [];
+				return;
+			}
+			
+			// 必须使用 $nextTick 确保 DOM 已经渲染
+			this.$nextTick(() => {
+				const query = uni.createSelectorQuery().in(this);
+				let scrollRectTop = 0;
+				
+				// 1. 获取 scroll-view 顶部到页面的距离 (作为基准点)
+				query.select('.goods-scroll-view').boundingClientRect(rect => {
+					scrollRectTop = rect.top;
+				}).exec();
+				
+				// 2. 获取所有分类 section 的位置信息
+				query.selectAll('.goods-category-section').boundingClientRect(data => {
+					if (!data.length) return;
+
+					this.categoryOffsetTops = data.map(item => ({
+						id: parseInt(item.dataset.categoryIndex), // 从 data-category-index 获取 categoryId
+						top: item.top - scrollRectTop // 计算相对于 scroll-view 顶部的距离 (即 scrollTop 的值)
+					}));
+				}).exec();
+			});
+		},
 	}
 };
 </script>

+ 143 - 90
pages/groupMeal/orders/order-blist.vue

@@ -1,14 +1,35 @@
 <template>
 	<view class="page-container">
-		<u-navbar title="订单明细" :autoBack="true" :placeholder="true"></u-navbar>
+		<u-navbar title="订单明细" :autoBack="true" :placeholder="true" :border-bottom="false"></u-navbar>
 		
 		<!-- 搜索框 -->
 		<view class="search-bar">
-			<u-search placeholder="套餐名称、团长" :showAction="true" actionText="搜索"></u-search>
+			<u-search bg-color="#F7F8FC" placeholder="请输入套餐名称或团长名" search-icon-color="#999"
+				:showAction="true" actionText="搜索"
+				:actionStyle="{
+					width: 'auto',
+					color: '#333',
+					padding: '0 20rpx',
+					borderLeft: '1rpx solid #DDDDDD'
+				}"
+			></u-search>
 		</view>
 
 		<!-- 状态Tabs -->
-		<u-tabs :list="statusTabs" :current="currentStatusTab" @change="onStatusTabChange"></u-tabs>
+		<u-tabs :list="statusTabs" 
+			:current="currentStatusTab" 
+			inactive-color="#666666"
+			:bar-style="{
+				bottom: '20rpx',
+				background: 'linear-gradient(90deg, #82BCFF 0%, rgba(130,188,255,0) 100%)'
+			}"
+			:active-item-style="{
+				fontWeight: '500',
+				fontSize: '32rpx',
+				color: '#000000',
+			}"		
+			@change="onTabChange"
+		></u-tabs>
 
 		<scroll-view scroll-y class="detail-scroll-view">
 			<view v-if="currentStatusTab !== 2">
@@ -19,7 +40,7 @@
 							<view class="location-address">{{ group.location.address }}</view>
 						</view>
 						<view class="nav-button">
-							<u-icon name="map" color="#2979ff" size="18"></u-icon>
+							<u-icon name="map" color="#2979ff" size="36"></u-icon>
 							<text>导航</text>
 						</view>
 					</view>
@@ -27,16 +48,20 @@
 						<text>取餐号:{{ group.pickupCode }}</text>
 					</view>
 					<view class="order-item" v-for="item in group.items" :key="item.id">
-						<image class="goods-image" :src="item.image" mode="aspectFill"></image>
+						<u-image width="120rpx" height="120rpx" border-radius="12rpx" :src="item.image" mode="aspectFill"></u-image>
+						<!-- <image class="goods-image" :src="item.image" mode="aspectFill"></image> -->
 						<view class="item-details">
 							<view class="item-title">{{ item.title }}</view>
 							<view class="item-desc">{{ item.description }}</view>
 							<view class="item-quantity">数量:{{ item.quantity }}</view>
-							<view class="item-price">成团价:<text class="price-value">¥{{ item.price }}</text></view>
+							<view class="item-price">成团价:<text class="price-value"><text class="unit">¥</text>{{ item.price }}</text></view>
 						</view>
 					</view>
 					<view class="group-footer">
-						<text>合计:{{ group.totalQuantity }}份</text>
+						<view class="info">
+							<view class="m">合计金额 ¥<text class="v">{{ group.totalQuantity }}</text></view>
+							<view class="n">共{{ group.totalQuantity }}份</view>
+						</view>
 						<u-button v-if="currentStatusTab === 0" type="primary" size="small" text="出餐"></u-button>
 					</view>
 				</view>
@@ -58,7 +83,8 @@
 						<text>取餐号:{{ item.pickupCode }}</text>
 					</view>
 					<view class="order-item">
-						<image class="goods-image" :src="item.image" mode="aspectFill"></image>
+						<u-image width="120rpx" height="120rpx" border-radius="12rpx" :src="item.image" mode="aspectFill"></u-image>
+						<!-- <image class="goods-image" :src="item.image" mode="aspectFill"></image> -->
 						<view class="item-details">
 							<view class="item-title">{{ item.title }}</view>
 							<view class="item-desc">{{ item.description }}</view>
@@ -110,8 +136,8 @@ export default {
 		};
 	},
 	methods: {
-		onStatusTabChange(e) {
-			this.currentStatusTab = e.index;
+		onTabChange(e) {
+			this.currentStatusTab = e;
 		}
 	}
 };
@@ -122,99 +148,126 @@ export default {
 	height: 100vh;
 	display: flex;
 	flex-direction: column;
-	background-color: #f5f5f5;
-}
-.search-bar {
-	padding: 16rpx 24rpx;
-	background-color: #fff;
+	background-color: #F7F8FC;
+
+	.search-bar {
+		padding: 12rpx 32rpx;
+		background-color: #fff;
+		.u-search {
+			border-radius: 8rpx;
+			background-color: #F7F8FC;
+		}
+	}
 }
+
 .detail-scroll-view {
 	flex: 1;
 	height: 0;
-}
-.location-group, .refund-group {
-	margin: 24rpx;
-	background-color: #fff;
-	border-radius: 16rpx;
-	overflow: hidden;
-}
-.location-header {
-	display: flex;
-	justify-content: space-between;
-	align-items: flex-start;
-	padding: 24rpx;
-	background-color: #eaf3ff;
-	.location-info {
-		.location-name {
-			font-size: 30rpx;
-			font-weight: bold;
-			color: #303133;
-		}
-		.location-address {
-			font-size: 24rpx;
-			color: #606266;
-			margin-top: 8rpx;
-		}
+
+	.location-group, .refund-group {
+		margin: 24rpx;
+		background-color: #fff;
+		border-radius: 16rpx;
+		overflow: hidden;
 	}
-	.nav-button {
+
+	.location-header {
+		padding: 24rpx;
 		display: flex;
-		flex-direction: column;
-		align-items: center;
-		color: #2979ff;
-		font-size: 22rpx;
+		align-items: flex-start;
+		justify-content: space-between;
+		background: linear-gradient(90deg, #FDFDFF 0%, #E3F0FF 100%);
+		.location-info {
+			.location-name {
+				font-size: 30rpx;
+				font-weight: bold;
+				color: #303133;
+			}
+			.location-address {
+				font-size: 26rpx;
+				color: #606266;
+				margin-top: 4rpx;
+			}
+		}
+		.nav-button {
+			font-weight: 500;
+			font-size: 26rpx;
+			color: #449AFF;
+			display: flex;
+			align-items: center;
+			flex-direction: column;
+		}
+		.refund-status {
+			font-size: 26rpx;
+			&.status-processing { color: #f9ae3d; }
+			&.status-applying { color: #f9ae3d; }
+			&.status-failed { color: #fa3534; }
+			&.status-success { color: #19be6b; }
+		}
 	}
-	.refund-status {
+	.pickup-info {
+		font-weight: 500;
 		font-size: 26rpx;
-		&.status-processing { color: #f9ae3d; }
-		&.status-applying { color: #f9ae3d; }
-		&.status-failed { color: #fa3534; }
-		&.status-success { color: #19be6b; }
-	}
-}
-.pickup-info {
-	padding: 16rpx 24rpx;
-	font-size: 26rpx;
-	color: #303133;
-	border-bottom: 1rpx solid #f0f0f0;
-}
-.order-item {
-	display: flex;
-	padding: 24rpx;
-	.goods-image {
-		width: 120rpx;
-		height: 120rpx;
-		border-radius: 8rpx;
-		flex-shrink: 0;
+		color: #449AFF;
+		padding: 24rpx 25rpx 12rpx;
 	}
-	.item-details {
-		flex: 1;
-		margin-left: 20rpx;
-		.item-title {
-			font-size: 28rpx;
-			font-weight: bold;
-		}
-		.item-desc, .item-quantity {
-			font-size: 24rpx;
-			color: #909399;
-			margin-top: 6rpx;
+	.order-item {
+		display: flex;
+		padding: 12rpx 24rpx;
+		.goods-image {
+			width: 120rpx;
+			height: 120rpx;
+			border-radius: 12rpx;
+			flex-shrink: 0;
 		}
-		.item-price {
-			font-size: 26rpx;
-			color: #303133;
-			margin-top: 6rpx;
-			.price-value {
-				color: #fa3534;
+		.item-details {
+			flex: 1;
+			margin-left: 20rpx;
+			.item-title {
+				font-size: 28rpx;
 				font-weight: bold;
 			}
+			.item-desc, .item-quantity {
+				font-size: 22rpx;
+				color: #8A91A8;
+				margin-top: 6rpx;
+			}
+			.item-price {
+				font-size: 22rpx;
+				color: #8A91A8;
+				margin-top: 6rpx;
+				.price-value {
+					color: #FD4912;
+					font-size: 32rpx;
+					font-weight: bold;
+					.unit {
+						font-size: 22rpx;
+					}
+				}
+			}
+		}
+	}
+	.group-footer {
+		padding: 24rpx;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		border-top: 1rpx solid #f0f0f0;
+		.info {
+			.m {
+				font-weight: 500;
+				font-size: 22rpx;
+				color: #FF6A42;
+				.v {
+					font-size: 36rpx;
+				}
+			}
+			.n {
+				font-weight: 400;
+				font-size: 22rpx;
+				color: #666666;
+			}
 		}
 	}
-}
-.group-footer {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	padding: 24rpx;
-	border-top: 1rpx solid #f0f0f0;
-	font-size: 28rpx;
 }
 </style>

+ 189 - 0
pages/groupMeal/users/bankCard-edit.vue

@@ -0,0 +1,189 @@
+<template>
+	<view class="page-container">
+		<u-navbar title="" :autoBack="true" :placeholder="true"></u-navbar>
+		
+		<view class="header-tips">
+			<view class="name">添加银行卡</view>
+			<view class="desc">请填写本人的银行卡信息</view>
+		</view>
+
+		<view class="form-section">
+			<u-form :model="form" :rules="rules" ref="formRef" labelPosition="left" labelWidth="160"
+				:labelStyle="{
+					fontWeight: '500',
+					fontSize: '28rpx',
+					color: '#333333',
+				}"		
+			>
+				<u-form-item label="存管银行" prop="bankName" @click="selectBank">
+					<u-input v-model="form.bankName" placeholder="请选择"></u-input>
+					<u-icon slot="right" name="arrow-right"></u-icon>
+				</u-form-item>
+
+				<u-form-item label="银行账号" prop="cardNumber">
+					<u-input v-model="form.cardNumber" type="number" placeholder="请输入银行卡号"></u-input>
+				</u-form-item>
+
+				<u-form-item label="开户行" prop="branchName">
+					<u-input v-model="form.branchName" placeholder="请输入开户行名称"></u-input>
+				</u-form-item>
+				
+				<u-form-item label="姓名" prop="name">
+					<u-input v-model="form.name" placeholder="请输入姓名"></u-input>
+				</u-form-item>
+
+				<u-form-item label="手机号" prop="phone">
+					<u-input v-model="form.phone" type="number" placeholder="请输入手机号"></u-input>
+				</u-form-item>
+				
+				<u-form-item label="短信验证码" prop="verificationCode">
+					<u-input v-model="form.verificationCode" type="number" placeholder="6位数字"></u-input>
+					<u-button slot="right" type="primary" size="mini" shape="circle" plain @click="getCode">{{tips}}</u-button>
+				</u-form-item>
+			</u-form>
+		</view>
+		
+		<view class="agreement-section">
+			<u-checkbox-group v-model="isAgreed">
+				<u-checkbox name="agree" shape="circle" v-model="isAgreed">
+					<text class="agreement-text">我已阅读并同意《用户服务协议》</text>
+				</u-checkbox>
+			</u-checkbox-group>
+		</view>
+		
+		<view class="footer-bar">
+			<u-button type="primary" @click="submit">确认绑定</u-button>
+		</view>
+
+		<u-verification-code seconds="60" ref="uCode" @change="codeChange" />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			form: {
+				bankName: '',
+				cardNumber: '',
+				branchName: '',
+				name: '',
+				phone: '',
+				verificationCode: '',
+			},
+			rules: {
+				bankName: [{ required: true, message: '请选择存管银行', trigger: ['blur', 'change'] }],
+				cardNumber: [{ required: true, message: '请输入银行卡号', trigger: ['blur', 'change'] }],
+				branchName: [{ required: true, message: '请输入开户行名称', trigger: ['blur', 'change'] }],
+				name: [{ required: true, message: '请输入姓名', trigger: ['blur', 'change'] }],
+				phone: [{ required: true, message: '请输入手机号', trigger: ['blur', 'change'] }, { validator: (rule, value, callback) => uni.$u.test.mobile(value), message: '手机号码不正确' }],
+				verificationCode: [{ required: true, message: '请输入验证码', trigger: ['blur', 'change'] }, { len: 6, message: '验证码必须为6位' }],
+			},
+			tips: '',
+			isAgreed: false,
+		};
+	},
+	mounted() {
+		this.$nextTick(() => {
+			this.$refs.formRef.setRules(this.rules);
+		});
+	},
+	methods: {
+		selectBank() {
+			// 模拟跳转到银行选择页面
+			uni.showToast({ title: '跳转到银行选择页', icon: 'none' });
+		},
+		codeChange(text) {
+			this.tips = text;
+		},
+		getCode() {
+			if (this.$refs.uCode.canGetCode) {
+				// 模拟向后端请求验证码
+				uni.showLoading({ title: '正在获取验证码' });
+				setTimeout(() => {
+					uni.hideLoading();
+					uni.showToast({ title: '验证码已发送', icon: 'none' });
+					this.$refs.uCode.start();
+				}, 1000);
+			} else {
+				uni.$u.toast('倒计时结束后再发送');
+			}
+		},
+		submit() {
+			if(this.isAgreed.length === 0) {
+				uni.showToast({ title: '请先同意用户协议', icon: 'none' });
+				return;
+			}
+			
+			this.$refs.formRef.validate().then(res => {
+				console.log('表单校验成功', this.form);
+				// uni.showToast({ title: '绑定成功', icon: 'success' });
+				// setTimeout(() => {
+				// 	uni.navigateBack();
+				// }, 1500);
+			}).catch(errors => {
+				
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+	min-height: 100vh;
+	background-color: #F7F8FC;
+	.header-tips {
+		color: #333333;
+		padding: 20rpx 30rpx;
+		text-align: center;
+		.name {
+			font-weight: 500;
+			font-size: 40rpx;
+		}
+		.desc {
+			font-weight: 400;
+			font-size: 28rpx;
+		}
+	}
+	.form-section {
+		margin: 0 24rpx;
+		padding: 20rpx 24rpx;
+		background-color: #fff;
+
+		::v-deep .u-form-item {
+			padding: 6rpx 0;
+			line-height: 1;
+			.u-form-item--left__content {
+				flex: none;
+				.u-form-item--left__content--required {
+					color: #fa3534; 
+					left: auto;
+					right: 0;
+				}
+			}
+		}
+	}
+	.agreement-section {
+		display: flex;
+		align-items: center;
+		padding: 20rpx 30rpx;
+		.agreement-text {
+			font-size: 24rpx;
+			color: #606266;
+			margin-left: 10rpx;
+		}
+	}
+}
+.footer-bar {
+	::v-deep .u-btn {
+		width: 100%;
+		height: 76rpx;
+		border-radius: 54rpx;
+		background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
+		&.u-btn--primary--disabled {
+			background: #a0cfff;
+		}
+	}
+}
+</style>

+ 196 - 0
pages/groupMeal/users/bankCard-list.vue

@@ -0,0 +1,196 @@
+<template>
+	<view class="page-container">
+		<u-navbar title="银行卡" :autoBack="true" :placeholder="true" :border-bottom="false"></u-navbar>
+		
+		<view class="card-list">
+			<view 
+				class="card-item" 
+				v-for="card in cardList" 
+				:key="card.id"
+				:style="{ background: getCardBackground(card.type) }"
+			>
+				<view class="card-header">
+					<image class="bank-logo" :src="card.logo" mode="aspectFit"></image>
+					<view class="bank-info">
+						<view class="bank-name">{{ card.bankName }}</view>
+						<view class="card-type">{{ card.cardType }}</view>
+					</view>
+					<u-icon name="more-dot-fill" color="#fff" size="24" @click="showCardActions(card)"></u-icon>
+				</view>
+				<view class="card-number">
+					<text>****</text>
+					<text>****</text>
+					<text>****</text>
+					<text>{{ card.last4Digits }}</text>
+				</view>
+			</view>
+		</view>
+
+		<view class="footer-bar">
+			<u-button type="primary" @click="addBankCard">添加银行卡</u-button>
+		</view>
+		
+		<!-- 操作菜单 -->
+		<u-action-sheet
+			:tips="{
+				text: '解除绑定后从银行卡列表中移除,需要重新添加使用'
+			}"
+			:list="actions"
+			:border-radius="20"
+			:safe-area-inset-bottom="true"
+			v-model="showActions"
+			@click="onActionSelect"
+			@close="showActions = false"
+		></u-action-sheet>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			colorData: [
+				{'工商银行': '#C7000A'},
+				{'交通银行': '#00377A'},
+				{'招商银行': '#A30030'},
+				{'民生银行': '#0072BC'},
+				{'中信银行': '#D70010'},
+				{'浦发银行': '#000073'},
+				{'兴业银行': '#003F97'},
+				{'光大银行': '#6A1685'},
+				{'广发银行': '#E60021'},
+				{'平安银行': '#F15A25'},
+				{'北京银行': '#CB030D'},
+				{'华夏银行': '#DB0D17'},
+				{'农业银行': '#319C8B'},
+				{'建设银行': '#0066B3'},
+				{'邮政银行': '#02724A'},
+				{'中国银行': '#A71E32'},
+				{'宁波银行': '#EF8F38'},
+			],
+			cardList: [
+				{ id: 1, bankName: '中国建设银行', cardType: '储蓄卡', last4Digits: '0882', logo: '/static/bank_logo/ccb.png', type: 'ccb' },
+				{ id: 2, bankName: '中国光大银行', cardType: '储蓄卡', last4Digits: '0882', logo: '/static/bank_logo/ceb.png', type: 'ceb' },
+				{ id: 3, bankName: '中国工商银行', cardType: '储蓄卡', last4Digits: '0882', logo: '/static/bank_logo/icbc.png', type: 'icbc' },
+				{ id: 4, bankName: '中国邮政储蓄银行', cardType: '储蓄卡', last4Digits: '0882', logo: '/static/bank_logo/psbc.png', type: 'psbc' },
+			],
+			showActions: false,
+			actions: [{ text: '解绑' }],
+			selectedCard: null,
+		};
+	},
+	methods: {
+		linearGradient(angle, ...colorStops) {
+			if (colorStops.length % 2 !== 0) {
+				throw new Error('linearGradient: 颜色和透明度必须成对传入');
+			}
+			const stops = [];
+			for (let i = 0; i < colorStops.length; i += 2) {
+				const hex = colorStops[i];
+				const alpha = colorStops[i + 1];
+				stops.push(this.hexToRgba(hex, alpha));
+			}
+			return `linear-gradient(${angle}deg, ${stops.join(', ')})`;
+		},
+		hexToRgba(hex, alpha) {
+			hex = hex.replace(/^#/, '');
+			if (hex.length === 3) {
+				hex = hex.split('').map(ch => ch + ch).join('');
+			}
+			const r = parseInt(hex.substring(0, 2), 16);
+			const g = parseInt(hex.substring(2, 4), 16);
+			const b = parseInt(hex.substring(4, 6), 16);
+			return `rgba(${r}, ${g}, ${b}, ${alpha})`;
+		},
+		getCardBackground(type) {
+			const gradients = {
+				ccb: this.linearGradient(90, '#0066B3', 0.5, '#0066B3', 1),
+				ceb: this.linearGradient(90, '#6A1685', 0.5, '#6A1685', 1),
+				icbc: this.linearGradient(90, '#C7000A', 0.5, '#C7000A', 1),
+				psbc: this.linearGradient(90, '#02724A', 0.5, '#02724A', 1),
+			};
+			return gradients[type] || 'linear-gradient(90deg, #888, #aaa)';
+		},
+		addBankCard() {
+			uni.navigateTo({
+				url: '/pages/groupMeal/users/bankCard-edit'
+			});
+		},
+		showCardActions(card) {
+			this.selectedCard = card;
+			this.showActions = true;
+		},
+		onActionSelect(action) {
+			if (action.name === '解绑') {
+				uni.showModal({
+					title: '确认解绑',
+					content: `您确定要解绑尾号为 ${this.selectedCard.last4Digits} 的银行卡吗?`,
+					success: (res) => {
+						if (res.confirm) {
+							console.log('执行解绑操作', this.selectedCard.id);
+							uni.showToast({ title: '解绑成功', icon: 'success' });
+						}
+					}
+				});
+			}
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+	background-color: #f5f5f5;
+	min-height: 100vh;
+}
+.card-list {
+	padding: 24rpx;
+}
+.card-item {
+	color: #fff;
+	padding: 28rpx;
+	margin-bottom: 20rpx;
+	border-radius: 12rpx;
+	box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.1);
+	.card-header {
+		display: flex;
+		align-items: center;
+		margin-bottom: 40rpx;
+		.bank-logo {
+			width: 80rpx;
+			height: 80rpx;
+			border-radius: 12rpx;
+			background-color: #fff;
+		}
+		.bank-info {
+			flex: 1;
+			margin-left: 20rpx;
+			.bank-name {
+				font-size: 32rpx;
+				font-weight: 500;
+			}
+			.card-type {
+				font-size: 24rpx;
+				opacity: 0.8;
+			}
+		}
+	}
+	.card-number {
+		font-size: 36rpx;
+		letter-spacing: 2rpx;
+		display: flex;
+		justify-content: space-between;
+	}
+}
+.footer-bar {
+	::v-deep .u-btn {
+		width: 100%;
+		height: 76rpx;
+		border-radius: 54rpx;
+		background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
+		&.u-btn--primary--disabled {
+			background: #a0cfff;
+		}
+	}
+}
+</style>

+ 132 - 0
pages/groupMeal/users/bankCard-select.vue

@@ -0,0 +1,132 @@
+<template>
+	<u-popup mode="bottom" :border-radius="20" 
+        :safe-area-inset-bottom="true"
+        v-model="show" @close="close"
+    >
+		<view class="popup-container">
+			<view class="popup-header">
+				<view class="title">选择提现银行卡</view>
+				<view class="subtitle">请留意各银行到账时间</view>
+			</view>
+
+			<scroll-view scroll-y class="card-list-scroll">
+				<!-- 银行卡列表 -->
+				<view 
+					class="card-item" 
+					v-for="card in dataList" 
+					:key="card.id"
+					@click="selectCard(card)"
+				>
+					<image class="bank-icon" :src="card.icon" mode="aspectFit"></image>
+					<text class="card-name">{{ card.name }} ({{ card.last4 }})</text>
+					<u-icon v-if="selectedCardId === card.id" name="checkbox-mark" color="#2979ff" size="40"></u-icon>
+				</view>
+
+				<!-- 添加银行卡 -->
+				<view class="card-item add-card" @click="addCard">
+					<u-icon name="plus-circle" color="#2979ff" size="40"></u-icon>
+					<text class="card-name">添加银行卡</text>
+					<u-icon name="arrow-right" color="#909399" size="32"></u-icon>
+				</view>
+			</scroll-view>
+		</view>
+	</u-popup>
+</template>
+
+<script>
+export default {
+	name: 'BankCardSelector',
+	props: {
+		// 银行卡列表
+		dataList: {
+			type: Array,
+			default: () => []
+		},
+		// 当前选中的银行卡ID (v-model)
+		value: {
+			type: [String, Number],
+			default: ''
+		}
+	},
+	data() {
+		return {
+            show: false,
+			selectedCardId: this.value
+		};
+	},
+	watch: {
+		// 监听v-model的变化,同步内部状态
+		value(newVal) {
+			this.selectedCardId = newVal;
+		}
+	},
+	methods: {
+		open() {
+			this.show = true;
+		},
+		close() {
+			this.show = false;
+		},
+		selectCard(card) {
+			this.selectedCardId = card.id;
+			// 通过v-model更新父组件的值
+			this.$emit('input', card.id);
+			this.$emit('select', card);
+			this.close();
+		},
+		addCard() {
+			console.log('跳转到添加银行卡页面');
+			uni.navigateTo({
+				url: '/pages/wallet/AddBankCard' // 假设这是添加银行卡的页面路径
+			});
+			this.close();
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.popup-container {
+    .popup-header {
+        padding: 20rpx 30rpx;
+        text-align: center;
+        border-bottom: 1rpx solid #f0f0f0;
+        .title {
+            font-size: 30rpx;
+            font-weight: 500;
+            color: #232832;
+        }
+        .subtitle {
+            font-weight: 400;
+            font-size: 24rpx;
+            color: rgba(51,51,51,0.8);
+        }
+    }
+    .card-list-scroll {
+        max-height: 60vh; // 限制最大高度,超出则滚动
+    }
+    .card-item {
+        display: flex;
+        align-items: center;
+        padding: 30rpx;
+        border-bottom: 1rpx solid #f0f0f0;
+
+        .bank-icon {
+            width: 40rpx;
+            height: 40rpx;
+            margin-right: 20rpx;
+            background: #eee;
+        }
+        .card-name {
+            flex: 1;
+            font-size: 30rpx;
+            color: #303133;
+        }
+        &.add-card {
+            .card-name {
+                color: #2979ff;
+            }
+        }
+    }
+}
+</style>

+ 67 - 0
pages/groupMeal/users/index.vue

@@ -0,0 +1,67 @@
+<template>
+	<view>
+		<u-cell-group :border="false">
+			<u-cell-item v-for="(item, i) in data" :key="i" value="" @click="onClick(item)">
+				<view class="cell-box" slot="title">
+					<image class="img" :src="item.icon" />
+					<text class="text">{{ item.name }}</text>
+				</view>
+			</u-cell-item>
+		</u-cell-group>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			data: [
+				{
+					name: '我的团长',
+					icon: '/static/icon/icon_edit.png',
+					path: ''
+				},
+				{
+					name: '团餐设置',
+					icon: '/static/icon/icon_edit.png',
+					path: '/pages/groupMeal/users/settings'
+				},
+				{
+					name: '企业团餐设置',
+					icon: '/static/icon/icon_edit.png',
+					path: ''
+				},
+			]
+		}
+	},
+	onShow() {
+		
+	},
+	methods: {
+		onClick(e) {
+			console.log(e)
+			if (!e.path) return;
+			uni.navigateTo({
+				url: `${e.path}`
+			});
+		},
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.cell-box {
+	display: flex;
+	align-items: center;
+	.img {
+		width: 40rpx;
+		height: 40rpx;
+		margin-right: 16rpx
+	}
+	.text {
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #232832;
+	}
+}
+</style>

+ 214 - 0
pages/groupMeal/users/settings.vue

@@ -0,0 +1,214 @@
+<template>
+	<view class="page-container">
+		<u-navbar title="团餐设置" :autoBack="true" :placeholder="true" :border-bottom="false"></u-navbar>
+		
+		<u-form :model="form" :rules="rules" ref="formRef" labelPosition="left" labelWidth="auto">
+			<view class="meal-section" v-for="(meal, index) in form.mealTimes" :key="index">
+				<view class="section-title">{{ meal.name }}</view>
+				
+				<u-form-item :label="`拼团最低起送量`" :prop="`mealTimes.${index}.minAmount`" borderBottom :required="isEdited(index)">
+					<u-input v-model="meal.minAmount" type="number" placeholder="输入数量" height="41" inputAlign="right"></u-input>
+				</u-form-item>
+				
+				<u-form-item :label="`开团时间`" :prop="`mealTimes.${index}.startTime`" borderBottom :required="isEdited(index)">
+					<u-input v-model="meal.startTime" :clearable="false" placeholder="去设置" height="41" inputAlign="right" @click="openTimePicker(index, 'startTime')"></u-input>
+					<u-icon slot="right" name="arrow-right"></u-icon>
+				</u-form-item>
+
+				<u-form-item :label="`闭团时间`" :prop="`mealTimes.${index}.endTime`" @click="openTimePicker(index, 'endTime')" :required="isEdited(index)">
+					<u-input v-model="meal.endTime" :clearable="false" placeholder="去设置" height="41" inputAlign="right" @click="openTimePicker(index, 'endTime')"></u-input>
+					<u-icon slot="right" name="arrow-right"></u-icon>
+				</u-form-item>
+			</view>
+		</u-form>
+
+		<view class="footer-bar">
+			<u-button type="primary" 
+				:disabled="isSubmitDisabled"
+				@click="submit" 
+			>提交</u-button>
+		</view>
+
+		<u-picker 
+		 	mode="time"
+			:params="{
+				hour: true,
+				minute: true,
+				timestamp: true
+			}"
+			v-model="showPicker"
+			@confirm="onTimeConfirm"
+			@cancel="showPicker = false"
+		></u-picker>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			form: {
+				mealTimes: [
+					{ id: 'breakfast', name: '早餐', minAmount: '', startTime: '', endTime: '' },
+					{ id: 'lunch', name: '午餐', minAmount: '', startTime: '', endTime: '' },
+					{ id: 'dinner', name: '晚餐', minAmount: '', startTime: '', endTime: '' },
+				],
+			},
+			rules: {}, // 规则将动态生成
+			showPicker: false,
+			pickerValue: '',
+			currentEditing: { // 记录当前正在编辑的时间
+				index: null,
+				field: ''
+			},
+		};
+	},
+	computed: {
+		// 判断提交按钮是否应该被禁用
+		isSubmitDisabled() {
+			// 如果所有餐次的所有字段都为空,则禁用
+			return this.form.mealTimes.every(meal => 
+				!meal.minAmount && !meal.startTime && !meal.endTime
+			);
+		}
+	},
+	watch: {
+		// 深度监听表单数据变化,动态设置校验规则
+		'form.mealTimes': {
+			handler() {
+				// 使用 nextTick 确保在 DOM 更新后再设置规则,增加稳定性
+				this.$nextTick(() => {
+					this.updateValidationRules();
+				});
+			},
+			deep: true
+		}
+	},
+	mounted() {
+		// 页面加载完成后,为 u-form 实例设置初始规则
+		this.$nextTick(() => {
+			this.$refs.formRef.setRules(this.rules);
+		});
+	},
+	methods: {
+		// 判断一个餐次区块是否被编辑过
+		isEdited(index) {
+			const meal = this.form.mealTimes[index];
+			return !!(meal.minAmount || meal.startTime || meal.endTime);
+		},
+		updateValidationRules() {
+			// 确保 u-form 实例存在
+			if (!this.$refs.formRef) {
+				return;
+			}
+			
+			const newRules = {};
+			this.form.mealTimes.forEach((meal, index) => {
+				if (this.isEdited(index)) {
+					// 如果有任何一个字段被填写,则该餐次的所有字段都变为必填
+					newRules[`mealTimes.${index}.minAmount`] = [{ required: true, message: '请输入起送量', trigger: ['blur', 'change'] }];
+					newRules[`mealTimes.${index}.startTime`] = [
+						{ required: true, message: '请设置开团时间', trigger: ['blur', 'change'] },
+						{
+							validator: (rule, value, callback) => {
+								const endTime = this.form.mealTimes[index].endTime;
+								console.log(endTime, value)
+								let flag = endTime && value && value >= endTime;
+								return !flag;
+							},
+							message: '开团时间必须早于闭团时间',
+							trigger: ['change', 'blur'],
+						}
+					];
+					newRules[`mealTimes.${index}.endTime`] = [
+						{ required: true, message: '请设置闭团时间', trigger: ['blur', 'change'] },
+						{
+							asyncValidator: (rule, value, callback) => {
+								const startTime = this.form.mealTimes[index].startTime;
+								if (startTime && value && value <= startTime) {
+									callback(new Error('闭团时间必须晚于开团时间'));
+								} else {
+									callback();
+								}
+							},
+							trigger: ['change', 'blur'],
+						}
+					];
+				}
+			});
+			this.rules = newRules;
+			this.$refs.formRef.setRules(this.rules);
+		},
+		openTimePicker(index, field) {
+			this.currentEditing = { index, field };
+			this.pickerValue = this.form.mealTimes[index][field] || '08:00'; // 默认值
+			this.showPicker = true;
+		},
+		onTimeConfirm(e) {
+			const { value } = e;
+			const { index, field } = this.currentEditing;
+			this.form.mealTimes[index][field] = value;
+			this.showPicker = false;
+		},
+		submit() {
+			this.$refs.formRef.validate().then(res => {
+				console.log('表单校验成功', this.form);
+				uni.showToast({
+					title: '提交成功',
+					icon: 'success'
+				});
+			}).catch(errors => {
+				console.log('表单校验失败', errors);
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+	background-color: #f5f5f5;
+	min-height: 100vh;
+	padding-bottom: 140rpx;
+}
+.meal-section {
+	margin: 24rpx;
+	padding: 20rpx 30rpx;
+	border: 1rpx solid #F0F3F5;
+	border-radius: 16rpx;
+	box-shadow: 0 2rpx 8rpx 0 rgba(214,225,237,0.1);
+	background-color: #fff;
+	.section-title {
+		font-size: 32rpx;
+		font-weight: 500;
+		padding: 0 0 16rpx;
+	}
+	::v-deep .u-form-item {
+		padding: 16rpx 0;
+		line-height: 1;
+		.u-form-item--left__content {
+			flex: none;
+			.u-form-item--left__content--required {
+				color: #fa3534; 
+				left: auto;
+				right: 0;
+			}
+		}
+	}
+}
+.footer-bar {
+	::v-deep .u-btn {
+		width: 100%;
+		height: 76rpx;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #FFFFFF;
+		border-radius: 54rpx;
+		background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
+		&.u-btn--primary--disabled {
+			background: #a0cfff;
+		}
+	}
+}
+</style>
+

+ 86 - 66
pages/groupMeal/users/withdrawal.vue

@@ -1,16 +1,16 @@
 <template>
 	<view class="page-container">
-		<u-navbar title="提现" :autoBack="true" :placeholder="true"></u-navbar>
+		<u-navbar title="提现" :autoBack="true" :placeholder="true" :border-bottom="false"></u-navbar>
 
 		<view class="form-card">
 			<view class="section-item" @click="selectBankCard">
 				<view class="label">提现至</view>
 				<view class="content">
 					<view class="bank-info">
-						<u--image src="/static/images/bank-icon-icbc.png" width="40rpx" height="40rpx" mode="aspectFit" class="bank-icon"></u--image>
+						<u-image class="bank-icon" src="/static/icon/icon_plus.png" width="48rpx" height="48rpx" mode="aspectFit"></u-image>
 						<text class="bank-name">{{ bankCard.name }} ({{ bankCard.tailNumber }})</text>
 					</view>
-					<u-icon name="arrow-right" color="#c0c4cc" size="28rpx"></u-icon>
+					<u-icon name="arrow-right" color="#c0c4cc" size="32rpx"></u-icon>
 				</view>
 			</view>
 
@@ -18,14 +18,16 @@
 				<view class="label">提现金额</view>
 				<view class="input-row">
 					<text class="currency-symbol">¥</text>
-					<u--input 
-						v-model="withdrawalAmount" 
-						placeholder="请输入提现金额" 
+					<u-input 
 						type="digit" 
-						border="none"
-						:customStyle="{ padding: '0 10rpx' }"
-						placeholderStyle="color: #c0c4cc;"
-					></u--input>
+						height="80"
+						placeholder="请输入提现金额" 
+						:customStyle="{ 
+							fontSize: '52rpx',
+							padding: '0 10rpx' 
+						}"
+						v-model="withdrawalAmount" 
+					></u-input>
 				</view>
 				
 				<view class="balance-info">
@@ -35,20 +37,29 @@
 			</view>
 		</view>
 
-		<view class="footer-button">
+		<view class="footer-bar">
 			<u-button 
 				type="primary" 
-				text="申请提现" 
 				:disabled="!withdrawalAmount || parseFloat(withdrawalAmount) <= 0" 
 				@click="applyWithdrawal"
-			></u-button>
-		</view>
-		
+			>申请提现</u-button>
 		</view>
+		<!-- 调用选择器组件 -->
+		<BankCardSelector 
+			ref="bcSelector" 
+			:data-list="bankCards"
+			v-model="selectedCardId"
+			@select="handleCardSelect"
+		/>
+	</view>
 </template>
 
 <script>
+import BankCardSelector from './bankCard-select.vue';
 export default {
+	components: {
+		BankCardSelector
+	},
 	data() {
 		return {
 			// 模拟数据
@@ -59,30 +70,42 @@ export default {
 			},
 			availableBalance: '821.33', // 当前可提现余额
 			withdrawalAmount: '', // 提现金额输入框的值
+			// 模拟的银行卡数据
+			bankCards: [
+				{ id: 101, name: '中国工商银行储蓄卡', last4: '0882', icon: '/static/demo/icbc.png' },
+				{ id: 102, name: '中国建设银行储蓄卡', last4: '0882', icon: '/static/demo/ccb.png' },
+				{ id: 103, name: '中国光大银行储蓄卡', last4: '0882', icon: '/static/demo/ceb.png' },
+				// 模拟更多数据以测试滚动
+				{ id: 104, name: '中国农业银行储蓄卡', last4: '1234', icon: '/static/demo/abc.png' },
+				{ id: 105, name: '招商银行储蓄卡', last4: '5678', icon: '/static/demo/cmb.png' },
+				{ id: 106, name: '交通银行储蓄卡', last4: '9012', icon: '/static/demo/boc.png' },
+			],
+			selectedCardId: 101, // 默认选中的卡ID
 		};
 	},
 	methods: {
-		/**
-		 * 选择银行卡/修改提现银行卡
-		 */
+		// 选择/修改银行卡
 		selectBankCard() {
-			console.log('跳转到银行卡列表或选择页面');
-			// uni.navigateTo({
-			// 	url: '/pages/bankcard/list' // 假设的银行卡列表页路径
-			// });
+			this.$refs.bcSelector.open();
+			return;
+			uni.navigateTo({
+				url: '/pages/groupMeal/users/bankCard-list' 
+			});
 		},
-		
-		/**
-		 * 全部提现操作
-		 */
+		// 选择事件回调
+		handleCardSelect(card) {
+			console.log('您选择了:', card);
+			uni.showToast({
+				title: `已选择: ${card.name}`,
+				icon: 'none'
+			});
+		},
+		// 全部提现操作
 		allWithdraw() {
 			this.withdrawalAmount = this.availableBalance;
 			console.log('已设置全部提现:', this.withdrawalAmount);
 		},
-
-		/**
-		 * 申请提现按钮点击事件
-		 */
+		// 申请提现
 		applyWithdrawal() {
 			if (parseFloat(this.withdrawalAmount) > parseFloat(this.availableBalance)) {
 				uni.showToast({
@@ -115,27 +138,27 @@ $uni-color-primary: #2979ff;
 $uni-text-color-placeholder: #909399;
 
 .page-container {
-	background-color: #f5f5f5;
 	min-height: 100vh;
-}
+	background-color: #F7F8FC;
 
-.form-card {
-	background-color: #fff;
-	padding: 0 30rpx;
-	margin-top: 20rpx;
+	.form-card {
+		background-color: #fff;
+		padding: 0 30rpx;
+	}
 }
 
 // 提现至:银行卡选择区域
 .section-item {
 	display: flex;
-	justify-content: space-between;
 	align-items: center;
+	justify-content: space-between;
 	padding: 30rpx 0;
 	border-bottom: 1rpx solid #eee;
 	
 	.label {
-		font-size: 30rpx;
-		color: $uni-text-color;
+		font-weight: 500;
+		font-size: 32rpx;
+		color: #333333;
 	}
 	
 	.content {
@@ -166,8 +189,9 @@ $uni-text-color-placeholder: #909399;
 	padding: 30rpx 0 20rpx;
 	
 	.label {
+		font-weight: 400;
 		font-size: 30rpx;
-		color: $uni-text-color;
+		color: #333333;
 		margin-bottom: 20rpx;
 	}
 	
@@ -176,31 +200,26 @@ $uni-text-color-placeholder: #909399;
 		align-items: center;
 		padding: 20rpx 0;
 		border-bottom: 1rpx solid #eee;
-	}
-	
-	.currency-symbol {
-		font-size: 64rpx; // 放大货币符号
-		font-weight: bold;
-		color: $uni-text-color;
-		padding-right: 10rpx;
-	}
 	
-	// 覆盖uView input的默认样式,使其看起来像一个大的金额输入框
-	::v-deep .u-input__content__field-wrapper__field {
-		font-size: 64rpx; 
-		font-weight: bold;
-		height: 80rpx !important;
+		.currency-symbol {
+			font-size: 52rpx; 
+			font-weight: bold;
+			color: #333;
+			padding-right: 10rpx;
+		}
 	}
 
 	.balance-info {
-		margin-top: 15rpx;
+		font-weight: 400;
 		font-size: 26rpx;
-		color: $uni-text-color-placeholder;
+		color: rgba(51,51,51,0.6);
+		margin-top: 16rpx;
 		
 		.all-withdraw-btn {
-			color: $uni-color-primary;
+			font-weight: 400;
+			font-size: 26rpx;
+			color: #2D4D89;
 			margin-left: 10rpx;
-			font-weight: bold;
 			
 			&:active {
 				opacity: 0.8;
@@ -210,14 +229,15 @@ $uni-text-color-placeholder: #909399;
 }
 
 // 底部按钮
-.footer-button {
-	position: fixed;
-	bottom: 0;
-	left: 0;
-	right: 0;
-	background-color: #f5f5f5; // 与背景色一致
-	padding: 30rpx;
-	padding-bottom: calc(30rpx + constant(safe-area-inset-bottom));
-	padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
+.footer-bar {
+	::v-deep .u-btn {
+		width: 100%;
+		height: 76rpx;
+		border-radius: 54rpx;
+		background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
+		&.u-btn--primary--disabled {
+			background: #a0cfff;
+		}
+	}
 }
 </style>

+ 1 - 1
uni.scss

@@ -12,7 +12,7 @@
  * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
  */
 
-@import 'uview-ui/theme.scss';
+@import '@/uni_modules/uview-ui/theme.scss';
 /* 颜色变量 */
 /* 行为相关颜色 */
 $uni-color-primary: #007aff;

+ 3 - 3
uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue

@@ -7,7 +7,7 @@
 		<block v-for="(item, index) in list" :key="index">
 			<view 
 				@touchmove.stop.prevent 
-				@tap="itemClick(index)" 
+				@tap="itemClick(item, index)" 
 				:style="[itemStyle(index)]" 
 				class="u-action-sheet-item u-line-1" 
 				:class="[index < list.length - 1 ? 'u-border-bottom' : '']"
@@ -142,10 +142,10 @@
 				this.$emit('input', false);
 			},
 			// 点击某一个item
-			itemClick(index) {
+			itemClick(item, index) {
 				// disabled的项禁止点击
 				if(this.list[index].disabled) return;
-				this.$emit('click', index);
+				this.$emit('click', { name: item.text, index });
 				this.$emit('input', false);
 			}
 		}

+ 52 - 22
uni_modules/uview-ui/components/u-form-item/u-form-item.vue

@@ -1,31 +1,36 @@
 <template>
 	<view class="u-form-item" :class="{'u-border-bottom': elBorderBottom, 'u-form-item__border-bottom--error': validateState === 'error' && showError('border-bottom')}">
-		<view class="u-form-item__body" :style="{
-			flexDirection: elLabelPosition == 'left' ? 'row' : 'column'
-		}">
+		<view class="u-form-item__body"
+			@tap="clickHandler" 
+			:style="{
+				flexDirection: elLabelPosition == 'left' ? 'row' : 'column'
+			}"
+		>
 			<!-- 微信小程序中,将一个参数设置空字符串,结果会变成字符串"true" -->
-			<view class="u-form-item--left" :style="{
-				width: uLabelWidth,
-				flex: `0 0 ${uLabelWidth}`,
-				marginBottom: elLabelPosition == 'left' ? 0 : '10rpx',
-			}">
-				<!-- 为了块对齐 -->
-				<view class="u-form-item--left__content" v-if="required || leftIcon || label">
-					<!-- nvue不支持伪元素before -->
-					<text v-if="required" class="u-form-item--left__content--required">*</text>
-					<view class="u-form-item--left__content__icon" v-if="leftIcon">
-						<u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon>
-					</view>
-					<view class="u-form-item--left__content__label" :style="[elLabelStyle, {
-						'justify-content': elLabelAlign == 'left' ? 'flex-start' : elLabelAlign == 'center' ? 'center' : 'flex-end'
-					}]">
-						{{label}}
+			<slot name="label">
+				<view class="u-form-item--left" :style="{
+					width: uLabelWidth,
+					flex: `0 0 ${uLabelWidth}`,
+					marginBottom: elLabelPosition == 'left' ? 0 : '10rpx',
+				}">
+					<!-- 为了块对齐 -->
+					<view class="u-form-item--left__content" v-if="required || leftIcon || label">
+						<!-- nvue不支持伪元素before -->
+						<text v-if="required" class="u-form-item--left__content--required">*</text>
+						<view class="u-form-item--left__content__icon" v-if="leftIcon">
+							<u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon>
+						</view>
+						<view class="u-form-item--left__content__label" :style="[elLabelStyle, {
+							'justify-content': elLabelAlign == 'left' ? 'flex-start' : elLabelAlign == 'center' ? 'center' : 'flex-end'
+						}]">
+							{{label}}
+						</view>
 					</view>
 				</view>
-			</view>
+			</slot>
 			<view class="u-form-item--right u-flex">
 				<view class="u-form-item--right__content">
-					<view class="u-form-item--right__content__slot ">
+					<view class="u-form-item--right__content__slot">
 						<slot />
 					</view>
 					<view class="u-form-item--right__content__icon u-flex" v-if="$slots.right || rightIcon">
@@ -273,7 +278,7 @@
 			// 校验数据
 			validation(trigger, callback = () => {}) {
 				// 检验之间,先获取需要校验的值
-				this.fieldValue = this.parent.model[this.prop];
+				this.fieldValue = this.getProperty(this.parent.model, this.prop);
 				// blur和change是否有当前方式的校验规则
 				let rules = this.getFilteredRule(trigger);
 				// 判断是否有验证规则,如果没有规则,也调用回调方法,否则父组件u-form会因为
@@ -299,12 +304,37 @@
 					callback(this.validateMessage);
 				});
 			},
+			getProperty(obj, key) {
+				if (!obj) {
+					return
+				}
+				if (typeof key !== 'string' || key === '') {
+					return ''
+				}
+				if (key.indexOf('.') !== -1) {
+					const keys = key.split('.')
+					let firstObj = obj[keys[0]] || {}
+
+					for (let i = 1; i < keys.length; i++) {
+						if (firstObj) {
+							firstObj = firstObj[keys[i]]
+						}
+					}
+					return firstObj
+				}
+				return obj[key]
+			},
 
 			// 清空当前的u-form-item
 			resetField() {
 				this.parent.model[this.prop] = this.initialValue;
 				// 设置为`success`状态,只是为了清空错误标记
 				this.validateState = 'success';
+			},
+
+			// 点击组件
+			clickHandler() {
+				this.$emit('click')
 			}
 		},
 

+ 7 - 2
uni_modules/uview-ui/components/u-form/u-form.vue

@@ -98,7 +98,7 @@ export default {
 		},
 		// 校验全部数据
 		validate(callback) {
-			return new Promise(resolve => {
+			return new Promise((resolve, reject) => {
 				// 对所有的u-form-item进行校验
 				let valid = true; // 默认通过
 				let count = 0; // 用于标记是否检查完毕
@@ -113,7 +113,12 @@ export default {
 						}
 						// 当历遍了所有的u-form-item时,调用promise的then方法
 						if (++count === this.fields.length) {
-							resolve(valid); // 进入promise的then方法
+							// 进入promise的then方法
+							if (valid) {
+								resolve(valid); 
+							} else {
+								reject(errorArr);
+							}
 							// 判断是否设置了toast的提示方式,只提示最前面的表单域的第一个错误信息
 							if(this.errorType.indexOf('none') === -1 && this.errorType.indexOf('toast') >= 0 && errorArr.length) {
 								this.$u.toast(errorArr[0]);

+ 3 - 1
uni_modules/uview-ui/components/u-navbar/u-navbar.vue

@@ -231,7 +231,9 @@
 					// 通过bind()方法,绑定父组件的this,让this.customBack()的this为父组件的上下文
 					this.customBack.bind(this.$u.$parent.call(this))();
 				} else {
-					uni.navigateBack();
+					uni.navigateBack({
+						delta: 1
+					});
 				}
 			}
 		}

+ 3 - 0
uni_modules/uview-ui/components/u-picker/u-picker.vue

@@ -571,6 +571,9 @@ export default {
 				if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
 				if (this.params.second) result.second = this.formatNumber(this.second || 0);
 				if (this.params.timestamp) result.timestamp = this.getTimestamp();
+				if (this.params.hour && this.params.minute) {
+					result.value = this.$u.timeFormat(this.getTimestamp(), 'hh:MM')
+				}
 			} else if (this.mode == 'region') {
 				if (this.params.province) result.province = provinces[this.province];
 				if (this.params.city) result.city = citys[this.province][this.city];