|
|
@@ -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;
|
|
|
}
|