瀏覽代碼

feat 订单复审功能

ylong 1 月之前
父節點
當前提交
1f23d6cd5a

+ 1 - 1
.env.dev.js

@@ -1,5 +1,5 @@
 export default {
     "NODE_ENV": 'development',
-    "apiUrl":"https://bpi.shuhi.com",
+    "apiUrl":"https://bk.shuhi.com",
     "apiUrlPrefix":"/api",
 };

+ 19 - 1
pages-mine/components/order-actions.vue

@@ -4,6 +4,21 @@
             <!-- 未提交 -->
             <button v-if="status == 0" class="action-btn" @click.stop="handleAction('submit')">提交订单</button>
 
+            <!-- 显示复审按钮 -->
+            <template v-if="order.showReview > 0">
+                <!-- 1-可申请 2-已申请 3-已复审(展示审核图片按钮) -->
+                <button v-if="order.showReview == 1" class="action-btn"
+                    @click.stop="handleAction('review')">申请复审</button>
+                <!-- 2-已申请 -->
+                <div style="display: flex;align-items: center;font-size: 14px;" v-if="order.showReview == 2">
+                    已用时长:
+                    <time-clock :initialSeconds="order.reviewCostTime"></time-clock>
+                </div>
+                <button v-if="order.showReview == 2" class="action-btn plain">已申请复审</button>
+                <button class="action-btn" v-if="order.showReview == 3"
+                    @click.stop="handleAction('reviewImage')">审核图片</button>
+            </template>
+
             <!-- 待初审 -->
             <template v-if="status == 2">
                 <view class="flex-row w-full" style="display: flex;justify-content: space-between;">
@@ -46,9 +61,12 @@
 </template>
 
 <script>
-
+import timeClock from './time-clock.vue';
 export default {
     name: 'OrderActions',
+    components: {
+        timeClock
+    },
     props: {
         status: {
             type: [Number, String],

+ 14 - 6
pages-mine/components/order-return-item.vue

@@ -8,7 +8,8 @@
                 }}</text>
 
             <template v-else>
-                <text class="order-status" style="color: #FF000C" v-if="!order.restTime">已超时</text>
+                <text class="order-status" style="color: #FF000C" v-if="order.refundStatus==3">订单复审中</text>
+                <text class="order-status" style="color: #FF000C" v-else-if="!order.restTime&&order.refundStatus!=3">已超时</text>
                 <view class="time-container" style="min-width: 220rpx;" v-else>
                     <u-count-down class="time" :timestamp="order.restTime" separator="zh" separator-size="28"
                         separator-color="#FF0000" color="#FF0000" bg-color="transparent" :show-seconds="false"
@@ -80,13 +81,20 @@ export default {
                     url: `/pages-mine/pages/return-detail?orderId=${this.order.orderId}`
                 })
             } else {
-                if (this.order.restTime) {
-                    uni.navigateTo({
-                        url: `/pages-mine/pages/apply?orderId=${this.order.orderId}`
-                    })
+                if (this.order.refundStatus != 3) {
+                    if (this.order.restTime) {
+                        uni.navigateTo({
+                            url: `/pages-mine/pages/apply?orderId=${this.order.orderId}`
+                        })
+                    } else {
+                        uni.showToast({
+                            title: '已超时',
+                            icon: 'none'
+                        })
+                    }
                 } else {
                     uni.showToast({
-                        title: '已超时',
+                        title: '订单复审中,暂时不能操作退回订单',
                         icon: 'none'
                     })
                 }

+ 79 - 0
pages-mine/components/time-clock.vue

@@ -0,0 +1,79 @@
+<template>
+    <div class="time-counter">
+        {{ formattedTime }}
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'TimeClock',
+    // props 定义(与 Vue3 逻辑一致,保留非负整数校验)
+    props: {
+        initialSeconds: {
+            type: Number,
+            required: true,
+            validator(value) {
+                // 校验:必须是非负整数
+                return Number.isInteger(value) && value >= 0
+            }
+        }
+    },
+    data() {
+        return {
+            // 当前累计秒数(对应 Vue3 的 ref 响应式变量)
+            currentSeconds: this.initialSeconds,
+            // 定时器实例(用于清理)
+            timer: null
+        }
+    },
+    computed: {
+        // 格式化时间:秒数 → 00:00:00 格式(逻辑与 Vue3 完全一致)
+        formattedTime() {
+            const hours = String(Math.floor(this.currentSeconds / 3600)).padStart(2, '0')
+            const minutes = String(Math.floor((this.currentSeconds % 3600) / 60)).padStart(2, '0')
+            const seconds = String(this.currentSeconds % 60).padStart(2, '0')
+            return `${hours}:${minutes}:${seconds}`
+        }
+    },
+    watch: {
+        // 监听初始秒数变化(对应 Vue3 的 watch 函数)
+        initialSeconds: {
+            handler(newVal) {
+                this.currentSeconds = newVal // 更新当前秒数为新初始值
+                this.startTimer() // 重启定时器
+            },
+            immediate: true
+        }
+    },
+    methods: {
+        // 启动计时(逻辑与 Vue3 一致)
+        startTimer() {
+            // 清除已有定时器,避免重复计时
+            if (this.timer) clearInterval(this.timer)
+            // 每秒递增 1 秒
+            this.timer = setInterval(() => {
+                this.currentSeconds += 1
+            }, 1000)
+        }
+    },
+    // 初始化时启动计时(对应 Vue3 的 setup 初始化逻辑)
+    mounted() {
+        this.startTimer()
+    },
+    // 组件卸载时清理定时器(避免内存泄漏,与 Vue3 一致)
+    beforeDestroy() {
+        if (this.timer) clearInterval(this.timer)
+    }
+}
+</script>
+
+<style scoped>
+.time-counter {
+    font-size: 13px;
+    font-weight: 500;
+    color: #ff0000;
+    letter-spacing: 2px;
+    font-family: 'Arial', sans-serif;
+    /* 确保数字显示整齐 */
+}
+</style>

+ 8 - 0
pages-mine/mixin/btnAction.js

@@ -145,6 +145,14 @@ export default {
                 case "compensation":
                     this.$emit("compensation", this.order);
                     break;
+                case "review":
+                    this.$refs.reviewDialog.openPopup();
+                    break;
+                case "reviewImage":
+                    uni.navigateTo({
+                        url: `/pages-mine/pages/review-image?orderId=${this.order.orderId}`,
+                    });
+                    break;
             }
         },
 

+ 26 - 5
pages-mine/pages/order-page.vue

@@ -10,19 +10,27 @@
         <page-scroll :page-size="12" @updateList="handleUpdateList" ref="pageRef" slotEmpty
             url="/token/order/getMyOrderList" :params="params" :immediate="false">
             <view v-if="orderList.length > 0" class="pad-20">
-                <order-item v-for="order in orderList" :key="order.orderNo" :order="order"
-                    @action="handleAction" @success="handleSuccess"></order-item>
+                <order-item v-for="order in orderList" :key="order.orderNo" :order="order" @action="handleAction"
+                    @success="handleSuccess"></order-item>
             </view>
         </page-scroll>
 
         <u-action-sheet v-model="showReportSheet" :list="actionList" @close="showReportSheet = false"
             @click="handleReportSelect" cancelText="取消" :mask-close-able="false" :safe-area-inset-bottom="true" />
+
+        <common-dialog ref="reviewDialog" title="温馨提示" @confirm="confirmReview">
+            <text>对复审结果有疑问,申请复审?</text>
+        </common-dialog>
+        <common-dialog ref="processDialog" title="温馨提示" @confirm="handleSuccess">
+            <text>{{ reviewMsg }}</text>
+        </common-dialog>
     </view>
 </template>
 
 <script>
 import OrderItem from '../components/order-item.vue'
 import pageScroll from '@/components/pageScroll/index.vue'
+import CommonDialog from '@/components/common-dialog.vue'
 import mixin from '../mixin/btnAction.js'
 
 export default {
@@ -30,6 +38,7 @@ export default {
     components: {
         OrderItem,
         pageScroll,
+        CommonDialog,
     },
     data() {
         return {
@@ -60,7 +69,8 @@ export default {
             page: 1,
             pageSize: 10,
             hasMore: true,
-            params: {}
+            params: {},
+            reviewMsg: ""
         }
     },
     onLoad(options) {
@@ -78,11 +88,11 @@ export default {
             this.loadOrders(true, this.params)
         })
     },
-    
+
     onUnload() {
         uni.$off('btnActionSuccess')
     },
-    
+
     methods: {
         loadOrders(bool = false, params = {}) {
             console.log(this.$refs.pageRef, 'params')
@@ -91,6 +101,17 @@ export default {
             })
         },
 
+        confirmReview() {
+            uni.$u.http.post('/token/order/applyReview?orderId=' + this.order.orderId).then(res => {
+                if (res.code == 200) {
+                    this.reviewMsg = res.data || '申请复审成功'
+                    this.$refs.processDialog.openPopup()
+                } else {
+                    this.reviewMsg = res.data || '申请复审失败'
+                }
+            })
+        },
+
         handleSuccess() {
             this.loadOrders(true, this.params)
         },

+ 257 - 0
pages-mine/pages/review-image.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="review-detail">
+		<!-- 复审列表 -->
+		<view class="review-list">
+			<view class="review-item" v-for="(item, index) in reviewList" :key="index">
+				<!-- 标题 -->
+				<view class="review-title">
+					<text class="title-text">{{ item.bookName }}</text>
+					<text class="title-tag" v-if="item.reviewAudit && item.reviewAuditSts==3">复审结果:{{ item.reviewAudit }}</text>
+					<text class="title-tag success-tag" v-if="item.reviewAuditSts==1">复审结果:良好</text>
+				</view>
+
+				<!-- 文字说明 -->
+				<view class="review-desc" v-if="item.reviewRemark">
+					<text class="desc-label">文字说明:{{ item.reviewRemark }}</text>
+				</view>
+
+				<!-- 图片网格 -->
+				<view class="image-grid">
+					<view class="image-item" v-for="(img, imgIndex) in item.reviewImg" :key="imgIndex" @click="previewImage(item.reviewImg, imgIndex)">
+						<u-image :src="img" width="100%" height="200rpx" border-radius="10rpx"
+							mode="aspectFill"></u-image>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 订单信息 -->
+		<view class="info-block">
+			<view class="info-row">
+				<text class="info-label">订单编号</text>
+				<view class="info-value-row">
+					<text class="info-value">{{ orderInfo.orderId }}</text>
+					<text class="copy-btn" @click="copyOrderNo">复制</text>
+				</view>
+			</view>
+			<view class="info-row">
+				<text class="info-label">发货人</text>
+				<text class="info-value">{{ orderInfo.sendName }} {{ orderInfo.sendMobile }}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">取件地址</text>
+				<text class="info-value">{{ orderInfo.sendAddress }}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			orderId: "",
+			// 复审列表数据(假数据)
+			reviewList: [
+				{
+					title: "科学百科",
+					tag: "复审结果:笔记杂乱/习题做完",
+					images: [
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+					],
+					showAll: false,
+				},
+				{
+					title: "科学百科",
+					tag: "复审结果:笔记杂乱/习题做完",
+					images: [
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+					],
+					showAll: false,
+				},
+				{
+					title: "科学百科",
+					tag: "复审结果:笔记杂乱/习题做完",
+					images: [
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+						"https://wx3.sinaimg.cn/mw690/88e90961ly1hwvqdknjo4j20u0140tav.jpg",
+					],
+					showAll: false,
+				},
+			],
+			// 订单信息(假数据)
+			orderInfo: {
+				orderId: "14847984",
+				senderName: "张潇潇",
+				senderPhone: "18888888888",
+				address:
+					"hi是u发hi跟带回家大饭店计算度假村计算度假村计算度假村计算度假村计算度假村计算度假村几集",
+			},
+		};
+	},
+	onLoad(options) {
+		if (options.orderId) {
+			this.orderId = options.orderId;
+			this.getReviewDetail();
+		}
+	},
+	methods: {
+		// 预览图片
+		previewImage(images, current) {
+			uni.previewImage({
+				urls: images,
+				current: current,
+			});
+		},
+
+		// 复制订单号
+		copyOrderNo() {
+			uni.setClipboardData({
+				data: this.orderInfo.orderId.toString(),
+				success: () => {
+					uni.$u.toast("复制成功");
+				},
+				fail: () => {
+					uni.$u.toast("复制失败");
+				},
+			});
+		},
+
+		// 获取复审详情(接口调用)
+		getReviewDetail() {
+			uni.$u.http
+				.post("/token/order/reviewDetail?orderId=" + this.orderId)
+				.then((res) => {
+					if (res.code === 200) {
+						// 处理返回的数据
+						this.reviewList = res.data.reviewDetailList;
+						this.orderInfo = res.data;
+					}
+				});
+		},
+	},
+};
+</script>
+
+<style lang="scss" scoped>
+.review-detail {
+	min-height: 100vh;
+	background: #f8f8f8;
+	padding-bottom: 30rpx;
+}
+
+.review-item {
+	background: #ffffff;
+	padding: 30rpx;
+}
+
+.review-title {
+	// display: flex;
+	flex-direction: row;
+	align-items: center;
+	margin-bottom: 20rpx;
+	line-height: 50rpx;
+
+	.title-text {
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #101010;
+		margin-right: 20rpx;
+	}
+
+	.title-tag {
+		font-size: 24rpx;
+		color: #666666;
+		background-color: #f2f2f2;
+		padding: 8rpx 16rpx;
+		border-radius: 6rpx;
+		width: fit-content;
+	}
+
+	.success-tag {
+		color: #38c148;
+		background-color: #e8f5e9;
+	}
+}
+
+.review-desc {
+	margin-bottom: 20rpx;
+
+	.desc-label {
+		font-size: 26rpx;
+		color: #333333;
+	}
+}
+
+.image-grid {
+	display: grid;
+	grid-template-columns: repeat(3, 1fr);
+	gap: 20rpx;
+}
+
+.image-item {
+	border-radius: 10rpx;
+	overflow: hidden;
+}
+
+.show-all-btn {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	padding: 20rpx 0;
+
+	.show-all-text {
+		font-size: 28rpx;
+		color: #38c148;
+		margin-right: 10rpx;
+	}
+}
+
+.info-block {
+	background: #ffffff;
+	padding: 30rpx;
+	margin-top: 20rpx;
+}
+
+.info-row {
+	display: flex;
+	align-items: flex-start;
+	margin-bottom: 24rpx;
+
+	&:last-child {
+		margin-bottom: 0;
+	}
+
+	.info-label {
+		font-size: 28rpx;
+		color: #666666;
+		width: 140rpx;
+		flex-shrink: 0;
+	}
+
+	.info-value {
+		font-size: 28rpx;
+		color: #333333;
+		flex: 1;
+		word-break: break-all;
+	}
+
+	.info-value-row {
+		display: flex;
+		align-items: center;
+		flex: 1;
+	}
+
+	.copy-btn {
+		font-size: 28rpx;
+		color: #38c148;
+		margin-left: 20rpx;
+		flex-shrink: 0;
+	}
+}
+</style>

+ 6 - 0
pages.json

@@ -212,6 +212,12 @@
                     "style": {
                         "navigationBarTitleText": "在线客服"
                     }
+                },
+                {
+                    "path": "pages/review-image",
+                    "style": {
+                        "navigationBarTitleText": "复审详情"
+                    }
                 }
             ]
         },