From e56792f78e4df0df2f12552d1a61dd8ca1db5c67 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期一, 27 四月 2026 22:26:28 +0800
Subject: [PATCH] app
---
app/pages/order/order.vue | 493 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 457 insertions(+), 36 deletions(-)
diff --git a/app/pages/order/order.vue b/app/pages/order/order.vue
index ab8b487..faa455c 100644
--- a/app/pages/order/order.vue
+++ b/app/pages/order/order.vue
@@ -19,7 +19,7 @@
<view class="order-card__head">
<view class="order-card__head-left">
<image class="order-card__badge-icon" :src="getBadgeIcon(item)" mode="widthFix"></image>
- <text class="order-card__time-text">{{ item.code }}</text>
+ <text class="order-card__time-text">涓嬪崟鏃堕棿锛歿{ item.createTime }}</text>
</view>
<text class="order-card__status" :class="{ 'order-card__status--highlight': item.status === 3 || item.status === 4 }">{{ getStatusText(item.status) }}</text>
</view>
@@ -51,15 +51,20 @@
</view>
<view v-if="getActions(item).length" class="order-card__actions">
- <button
- v-for="action in getActions(item)"
- :key="action.text"
- class="order-card__action-btn"
- :class="['order-card__action-btn--' + action.type, { 'order-card__action-btn--primary-fill': action.fill }]"
- hover-class="order-card__action-btn--hover"
- >
- {{ action.text }}
- </button>
+ <view></view>
+ <view style="display: flex;flex-wrap: wrap;gap: 20rpx;">
+ <button
+ v-for="action in getActions(item)"
+ :key="action.text"
+ class="order-card__action-btn"
+ :class="['order-card__action-btn--' + action.type, { 'order-card__action-btn--primary-fill': action.fill }]"
+ hover-class="order-card__action-btn--hover"
+ @click.stop="handleAction(item, action)"
+ >
+ {{ action.text }}
+ </button>
+ </view>
+
</view>
</view>
@@ -72,6 +77,70 @@
</view>
</view>
</scroll-view>
+
+ <u-modal
+ :show="showCancelModal"
+ showCancelButton
+ @cancel="showCancelModal = false"
+ cancelColor="#666666"
+ confirmColor="#0055FF"
+ title="鍙栨秷璁㈠崟纭"
+ @confirm="confirmCancelOrder">
+ <view style="text-align: center;color: #333333;font-size: 28rpx;font-weight: 400;">
+ 鎮ㄤ粖鏃ヨ繕鍙彇娑� {{ cancelRemain }} 娆¤鍗曪紝娆℃暟鐢ㄥ敖鍚庝粖鏃ュ皢鏃犳硶鎺ュ崟锛屾槸鍚︾‘璁ゅ彇娑堬紵
+ </view>
+ </u-modal>
+
+ <u-popup :show="showQRPopup" round="20" mode="bottom">
+ <view class="qrcode">
+ <view class="qrcode-title">
+ <image src="/static/image/ic_close@2x.png" mode="widthFix" style="opacity: 0;"></image>
+ <text>{{ selectedOrder && selectedOrder.status === 4 ? '瀛樹欢鐮�' : '鍙栬揣鐮�' }}</text>
+ <image src="/static/image/ic_close@2x.png" mode="widthFix" @click="showQRPopup = false"></image>
+ </view>
+ <view class="qrcode-image">
+ <image v-if="selectedOrder && selectedOrder.driverVerifyCode" :src="'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' + selectedOrder.driverVerifyCode" mode="widthFix"></image>
+ </view>
+ <view class="qrcode-btn" hover-class="qrcode-btn--hover" @click="showQRPopup = false">鍏抽棴</view>
+ </view>
+ </u-popup>
+
+ <u-popup :show="showPhotoPopup" round="20" mode="bottom">
+ <view class="photo-popup">
+ <view class="photo-popup__header">
+ <view class="photo-popup__placeholder"></view>
+ <text class="photo-popup__title">{{ photoPopupTitle }}</text>
+ <image class="photo-popup__close" src="/static/image/ic_close2@2x.png" mode="aspectFit" @click="closePhotoPopup"></image>
+ </view>
+
+ <view class="photo-popup__section">
+ <view class="photo-popup__label-row">
+ <text class="photo-popup__label">{{ photoPopupLabel }}</text>
+ <text class="photo-popup__required">*</text>
+ <text class="photo-popup__hint">鏈�澶�3寮犵収鐗�</text>
+ </view>
+
+ <view class="photo-popup__photos">
+ <view v-for="(photo, index) in uploadedPhotos" :key="index" class="photo-popup__preview-card">
+ <image class="photo-popup__preview-image" :src="photo" mode="aspectFill"></image>
+ <view class="photo-popup__preview-mask" @click="deletePhoto(index)">
+ <text class="photo-popup__preview-delete">鍒犻櫎</text>
+ </view>
+ </view>
+ <view v-if="uploadedPhotos.length < 3" class="photo-popup__upload-btn" @click="choosePhoto">
+ <image src="/static/image/btn_upload2@2x.png" mode="aspectFit"></image>
+ </view>
+ </view>
+ </view>
+
+ <view class="photo-popup__section photo-popup__section--remark">
+ <text class="photo-popup__remark-title">澶囨敞淇℃伅</text>
+ <textarea v-model="photoRemark" class="photo-popup__textarea" maxlength="200" placeholder="璇疯緭鍏�" placeholder-style="color: #c7cbd3;" />
+ </view>
+
+ <button class="photo-popup__submit" hover-class="photo-popup__submit--hover" @click="submitPhotoPopup">{{ photoPopupSubmitText }}</button>
+ </view>
+ </u-popup>
</view>
</template>
@@ -91,29 +160,34 @@
orders: [],
page: 1,
hasMore: true,
- loading: false
+ loading: false,
+ showCancelModal: false,
+ showQRPopup: false,
+ showPhotoPopup: false,
+ selectedOrder: null,
+ cancelRemain: 0,
+ photoPopupMode: '',
+ photoRemark: '',
+ uploadedPhotos: [],
+ activeOrderCount: null
}
},
computed: {
displayTabs() {
- const countMap = {}
- this.tabs.forEach(tab => {
- if (tab.value === null) {
- countMap[null] = this.orders.length
- } else {
- countMap[tab.value] = this.orders.filter((item) => item.status === tab.value).length
- }
- })
-
return this.tabs.map((tab) => {
- if (!countMap[tab.value]) {
- return tab
+ let count = null
+ if (tab.value === 3) {
+ count = this.activeOrderCount?.grabbedCount
+ } else if (tab.value === 4) {
+ count = this.activeOrderCount?.deliveringCount
}
-
- return {
- ...tab,
- label: `${tab.label} ${countMap[tab.value]}`
+ if (count) {
+ return {
+ ...tab,
+ label: `${tab.label} ${count}`
+ }
}
+ return tab
})
},
@@ -122,6 +196,15 @@
marginTop: this.navHeight + uni.upx2px(88) + 'px',
height: `calc(100vh - ${this.navHeight + uni.upx2px(88)}px)`
}
+ },
+ photoPopupTitle() {
+ return this.photoPopupMode === 'deliver' ? '鎷嶇収閫佽揪' : '鎷嶇収鍙栬揣'
+ },
+ photoPopupLabel() {
+ return this.photoPopupMode === 'deliver' ? '鎷嶆憚閫佽揪鐓х墖' : '鎷嶆憚鍙栬揣鐓х墖'
+ },
+ photoPopupSubmitText() {
+ return this.photoPopupMode === 'deliver' ? '纭閫佽揪' : '纭鍙栬揣'
}
},
onLoad() {
@@ -131,10 +214,7 @@
this.getOrderList()
},
onShow() {
- this.page = 1
- this.hasMore = true
- this.orders = []
- this.getOrderList()
+ this.getActiveOrderCount()
},
onReachBottom() {
if (!this.hasMore || this.loading) return
@@ -150,6 +230,17 @@
}
},
methods: {
+ getActiveOrderCount() {
+ this.$u.api.activeOrderCount().then(res => {
+ if (res.code === 200) {
+ this.activeOrderCount = res.data
+ } else {
+ this.activeOrderCount = null
+ }
+ }).catch(() => {
+ this.activeOrderCount = null
+ })
+ },
getBadgeIcon(item) {
return item.isUrgent ? '/static/image/ic_jisuda@2x.png' : '/static/image/ic_biaosuda@2x.png'
},
@@ -158,6 +249,7 @@
2: '寰呮帴鍗�',
3: '寰呭彇璐�',
4: '閰嶉�佷腑',
+ 5: '宸插畬鎴�',
7: '宸插畬鎴�',
99: '宸插彇娑�'
}
@@ -171,9 +263,14 @@
{ text: '鎷嶇収鍙栬揣', type: 'primary', fill: true }
]
}
- if (item.status === 4) {
+ if (item.status === 4 && item.takeShopId) {
return [
{ text: '瀛樹欢鐮�', type: 'primary', fill: false }
+ ]
+ }
+ if (item.status === 4 && !item.takeShopId) {
+ return [
+ { text: '鎷嶇収閫佽揪', type: 'primary', fill: true }
]
}
return []
@@ -197,15 +294,140 @@
}
this.hasMore = list.length >= 10
}
- }).catch((err) => {
- console.log(err)
}).finally(() => {
this.loading = false
})
},
goToOrderDetail(item, index) {
uni.navigateTo({
- url: `/pages/order-detail/order-detail?id=${item.id}&index=${index + 1}`
+ url: `/pages/order-detail/order-detail?id=${item.id}`
+ })
+ },
+ handleAction(item, action) {
+ const text = action.text
+ if (text === '鍙栨秷璁㈠崟') {
+ this.handleCancelOrder(item)
+ } else if (text === '鍙栬揣鐮�' || text === '瀛樹欢鐮�') {
+ this.handleShowQRCode(item)
+ } else if (text === '鎷嶇収鍙栬揣') {
+ this.handlePhotoPickup(item)
+ } else if (text === '鎷嶇収閫佽揪') {
+ this.handlePhotoDeliver(item)
+ }
+ },
+ handleCancelOrder(item) {
+ this.selectedOrder = item
+ this.$u.api.cancelLimit().then(res => {
+ if (res.code === 200) {
+ this.cancelRemain = res.data.remain
+ }
+ }).finally(() => {
+ this.showCancelModal = true
+ })
+ },
+ confirmCancelOrder() {
+ if (!this.selectedOrder) return
+ this.$u.api.cancelOrder({ orderId: this.selectedOrder.id }).then(res => {
+ this.showCancelModal = false
+ if (res.code === 200) {
+ uni.showToast({ title: '鍙栨秷鎴愬姛', icon: 'success' })
+ this.getOrderList()
+ this.getActiveOrderCount()
+ } else {
+ uni.showToast({ title: res.message || '鍙栨秷澶辫触', icon: 'none' })
+ }
+ }).catch(() => {
+ this.showCancelModal = false
+ })
+ },
+ handleShowQRCode(item) {
+ this.selectedOrder = item
+ this.showQRPopup = true
+ },
+ handlePhotoPickup(item) {
+ this.selectedOrder = item
+ this.photoPopupMode = 'pickup'
+ this.uploadedPhotos = []
+ this.photoRemark = ''
+ this.showPhotoPopup = true
+ },
+ handlePhotoDeliver(item) {
+ this.selectedOrder = item
+ this.photoPopupMode = 'deliver'
+ this.uploadedPhotos = []
+ this.photoRemark = ''
+ this.showPhotoPopup = true
+ },
+ closePhotoPopup() {
+ this.showPhotoPopup = false
+ },
+ choosePhoto() {
+ if (this.uploadedPhotos.length >= 3) {
+ uni.showToast({ title: '鏈�澶氫笂浼�3寮犵収鐗�', icon: 'none' })
+ return
+ }
+ uni.chooseImage({
+ count: 3 - this.uploadedPhotos.length,
+ sourceType: ['camera', 'album'],
+ success: (res) => {
+ this.uploadedPhotos = [...this.uploadedPhotos, ...res.tempFilePaths]
+ }
+ })
+ },
+ deletePhoto(index) {
+ this.uploadedPhotos.splice(index, 1)
+ },
+ submitPhotoPopup() {
+ if (this.uploadedPhotos.length === 0) {
+ uni.showToast({ title: '璇蜂笂浼犵収鐗�', icon: 'none' })
+ return
+ }
+ uni.showLoading({ title: '涓婁紶涓�...' })
+ const uploadTasks = this.uploadedPhotos.map(path => {
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: this.$baseUrl + 'web/public/upload',
+ filePath: path,
+ name: 'file',
+ formData: {
+ folder: 'order'
+ },
+ success: (uploadRes) => {
+ const data = JSON.parse(uploadRes.data)
+ if (data.code === 200) {
+ resolve(data.data)
+ } else {
+ reject(new Error(data.msg))
+ }
+ },
+ fail: (err) => {
+ reject(err)
+ }
+ })
+ })
+ })
+
+ Promise.all(uploadTasks).then(images => {
+ const api = this.photoPopupMode === 'deliver' ? 'confirmDeliver' : 'confirmPickup'
+ const params = {
+ images: images.map(img => img.imgaddr),
+ orderId: this.selectedOrder.id,
+ remark: this.photoRemark
+ }
+ return this.$u.api[api](params)
+ }).then(res => {
+ uni.hideLoading()
+ if (res.code === 200) {
+ uni.showToast({ title: '鎻愪氦鎴愬姛', icon: 'success' })
+ this.showPhotoPopup = false
+ this.getOrderList()
+ this.getActiveOrderCount()
+ } else {
+ uni.showToast({ title: res.msg || '鎻愪氦澶辫触', icon: 'none' })
+ }
+ }).catch(err => {
+ uni.hideLoading()
+ uni.showToast({ title: err.message || '涓婁紶澶辫触', icon: 'none' })
})
}
}
@@ -472,8 +694,7 @@
&__actions {
display: flex;
- justify-content: flex-end;
- gap: 20rpx;
+ justify-content: space-between;
margin-top: 18rpx;
padding-top: 18rpx;
border-top: 1rpx solid #f0f2f6;
@@ -515,4 +736,204 @@
}
}
}
+
+.qrcode {
+ padding: 30rpx 40rpx 50rpx;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ &-title {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40rpx;
+
+ image {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ text {
+ font-size: 34rpx;
+ font-weight: 700;
+ color: #2d3139;
+ }
+ }
+
+ &-image {
+ width: 400rpx;
+ height: 400rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #f5f7fb;
+ border-radius: 16rpx;
+
+ image {
+ width: 360rpx;
+ height: 360rpx;
+ }
+ }
+
+ &-btn {
+ width: 100%;
+ height: 88rpx;
+ line-height: 88rpx;
+ text-align: center;
+ background: #106EFA;
+ border-radius: 44rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ margin-top: 40rpx;
+
+ &--hover {
+ background: #0d5fc7;
+ }
+ }
+}
+
+.photo-popup {
+ padding: 30rpx 30rpx calc(env(safe-area-inset-bottom) + 30rpx);
+
+ &__header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40rpx;
+ }
+
+ &__placeholder {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ &__title {
+ font-size: 34rpx;
+ font-weight: 700;
+ color: #2d3139;
+ }
+
+ &__close {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ &__section {
+ margin-bottom: 30rpx;
+
+ &--remark {
+ margin-top: 30rpx;
+ }
+ }
+
+ &__label-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20rpx;
+ }
+
+ &__label {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #2d3139;
+ }
+
+ &__required {
+ color: #ff4030;
+ margin-left: 8rpx;
+ }
+
+ &__hint {
+ font-size: 24rpx;
+ color: #8f96a3;
+ margin-left: auto;
+ }
+
+ &__photos {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+ }
+
+ &__preview-card {
+ position: relative;
+ width: 144rpx;
+ height: 144rpx;
+ border-radius: 12rpx;
+ overflow: hidden;
+ }
+
+ &__preview-image {
+ width: 100%;
+ height: 100%;
+ }
+
+ &__preview-mask {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ height: 56rpx;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__preview-delete {
+ font-size: 26rpx;
+ color: #ffffff;
+ }
+
+ &__upload-btn {
+ width: 144rpx;
+ height: 144rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ image {
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ &__remark-title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #2d3139;
+ margin-bottom: 20rpx;
+ display: block;
+ }
+
+ &__textarea {
+ width: 100%;
+ height: 160rpx;
+ padding: 20rpx;
+ background: #f5f7fb;
+ border-radius: 12rpx;
+ font-size: 28rpx;
+ color: #2d3139;
+ box-sizing: border-box;
+ }
+
+ &__submit {
+ width: 100%;
+ height: 88rpx;
+ line-height: 88rpx;
+ background: #2c7cff;
+ border-radius: 44rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ margin-top: 40rpx;
+
+ &--hover {
+ background: #2678e8;
+ }
+ }
+}
</style>
--
Gitblit v1.9.3