From f76f0a489050e3ebdc159b78e0f61d36b7eba5e0 Mon Sep 17 00:00:00 2001 From: wangfukang <15630117759@163.com> Date: Sat, 27 Jun 2026 18:14:46 +0800 Subject: [PATCH] 1 --- package1/buyFood/buyFood.vue | 27 ++- package1/order/orderDetail.vue | 328 ++++++++++++++++++++++++++----- package1/order/orderList.vue | 94 +++++++-- package1/order/returnOrder.vue | 8 +- package1/runErrand/runErrand.vue | 18 +- 5 files changed, 405 insertions(+), 70 deletions(-) diff --git a/package1/buyFood/buyFood.vue b/package1/buyFood/buyFood.vue index 103ba41..8099553 100644 --- a/package1/buyFood/buyFood.vue +++ b/package1/buyFood/buyFood.vue @@ -137,7 +137,7 @@ - + @@ -357,6 +357,9 @@ + + 佣金为团配送单总佣金,设置后会按照参团人数自动计算均摊 + 取消 确定 @@ -405,8 +408,11 @@ ¥{{backendTotalAmount ? backendTotalAmount.toFixed(2) : totalAmountCalc.toFixed(2)}} - - 若拼团失败,将会为您自动退款 + + 若24小时内拼团失败,将会为您自动退款 + + + 若1小时内拼团失败,将会为您自动退款 @@ -897,7 +903,6 @@ refreshDeliveryTimeByModeChange() { this.updateImmediateTimeStr(); if (this.formData.isImmediately === false) { - this.formData.deliveryTime = ''; this.generateDeliveryTimes(); } }, @@ -1027,7 +1032,7 @@ this.tui.request('/mall/coupon/available', 'GET', { userId: userId, regionId:JSON.parse(uni.getStorageSync('area')).id, - applyScene: 1, + applyScene: this.isStoreGroupOrder ? 4 : 1, amount: amount, merchantId: this.shopItem.id || this.shopItem.shopId || '0' }, false, true).then((res) => { @@ -1940,6 +1945,18 @@ } } + .commission-popup-tip { + margin-top: 18rpx; + padding: 14rpx 18rpx; + border-radius: 18rpx; + background: #fff5ec; + border: 1rpx solid rgba(255, 112, 67, 0.28); + color: #f0441f; + font-size: 22rpx; + font-weight: 800; + line-height: 34rpx; + } + .commission-popup-actions { display: flex; margin-top: 34rpx; diff --git a/package1/order/orderDetail.vue b/package1/order/orderDetail.vue index 27aeaf3..47ded27 100644 --- a/package1/order/orderDetail.vue +++ b/package1/order/orderDetail.vue @@ -154,7 +154,7 @@ - 创建时间 {{orderDetail.createTime | formatTime}} + 剩余支付时间 {{payCountdownText}} @@ -700,7 +700,7 @@ - 取消订单需要商家同意 + 请确认责任方,取消订单需要责任方同意! 请选择退款原因 @@ -783,6 +783,23 @@ + + + 确认取消订单吗 + 符合无责取消条件,订单金额将按平台退款处理 + + + 再想想 + + + 确认取消 + + + + + @@ -905,7 +922,7 @@ return { newQRList: '', pintuan: false, - sellTime: 2, + sellTime: '', menuButtonInfo: {}, refundType: 3, refundTypeStatus: 1, @@ -931,7 +948,10 @@ isRefreshing: false, groupBuyCancelPopupType: 'buy', assignWorkerModalVisible: false, - assignWorkerSelectionKey: '' + assignWorkerSelectionKey: '', + payCountdownText: '60:00', + payCountdownSeconds: 0, + payCountdownTimer: null } }, computed: { @@ -1047,11 +1067,66 @@ onPullDownRefresh() { this.getOrderDetail(this.orderId) }, + onHide() { + this.stopPayCountdown(); + }, onUnload() { uni.$off('updateDeliveryWorker'); + this.stopPayCountdown(); }, methods: { + startPayCountdown() { + this.stopPayCountdown(); + if (this.orderDetail.status != 0 || !this.orderDetail.createTime) { + this.setPayCountdown(0); + return; + } + this.setPayCountdown(this.getPayCountdownSeconds()); + this.payCountdownTimer = setInterval(() => { + if (this.orderDetail.status != 0) { + this.stopPayCountdown(); + return; + } + this.setPayCountdown(Math.max(this.payCountdownSeconds - 1, 0)); + if (this.payCountdownSeconds <= 0) { + this.stopPayCountdown(); + } + }, 1000); + }, + stopPayCountdown() { + if (this.payCountdownTimer) { + clearInterval(this.payCountdownTimer); + this.payCountdownTimer = null; + } + }, + getPayCountdownSeconds() { + const createTime = this.parseOrderTime(this.orderDetail.createTime); + if (!createTime) { + return 0; + } + const expireTime = createTime.getTime() + 60 * 60 * 1000; + const remainMs = expireTime - Date.now(); + return Math.max(Math.floor(remainMs / 1000), 0); + }, + setPayCountdown(totalSeconds) { + this.payCountdownSeconds = totalSeconds; + const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0'); + const seconds = String(totalSeconds % 60).padStart(2, '0'); + this.payCountdownText = `${minutes}:${seconds}`; + this.$forceUpdate(); + }, + parseOrderTime(value) { + if (!value) return null; + if (value instanceof Date) return isNaN(value.getTime()) ? null : value; + let date = new Date(value); + if (!isNaN(date.getTime())) { + return date; + } + const normalized = String(value).replace(/-/g, '/').replace('T', ' ').split('.')[0]; + date = new Date(normalized); + return isNaN(date.getTime()) ? null : date; + }, formatTimeText(value) { if (!value) return ''; if (value == '尽快送达') return '尽快送达'; @@ -1229,12 +1304,62 @@ } return false; }, + hasNoDeliveryWorker(item) { + return !item || !item.deliveryInfo || !item.deliveryInfo.workerId; + }, + isGroupSuccess(item) { + return item && item.groupInfo && (item.groupInfo.status == 1 || item.groupInfo.successTime); + }, + isAfterGroupSuccessMinutes(item, minutes) { + if (!item || !item.groupInfo || !item.groupInfo.successTime) { + return false; + } + const successTime = this.parseOrderTime(item.groupInfo.successTime); + if (!successTime) { + return false; + } + return Date.now() - successTime.getTime() >= minutes * 60 * 1000; + }, + isNoResponsibilityCancel(item) { + if (!item) return false; + + const isNormalOrder = item.orderType == 1 && item.otherOrder == null; + const isGroupDeliveryOrder = item.deliveryType == 1 && item.otherOrder == null && this.isGroupSuccess(item); + const isSelfPickupNoMake = item.deliveryType == 2 && item.status == 3 && isNormalOrder && + (item.userRequireMake == null || item.userRequireMake == 0) && !item.shopMakeTime; + + if (isNormalOrder && item.deliveryType == 1 && this.hasNoDeliveryWorker(item)) { + return true; + } + if (isSelfPickupNoMake) { + return true; + } + if (isGroupDeliveryOrder && item.orderType == 3 && item.groupInfo.headOrderId == item.id && + this.hasNoDeliveryWorker(item)) { + return true; + } + if (isGroupDeliveryOrder && item.orderType == 2 && this.isAfterGroupSuccessMinutes(item, 10) && + this.hasNoDeliveryWorker(item)) { + return true; + } + if (item.otherOrder == 2 && item.status == 3 && !item.shopMakeTime) { + return true; + } + if (item.otherOrder == 1 && this.hasNoDeliveryWorker(item)) { + return true; + } + return false; + }, returnPopupProp(item) { this.payData = item; if (item.status == 0) { this.cancelUnpaidOrder(item); return; } + if (this.isNoResponsibilityCancel(item)) { + this.$refs.noResponsibilityCancelPopup.open('center'); + return; + } if (this.payData.otherOrder == 1) { this.refundType = 3 @@ -1302,6 +1427,27 @@ } }).catch((res) => {}); }, + confirmNoResponsibilityCancel() { + this.$refs.noResponsibilityCancelPopup.close(); + let item = this.payData; + let that = this; + that.tui.request("/mall/order/cancel", "POST", { + status: 1, + refundType: 3, + refundTypeStatus: 4, + orderId: item.id, + userId: uni.getStorageSync('id') + }, false, true).then((res) => { + uni.hideLoading(); + if (res.code == 200) { + that.tui.toast("操作成功"); + that.getOrderDetail(item.id); + that.$forceUpdate(); + } else { + that.tui.toast(res.message, 2000); + } + }).catch((res) => {}); + }, returnPopupPropBuy(item) { this.payData = item; this.groupBuyCancelPopupType = 'buy'; @@ -1343,10 +1489,10 @@ this.$refs.returnPopupBuy.open('bottom'); }, returnOrder() { - /* if(this.sellTime == 5 && this.remark == ""){ - that.tui.toast("请填写备注"); + if(this.sellTime == ''){ + this.tui.toast("请选择退款责任方"); return - } */ + } this.$refs.returnPopup.close(); let item = this.payData let that = this @@ -1412,22 +1558,52 @@ id: that.payData.shopId, regionId: JSON.parse(uni.getStorageSync('area')).id }, false, true).then((res1) => { - if (res1.code == 200) { - uni.hideLoading(); - // 类似普通订单结算逻辑 - let cartItems = []; - for (let i = 0; i < that.payData.goodsList.length; i++) { - let productPrice = that.payData.goodsList[i].price - for (let a = 0; a < res1.result.products.length; a++) { - if (res1.result.products[a].id == that.payData.goodsList[i] - .productId) { - let priceToUse = 0; - if (res1.result.products[a].attributeListPrice) { - try { - let pObj = typeof res1.result.products[a] - .attributeListPrice === 'string' ? JSON.parse(res1 - .result.products[a].attributeListPrice) : - res1.result.products[a].attributeListPrice; + try { + if (res1.code == 200) { + uni.hideLoading(); + + // 1. 定义一个安全的 JSON 解析函数(防止遇到 undefined, null 或空字符串报错) + const safeJsonParse = (str, fallback = null) => { + if (!str || typeof str !== 'string') return fallback; + try { + return JSON.parse(str); + } catch (e) { + console.warn('JSON解析失败,原始数据:', str, '错误:', e.message); + return fallback; + } + }; + + let cartItems = []; + for (let i = 0; i < that.payData.goodsList.length; i++) { + let productPrice = that.payData.goodsList[i].price; + + for (let a = 0; a < res1.result.products.length; a++) { + if (res1.result.products[a].id == that.payData.goodsList[i].productId) { + let priceToUse = 0; + let rawAttrPrice = res1.result.products[a].attributeListPrice; + + // 2. 安全解析 attributeListPrice(兼容未转义的双引号问题) + let pObj = null; + if (typeof rawAttrPrice === 'string') { + pObj = safeJsonParse(rawAttrPrice); // 先尝试正常解析 + if (!pObj) { + // 如果正常解析失败,说明可能是后端没转义内部的双引号,尝试修复 + try { + // 简单修复:把最外层括号内部的双引号转义 + let fixedStr = rawAttrPrice.replace(/(\[{)(.*?)(\]})/g, (match, p1, p2, p3) => { + return p1 + p2.replace(/"/g, '\\"') + p3; + }); + pObj = JSON.parse(fixedStr); + } catch (err) { + console.warn('attributeListPrice 修复解析依然失败:', err.message); + } + } + } else { + pObj = rawAttrPrice; // 如果后端已经返回了对象,直接使用 + } + + // 3. 提取价格 + if (pObj) { if (Array.isArray(pObj) && pObj.length > 0) { priceToUse = parseFloat(pObj[0].specPrice); } else { @@ -1436,34 +1612,42 @@ break; } } - } catch (e) {} + } + productPrice = priceToUse; } - productPrice = priceToUse } + + that.payData.goodsList[i].id = that.payData.goodsList[i].productId; + let specStr = that.payData.goodsList[i].specs; + let cartId = that.payData.goodsList[i].productId + '_' + specStr; + + // 4. 安全解析 specs + let parsedSpecs = safeJsonParse(specStr, []); + + cartItems.push({ + cartId: cartId, + item: that.payData.goodsList[i], + specs: parsedSpecs, // 使用安全解析后的值 + quantity: that.payData.goodsList[i].quantity, + price: productPrice.toFixed(2) + }); } - that.payData.goodsList[i].id = that.payData.goodsList[i].productId - let specStr = that.payData.goodsList[i].specs; - let cartId = that.payData.goodsList[i].productId + '_' + specStr; - cartItems.push({ - cartId: cartId, - item: that.payData.goodsList[i], - specs: JSON.parse(that.payData.goodsList[i].specs), - quantity: that.payData.goodsList[i].quantity, - price: productPrice.toFixed(2) + + uni.navigateTo({ + url: '/package1/buyFood/buyFood?cart=' + encodeURIComponent(JSON.stringify(cartItems)) + + '&shopItem=' + encodeURIComponent(JSON.stringify(res1.result.shop)) + + '&packageFee=' + that.payData.packageFee }); + } else { + that.tui.toast(res.message, 2000); + return; } - uni.navigateTo({ - url: '/package1/buyFood/buyFood?cart=' + encodeURIComponent( - JSON.stringify(cartItems)) + - '&shopItem=' + encodeURIComponent(JSON.stringify(res1 - .result.shop)) + '&packageFee=' + - that.payData.packageFee - }); - } else { - that.tui.toast(res.message,2000); - return; + } catch (e) { + console.error('结算逻辑发生异常:', e.message); + } finally { + // 5. 无论成功失败,最后都隐藏 Loading(优化了原来在 if 里和外面重复调用的问题) + uni.hideLoading(); } - uni.hideLoading(); }).catch((res1) => {}); } else { that.tui.toast(res.message); @@ -1498,6 +1682,7 @@ uni.stopPullDownRefresh() if (res.code == 200) { that.orderDetail = res.result; + that.startPayCountdown(); if (that.orderDetail.mallRefundRecord != null && that.orderDetail.mallRefundRecord.length > 0) { for (let i = 0; i < that.orderDetail.mallRefundRecord.length; i++) { @@ -2463,6 +2648,59 @@ box-shadow: 0 28rpx 70rpx rgba(0, 35, 28, 0.18); } + .no-responsibility-cancel-popup { + width: 620rpx; + padding: 46rpx 36rpx 34rpx; + box-sizing: border-box; + border-radius: 32rpx; + background: #fff; + box-shadow: 0 28rpx 70rpx rgba(0, 35, 28, 0.18); + } + + .no-responsibility-cancel-title { + color: #243f38; + font-size: 36rpx; + font-weight: 900; + line-height: 52rpx; + text-align: center; + } + + .no-responsibility-cancel-desc { + margin-top: 16rpx; + color: #7b8883; + font-size: 26rpx; + font-weight: 700; + line-height: 38rpx; + text-align: center; + } + + .no-responsibility-cancel-actions { + display: flex; + gap: 18rpx; + margin-top: 42rpx; + } + + .no-responsibility-cancel-btn { + flex: 1; + height: 82rpx; + border-radius: 999rpx; + font-size: 28rpx; + font-weight: 900; + line-height: 82rpx; + text-align: center; + } + + .no-responsibility-cancel-btn-muted { + background: #f3f6f4; + color: #87938f; + } + + .no-responsibility-cancel-btn-confirm { + background: linear-gradient(135deg, #fff7d7 0%, #a6ffea 100%); + color: #243f38; + box-shadow: 0 12rpx 26rpx rgba(0, 191, 160, 0.12); + } + .commission-popup-title { color: #243f38; font-size: 34rpx; diff --git a/package1/order/orderList.vue b/package1/order/orderList.vue index ffd0481..93e8435 100644 --- a/package1/order/orderList.vue +++ b/package1/order/orderList.vue @@ -149,13 +149,15 @@ - - - - + + + + + + - - + + {{item.totalAmount}} 共{{item.num}}件 @@ -339,6 +341,10 @@ this.searchForm.pageNum++; this.getOrderList(); }, + onPullDownRefresh() { + this.resetOrderList() + this.getOrderList() + }, filters: { formatHourMinute(value) { if (!value) return ''; @@ -388,12 +394,19 @@ }, onShow() { - this.getOrderList() this.menuButtonInfo = uni.getMenuButtonBoundingClientRect() this.searchForm.userId = uni.getStorageSync('id') this.searchForm.regionId = JSON.parse(uni.getStorageSync('area')).id + this.resetOrderList() + this.getOrderList() }, methods: { + resetOrderList() { + this.orderList = [] + this.pageNum = 1 + this.searchForm.pageNum = 1 + this.loadStatus = 'more' + }, checkTab1(type) { this.tab1Checked = type if(type == 'quanbu'){ @@ -491,8 +504,22 @@ }); }, goEvaluate(item){ - uni.navigateTo({ - url: '/package1/order/orderEvaluate?item=' + JSON.stringify(item) + let that = this; + that.tui.request("/app/comment/getByOrderId?orderId=" + item.id, "POST", {}, false, true).then((res) => { + uni.hideLoading(); + if (res.code == 200) { + if (res.result != null && res.result.length > 0) { + that.tui.toast("该订单已经评价过了"); + return; + } + uni.navigateTo({ + url: '/package1/order/orderEvaluate?item=' + JSON.stringify(item) + }); + } else { + that.tui.toast(res.message); + } + }).catch((res) => { + uni.hideLoading(); }); }, checkTabs2(type) { @@ -515,7 +542,7 @@ getOrderList(){ this.loadStatus = 'loading' let that = this - that.tui.request("/mall/order/page", "POST", this.searchForm, false, false).then((res) => { + return that.tui.request("/mall/order/page", "POST", this.searchForm, false, false).then((res) => { that.loadStatus = 'nomore'; if (res.code == 200) { if (that.searchForm.pageNum == 1) { @@ -536,7 +563,9 @@ return; } uni.hideLoading(); - }).catch((res) => {}); + }).catch((res) => {}).finally(() => { + uni.stopPullDownRefresh(); + }); }, returnPopupProp(item){ this.payData = item; @@ -921,23 +950,58 @@ position: relative; background: #fff; border-radius: 24rpx; - margin-right: 10px; overflow: hidden; box-shadow: 0 12rpx 24rpx rgba(0, 35, 28, 0.08); - img { - width: 160rpx; - background-size: 100%; + img, + image { + width: 100%; height: 100%; border-radius: 24rpx; + display: block; } } + .goods-card { + display: flex; + align-items: center; + padding: 20rpx; + background: rgba(247, 248, 248, 0.6); + border-radius: 20rpx; + box-sizing: border-box; + } + + .goods-scroll { + flex: 1; + width: 0; + min-width: 0; + white-space: nowrap; + } + + .goods-scroll-inner { + display: inline-flex; + align-items: center; + } + + .goods-scroll-img { + flex: 0 0 160rpx; + margin-right: 20rpx; + } + + .goods-scroll-img:last-child { + margin-right: 0; + } + .goods-content { padding: 0 20rpx; text-align: center; } + .goods-price { + flex: 0 0 128rpx; + padding: 0 0 0 20rpx; + } + .goods-name { font-weight: 900; color: #243f38; diff --git a/package1/order/returnOrder.vue b/package1/order/returnOrder.vue index ee0e9ee..ae539d6 100644 --- a/package1/order/returnOrder.vue +++ b/package1/order/returnOrder.vue @@ -223,7 +223,7 @@ - + 商品退款 @@ -295,7 +295,7 @@ export default { data() { return { - sellTime: 0, + sellTime: 100, pintuan: false, menuButtonInfo: {}, orderId: '', @@ -402,6 +402,10 @@ this.$refs.carPopup.open('bottom'); }, chooseReturnType() { + if(this.sellTime == 100){ + this.tui.toast("请选择售后责任方"); + return + } this.$refs.carPopup.close() if (this.sellTime == 0) { this.returnData.refundAmount = 0 diff --git a/package1/runErrand/runErrand.vue b/package1/runErrand/runErrand.vue index c8da1ba..df3f52f 100644 --- a/package1/runErrand/runErrand.vue +++ b/package1/runErrand/runErrand.vue @@ -896,9 +896,21 @@ this.$refs.warnPopup.open(); return; } - if (this.isKuaidi && (!this.addFormData.codeList || this.addFormData.codeList[0].code.trim() === '') && this.addFormData.picture.length === 0) { - uni.showToast({ title: '请填写取件码或上传截图凭证', icon: 'none' }); - return; + if (this.isKuaidi) { + let hasEdit = false + if(this.addFormData.codeList && this.addFormData.codeList[0].code.trim() != ''){ + hasEdit = true + } + if(this.addFormData.picture.length != 0){ + hasEdit = true + } + if(this.addFormData.phoneNumber.length != 0){ + hasEdit = true + } + if(hasEdit == false){ + uni.showToast({ title: '请填写手机尾号或取件码或上传截图凭证', icon: 'none' }); + return; + } } this.submitOrderToBackend();