diff --git a/config/url.js b/config/url.js index 106577d..cbd2bfe 100644 --- a/config/url.js +++ b/config/url.js @@ -2,7 +2,7 @@ // export const URL = "https://manager.fdzpower.com/api" //正式国内服务器 export const URL = "https://ina.fdzpower.com/api" //正式国外服务器 // export const URL = "https://fansdev.gxfs123.com/api" //测试服务器 -// export const URL = "http://192.168.0.158:8080" //本地调试 +// export const URL = "http://192.168.0.58:8080" //本地调试 // export const URL = "http://127.0.0.1:8080" //本地调试 export const appid = "wx2165f0be356ae7a9" //微信小程序appid diff --git a/pages/device/detail.vue b/pages/device/detail.vue index 4d6927d..9193fc9 100644 --- a/pages/device/detail.vue +++ b/pages/device/detail.vue @@ -155,12 +155,6 @@ import { useI18n } from '@/utils/i18n.js' - import { - fetchAndCacheDanaPaymentConfig, - DANA_TOTAL_STORAGE_KEY, - DANA_SINGLE_STORAGE_KEY, - parseDanaStorageNumber - } from '@/utils/danaPaymentConfig.js' import DeviceDetailSkeleton from '@/components/DeviceDetailSkeleton.vue' const { @@ -185,32 +179,9 @@ const isWechatMiniProgram = ref(false) const isAlipayMiniProgram = ref(false) const isH5 = ref(false) - const IDR_DEPOSIT_DISPLAY = ref(99000) - const IDR_HOUR_PRICE_DISPLAY = ref(6000) - - const loadDanaPricingCache = () => { - try { - const totalCached = parseDanaStorageNumber(uni.getStorageSync(DANA_TOTAL_STORAGE_KEY)) - const singleCached = parseDanaStorageNumber(uni.getStorageSync(DANA_SINGLE_STORAGE_KEY)) - if (totalCached !== null && totalCached > 0) { - IDR_DEPOSIT_DISPLAY.value = totalCached - } - if (singleCached !== null && singleCached > 0) { - IDR_HOUR_PRICE_DISPLAY.value = singleCached - } - } catch (e) { - console.warn('读取 DANA 金额缓存失败,使用默认值:', e) - } - } - // 生命周期 onLoad 钩子 onLoad(async (options) => { - loadDanaPricingCache() - void fetchAndCacheDanaPaymentConfig() - .then(() => loadDanaPricingCache()) - .catch((e) => console.warn('DANA 配置刷新失败:', e)) - // 普通链接二维码进入时,参数通常在 options.q(且为编码后的完整 URL) if (!options.deviceNo && options.q) { const fullUrl = decodeURIComponent(options.q) @@ -629,12 +600,10 @@ const displayCurrencySymbol = computed(() => (isIdrCurrency.value ? 'Rp ' : '¥')) const displayHourlyPrice = computed(() => { - if (isIdrCurrency.value) return `${IDR_HOUR_PRICE_DISPLAY.value}` return deviceFeeConfig.value.maxHourPrice || '5.00' }) const displayDepositCap = computed(() => { - if (isIdrCurrency.value) return `${IDR_DEPOSIT_DISPLAY.value}` return deviceInfo.value.depositAmount || '99' }) diff --git a/pages/index/index.vue b/pages/index/index.vue index df0edca..18ccd2f 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -191,7 +191,6 @@ getCurrentAnnouncement, getCurrentAdvertisement } from '../../config/api/system.js' - import { fetchAndCacheDanaPaymentConfig } from '../../utils/danaPaymentConfig.js' import { getProductList } from '../../config/api/product.js' @@ -619,10 +618,7 @@ // 并行加载公告和广告(不依赖定位) await Promise.all([ getNoticeText(), - getBannerImages(), - fetchAndCacheDanaPaymentConfig().catch((e) => { - console.warn('获取 DANA 配置失败,继续使用本地默认值:', e) - }) + getBannerImages() ]) // #ifdef H5 diff --git a/pages/order/detail.vue b/pages/order/detail.vue index 6bca9a9..4e47e0b 100644 --- a/pages/order/detail.vue +++ b/pages/order/detail.vue @@ -264,12 +264,6 @@ import { useI18n } from '@/utils/i18n.js' - import { - fetchAndCacheDanaPaymentConfig, - DANA_SINGLE_STORAGE_KEY, - DANA_TOTAL_STORAGE_KEY, - parseDanaStorageNumber - } from '@/utils/danaPaymentConfig.js' const { t @@ -329,23 +323,6 @@ const convertToOwnPopup = ref(null) const lastDeviceEjectTime = ref(0) // 上次点击"宝未弹出"的时间戳 const currencyCode = ref('CNY') - const danaPaymentTotal = ref(0) - const danaPaymentSingle = ref(6000) - - const loadDanaPaymentCache = () => { - try { - const cachedTotal = parseDanaStorageNumber(uni.getStorageSync(DANA_TOTAL_STORAGE_KEY)) - const cachedSingle = parseDanaStorageNumber(uni.getStorageSync(DANA_SINGLE_STORAGE_KEY)) - if (cachedTotal !== null) { - danaPaymentTotal.value = cachedTotal - } - if (cachedSingle !== null && cachedSingle > 0) { - danaPaymentSingle.value = cachedSingle - } - } catch (e) { - console.warn('读取 DANA 金额缓存失败,使用默认值:', e) - } - } const resolveCurrencyCode = (orderData = {}) => { const explicitCurrency = String( @@ -546,7 +523,7 @@ const orderTypeText = orderTypeMap[orderInfo.value.orderType] || orderInfo.value.orderType if (currencyCode.value === 'IDR') { - return `Rp${formatAmountDisplay(danaPaymentSingle.value)}/${orderTypeText}` + return `Rp${formatAmountDisplay(orderInfo.value.unitPrice)}/${orderTypeText}` } return `${formatAmountDisplay(orderInfo.value.unitPrice)}${getCurrencyUnitText()}/${orderTypeText}` } @@ -686,9 +663,19 @@ return orderInfo.value.orderStatus === 'in_used' ? t('order.used') : t('order.duration') } - // 总金额展示:使用本地缓存 danaPaymentTotal(结构如 { type: 'number', data: 99000 }),由 loadDanaPaymentCache 同步到 danaPaymentTotal + // 获取订单费用(不含单位) const getOrderFee = () => { - return formatAmountDisplay(String(danaPaymentTotal.value)) + let fee + if (orderInfo.value.originalFee) { + fee = orderInfo.value.originalFee || '0' + } else if (orderInfo.value.payAmount) { + fee = orderInfo.value.payAmount + } else { + fee = orderInfo.value.currentFee + } + + // 移除小数位,仅显示整数金额 + return formatAmountDisplay(String(fee).replace(/[元¥]/g, '')) } // 解析开始时间 @@ -1446,10 +1433,6 @@ // 生命周期钩子 onLoad((options) => { - loadDanaPaymentCache() - void fetchAndCacheDanaPaymentConfig() - .then(() => loadDanaPaymentCache()) - .catch((e) => console.warn('DANA 配置刷新失败:', e)) console.log('订单详情页加载,参数:', JSON.stringify(options)) // 设置页面标题 @@ -1492,7 +1475,6 @@ }) onShow(() => { - loadDanaPaymentCache() isPageActive.value = true if (orderInfo.value.orderStatus === 'in_used' && orderInfo.value.isSupportExpressReturn !== 'no') { startExpressCountdown() diff --git a/subPackages/order/index.vue b/subPackages/order/index.vue index 5122fe2..d136d90 100644 --- a/subPackages/order/index.vue +++ b/subPackages/order/index.vue @@ -45,16 +45,13 @@ import { getOrderList, queryById, + getOrderByOrderNo, getOrderByOrderNoScorePayStatus, - cancelOrder, - createWxPayment + cancelOrder } from '../../config/api/order.js'; import { - updateUserBalance - } from '../../config/api/user.js'; - import { - URL - } from '../../config/url.js'; + getDeviceInfo + } from '../../config/api/device.js'; import { useI18n } from '@/utils/i18n.js' const { t } = useI18n() @@ -283,54 +280,79 @@ navigateToOrderDetail(order); }; - // 立即支付 + /** + * 待支付订单:与设备租借押金流程一致,进入支付详情页(微信/支付宝/H5-Antom/DANA 等在支付页内选择并完成) + */ const handlePayment = async (order) => { + const orderNo = order.orderNo + const orderId = order.orderId || order.orderNo + if (!orderId && !orderNo) { + uni.showToast({ + title: t('order.orderInfoMissing'), + icon: 'none' + }) + return + } + try { uni.showLoading({ - title: t('common.processing') - }); - - // 调用后端创建微信支付订单接口 - const res = await createWxPayment(order.orderNo); + title: t('common.loading') + }) - if (res && res.code === 200) { - const payParams = res.data; - - // 调用微信支付 - await uni.requestPayment({ - ...payParams, - success: async () => { - uni.showToast({ - title: t('payment.paymentSuccess'), - icon: 'success' - }); - - // 更新用户余额 - try { - await updateUserBalance(order.orderId || order.orderNo); - } catch (error) { - console.warn('更新用户余额失败:', error); - } - - // 刷新订单列表 - await loadOrderList(orderStatusTabs[currentTab.value].status); - }, - fail: (err) => { - console.error('支付失败:', err); - throw new Error(t('payment.paymentFailedRetry')); - } - }); - } else { - throw new Error(res?.msg || '创建支付订单失败'); + let od = null + if (orderNo) { + const res = await getOrderByOrderNo(orderNo) + if (res && res.code === 200 && res.data) { + od = res.data + } } - - uni.hideLoading(); + if (!od && orderId) { + const res = await queryById(orderId) + if (res && res.code === 200 && res.data) { + od = res.data + } + } + + const idForPay = String(od?.orderId ?? orderId ?? orderNo ?? '') + const qsParts = [`orderId=${encodeURIComponent(idForPay)}`] + + if (od) { + const deposit = parseFloat(od.depositAmount) + const packagePrice = parseFloat(od.unitPrice) + if (Number.isFinite(packagePrice)) { + qsParts.push(`packagePrice=${packagePrice}`) + } + if (Number.isFinite(deposit)) { + const totalAmount = deposit.toFixed(2) + qsParts.push(`totalAmount=${encodeURIComponent(totalAmount)}`) + qsParts.push(`depositAmount=${encodeURIComponent(String(deposit))}`) + } + + const deviceNo = od.deviceNo || order.deviceId + if (deviceNo) { + try { + const devRes = await getDeviceInfo(deviceNo) + const feeCfg = devRes?.data?.device?.feeConfig + if (feeCfg) { + qsParts.push(`feeConfig=${encodeURIComponent(feeCfg)}`) + } + } catch (e) { + console.warn('获取设备 feeConfig 失败,支付页将仅依赖订单信息:', e) + } + } + } + + uni.hideLoading() + uni.navigateTo({ + url: `/subPackages/order/payment?${qsParts.join('&')}` + }) } catch (error) { - uni.hideLoading(); + uni.hideLoading() + console.error('跳转支付页失败:', error) uni.showToast({ - title: error.message || t('payment.paymentFailed'), + title: error?.message || t('payment.paymentFailed'), icon: 'none' - }); + }) } }; diff --git a/subPackages/order/payment.vue b/subPackages/order/payment.vue index 49daf5c..0b278ed 100644 --- a/subPackages/order/payment.vue +++ b/subPackages/order/payment.vue @@ -117,12 +117,6 @@ import { useI18n } from '@/utils/i18n.js' - import { - fetchAndCacheDanaPaymentConfig, - DANA_TOTAL_STORAGE_KEY, - DANA_SINGLE_STORAGE_KEY, - parseDanaStorageNumber - } from '@/utils/danaPaymentConfig.js' const { t @@ -135,23 +129,6 @@ const passedTotalAmount = ref(null) const passedDepositAmount = ref(null) const currencyCode = ref('USD') - const IDR_DEPOSIT_DISPLAY = ref(99000) - const IDR_SINGLE_DISPLAY = ref(6000) - - const loadDanaTotalCache = () => { - try { - const cachedTotal = parseDanaStorageNumber(uni.getStorageSync(DANA_TOTAL_STORAGE_KEY)) - const cachedSingle = parseDanaStorageNumber(uni.getStorageSync(DANA_SINGLE_STORAGE_KEY)) - if (cachedTotal !== null && cachedTotal > 0) { - IDR_DEPOSIT_DISPLAY.value = cachedTotal - } - if (cachedSingle !== null && cachedSingle > 0) { - IDR_SINGLE_DISPLAY.value = cachedSingle - } - } catch (e) { - console.warn('读取 DANA 预支付缓存失败,使用默认值:', e) - } - } // 支付方式相关(微信/支付宝/H5-Antom 多平台) const paymentMethods = ref([]) @@ -178,7 +155,12 @@ const totalAmount = computed(() => { if (currencyCode.value === 'IDR') { - return `${IDR_DEPOSIT_DISPLAY.value}` + const raw = + passedTotalAmount.value != null && passedTotalAmount.value !== '' + ? passedTotalAmount.value + : orderInfo.value.deposit + const num = Number(String(raw ?? '').replace(/[^\d.-]/g, '')) + return Number.isFinite(num) ? String(Math.trunc(num)) : String(raw || '0') } if (passedTotalAmount.value !== null) { return parseFloat(passedTotalAmount.value).toFixed(2); @@ -281,10 +263,7 @@ currencyCode.value = (res.data?.position?.currency || currencyCode.value || 'USD').toUpperCase() if (deviceInfo.value && deviceInfo.value.depositAmount) { - orderInfo.value.deposit = deviceInfo.value.depositAmount; - } - if (currencyCode.value === 'IDR') { - orderInfo.value.deposit = `${IDR_DEPOSIT_DISPLAY.value}` + orderInfo.value.deposit = deviceInfo.value.depositAmount } } } catch (error) { @@ -350,14 +329,14 @@ paymentMethodType: 'ALIPAY_DANA', paymentMethodName: t('payment.ALIPAYDANA') }) - methods.push({ - paymentMethodType: 'ALIPAY_HK', - paymentMethodName: t('payment.alipayHk') - }) - methods.push({ - paymentMethodType: 'ALIPAY_ID', - paymentMethodName: t('payment.alipayId') - }) + // methods.push({ + // paymentMethodType: 'ALIPAY_HK', + // paymentMethodName: t('payment.alipayHk') + // }) + // methods.push({ + // paymentMethodType: 'ALIPAY_ID', + // paymentMethodName: t('payment.alipayId') + // }) } catch (error) { console.error('获取 Antom 支付方式失败:', error); @@ -713,10 +692,6 @@ } onLoad((options) => { - loadDanaTotalCache() - void fetchAndCacheDanaPaymentConfig() - .then(() => loadDanaTotalCache()) - .catch((e) => console.warn('DANA 配置刷新失败:', e)) // 设置导航栏标题为待支付 uni.setNavigationBarTitle({ title: t('payment.waitingForPayment') diff --git a/utils/danaPaymentConfig.js b/utils/danaPaymentConfig.js deleted file mode 100644 index 69fce79..0000000 --- a/utils/danaPaymentConfig.js +++ /dev/null @@ -1,79 +0,0 @@ -import { getSystemConfig } from '@/config/api/system.js' - -/** 系统配置项 key(与后台一致) */ -export const DANA_TOTAL_CONFIG_KEY = 'overseas_payment_dana_total' -export const DANA_SINGLE_CONFIG_KEY = 'overseas_payment_dana_single' - -/** 本地缓存 key */ -export const DANA_TOTAL_STORAGE_KEY = 'danaPaymentTotal' -export const DANA_SINGLE_STORAGE_KEY = 'danaPaymentSingle' - -/** 写入缓存的金额结构(与业务侧约定一致) */ -const wrapStorageNumber = (n) => ({ type: 'number', data: n }) - -/** - * 从本地缓存读取 DANA 金额;兼容 { type, data }、JSON 字符串、纯数字。 - */ -export function parseDanaStorageNumber(raw) { - if (raw === null || raw === undefined || raw === '') return null - let value = raw - if (typeof raw === 'string') { - const trimmed = raw.trim() - if (trimmed.startsWith('{')) { - try { - const parsed = JSON.parse(trimmed) - if (parsed && typeof parsed === 'object' && 'data' in parsed) { - value = parsed.data - } else { - value = parsed - } - } catch { - value = raw - } - } - } else if (typeof raw === 'object' && raw !== null && 'data' in raw) { - value = raw.data - } - const num = Number(value) - return Number.isFinite(num) ? num : null -} - -const parseConfigNumber = (rawValue) => { - if (rawValue === null || rawValue === undefined) return null - const cleaned = String(rawValue).replace(/[^0-9.]/g, '') - if (!cleaned) return null - const num = Number(cleaned) - return Number.isFinite(num) ? num : null -} - -const extractConfigValue = (res, configKey) => { - if (!res || res.code !== 200) return null - const row = (res.rows || []).find((item) => item && item.configKey === configKey) - if (row && row.configValue !== undefined) return row.configValue - return null -} - -/** - * 拉取 DANA 预扣款 / 单次扣款配置并写入本地缓存。 - * 用于首页及「直达」设备详情、订单详情、支付页等场景,避免仅依赖首页拉取。 - */ -export async function fetchAndCacheDanaPaymentConfig() { - const [totalRes, singleRes] = await Promise.all([ - getSystemConfig({ configKey: DANA_TOTAL_CONFIG_KEY }), - getSystemConfig({ configKey: DANA_SINGLE_CONFIG_KEY }) - ]) - - const totalRaw = extractConfigValue(totalRes, DANA_TOTAL_CONFIG_KEY) - const singleRaw = extractConfigValue(singleRes, DANA_SINGLE_CONFIG_KEY) - const totalValue = parseConfigNumber(totalRaw) - const singleValue = parseConfigNumber(singleRaw) - - if (totalValue !== null) { - uni.setStorageSync(DANA_TOTAL_STORAGE_KEY, wrapStorageNumber(totalValue)) - } - if (singleValue !== null) { - uni.setStorageSync(DANA_SINGLE_STORAGE_KEY, wrapStorageNumber(singleValue)) - } - - return { totalValue, singleValue } -}