Bladeren bron

团餐新

baijunde 2 maanden geleden
bovenliggende
commit
ce55b19726

+ 7 - 0
common/router/modules/routes.js

@@ -617,6 +617,13 @@ const routes = [{
 			title: '编辑商品1',
 		},
 	},
+	{
+		path: '/pages/groupMeal/goods/form-day',
+		name: 'groupMealGoodsFormDay',
+		meta: {
+			title: '编辑商品售卖时间',
+		},
+	},
 	{
 		path: '/pages/groupMeal/goods/form-step2',
 		name: 'groupMealGoodsFormStep2',

+ 1 - 1
components/upload/index.vue

@@ -340,4 +340,4 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-</style>
+</style>

+ 4 - 0
pages.json

@@ -481,6 +481,10 @@
 			"path": "pages/groupMeal/goods/form-step1",
 			"style": {}
 		},
+		{
+			"path": "pages/groupMeal/goods/form-day",
+			"style": {}
+		},
 		{
 			"path": "pages/groupMeal/goods/form-step2",
 			"style": {}

+ 178 - 0
pages/groupMeal/goods/form-day.vue

@@ -0,0 +1,178 @@
+<template>
+	<view class="page-container">
+		<u-navbar title="新建团餐" :autoBack="true" :placeholder="true"></u-navbar>
+		<view class="content">
+			<view class="title">
+				售卖时间
+			</view>
+			<view class="tips">
+				商品售卖周天(可多选)
+				<span>*</span>
+			</view>
+			<view class="day-list">
+				<view class="day-item" v-for="item in dayList" :key="item.code" @click="selectDay(item)"
+					:class="{ 'selected': isDaySelected(item) }">
+					{{item.name}}
+				</view>
+			</view>
+			<view class="footer-bar">
+				<u-button :custom-style="{
+					width: '324rpx',
+					fontWeight: '400',
+					fontSize: '28rpx',
+					color: '#449AFF',
+					border: '1rpx solid #449AFF',
+					background: '#fff',
+					marginRight: '24rpx'
+				}" @click="goBack">上一步</u-button>
+				<u-button :custom-style="{
+					width: '324rpx',
+					fontWeight: '400',
+					fontSize: '28rpx',
+					color: '#449AFF',
+					border: '1rpx solid #449AFF',
+					background: '#fff',
+					marginRight: '24rpx'
+				}" @click="goNextStep">下一步</u-button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				form: {
+					dayCodes: []
+				},
+				dayList: [],
+				selectedDayCodes: []
+			}
+		},
+		methods: {
+			goBack() {
+				uni.navigateBack({
+					delta: 1
+				});
+			},
+			async getDayList() {
+				const res = await this.$http.get('/groupmeal/gmMerchantPackage/getSaleDay')
+				if (res.data.code === 200 && res.data.result) {
+					this.dayList = res.data.result
+				}
+			},
+			normalizeDayCodes(codes) {
+				const dayCodes = Array.isArray(codes) ? codes : String(codes || '').split(',');
+				return dayCodes.map(code => String(code).trim()).filter(Boolean);
+			},
+			isDaySelected(item) {
+				return this.selectedDayCodes.includes(String(item.code));
+			},
+			selectDay(item) {
+				const code = String(item.code);
+				const index = this.selectedDayCodes.indexOf(code);
+				if (index > -1) {
+					this.selectedDayCodes.splice(index, 1);
+				} else {
+					this.selectedDayCodes.push(code);
+				}
+				this.form.dayCodes = [...this.selectedDayCodes];
+			},
+			goNextStep() {
+				const dayCodes = this.normalizeDayCodes(this.selectedDayCodes);
+				if (!dayCodes.length) {
+					this.$u.toast('请选择日期');
+					return;
+				}
+				this.selectedDayCodes = dayCodes;
+				this.form.dayCodes = [...dayCodes];
+				const goods = uni.getStorageSync('gm_goods') || {};
+				goods.saleDays = dayCodes.join(',');
+				uni.setStorageSync('gm_goods', goods);
+				uni.navigateTo({
+					url: '/pages/groupMeal/goods/form-step2'
+				});
+			}
+		},
+		async onShow() {
+			await this.getDayList()
+			const goods = uni.getStorageSync('gm_goods') || {}
+			if (goods.saleDays) {
+				this.selectedDayCodes = this.normalizeDayCodes(goods.saleDays)
+				this.form.dayCodes = [...this.selectedDayCodes]
+			} else if (goods.dayCodes?.length) {
+				this.selectedDayCodes = this.normalizeDayCodes(goods.dayCodes)
+				this.form.dayCodes = [...this.selectedDayCodes]
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.page-container {
+		min-height: 100vh;
+		background-color: #f5f5f5;
+
+		.content {
+			margin: 24rpx;
+			padding: 16rpx;
+			.title{
+				font-weight: 600;
+				font-size: 30rpx;
+				color: #333333;
+				margin-bottom: 18rpx;
+				height: 44rpx;
+				line-height: 44rpx;
+			}
+			.tips{
+				height: 40rpx;
+				line-height: 40rpx;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #333333;
+				span{
+					color: red;
+				}
+			}
+		}
+	}
+
+	.day-list {
+		display: flex;
+		flex-wrap: wrap;
+		padding: 16rpx;
+		.day-item {
+			margin: 0 38rpx 16rpx 0;
+			width: 132rpx;
+			height: 58rpx;
+			font-size: 26rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			box-sizing: border-box;
+			&:nth-child(4n) {
+				margin-right: 0;
+			}
+			&.selected {
+				color: #2983EC;
+				font-weight: bold;
+				border: 1rpx solid #2983EC;
+				background: rgba(68,154,255,0.1);
+				border-radius: 8rpx;
+			}
+		}
+	}
+
+	.footer-bar {
+		::v-deep .u-btn {
+			width: 324rpx;
+			height: 76rpx;
+			border-radius: 54rpx;
+
+			&::after {
+				display: none;
+			}
+		}
+	}
+</style>

+ 114 - 23
pages/groupMeal/goods/form-step1.vue

@@ -16,7 +16,12 @@
 				<u-form-item prop="name" label="商品名称" required borderBottom>
 					<u-input v-model="form.name" placeholder="请输入商品名称" height="41" inputAlign="right"></u-input>
 				</u-form-item>
-
+				
+				<u-form-item prop="specialCategoryId" label="特色分类" required borderBottom @click="showSpecial = true">
+					<u-input v-model="form.specialCategoryName" class="form-input" disabled placeholder="去设置" height="41" inputAlign="right"></u-input>
+					<u-icon slot="right" name="arrow-right" color="#C7C6CA"></u-icon>
+				</u-form-item>
+				
 				<u-form-item prop="productImage" label="商品封面图" required labelPosition="top">
 					<view class="upload-content">
 						<view class="upload-tip">支持jpg、png格式,建议尺寸为750px*750px,上传1-4张</view>
@@ -65,6 +70,15 @@
 					></u-input>
 					<text slot="right" class="input-suffix">元</text>
 				</u-form-item>
+				
+				<u-form-item prop="dailyStock" label="库存" required :borderBottom="true">
+					<u-input type="number" height="41" :clearable="false" 
+					 	inputAlign="right" placeholder="请输入每日库存"
+						v-model="form.dailyStock"
+					></u-input>
+					<text slot="right" class="input-suffix">份</text>
+				</u-form-item>
+				<view class="tips">每日库存最大量的设置,当天售完后关闭该团餐</view>
 			</u-form>
 		</view>
 
@@ -73,6 +87,8 @@
 		</view>
 		<!-- 商品分类选择 -->
 		<u-action-sheet :list="actionSheetList" v-model="show" @click="actionSheetCallback"></u-action-sheet>
+		<!-- 特色分类 -->
+		<u-action-sheet :list="categoryList" v-model="showSpecial" @click="specialCategoryCallback"></u-action-sheet>
 	</view>
 </template>
 
@@ -84,16 +100,23 @@ export default {
 		Upload,
 	},
 	data() {
-		return {
-			show: false,
-			form: {
-				name: '',
-				category: '',
-				productImage: '',
-				detailImages: '',
-				price: '',
-				sellingPrice: '',
-			},
+			return {
+				show: false,
+				showSpecial: false,
+				form: {
+					name: '',
+					category: '',
+					categoryName: '',
+					specialCategoryId: '',
+					specialCategoryName: '',
+					productImage: 'https://test.baoxianzhanggui.com/locallive-java/product/企业微信截图_1781494923590_1781494943931.png',
+					detailImages: 'https://test.baoxianzhanggui.com/locallive-java/product/企业微信截图_1781494923590_1781494943931.png',
+					price: '',
+					sellingPrice: '',
+					dailyStock:null,
+					saleDays:''
+				},
+			categoryList:[],
 			query: {},
 			fileList: {
 				cover: [],
@@ -124,7 +147,14 @@ export default {
 				category: [
 					{
 						required: true,
-						message: '请选择分类',
+						message: '请选择商品分类',
+						trigger: ['blur', 'change']
+					}
+				],
+				specialCategoryId: [
+					{
+						required: true,
+						message: '请选择特色分类',
 						trigger: ['blur', 'change']
 					}
 				],
@@ -178,31 +208,65 @@ export default {
 						trigger: ['blur', 'change']
 					}
 				],
+				dailyStock:[
+					{
+						required: true,
+						type: 'number',
+						message: '请填写库存',
+						trigger: ['blur', 'change']
+					}
+				]
 			}
 		};
 	},
-	onLoad(query) {
+	async onLoad(query) {
+			
 		if (query.id) {
 			this.query = query;
-			this.getData();
+		  await	this.getCategoryList()
+			await this.getData();
 		}
 		// 清除
 		uni.removeStorageSync('gm_goods');
 		// 获取餐品分类
 		this.getClassData();
+		
+	},
+	onShow() {
+		
 	},
 	onReady() {
 		this.$refs.uForm.setRules(this.rules);
 	},
 	methods: {
+		//获取特色分类
+		getCategoryList(){
+			this.$http.get('/groupmeal/gmSpecialCategory/listAll').then(res => {
+				if (res.data.code === 200 && res.data.result) {
+					this.categoryList = res.data.result.map(item => {
+						return {
+							text: item.categoryName,
+							value: item.id 
+						}
+					})
+				}
+			})
+		},
 		// 编辑数据
 		getData() {
 			this.$http.get('/groupmeal/gmCustomerPackage/queryById', { params: { id: this.query.id } }).then(res => {
 				if (res.data.code === 200) {
 					let data = res.data.result;
+					// 查找商品分类名称
+					const categoryItem = this.actionSheetList.find(item => item.value == data.category);
+					// 查找特色分类名称
+					const specialCategoryItem = this.categoryList.find(item => item.value == data.specialCategoryId);
+					console.log(specialCategoryItem)
 					this.form = {
 						...data,
-						categoryName: this.actionSheetList.find(item => item.value == data.category).text
+						categoryName: categoryItem ? categoryItem.text : '',
+						specialCategoryId: data.specialCategoryId+'',
+						specialCategoryName: specialCategoryItem ? specialCategoryItem.text : ''
 					};
 					this.fileList = {
 						cover: data.productImage.split(',').map(item => {
@@ -232,11 +296,17 @@ export default {
 				}
 			});
 		},
-		// 分类选择,打开弹窗
+		// 商品分类选择回调
 		actionSheetCallback(e) {
 			this.form.category = e.value;
 			this.form.categoryName = e.text;
 		},
+		// 特色分类选择回调
+		specialCategoryCallback(e) {
+			console.log(e)
+			this.form.specialCategoryId = e.value;
+			this.form.specialCategoryName = e.text;
+		},
 		// 价格数值处理
 		onInput(value, key) {
 			// 过滤所有非数字和非小数点的字符
@@ -267,18 +337,17 @@ export default {
 		// 图片处理
 		onUpload(event, type) {
 			this.fileList[type] = event;
-			this.form[type === 'cover' ? 'productImage' : 'detailImages'] = this.fileList[type].map(f => `${configService.apiUrl}/${f.message}`).join();
+			this.form[type == 'cover' ? 'productImage' : 'detailImages'] = this.fileList[type].map(f => f.url).join();
 		},
 		// 下一步
 		goNextStep() {
 			// 表单校验
 			this.$refs.uForm.validate(valid => {
 				if (valid) {
-					console.log('Form Data:', this.form, this.fileList);
-					const { categoryName, ...form } = this.form;
+					const { categoryName, specialCategoryName, ...form } = this.form;
 					uni.setStorageSync('gm_goods', form);
 					uni.navigateTo({
-						url: '/pages/groupMeal/goods/form-step2'
+						url: '/pages/groupMeal/goods/form-day'
 					});
 				} else {
 					console.log('验证失败');
@@ -300,12 +369,13 @@ $uni-color-primary: #2979ff;
 		font-weight: 500;
 		font-size: 30rpx;
 		color: #333333;
+		margin-bottom: 32rpx;
 	}
 }
 
 .form-card {
 	margin: 24rpx;
-	padding: 20rpx 24rpx;
+	padding: 16rpx 16rpx;
 	background-color: #fff;
 	border-radius: 16rpx;
 
@@ -314,6 +384,9 @@ $uni-color-primary: #2979ff;
 		line-height: 1;
 		.u-form-item--left__content {
 			flex: none;
+			.u-form-item--left__content__label {
+				font-weight: 600;
+			}
 			.u-form-item--left__content--required {
 				color: #fa3534; 
 				left: auto;
@@ -346,10 +419,28 @@ $uni-color-primary: #2979ff;
 		}
 
 		::v-deep .u-add-tips {
-			margin-top: 10rpx;
+			display: none !important;
+		}
+
+		::v-deep .u-add-wrap {
+			background: url('/static/groupMeal/upload.png') center center / 100% 100% no-repeat !important;
+			border: none !important;
+		}
+
+		::v-deep .u-add-btn {
+			display: none !important;
 		}
 	}
 }
+.tips{
+	
+	width: 100%;
+	font-weight: 400;
+	font-size: 20rpx;
+	color: #999999;
+	margin-top: 66rpx;
+	text-align: center;
+}
 
 // 底部按钮
 .footer-bar {
@@ -404,4 +495,4 @@ $uni-color-primary: #2979ff;
 		padding-top: 30rpx;
 	}
 }
-</style>
+</style>

+ 356 - 317
pages/groupMeal/goods/form-step2.vue

@@ -1,32 +1,19 @@
 <template>
 	<view class="page-container">
 		<u-navbar title="新建团餐" :autoBack="true" :placeholder="true"></u-navbar>
-		
+
 		<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="{
+			<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"
-				>
+					}" 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>
 						<text class="num" v-if="isEditedShow(category)">({{ category.items.length }})</text>
-						<u-switch 
-							v-if="false"
-							size="20"
-							activeColor="#3c9cff"
-							:value="category.isActive" 
-							@change="onSwitchChange($event, category.id)" 
-						></u-switch>
+						<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">
@@ -34,50 +21,48 @@
 									<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-form">
-								<u-form-item label="名称" :prop="`dishCategories.${catIndex}.items.${dishIndex}.name`" :required="isEdited(dish)">
+								<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.number="dish.price" type="digit" height="41" placeholder="输入金额" :clearable="false" inputAlign="right"></u-input>
+								<u-form-item label="价格" :prop="`dishCategories.${catIndex}.items.${dishIndex}.price`"
+									:required="isEdited(dish)">
+									<u-input v-model.number="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-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 class="dish-actions">
+								<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>
+								<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>
+								
 							</view>
 						</view>
 					</view>
@@ -86,8 +71,7 @@
 		</u-form>
 
 		<view class="footer-bar">
-			<u-button 
-				:custom-style="{
+			<u-button :custom-style="{
 					width: '205rpx',
 					fontWeight: '400',
 					fontSize: '28rpx',
@@ -95,306 +79,361 @@
 					border: '1rpx solid #449AFF',
 					background: '#fff',
 					marginRight: '24rpx'
-				}"
-				@click="goBack"
-			>上一步</u-button>
-			<u-button
-				:custom-style="{
+				}" @click="goBack">上一步</u-button>
+			<u-button :custom-style="{
 					fontWeight: '400',
 					fontSize: '28rpx',
 					color: '#FFFFFF',
 					background: 'linear-gradient(90deg, #77B6FF 0%, #449AFF 100%)',
-				}"
-				@click="submit"
-			>提交审核</u-button>
+				}" @click="submit">提交审核</u-button>
 		</view>
 	</view>
 </template>
 
 <script>
-let dishIdCounter = 100; // 简单的唯一ID生成器
-export default {
-	data() {
-		return {
-			// 数据
-			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
-		}
-	},
-	onLoad() {
-		const goods = uni.getStorageSync('gm_goods');
-		if (goods.gmMerchantPackageDetails && goods.gmMerchantPackageDetails.length > 0) {
-			this.form.dishCategories.map(a => {
-				let items = goods.gmMerchantPackageDetails.filter(b => b.category == a.id);
-				if (items.length > 0) a.items = items;
-			});
-		}
-	},
-	mounted() {
-		this.$nextTick(() => {
-			this.$refs.formRef.setRules(this.rules);
-		});
-	},
-	methods: {
-		// 判断一个菜品是否被编辑过
-		isEdited(dish) {
-			return !!(dish.name || dish.price || dish.description);
-		},
-		isEditedShow(e) {
-			const goods = uni.getStorageSync('gm_goods');
-			return goods.gmMerchantPackageDetails && goods.gmMerchantPackageDetails.length > 0 && goods.gmMerchantPackageDetails.some(b => b.category == e.id);;
-		},
-		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, type: 'number', message: '请输入价格', trigger: ['blur', 'change'] }];
-						newRules[descProp] = [{ required: true, message: '请输入描述', trigger: ['blur', 'change'] }];
-					}
-				});
-			});
-			
-			this.rules = newRules;
-			this.$refs.formRef.setRules(this.rules);
+	let dishIdCounter = 100; // 简单的唯一ID生成器
+	export default {
+		data() {
+			return {
+				// 数据
+				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数组
+			};
 		},
-		// Switch开关状态变化
-		onSwitchChange(isActive, categoryId) {
-			const index = this.activeNames.indexOf(categoryId);
-			if (isActive) {
-				if (index === -1) {
-					this.activeNames.push(categoryId);
-				}
-			} else {
-				if (index > -1) {
-					this.activeNames.splice(index, 1);
-				}
+		watch: {
+			'form.dishCategories': {
+				handler() {
+					this.$nextTick(() => {
+						this.updateValidationRules();
+					});
+				},
+				deep: true
 			}
 		},
-		// 折叠面板状态变化
-		onCollapseChange(names) {
-			console.log(names)
-			this.activeNames = names;
-		},
-		// 添加菜品
-		addDish(categoryId) {
-			const category = this.form.dishCategories.find(c => c.id === categoryId);
-			if (category) {
-				category.items.push({
-					id: dishIdCounter++,
-					name: '',
-					price: '',
-					description: ''
+		onLoad() {
+			const goods = uni.getStorageSync('gm_goods');
+			if (goods.gmMerchantPackageDetails && goods.gmMerchantPackageDetails.length > 0) {
+				this.form.dishCategories.map(a => {
+					let items = goods.gmMerchantPackageDetails.filter(b => b.category == a.id);
+					if (items.length > 0) a.items = items;
 				});
 			}
 		},
-		// 删除菜品
-		removeDish(categoryId, dishId) {
-			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) {
-					category.items.splice(index, 1);
-				}
-			}
-		},
-		// 上一步
-		goBack() {
-			uni.navigateBack({
-				delta: 1
+		mounted() {
+			this.$nextTick(() => {
+				this.$refs.formRef.setRules(this.rules);
 			});
 		},
-		// 提交审核
-		submit() {
-			this.$refs.formRef.validate().then(res => {
+		methods: {
+			// 判断一个菜品是否被编辑过
+			isEdited(dish) {
+				return !!(dish.name || dish.price || dish.description);
+			},
+			isEditedShow(e) {
 				const goods = uni.getStorageSync('gm_goods');
-				const activeCategories = this.form.dishCategories.filter(c => c.items.some(this.isEdited));
-				const details = [];
-				// 遍历一级分类
-				activeCategories.forEach(category => {
-					// 检查是否有items属性且为数组
-					if (category.items && Array.isArray(category.items)) {
-						// 遍历二级菜品
-						category.items.forEach(item => {
-							// 创建新对象,只保留需要的属性
-							if (this.isEdited(item)) {
-								details.push({
-									category: category.id,
-									name: item.name,
-									price: item.price,
-									description: item.description
-								});
-							}
-						});
-					}
+				return goods.gmMerchantPackageDetails && goods.gmMerchantPackageDetails.length > 0 && goods
+					.gmMerchantPackageDetails.some(b => b.category == e.id);;
+			},
+			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,
+								type: 'number',
+								message: '请输入价格',
+								trigger: ['blur', 'change']
+							}];
+							newRules[descProp] = [{
+								required: true,
+								message: '请输入描述',
+								trigger: ['blur', 'change']
+							}];
+						}
+					});
 				});
-				let params = {
-					...goods,
-					gmMerchantPackageDetails: [...details]
-				};
-				console.log('表单校验成功, 提交的数据:', activeCategories, params);
-				this.$http.post('/groupmeal/gmMerchantPackage/submit', params).then(res => {
-					let type = res.data.code === 200 ? 'success' : 'error';
-					this.$tip[type](res.data.message);
-					if (res.data.code === 200) {
-						// 清除
-						uni.removeStorageSync('gm_goods');
-						// 返回列表
-						uni.navigateBack({
-							delta: 2
-						});
+
+				this.rules = newRules;
+				this.$refs.formRef.setRules(this.rules);
+			},
+			// Switch开关状态变化
+			onSwitchChange(isActive, categoryId) {
+				const index = this.activeNames.indexOf(categoryId);
+				if (isActive) {
+					if (index === -1) {
+						this.activeNames.push(categoryId);
+					}
+				} else {
+					if (index > -1) {
+						this.activeNames.splice(index, 1);
 					}
+				}
+			},
+			// 折叠面板状态变化
+			onCollapseChange(names) {
+				console.log(names)
+				this.activeNames = names;
+			},
+			// 添加菜品
+			addDish(categoryId) {
+				const category = this.form.dishCategories.find(c => c.id === categoryId);
+				if (category) {
+					category.items.push({
+						id: dishIdCounter++,
+						name: '',
+						price: '',
+						description: ''
+					});
+				}
+			},
+			// 删除菜品
+			removeDish(categoryId, dishId) {
+				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) {
+						category.items.splice(index, 1);
+					}
+				}
+			},
+			// 上一步
+			goBack() {
+				uni.navigateBack({
+					delta: 1
 				});
-			}).catch(errors => {
-				console.log('校验失败', errors);
-			});
+			},
+			// 提交审核
+			submit() {
+				this.$refs.formRef.validate().then(res => {
+					const goods = uni.getStorageSync('gm_goods');
+					const activeCategories = this.form.dishCategories.filter(c => c.items.some(this.isEdited));
+					const details = [];
+					// 遍历一级分类
+					activeCategories.forEach(category => {
+						// 检查是否有items属性且为数组
+						if (category.items && Array.isArray(category.items)) {
+							// 遍历二级菜品
+							category.items.forEach(item => {
+								// 创建新对象,只保留需要的属性
+								if (this.isEdited(item)) {
+									details.push({
+										category: category.id,
+										name: item.name,
+										price: item.price,
+										description: item.description
+									});
+								}
+							});
+						}
+					});
+					let params = {
+						...goods,
+						gmMerchantPackageDetails: [...details]
+					};
+					console.log('表单校验成功, 提交的数据:', activeCategories, params);
+					this.$http.post('/groupmeal/gmMerchantPackage/submit', params).then(res => {
+						let type = res.data.code === 200 ? 'success' : 'error';
+						this.$tip[type](res.data.message);
+						if (res.data.code === 200) {
+							// 清除
+							uni.removeStorageSync('gm_goods');
+							// 返回列表
+							uni.navigateBack({
+								delta: 3
+							});
+						}
+					});
+				}).catch(errors => {
+					console.log('校验失败', errors);
+				});
+			}
 		}
-	}
-};
+	};
 </script>
 
 <style lang="scss" scoped>
-.page-container {
-	min-height: 100vh;
-	background-color: #f5f5f5;
-	padding-bottom: 160rpx;
+	.page-container {
+		min-height: 100vh;
+		background-color: #f5f5f5;
+		padding-bottom: 160rpx;
 
-	::v-deep .u-collapse-item {
-		margin-bottom: 16rpx;
-		.u-collapse-head {
-			padding: 20rpx 32rpx;
-			background-color: #fff;
-		}
-		&.active {
-			.u-collapse-body {
-				height: auto !important;
+		::v-deep .u-collapse-item {
+			margin-bottom: 16rpx;
+
+			.u-collapse-head {
+				padding: 20rpx 32rpx;
+				background-color: #fff;
+			}
+
+			&.active {
+				.u-collapse-body {
+					height: auto !important;
+				}
 			}
 		}
-	}
 
-	.collapse-title {
-		font-weight: 500;
-		font-size: 32rpx;
-		color: #333333;
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		.num {
-			padding: 0 10rpx;
+		.collapse-title {
+			font-weight: 500;
+			font-size: 32rpx;
+			color: #333333;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+
+			.num {
+				padding: 0 10rpx;
+			}
 		}
-	}
-	.collapse-content {
-		.dish-item {
-			margin-top: 16rpx;
-			padding: 20rpx 32rpx;
-			background: #FFFFFF;
-			box-shadow: 0 2rpx 8rpx 0 rgba(214,225,237,0.1);
-			border: 1rpx solid #F0F3F5;
-			border-radius: 16rpx;
-			.dish-header {
-				margin-bottom: 20rpx;
-				display: flex;
-				align-items: center;
-				justify-content: space-between;
-				.dish-title {
-					font-size: 28rpx;
-					color: #333333;
+
+		.collapse-content {
+			.dish-item {
+				margin-top: 16rpx;
+				padding: 20rpx 32rpx;
+				background: #FFFFFF;
+				box-shadow: 0 2rpx 8rpx 0 rgba(214, 225, 237, 0.1);
+				border: 1rpx solid #F0F3F5;
+				border-radius: 16rpx;
+
+				.dish-header {
+					margin-bottom: 20rpx;
 					display: flex;
 					align-items: center;
-				}
-				.dish-actions {
-					display: flex;
-					gap: 16rpx;
-					::v-deep .u-btn {
-						font-weight: 400;
-						font-size: 22rpx;
-					}
-					.text {
+					justify-content: space-between;
+
+					.dish-title {
+						font-size: 28rpx;
+						color: #333333;
 						display: flex;
 						align-items: center;
-						text {
-							line-height: 1;
-							margin-left: 4rpx;
-						}
 					}
+
 				}
-			}
-			.dish-form {
-				padding: 6rpx 16rpx;
-				border-radius: 8rpx;
-				background: #F7F8FC;
-			}
-			::v-deep .u-form-item {
-				padding: 16rpx 0;
-				line-height: 1;
-				.u-form-item--left__content {
-					flex: none;
+
+				.dish-form {
+					padding: 6rpx 16rpx;
+					border-radius: 8rpx;
+					background: #F7F8FC;
+				}
+
+				::v-deep .u-form-item {
+					padding: 16rpx 0;
+					line-height: 1;
+
+					.u-form-item--left__content {
+						flex: none;
+					}
 				}
 			}
 		}
 	}
-}
 
-.footer-bar {
-	::v-deep .u-btn {
+	.dish-actions {
 		width: 100%;
-		height: 76rpx;
-		border-radius: 54rpx;
-		&::after {
-			display: none;
+		text-align: end;
+		margin-top: 16rpx;
+		// display: flex;
+		// align-items: center;
+		// justify-content: end;
+		// gap: 16rpx;
+		
+
+		::v-deep .u-btn {
+			font-weight: 400;
+			font-size: 22rpx;
+			margin-left: 16rpx;
+		}
+
+		.text {
+			display: flex;
+			align-items: center;
+
+			text {
+				line-height: 1;
+				margin-left: 4rpx;
+			}
+		}
+	}
+
+	.footer-bar {
+		::v-deep .u-btn {
+			width: 100%;
+			height: 76rpx;
+			border-radius: 54rpx;
+
+			&::after {
+				display: none;
+			}
 		}
 	}
-}
-</style>
+</style>

+ 7 - 5
pages/groupMeal/orders/order-alist.vue

@@ -5,7 +5,7 @@
 			<view class="navbar-title">团餐订单</view>
 			<view slot="right" class="navbar-right">
 				<text class="nav-btn" @click="goToDetail">订单明细</text>
-				<text class="nav-btn manage-btn" v-if="currentStatusTab == 0" @click="toggleManageMode">{{ isManaging ? '退出管理' : '批量管理' }}</text>
+				<!-- <text class="nav-btn manage-btn" v-if="currentStatusTab == 0" @click="toggleManageMode">{{ isManaging ? '退出管理' : '批量管理' }}</text> -->
 			</view>
 		</u-navbar>
 
@@ -27,12 +27,14 @@
 		<u-tabs :list="statusTabs" 
 			:current="currentStatusTab" 
 			inactive-color="#666666"
+			:bar-width="72"
 			:bar-style="{
 				bottom: '20rpx',
+				marginLeft: '-12rpx',
 				background: 'linear-gradient(90deg, #82BCFF 0%, rgba(130,188,255,0) 100%)'
 			}"
 			:active-item-style="{
-				fontWeight: '500',
+				fontWeight: '600',
 				fontSize: '32rpx',
 				color: '#000000',
 			}"		
@@ -40,7 +42,7 @@
 		></u-tabs>
 
 		<!-- 订单列表 -->
-		<view class="order-scroll-view" :style="{ paddingBottom: isManaging ? '120rpx' : '0' }">
+		<view class="order-scroll-view" >
 			<ListScrollView ref="listScroll" 
 				:api="api"
 				:init="{
@@ -70,7 +72,7 @@
 										<view class="btext">{{ item.region }}</view>
 									</view>
 								</view>
-								<view class="order-actions" v-if="isManaging">
+								<view class="order-actions" >
 									<u-checkbox :name="item.orderId" shape="circle" v-model="item.checked"></u-checkbox>
 								</view>
 							</view>
@@ -97,7 +99,7 @@
 		</view>
 
 		<!-- 批量操作底部栏 -->
-		<view class="footer-bar" v-if="isManaging">
+		<view class="footer-bar" >
 			<u-checkbox-group v-model="isAllSelected" placement="row">
 				<u-checkbox name="all" shape="circle" v-model="isAllSelected" @change="onSelectAll">全选</u-checkbox>
 			</u-checkbox-group>

BIN
static/groupMeal/upload.png