fix:修复bug

This commit is contained in:
2026-02-02 14:08:17 +08:00
parent 6a1dff4b94
commit 9f66ee9658
33 changed files with 9381 additions and 153 deletions
+106 -78
View File
@@ -89,7 +89,8 @@
<view class="rent-label">{{ $t('order.usedPromotion') }}</view>
<view class="rent-value promotion-value">
<image src="/static/promotion-icon.png" class="promotion-icon" mode="aspectFit"></image>
{{ orderInfo.discountTypeName }}
{{ orderInfo.discountTypeName }}<text
v-if="orderInfo.discountAmount">{{'-'+orderInfo.discountAmount||''}}</text>
</view>
</view>
<view class="rent-item" v-if="isOrderCompleted() && orderInfo.endTime">
@@ -108,7 +109,8 @@
</view>
<view class="">
<view class="" style="font-size: 24rpx;text-align: center;">
{{ $t('order.returnProblemTip') }}<text @click="contactService" style="color:#07c160 ;">{{ $t('user.customerService') }}</text>{{ $t('order.contactStaff') }}
{{ $t('order.returnProblemTip') }}<text @click="contactService"
style="color:#07c160 ;">{{ $t('user.customerService') }}</text>{{ $t('order.contactStaff') }}
</view>
</view>
@@ -161,7 +163,8 @@
<!-- 已完成状态 -->
<template v-if="isOrderCompleted()">
<view class="bottom-icon-btn" @click="handleWithdraw" v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">
<view class="bottom-icon-btn" @click="handleWithdraw"
v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">
<image src="/static/suggess.png" class="icon" mode="aspectFit"></image>
<text>{{ $t('order.feeAppeal') }}</text>
</view>
@@ -187,14 +190,8 @@
</view>
<!-- 转为自用确认弹窗 -->
<uv-popup
ref="convertToOwnPopup"
mode="center"
round="20"
:overlay="true"
:closeOnClickOverlay="false"
:safeAreaInsetBottom="false"
>
<uv-popup ref="convertToOwnPopup" mode="center" round="20" :overlay="true" :closeOnClickOverlay="false"
:safeAreaInsetBottom="false">
<view class="convert-to-own-popup">
<view class="popup-header">
<text class="popup-title">{{ $t('order.convertToOwnWithMaxFeeTitle') }}</text>
@@ -216,8 +213,19 @@
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import {
ref,
computed,
onMounted,
onUnmounted,
getCurrentInstance
} from 'vue'
import {
onLoad,
onShow,
onHide,
onUnload
} from '@dcloudio/uni-app'
import {
queryById,
cancelOrder,
@@ -238,9 +246,13 @@
import {
URL
} from "@/config/url.js"
import { useI18n } from '@/utils/i18n.js'
import {
useI18n
} from '@/utils/i18n.js'
const { t } = useI18n()
const {
t
} = useI18n()
const instance = getCurrentInstance()
const $orderMonitor = instance?.proxy?.$orderMonitor || null
@@ -274,7 +286,9 @@
canUseCoupon: false,
userMemberCardId: '',
userPurchaseId: '',
discountTypeName: ''
discountTypeName: '',
originalFee:'',
discountAmount:''
})
const timer = ref(null)
const statusCheckTimer = ref(null)
@@ -289,12 +303,12 @@
const countdownTimer = ref(null)
const feeRuleText = ref('')
const convertToOwnPopup = ref(null)
// 计算属性:是否显示优惠券/会员卡可用提示
const canUsePromotionTag = computed(() => {
return orderInfo.value.canUseMember === true || orderInfo.value.canUseCoupon === true
})
// 计算属性:是否使用了优惠
const hasUsedPromotion = computed(() => {
return !!(orderInfo.value.userMemberCardId || orderInfo.value.userPurchaseId)
@@ -308,11 +322,11 @@
}
return '-'
}
// 判断订单是否已完成
const isOrderCompleted = () => {
return orderInfo.value.orderStatus === 'used_done' ||
orderInfo.value.orderStatus === 'used_down'
return orderInfo.value.orderStatus === 'used_done' ||
orderInfo.value.orderStatus === 'used_down'
}
// 获取订单状态文字
@@ -362,13 +376,13 @@
// 获取计费规则显示
const getPricingRuleDisplay = () => {
if (!orderInfo.value.unitPrice || !orderInfo.value.orderType) return '-'
const orderTypeMap = {
'hours': t('time.hours'),
'minutes': t('time.minutes'),
'halfhours': t('time.halfHours')
}
const orderTypeText = orderTypeMap[orderInfo.value.orderType] || orderInfo.value.orderType
return `${orderInfo.value.unitPrice}${t('unit.yuan')}/${orderTypeText}`
}
@@ -407,39 +421,40 @@
// 获取使用时长显示信息
const getUsedTimeDisplay = () => {
let usedTime = orderInfo.value.usedTime
// 如果 usedTime 为空,通过开始时间和结束时间计算
if (usedTime === '0分钟' && orderInfo.value.startTime && orderInfo.value.endTime) {
const startMs = parseStartTimeToMs(orderInfo.value.startTime)
const endMs = parseStartTimeToMs(orderInfo.value.endTime)
if (!isNaN(startMs) && !isNaN(endMs)) {
const diffMs = endMs - startMs
const totalMinutes = Math.floor(diffMs / (1000 * 60))
// 格式化为 "X小时X分钟" 或 "X分钟"
if (totalMinutes >= 60) {
const hours = Math.floor(totalMinutes / 60)
const minutes = totalMinutes % 60
usedTime = minutes > 0 ? `${hours}${t('time.hour')}${minutes}${t('time.minute')}` : `${hours}${t('time.hour')}`
usedTime = minutes > 0 ? `${hours}${t('time.hour')}${minutes}${t('time.minute')}` :
`${hours}${t('time.hour')}`
} else {
usedTime = `${totalMinutes}${t('time.minute')}`
}
}
}
// 如果还是没有值,使用默认值
if (!usedTime) {
usedTime = `0${t('time.minute')}`
}
// 解析时长字符串,例如 "1小时5分钟" 或 "5分钟"
const hourMatch = usedTime.match(new RegExp(`(\\d+)${t('time.hour')}`))
const minuteMatch = usedTime.match(new RegExp(`(\\d+)${t('time.minute')}`))
let displayNumber = ''
let displayUnit = ''
if (hourMatch && minuteMatch) {
// 有小时也有分钟,如 "1小时5分钟"
displayNumber = `${hourMatch[1]}`
@@ -457,7 +472,7 @@
displayNumber = '0'
displayUnit = t('time.minute')
}
return {
number: displayNumber,
unit: displayUnit
@@ -472,7 +487,8 @@
// 获取订单费用(不含单位)
const getOrderFee = () => {
const fee = orderInfo.value.currentFee || orderInfo.value.payAmount || '0'
const fee = orderInfo.value.originalFee || orderInfo.value.originalFee || '0'
// 移除可能的"元"字符
return String(fee).replace(/[元¥]/g, '')
}
@@ -526,7 +542,7 @@
countdownRemaining.value = 0
return
}
if (orderInfo.value.orderStatus !== 'in_used') {
showExpressAction.value = false
countdownRemaining.value = 0
@@ -559,7 +575,7 @@
countdownRemaining.value = 0
return
}
clearExpressCountdown()
recomputeExpressCountdownFromStartTime()
if (showExpressAction.value) return
@@ -590,13 +606,16 @@
const loadSystemConfig = async () => {
try {
// 优先使用订单数据中的 expressReturnStart(小时转秒)
if (orderInfo.value.expressReturnStart && typeof orderInfo.value.expressReturnStart === 'number' && orderInfo.value.expressReturnStart > 0) {
if (orderInfo.value.expressReturnStart && typeof orderInfo.value.expressReturnStart === 'number' &&
orderInfo.value.expressReturnStart > 0) {
expressThresholdSeconds.value = orderInfo.value.expressReturnStart * 3600
console.log('使用订单配置的快递归还阈值:', orderInfo.value.expressReturnStart, '小时 =>', expressThresholdSeconds.value, '秒')
console.log('使用订单配置的快递归还阈值:', orderInfo.value.expressReturnStart, '小时 =>', expressThresholdSeconds
.value, '秒')
} else {
// 如果订单数据中没有,则使用系统配置
const res = await getSystemConfig()
if (res && res.code === 200 && res.data && typeof res.data.expressReturnCountdownSeconds === 'number') {
if (res && res.code === 200 && res.data && typeof res.data.expressReturnCountdownSeconds ===
'number') {
const seconds = res.data.expressReturnCountdownSeconds
if (seconds > 0) {
expressThresholdSeconds.value = seconds
@@ -604,7 +623,7 @@
}
}
}
if (orderInfo.value.orderStatus === 'in_used' && orderInfo.value.startTime) {
recomputeExpressCountdownFromStartTime()
}
@@ -692,13 +711,13 @@
clearStatusCheckTimer()
return
}
if (orderInfo.value.orderStatus !== 'in_used') {
console.log('订单状态已变更,停止状态检查计时器')
clearStatusCheckTimer()
return
}
currentStatusChecks.value++
console.log(`执行归还状态检查 (${currentStatusChecks.value}/${maxStatusChecks.value})`)
checkReturnStatus()
@@ -730,9 +749,10 @@
// 更新订单信息
const updateOrderInfo = (orderData) => {
const oldStatus = orderInfo.value.orderStatus
orderInfo.value.usedTime = orderData.usedTime || '0分钟'
orderInfo.value.currentFee = orderData.currentFee || orderData.actualDeviceAmount || orderData.payAmount || '0.00'
orderInfo.value.currentFee = orderData.currentFee || orderData.actualDeviceAmount || orderData.payAmount ||
'0.00'
orderInfo.value.orderStatus = orderData.orderStatus || ''
orderInfo.value.payWay = orderData.payWay || ''
orderInfo.value.startTime = orderData.startTime || orderData.createTime || ''
@@ -747,47 +767,52 @@
orderInfo.value.withdrawStatus = orderData.withdrawStatus || 'waiting'
orderInfo.value.isWithdrawn = orderData.withdrawStatus === 'success'
orderInfo.value.positionName = orderData.positionName || orderData.positionLocation || ''
orderInfo.value.returnPosition = orderData.returnPosition || orderData.positionName || orderData.positionLocation || ''
orderInfo.value.returnPosition = orderData.returnPosition || orderData.positionName || orderData
.positionLocation || ''
orderInfo.value.freeRentTime = orderData.freeRentTime || ''
orderInfo.value.unitPrice = orderData.unitPrice || ''
orderInfo.value.orderType = orderData.orderType || ''
orderInfo.value.discountAmount = orderData.discountAmount||''
// 保存优惠券/会员卡相关信息
orderInfo.value.canUseMember = orderData.canUseMember === true
orderInfo.value.canUseCoupon = orderData.canUseCoupon === true
orderInfo.value.userMemberCardId = orderData.userMemberCardId || ''
orderInfo.value.userPurchaseId = orderData.userPurchaseId || ''
orderInfo.value.discountTypeName = orderData.discountTypeName || ''
orderInfo.value.originalFee = orderData.originalFee||''
// 保存快递归还开始时间(小时为单位)
orderInfo.value.expressReturnStart = orderData.expressReturnStart || null
// 保存是否支持快递归还
orderInfo.value.isSupportExpressReturn = orderData.isSupportExpressReturn || 'yes'
// 如果有有效的 expressReturnStart,立即更新倒计时阈值(小时转秒)
if (orderInfo.value.expressReturnStart && typeof orderInfo.value.expressReturnStart === 'number' && orderInfo.value.expressReturnStart > 0) {
if (orderInfo.value.expressReturnStart && typeof orderInfo.value.expressReturnStart === 'number' && orderInfo
.value.expressReturnStart > 0) {
expressThresholdSeconds.value = orderInfo.value.expressReturnStart * 3600
console.log('从订单数据更新快递归还阈值:', orderInfo.value.expressReturnStart, '小时 =>', expressThresholdSeconds.value, '秒')
console.log('从订单数据更新快递归还阈值:', orderInfo.value.expressReturnStart, '小时 =>', expressThresholdSeconds.value,
'秒')
}
if (orderData.deviceNo && !deviceId.value) {
deviceId.value = orderData.deviceNo
}
// 如果订单已完成,从监控中移除
if (isOrderCompleted()) {
removeFromOrderMonitor()
console.log('订单已完成,已从监控队列移除')
}
// 如果订单状态从 'in_used' 变为其他状态,清理所有定时器
if (oldStatus === 'in_used' && orderInfo.value.orderStatus !== 'in_used') {
console.log('订单状态已从使用中变为:', orderInfo.value.orderStatus, ',清理所有定时器')
clearTimer()
clearStatusCheckTimer()
clearExpressCountdown()
// 显示订单完成提示
if (orderInfo.value.orderStatus === 'used_done' || orderInfo.value.orderStatus === 'used_down') {
uni.showToast({
@@ -841,7 +866,8 @@
// 如果订单已完成,从监控中移除
if (isOrderCompleted()) {
removeFromOrderMonitor()
console.log('订单已完成,已从监控队列移除:', orderInfo.value.orderId, '当前状态:', orderInfo.value.orderStatus)
console.log('订单已完成,已从监控队列移除:', orderInfo.value.orderId, '当前状态:', orderInfo.value
.orderStatus)
} else {
// 订单未完成,添加到监控队列
uni.setStorageSync('activeOrderId', orderInfo.value.orderId)
@@ -853,7 +879,8 @@
$orderMonitor.addOrder({
orderId: orderInfo.value.orderId
}, 'detail')
console.log('订单已添加到监控队列:', orderInfo.value.orderId, '当前状态:', orderInfo.value.orderStatus)
console.log('订单已添加到监控队列:', orderInfo.value.orderId, '当前状态:', orderInfo.value
.orderStatus)
} else {
console.warn('$orderMonitor 未定义,无法添加订单到监控队列')
}
@@ -1035,7 +1062,7 @@
}
})
})
uni.showToast({
title: t('payment.subscriptionSuccess'),
icon: 'success',
@@ -1055,7 +1082,8 @@
// 处理"不想还了转为自用"(按最高费用)
const handleConvertToOwnedWithMaxFee = () => {
try {
convertToOwnPopup.value && typeof convertToOwnPopup.value.open === 'function' && convertToOwnPopup.value.open()
convertToOwnPopup.value && typeof convertToOwnPopup.value.open === 'function' && convertToOwnPopup.value
.open()
} catch (e) {
console.error('打开弹窗失败', e)
}
@@ -1064,7 +1092,8 @@
// 关闭转为自用弹窗
const closeConvertToOwnPopup = () => {
try {
convertToOwnPopup.value && typeof convertToOwnPopup.value.close === 'function' && convertToOwnPopup.value.close()
convertToOwnPopup.value && typeof convertToOwnPopup.value.close === 'function' && convertToOwnPopup.value
.close()
} catch (e) {
console.error('关闭弹窗失败', e)
}
@@ -1077,9 +1106,9 @@
uni.showLoading({
title: t('common.processing')
})
const result = await closeWithMaxFee(orderInfo.value.orderNo)
if (result.code === 200) {
uni.hideLoading()
uni.showToast({
@@ -1087,7 +1116,7 @@
icon: 'success',
duration: 2000
})
// 刷新订单详情
setTimeout(() => {
getOrderDetails()
@@ -1115,7 +1144,7 @@
})
isPageActive.value = true
// 从缓存读取通知内容(计费规则)
try {
const cachedNotice = uni.getStorageSync('noticeContent')
@@ -1196,7 +1225,7 @@
.header-left {
flex: 1;
}
.header-title-row {
display: flex;
align-items: center;
@@ -1218,7 +1247,7 @@
.header-right {
display: flex;
align-items: center;
height:100%;
height: 100%;
text-align: center;
}
@@ -1227,7 +1256,7 @@
flex-direction: column;
align-items: center;
justify-content: center;
// padding: 12rpx 20rpx;
// background: #E8F5E9;
// border-radius: 12rpx;
@@ -1251,7 +1280,7 @@
}
}
}
.promotion-tag {
padding: 6rpx 16rpx;
background: linear-gradient(135deg, #FFF4E6 0%, #FFE9CC 100%);
@@ -1366,7 +1395,7 @@
border-radius: 12rpx;
font-size: 26rpx;
z-index: 9;
&:active {
opacity: 0.85;
}
@@ -1408,14 +1437,14 @@
color: #333;
text-align: right;
max-width: 400rpx;
&.promotion-value {
display: flex;
align-items: center;
justify-content: flex-end;
color: #FF8C00;
font-weight: 500;
.promotion-icon {
width: 32rpx;
height: 32rpx;
@@ -1431,7 +1460,7 @@
align-items: baseline;
padding-top: 20rpx;
margin-top: 10rpx;
border-top: 1rpx solid #f0f0f0;
// border-top: 1rpx solid #f0f0f0;
.paid-label {
font-size: 28rpx;
@@ -1580,7 +1609,7 @@
padding: 0 0 40rpx;
box-sizing: border-box;
text-align: left;
.popup-text {
font-size: 28rpx;
color: #666;
@@ -1596,7 +1625,7 @@
border-top: 1rpx solid #f0f0f0;
margin-left: -40rpx;
margin-right: -40rpx;
.popup-btn {
flex: 1;
height: 88rpx;
@@ -1605,20 +1634,20 @@
justify-content: center;
font-size: 32rpx;
box-sizing: border-box;
&.cancel-btn {
color: #666;
border-right: 1rpx solid #f0f0f0;
&:active {
background-color: #f5f5f5;
}
}
&.confirm-btn {
color: #07c160;
font-weight: 600;
&:active {
background-color: #f0f9f4;
}
@@ -1626,5 +1655,4 @@
}
}
}
</style>
</style>