diff --git a/api/modules/asset.js b/api/modules/asset.js index ae460d8..ebe376c 100644 --- a/api/modules/asset.js +++ b/api/modules/asset.js @@ -1,12 +1,31 @@ import request from '@/utils/request.js'; +export const normalizeAssetInfo = (data = {}) => ({ + ...data, + allowed_payment_methods: Array.isArray(data.allowed_payment_methods) + ? data.allowed_payment_methods + : [], + real_name_status: data.real_name_status === undefined || data.real_name_status === null + ? data.real_name_status + : Number(data.real_name_status), + realname_required: data.realname_required === undefined || data.realname_required === null + ? data.realname_required + : data.realname_required === true || data.realname_required === 1, + days_until_final_expiry: data.days_until_final_expiry === null || data.days_until_final_expiry === undefined + ? data.days_until_final_expiry + : Number(data.days_until_final_expiry), + is_expiring: data.is_expiring === undefined || data.is_expiring === null + ? data.is_expiring + : data.is_expiring === true || data.is_expiring === 1 +}); + export const assetApi = { getInfo(identifier) { return request({ url: '/api/c/v1/asset/info', method: 'GET', data: { identifier } - }); + }).then(normalizeAssetInfo); }, getPackageHistory(identifier, page, page_size, params = {}) { @@ -32,4 +51,4 @@ export const assetApi = { data: { identifier } }); } -}; \ No newline at end of file +}; diff --git a/api/modules/auth.js b/api/modules/auth.js index a229aeb..95c015e 100644 --- a/api/modules/auth.js +++ b/api/modules/auth.js @@ -5,7 +5,8 @@ export const authApi = { return request({ url: '/api/c/v1/auth/verify-asset', method: 'POST', - data: { identifier } + data: { identifier }, + showError: false }); }, @@ -47,4 +48,4 @@ export const authApi = { method: 'POST' }); } -}; \ No newline at end of file +}; diff --git a/api/modules/order.js b/api/modules/order.js index f3c1bb2..bc5a82b 100644 --- a/api/modules/order.js +++ b/api/modules/order.js @@ -22,10 +22,8 @@ export const orderApi = { }, create(identifier, package_ids, payment_method) { - const data = { identifier, package_ids }; - if (payment_method === 'alipay') { - data.payment_method = payment_method; - } else { + const data = { identifier, package_ids, payment_method }; + if (payment_method === 'wechat') { data.app_type = APP_TYPE; } diff --git a/components/NotificationPopup.vue b/components/NotificationPopup.vue index 69316e5..0e4d4a6 100644 --- a/components/NotificationPopup.vue +++ b/components/NotificationPopup.vue @@ -10,6 +10,7 @@ {{ item.title || '业务通知' }} + {{ getNotificationMeta(item) }} {{ formatDate(item.created_at) }} {{ item.body || '暂无通知内容' }} @@ -47,6 +48,20 @@ if (!value) return '-'; return value.replace('T', ' ').slice(0, 16); }; + + const getNotificationMeta = (item) => { + const category = { + expiry: '套餐临期', + exchange: '换货' + }[item?.category] || '业务通知'; + const severity = { + info: '提示', + warning: '警告', + error: '错误', + critical: '严重' + }[item?.severity]; + return severity ? `${category} · ${severity}` : category; + }; diff --git a/pages/order-list/order-list.vue b/pages/order-list/order-list.vue index b45fbfe..2899c81 100644 --- a/pages/order-list/order-list.vue +++ b/pages/order-list/order-list.vue @@ -21,7 +21,7 @@ - + @@ -44,6 +44,14 @@ + + 购买角色 + {{ item.purchase_role || '-' }} + + + 资产标识 + {{ item.asset_identifier || '-' }} + 订单金额 ¥{{ formatMoney(item.total_amount) }} @@ -55,10 +63,13 @@ - + + + @@ -87,6 +98,8 @@ showPaymentToast, wechatH5Pay } from '@/utils/payment.js'; + import { formatMoney } from '@/utils/display.js'; + import { getPaymentMethodOptions, normalizePaymentMethods } from '@/utils/payment-methods.js'; const userStore = useUserStore(); @@ -97,12 +110,9 @@ const orderPayingId = ref(null); const pageSize = 10; const filterIndex = ref(0); - const isDeviceAsset = ref(true); + const allowedPaymentMethods = ref([]); let assetTypePromise = null; - const paymentMethodOptions = computed(() => [ - { label: '支付宝支付', value: 'alipay' }, - { label: '钱包支付', value: 'wallet' } - ]); + const paymentMethodOptions = computed(() => getPaymentMethodOptions(allowedPaymentMethods.value)); const filterOptions = [ { label: '全部', value: null }, { label: '待支付', value: 1 }, @@ -111,11 +121,6 @@ { label: '已退款', value: 4 } ]; - const formatMoney = (amount) => { - if (!amount && amount !== 0) return '0.00'; - return (amount / 100).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ','); - }; - const getStatusClass = (status) => { const classMap = { 1: 'tag-warning', @@ -132,7 +137,7 @@ assetTypePromise = assetApi.getInfo(userStore.state.identifier) .then((data) => { - isDeviceAsset.value = data.asset_type === 'device'; + allowedPaymentMethods.value = normalizePaymentMethods(data.allowed_payment_methods); }) .catch((error) => { console.error('加载资产类型失败', error); @@ -185,6 +190,7 @@ const newData = (data.items || []).map((item) => ({ ...item, + asset_identifier: item.asset_identifier || item.virtual_no || item.VirtualNo || item.imei || '', payment_status_name: item.payment_status === 1 ? '待支付' : item.payment_status === 2 @@ -223,10 +229,27 @@ const isOrderPaying = (order) => orderPayingId.value === order.order_id; + const openOrderDetail = (order) => { + if (!order?.order_id || orderPayingId.value !== null) return; + uni.navigateTo({ url: `/pages/order-detail/order-detail?id=${order.order_id}` }); + }; + + const startHistoricalRenewal = (order) => { + const packageIds = Array.isArray(order?.package_ids) ? order.package_ids.filter(Boolean) : []; + if (!packageIds.length) return; + const packageNames = Array.isArray(order.package_names) ? order.package_names : []; + const query = `renewal_package_ids=${encodeURIComponent(packageIds.join(','))}&renewal_package_names=${encodeURIComponent(packageNames.join('|'))}`; + uni.navigateTo({ url: `/pages/package-order/package-order?${query}` }); + }; + const showOrderPaymentMethods = async (order) => { if (orderPayingId.value !== null || !order?.order_id) return; await loadAssetType(); const options = paymentMethodOptions.value; + if (!options.length) { + uni.showToast({ title: '暂无可用支付方式', icon: 'none' }); + return; + } uni.showActionSheet({ itemList: options.map((item) => item.label), @@ -253,7 +276,7 @@ uni.hideLoading(); if (paymentMethod === 'wallet') { - showPaymentToast(true, '支付成功'); + await confirmOrderStatus(order); setTimeout(() => { resetOrderListAndLoad(); }, 1500); @@ -271,7 +294,7 @@ try { await wechatH5Pay(payData.pay_config); - showPaymentToast(true, '支付成功'); + await confirmOrderStatus(order); setTimeout(() => { resetOrderListAndLoad(); }, 1500); @@ -302,6 +325,17 @@ } }; + const confirmOrderStatus = async (order) => { + try { + const detail = await orderApi.getDetail(order.order_id); + const status = detail?.payment_status ?? detail?.order?.payment_status; + showPaymentToast(status === 2, status === 2 ? '支付成功' : '支付结果确认中'); + } catch (error) { + console.error('确认订单支付状态失败', error); + showPaymentToast(false, '支付结果确认失败,请稍后查看订单'); + } + }; + onShow(() => { if (!consumePendingPaymentRefresh(PAYMENT_REFRESH_TARGETS.ORDER_LIST)) { return; @@ -491,7 +525,7 @@ display: flex; justify-content: flex-end; - .btn-pay { + .btn-pay { background: #1890ff; color: #fff; border: none; @@ -508,6 +542,8 @@ &::after { border: none; } + + &.btn-renew { background: #52c41a; } } } } diff --git a/pages/package-order/package-order.vue b/pages/package-order/package-order.vue index 7b33acf..4d0bf66 100644 --- a/pages/package-order/package-order.vue +++ b/pages/package-order/package-order.vue @@ -9,8 +9,8 @@ {{ item.package_name }} - - {{ item.is_addon ? '加油包' : '正式套餐' }} + + {{ item.is_renewal ? '续费套餐' : (item.is_addon ? '加油包' : '正式套餐') }} @@ -27,7 +27,7 @@ ¥ - {{ formatMoney(item.retail_price) }} + {{ formatPackagePrice(item.retail_price) }} 立即订购 @@ -44,7 +44,7 @@ {{ currentPackage?.package_name }} - ¥{{ formatMoney(currentPackage?.retail_price) }} + ¥{{ formatPackagePrice(currentPackage?.retail_price) }} 套餐流量 @@ -59,21 +59,17 @@ - + - - 支付宝支付 + + + + {{ method.label }} - - - - - - - 账户余额(¥{{ formatMoney(walletBalance) }}) - - + + 暂无可用支付方式 @@ -88,8 +84,8 @@