From 50a711bba83acc4307d00c08bd2aeef76f60fcc6 Mon Sep 17 00:00:00 2001 From: ISFP_T <68358856@qq.com> Date: Sat, 8 Nov 2025 16:00:44 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9B=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/MapComponent.vue | 13 +-- components/OrderItemCard.vue | 42 +++++++--- config/api/system.js | 9 ++ config/url.js | 4 +- locale/en-US.js | 1 + locale/zh-CN.js | 1 + pages/device/detail.vue | 157 ++++++++++++++--------------------- pages/help/index.vue | 90 ++++++-------------- pages/index/index.vue | 113 ++++++++++++++++++++++++- pages/search/index.vue | 6 +- static/luxian.png | Bin 0 -> 355 bytes static/order_price.png | Bin 0 -> 6286 bytes static/order_time.png | Bin 0 -> 6318 bytes 13 files changed, 248 insertions(+), 188 deletions(-) create mode 100644 static/luxian.png create mode 100644 static/order_price.png create mode 100644 static/order_time.png diff --git a/components/MapComponent.vue b/components/MapComponent.vue index 270ae6c..585acf3 100644 --- a/components/MapComponent.vue +++ b/components/MapComponent.vue @@ -17,18 +17,19 @@ + + + + - + - - - - + @@ -530,7 +531,7 @@ const handleSearch = () => { flex-direction: row; align-items: center; justify-content: center; - box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12); + // box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.12); padding: 20rpx; border: 2rpx solid #e0e0e0; diff --git a/components/OrderItemCard.vue b/components/OrderItemCard.vue index dee3cfc..8aedfcf 100644 --- a/components/OrderItemCard.vue +++ b/components/OrderItemCard.vue @@ -16,6 +16,9 @@ {{ $t('order.depositFree') }} + + {{ $t('order.whitelistOrder') }} + {{ $t('order.memberOrder') }} @@ -59,10 +62,22 @@ - {{ $t('order.renting') }} + + + {{ $t('order.renting') }} + - {{ usedDurationText }} - {{ displayAmount }} + + + {{ usedDurationText }} + + + + {{ displayAmount }} + + + + {{ $t('order.orderCancelled') }} @@ -127,6 +142,7 @@ const isWaitingForPayment = computed(() => normalizedStatus.value === 'waiting_for_payment'); const isInUse = computed(() => normalizedStatus.value === 'in_used'); const isFinished = computed(() => normalizedStatus.value === 'used_done'); + const isCancelled = computed(() => normalizedStatus.value === 'order_cancelled'); const titleText = computed(() => $t('order.rentFan')); @@ -202,16 +218,15 @@ border-radius: 0; white-space: nowrap; - &.wx-score { } - &.member { } - &.deposit { } - .badge-icon { width: 32rpx; height: 26rpx; margin-right: 8rpx; } .badge-text { font-size: 22rpx; color: #07c160; font-weight: 500; background: transparent; } .divider { margin: 0 6rpx; color: #07c160; } } // 不同支付方式的文字颜色 + .payment-badge.whitelist { + .badge-text, .divider { color: #FF9800; } + } .payment-badge.member { .badge-text, .divider { color: #1976D2; } } @@ -333,12 +348,13 @@ background: #fafafa; border-top: 1rpx solid #f0f0f0; - .footer-left { display: flex; align-items: center; } - .renting { font-size: 26rpx; color: #333; display: flex; align-items: center; } - .meta { display: flex; align-items: center; } - .meta-item { font-size: 26rpx; color: #333; display: flex; align-items: center; margin-right: 28rpx; } - .dot { width: 16rpx; height: 16rpx; background: #000; border-radius: 50%; margin-right: 12rpx; display: inline-block; } - .currency { margin-right: 4rpx; color: #333; } + .footer-left { display: flex; align-items: center; } + .renting { font-size: 26rpx; color: #333; display: flex; align-items: center; } + .meta { display: flex; align-items: center; } + .meta-item { font-size: 26rpx; color: #333; display: flex; align-items: center; margin-right: 28rpx; } + .cancelled { font-size: 26rpx; color: #999; } + .icon-time { width: 32rpx; height: 32rpx; margin-right: 8rpx; } + .icon-price { width: 32rpx; height: 32rpx; margin-right: 8rpx; } .actions { display: flex; diff --git a/config/api/system.js b/config/api/system.js index 9f16f1c..67e88a6 100644 --- a/config/api/system.js +++ b/config/api/system.js @@ -27,3 +27,12 @@ export const getCommonByBrand = (brandName) => { }) } +// 查询激活的且临近关闭时间最近的活动 +export const getActiveActivity = () => { + return request({ + url: '/app/activity/nearest-active', + method: 'get', + hideLoading: true + }) +} + diff --git a/config/url.js b/config/url.js index cb4e171..fe70554 100644 --- a/config/url.js +++ b/config/url.js @@ -1,5 +1,5 @@ -export const URL = "https://my.gxfs123.com/api" //正式服务器 -// export const URL = "https://fansdev.gxfs123.com/api" //测试服务器 +// export const URL = "https://my.gxfs123.com/api" //正式服务器 +export const URL = "https://fansdev.gxfs123.com/api" //测试服务器 // export const URL = "http://192.168.5.149:8080" //本地调试 // export const URL = "http://127.0.0.1:8080" //本地调试 diff --git a/locale/en-US.js b/locale/en-US.js index ca17ce1..bafdeb5 100644 --- a/locale/en-US.js +++ b/locale/en-US.js @@ -188,6 +188,7 @@ export default { confirmReturn: 'Confirm to return device?', wxPayScore: 'WeChat Pay Score', depositFree: 'Deposit-free', + whitelistOrder: 'Whitelist Order', memberOrder: 'Member Order', wxPay: 'WeChat Pay', depositPay: 'Deposit Pay', diff --git a/locale/zh-CN.js b/locale/zh-CN.js index 302a10f..5e8d9b1 100644 --- a/locale/zh-CN.js +++ b/locale/zh-CN.js @@ -188,6 +188,7 @@ export default { confirmReturn: '确认归还设备?', wxPayScore: '微信支付分', depositFree: '免押租借', + whitelistOrder: '白名单订单', memberOrder: '会员订单', wxPay: '微信支付', depositPay: '押金租借', diff --git a/pages/device/detail.vue b/pages/device/detail.vue index ebe6509..d9bc0a6 100644 --- a/pages/device/detail.vue +++ b/pages/device/detail.vue @@ -23,16 +23,16 @@ {{ $t('device.pricingRules') }} - - - ¥ - {{ deviceFeeConfig.maxHourPrice || '5.00' }} - /{{ $t('time.hour') }} - - - {{ deviceInfo.depositAmount || '99' }}{{ $t('device.capLimit') }} - + + + ¥ + {{ deviceFeeConfig.maxHourPrice || '5.00' }} + /{{ getPriceUnit() }} + + {{ deviceInfo.depositAmount || '99' }}{{ $t('device.capLimit') }} + + @@ -111,8 +111,7 @@ onMounted } from 'vue' import { - onLoad, - onShow + onLoad } from '@dcloudio/uni-app' import { getDeviceInfo, @@ -120,14 +119,9 @@ } from '@/config/api/device.js' import { getOrderByOrderNoScore, - getOrderByOrderNoScorePayStatus, getOrderByOrderNo, - updateOrderPackage, cancelOrder } from '@/config/api/order.js' - import { - URL - } from "@/config/url.js" import { initiateWeChatScorePayment, getUserInfo, @@ -147,7 +141,6 @@ const deviceFeeConfig = ref({}) const positionInfo = ref({}) const deviceLocation = ref('一号教学楼大厅') - const batteryLevel = ref(95) const hasActiveOrder = ref(false) const deviceStatus = reactive({ text: $t('device.available'), @@ -164,7 +157,6 @@ uni.setStorageSync('deviceId', options.deviceNo) } else { deviceId.value = uni.getStorageSync('deviceId') - // uni.removeStorageSync('deviceId') } await checkOrderStatus() await fetchDeviceInfo() @@ -178,10 +170,6 @@ await fetchDeviceInfo() }) - // onShow(async () => { - // await fetchDeviceInfo() - // }) - const checkUserPhone = async () => { try { const userInfoRes = await getUserInfo() @@ -318,15 +306,14 @@ } } - if (deviceInfo.value.feeConfig) { - deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {} - console.log('deviceFeeConfig', deviceFeeConfig.value); - } else { - deviceFeeConfig.value = { - maxHourPrice: '5.00', - } - discount.value = '99.00' + if (deviceInfo.value.feeConfig) { + deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {} + console.log('deviceFeeConfig', deviceFeeConfig.value); + } else { + deviceFeeConfig.value = { + maxHourPrice: '5.00', } + } } @@ -395,14 +382,23 @@ submitRentOrder(payWay) } - const selectedPkg = reactive({ - time: '1小时', - price: '5' - }) - const depositAmount = ref('99.00') + // 获取价格单位文本 + const getPriceUnit = () => { + // 按分钟计费 + if (deviceInfo.value && deviceInfo.value.feeType === 'minute') { + return '分钟' + } + // 按小时计费(默认) + return $t('time.hour') + } // 计算计费单位时间(分钟) const getBillingUnitMinutes = () => { + // 按分钟计费时,单位为1分钟 + if (deviceInfo.value && deviceInfo.value.feeType === 'minute') { + return 1 + } + // 按小时计费 if (!deviceFeeConfig.value || !deviceFeeConfig.value.hourPrice) return 60 const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice) // hourPrice 为 0.5 时表示 30 分钟,为 1 时表示 60 分钟 @@ -413,8 +409,14 @@ const getBillingUnitPrice = () => { if (!deviceFeeConfig.value || !deviceFeeConfig.value.maxHourPrice) return '5' const maxHourPrice = parseFloat(deviceFeeConfig.value.maxHourPrice) + + // 按分钟计费时,直接返回每分钟价格 + if (deviceInfo.value && deviceInfo.value.feeType === 'minute') { + return maxHourPrice.toFixed(2) + } + + // 按小时计费 const hourPrice = parseFloat(deviceFeeConfig.value.hourPrice || 1) - // maxHourPrice 是1小时的价格,需要根据 hourPrice 换算 const unitPrice = maxHourPrice * hourPrice return unitPrice.toFixed(2) } @@ -425,21 +427,18 @@ return parseInt(positionInfo.value.freeRentTime) } - // 计算24小时封顶价格 - const get24HourCapPrice = () => { - if (!deviceFeeConfig.value || !deviceFeeConfig.value.maxHourPrice || !deviceFeeConfig.value.maxHour) - return '45.00' - const maxHourPrice = parseFloat(deviceFeeConfig.value.maxHourPrice) - const maxHour = parseFloat(deviceFeeConfig.value.maxHour) - return (maxHourPrice * maxHour).toFixed(2) - } - // 生成计费说明文本 const getPricingInfoText = () => { - const unitMinutes = getBillingUnitMinutes() const unitPrice = getBillingUnitPrice() const maxHourPrice = deviceFeeConfig.value.maxHourPrice || '5' + // 按分钟计费 + if (deviceInfo.value && deviceInfo.value.feeType === 'minute') { + return `${unitPrice}元/分钟` + } + + // 按小时计费 + const unitMinutes = getBillingUnitMinutes() if (unitMinutes === 30) { return `${unitPrice}元/${unitMinutes}分钟,${maxHourPrice}元/小时` } else { @@ -453,6 +452,12 @@ const unitMinutes = getBillingUnitMinutes() const depositAmount = deviceInfo.value.depositAmount || '99' + // 按分钟计费 + if (deviceInfo.value && deviceInfo.value.feeType === 'minute') { + return `前${freeMinutes}分钟内归还免费,不足${unitMinutes}分钟按${unitMinutes}分钟计费,封顶${depositAmount}元,持续计费至${depositAmount}元视为买断` + } + + // 按小时计费 return `前${freeMinutes}分钟内归还免费,不足${unitMinutes}分钟按${unitMinutes}分钟计费,封顶${depositAmount}元,持续计费至${depositAmount}元视为买断` } @@ -496,54 +501,23 @@ throw new Error(rentResult.msg || $t('device.rentFailed')) } - // 获取后端返回的订单信息 - const order = rentResult.data - console.log('订单信息', order); + // 获取后端返回的订单信息 + const order = rentResult.data + console.log('订单信息', order); - // // --- 统一:先更新订单套餐信息 --- - // try { - // let packageTimeMinutes = 0; - // if (selectedPkg.time.includes('小时')) { - // packageTimeMinutes = parseInt(selectedPkg.time) * 60; - // } else if (selectedPkg.time.includes('分钟')) { - // packageTimeMinutes = parseInt(selectedPkg.time); - // } else { - // packageTimeMinutes = parseInt(selectedPkg.time) * 60; // 默认按小时处理 - // } - - // const updateRes = await updateOrderPackage({ - // orderId: order.orderId, - // packageTime: packageTimeMinutes, - // packagePrice: parseFloat(selectedPkg.price) - // }); - // if (updateRes.code !== 200) { - // console.warn("更新订单套餐信息失败:", updateRes.msg); - // // 这里可以选择是否提示用户或阻止流程,当前不阻止 - // } else { - // console.log("订单套餐信息已提前更新"); - // } - // } catch (updateError) { - // console.error("更新订单套餐信息时出错:", updateError); - // // 即使更新失败,也继续流程 - // } - // --- 套餐信息更新结束 --- - - if (payWay == 'wx-pay') { - //当支付方式为押金支付时 + if (payWay == 'wx-pay') { + // 当支付方式为押金支付时 uni.hideLoading() const res = await getOrderByOrderNo(order.orderNo); console.log(res); - // --- 新增:计算总金额 --- + const deposit = parseFloat(order.depositAmount); const packagePrice = parseFloat(order.unitPrice); const totalAmount = deposit.toFixed(2); - // --- 计算结束 --- - uni.hideLoading() - - // 跳转到订单支付页面,传递订单ID、套餐信息和总金额 + // 跳转到订单支付页面 uni.redirectTo({ - url: `/pages/order/payment?orderId=${order.orderId}&packageTimeHours=${selectedPkg.time.replace('小时', '')}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${depositAmount.value}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}` + url: `/pages/order/payment?orderId=${order.orderId}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${deposit}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}` }) } else if (payWay == 'wx-score-pay') { @@ -915,15 +889,10 @@ margin-right: 8rpx; } - .credit-text { - font-size: 24rpx; - color: #999; - - .divider { - margin: 0 8rpx; - color: #ddd; - } - } + .credit-text { + font-size: 24rpx; + color: #999; + } } } diff --git a/pages/help/index.vue b/pages/help/index.vue index 9ec0fd1..8bd8bbf 100644 --- a/pages/help/index.vue +++ b/pages/help/index.vue @@ -1,21 +1,19 @@ @@ -176,7 +194,8 @@ getPotionsDetail } from '../../config/api/order.js' import { - getNoticeTextData + getNoticeTextData, + getActiveActivity } from '../../config/api/system.js' // 导入地图工具函数 import { @@ -214,6 +233,8 @@ const showLocationPopup = ref(false) const isRelocating = ref(false) // 防抖标志:是否正在重新定位 const showGuidePopup = ref(false) // 使用指南弹窗显示状态 const showNoticePopup = ref(false) // 通知详情弹窗显示状态 +const showActivityPopup = ref(false) // 活动弹窗显示状态 +const activityData = ref(null) // 活动数据 // 导航栏高度相关 const statusBarHeight = ref(0) @@ -267,6 +288,31 @@ const statusBarHeight = ref(0) console.warn('缓存通知内容失败:', e); } } + + // 查询最近的活动 + const checkActiveActivity = async () => { + try { + // 检查是否已经显示过活动弹窗(本次会话) + const hasShownActivity = uni.getStorageSync('hasShownActivityInSession'); + if (hasShownActivity) { + console.log('本次会话已显示过活动弹窗,跳过'); + return; + } + + const res = await getActiveActivity(); + if (res.code === 200 && res.data) { + activityData.value = res.data; + // 延迟一下显示,避免与其他弹窗冲突 + setTimeout(() => { + openActivityPopup(); + // 标记本次会话已显示过活动弹窗 + uni.setStorageSync('hasShownActivityInSession', true); + }, 500); + } + } catch (e) { + console.warn('查询活动失败:', e); + } + } // 距离格式化函数 const formatDistance = (distanceInMeters) => { @@ -282,6 +328,7 @@ const statusBarHeight = ref(0) const mapRef = ref(null) const guidePopup = ref(null) const noticePopup = ref(null) +const activityPopup = ref(null) // 计算属性 const searchPlaceholder = computed(() => { @@ -344,8 +391,8 @@ const noticePopup = ref(null) // 2. 加载场地列表 await loadPositions() - // 3. 检查是否需要显示使用指南(可以根据用户行为记录来决定) - // 这里暂时默认显示,后续可以根据用户使用情况优化 + // 3. 查询活动并显示弹窗 + await checkActiveActivity() } catch (error) { console.error('初始化失败:', error) @@ -843,6 +890,21 @@ const closeNoticePopup = () => { noticePopup.value && typeof noticePopup.value.close === 'function' && noticePopup.value.close() } catch (e) {} } + +// 活动弹窗控制 +const openActivityPopup = () => { + try { + showActivityPopup.value = true + activityPopup.value && typeof activityPopup.value.open === 'function' && activityPopup.value.open() + } catch (e) {} +} + +const closeActivityPopup = () => { + try { + showActivityPopup.value = false + activityPopup.value && typeof activityPopup.value.close === 'function' && activityPopup.value.close() + } catch (e) {} +}