Procházet zdrojové kódy

出餐按钮判断

baijunde před 3 týdny
rodič
revize
d0fdfd31dd

+ 7 - 0
api/merchantDish.js

@@ -203,6 +203,13 @@ const api = {
 		})
 	},
 
+	/** 商户团餐订单出餐 */
+	packageOrderReady(orderId) {
+		return http.get('/groupmeal/merchantPackageOrder/orderReady', {
+			params: { orderId }
+		})
+	},
+
 	/** 餐盒分页 */
 	mealBoxList(params = {}) {
 		return http.get(`${MEALBOX_BASE}/list`, {

+ 182 - 3
pages/merchantDish/orders/index.vue

@@ -60,9 +60,15 @@
 			>
 				<template v-slot:list="{ data }">
 					<view class="order-list">
-						<view class="order-item" v-for="item in data" :key="item.hostOrderId || item.id" @click="openOrder(item)">
+						<view
+							class="order-item"
+							:class="{ 'order-item-selectable': currentTab === 1 }"
+							v-for="item in data"
+							:key="item.hostOrderId || item.id"
+							@click="openOrder(item)"
+						>
 							<view class="order-summary">
-								<view class="summary-row date-row">
+								<view v-if="currentTab === 0" class="summary-row date-row">
 									<view class="summary-label">
 										<u-icon name="clock" color="#8b929c" size="27"></u-icon>
 										<text>预约日期:{{ getReserveDate(item) }}</text>
@@ -81,6 +87,14 @@
 									<text>{{ item.address || '暂无地址' }}</text>
 								</view>
 								<view class="region">{{ item.region || '' }}</view>
+								<view
+									v-if="currentTab === 1"
+									class="order-select summary-select"
+									:class="{ checked: isOrderSelected(item) }"
+									@click.stop="toggleOrder(item)"
+								>
+									<u-icon v-if="isOrderSelected(item)" name="checkmark" color="#fff" size="22"></u-icon>
+								</view>
 							</view>
 							<view class="product-list">
 								<view
@@ -108,6 +122,16 @@
 			</ListScrollView>
 		</view>
 
+		<view v-if="currentTab === 1" class="footer-bar">
+			<view class="select-all" @click="toggleAllOrders">
+				<view class="order-select footer-select" :class="{ checked: isAllSelected }">
+					<u-icon v-if="isAllSelected" name="checkmark" color="#fff" size="22"></u-icon>
+				</view>
+				<text>全选</text>
+			</view>
+			<view class="ready-button" :class="{ disabled: readySubmitting }" @click="handleReady">出餐</view>
+		</view>
+
 		<u-action-sheet
 			:list="mealTypeOptions"
 			v-model="mealPickerVisible"
@@ -127,6 +151,7 @@
 <script>
 import ListScrollView from '@/components/list-scroll-view/index.vue'
 import rangTime from '@/components/dengrq-datetime-picker/dateSelector/index.vue'
+import merchantDishApi from '@/api/merchantDish.js'
 
 const MEAL_TYPE_OPTIONS = [
 	{ text: '全部', value: '' },
@@ -157,6 +182,8 @@ export default {
 			startDate: '',
 			endDate: '',
 			total: 0,
+			selectedOrderKeys: [],
+			readySubmitting: false,
 			mealPickerVisible: false,
 			mealTypeOptions: MEAL_TYPE_OPTIONS,
 			actionStyle: {
@@ -188,6 +215,11 @@ export default {
 			if (!this.startDate || !this.endDate) return '选择日期'
 			return `${this.formatDateLabel(this.startDate)}-${this.formatDateLabel(this.endDate)}`
 		},
+		isAllSelected() {
+			const orders = this.getVisibleOrders()
+			const selectedCount = this.selectedOrderKeys.length
+			return orders.length > 0 && selectedCount === orders.length && orders.every((item) => this.isOrderSelected(item))
+		}
 	},
 	methods: {
 		goToDetail() {
@@ -199,6 +231,7 @@ export default {
 		},
 		onTabChange(index) {
 			this.currentTab = index
+			this.selectedOrderKeys = []
 			this.reloadList()
 		},
 		openMealPicker() {
@@ -235,8 +268,76 @@ export default {
 		openOrder(item) {
 			const orderId = this.getOrderId(item)
 			if (!orderId) return
+			const reservationParam = this.currentTab === 0 ? '&isReservation=1' : ''
 			uni.navigateTo({
-				url: `/pages/merchantDish/orders/order-details?hostOrderId=${encodeURIComponent(orderId)}`
+				url: `/pages/merchantDish/orders/order-details?hostOrderId=${encodeURIComponent(orderId)}${reservationParam}`
+			})
+		},
+		getOrderKey(item) {
+			return String(this.getOrderId(item) || '')
+		},
+		isOrderSelected(item) {
+			return this.selectedOrderKeys.includes(this.getOrderKey(item))
+		},
+		toggleOrder(item) {
+			const key = this.getOrderKey(item)
+			if (!key) return
+			const index = this.selectedOrderKeys.indexOf(key)
+			if (index >= 0) this.selectedOrderKeys.splice(index, 1)
+			else this.selectedOrderKeys.push(key)
+		},
+		getVisibleOrders() {
+			const list = this.$refs.listScroll
+			return (list && Array.isArray(list.dataList)) ? list.dataList : []
+		},
+		toggleAllOrders() {
+			if (this.isAllSelected) {
+				this.selectedOrderKeys = []
+				return
+			}
+			this.selectedOrderKeys = this.getVisibleOrders().map((item) => this.getOrderKey(item)).filter(Boolean)
+		},
+		getReadyOrderIds() {
+			const selected = this.getVisibleOrders().filter((item) => this.isOrderSelected(item))
+			return selected.reduce((ids, item) => {
+				const products = Array.isArray(item.merchantPackageOrderDTOS) ? item.merchantPackageOrderDTOS : []
+				products.forEach((product) => {
+					String(product.merchantOrderIds || product.merchantOrderId || '')
+						.split(',')
+						.map((id) => id.trim())
+						.filter(Boolean)
+						.forEach((id) => ids.push(id))
+				})
+				return ids
+			}, [])
+		},
+		handleReady() {
+			if (this.readySubmitting) return
+			const orderIds = [...new Set(this.getReadyOrderIds())]
+			if (!orderIds.length) {
+				uni.showToast({ title: '请先选择订单', icon: 'none' })
+				return
+			}
+			uni.showModal({
+				title: '提示',
+				content: '是否确认已经出餐?',
+				success: ({ confirm }) => {
+					if (!confirm) return
+					this.readySubmitting = true
+					merchantDishApi.packageOrderReady(orderIds.join(',')).then((res) => {
+						if (res.data.code !== 200) {
+							uni.showToast({ title: res.data.message || '出餐失败', icon: 'none' })
+							return
+						}
+						this.selectedOrderKeys = []
+						uni.showToast({ title: res.data.message || '出餐成功', icon: 'success' })
+						this.reloadList()
+					}).catch(() => {
+						uni.showToast({ title: '出餐失败', icon: 'none' })
+					}).finally(() => {
+						this.readySubmitting = false
+					})
+				}
 			})
 		},
 		getReserveDate(item) {
@@ -259,6 +360,7 @@ export default {
 			return String(value || '').split(',').filter(Boolean)[0] || ''
 		},
 		reloadList() {
+			this.selectedOrderKeys = []
 			this.$nextTick(() => {
 				const list = this.$refs.listScroll
 				if (list && list.mescroll) list.reloadList(this.initParams)
@@ -348,6 +450,83 @@ export default {
 	overflow: hidden;
 }
 
+.order-item-selectable {
+	position: relative;
+}
+
+.order-select {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 34rpx;
+	height: 34rpx;
+	box-sizing: border-box;
+	border: 1rpx solid #c9cdd4;
+	border-radius: 50%;
+	background: #fff;
+}
+
+.summary-select {
+	position: absolute;
+	right: 24rpx;
+	top: 50%;
+	transform: translateY(-50%);
+}
+
+.order-item-selectable .order-summary {
+	padding-right: 80rpx;
+}
+
+.order-item-selectable .date-row {
+	padding-right: 68rpx;
+}
+
+.order-select.checked {
+	border-color: #1677ff;
+	background: #1677ff;
+}
+
+.footer-bar {
+	display: flex;
+	flex-shrink: 0;
+	align-items: center;
+	justify-content: space-between;
+	min-height: 112rpx;
+	box-sizing: border-box;
+	margin: 0 -32rpx;
+	padding: 16rpx 48rpx calc(16rpx + env(safe-area-inset-bottom));
+	background: #fff;
+	box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
+}
+
+.select-all {
+	display: flex;
+	align-items: center;
+	gap: 16rpx;
+	color: #1d2129;
+	font-size: 28rpx;
+}
+
+.footer-select {
+	position: static;
+}
+
+.ready-button {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 240rpx;
+	height: 80rpx;
+	border-radius: 80rpx;
+	background: linear-gradient(93deg, #10abfe 0%, #2260f6 100%);
+	color: #fff;
+	font-size: 32rpx;
+}
+
+.ready-button.disabled {
+	opacity: 0.6;
+}
+
 .order-list {
 	padding-bottom: 24rpx;
 }

+ 4 - 1
pages/merchantDish/orders/order-details.vue

@@ -24,6 +24,7 @@
 					class="detail-item"
 				>
 					<view
+						v-if="showRefundActions"
 						class="select-circle"
 						:class="{ checked: isSelected(item, index) }"
 						@click.stop="toggleItem(item, index)"
@@ -72,7 +73,7 @@
 			</view>
 		</scroll-view>
 
-		<view v-if="!loading && detail.hostOrderId" class="footer-bar">
+		<view v-if="showRefundActions && !loading && detail.hostOrderId" class="footer-bar">
 			<view class="select-all" @click="toggleAll">
 				<view class="select-circle" :class="{ checked: isAllSelected }">
 					<u-icon v-if="isAllSelected" name="checkmark" color="#fff" size="22"></u-icon>
@@ -105,6 +106,7 @@ export default {
 			detail: {},
 			loading: true,
 			selectedKeys: [],
+			showRefundActions: false,
 			refundVisible: false,
 			refundTarget: null,
 			refundSubmitting: false
@@ -125,6 +127,7 @@ export default {
 	},
 	onLoad(query) {
 		this.hostOrderId = (query && query.hostOrderId) || ''
+		this.showRefundActions = String((query && query.isReservation) || '') === '1'
 		this.loadDetail()
 	},
 	methods: {