From 01cddd7edad972e4b7fec0e0654a94354bbf7169 Mon Sep 17 00:00:00 2001 From: luo Date: Tue, 8 Sep 2026 10:59:38 +0800 Subject: [PATCH] fix:bug --- .../proposal.md | 17 +++ .../spec.md | 19 +++ .../tasks.md | 10 ++ .../business/UpdateRealnameStatusDialog.vue | 1 - .../device/RealnamePolicyDialog.vue | 1 - src/components/device/SwitchCardDialog.vue | 1 - .../components/dialogs/DailyRecordsDialog.vue | 1 - .../components/dialogs/OrderHistoryDialog.vue | 1 - .../dialogs/PackageRechargeDialog.vue | 1 - .../components/dialogs/SpeedLimitDialog.vue | 2 +- .../components/dialogs/SwitchModeDialog.vue | 1 - .../components/dialogs/WiFiConfigDialog.vue | 1 - .../composables/useAssetInfo.ts | 8 +- .../asset-information/index.vue | 109 ------------------ .../order-management/order-list/index.vue | 32 +++-- 15 files changed, 78 insertions(+), 127 deletions(-) create mode 100644 openspec/changes/add-order-list-purchased-package-names/proposal.md create mode 100644 openspec/changes/add-order-list-purchased-package-names/specs/order-list-purchased-package-names/spec.md create mode 100644 openspec/changes/add-order-list-purchased-package-names/tasks.md diff --git a/openspec/changes/add-order-list-purchased-package-names/proposal.md b/openspec/changes/add-order-list-purchased-package-names/proposal.md new file mode 100644 index 0000000..addb666 --- /dev/null +++ b/openspec/changes/add-order-list-purchased-package-names/proposal.md @@ -0,0 +1,17 @@ +# Change: Add purchased package names to the order list + +## Why + +Order list records already include their purchased line items, but operators cannot identify the purchased packages without opening the order detail. Showing these names next to the order number makes multi-package orders immediately understandable. + +## What Changes + +- Place the existing `资产标识符` column immediately after `订单编号`, followed by a `购买套餐名称` column in the order list. +- Render `items[].package_name` in the API-returned order, joining multiple item names with the Chinese enumeration separator `、`. +- Show a placeholder when an order has no returned items or no usable package name. + +## Impact + +- Affected specs: `order-list-purchased-package-names` +- Affected code: `src/views/order-management/order-list/index.vue` +- Dependencies: `GET /api/admin/orders` returns `items` with each item's `package_name`. diff --git a/openspec/changes/add-order-list-purchased-package-names/specs/order-list-purchased-package-names/spec.md b/openspec/changes/add-order-list-purchased-package-names/specs/order-list-purchased-package-names/spec.md new file mode 100644 index 0000000..4b12261 --- /dev/null +++ b/openspec/changes/add-order-list-purchased-package-names/specs/order-list-purchased-package-names/spec.md @@ -0,0 +1,19 @@ +## ADDED Requirements + +### Requirement: Order list purchased package name display + +The order list SHALL display `资产标识符` immediately after `订单编号`, followed by a `购买套餐名称` column. The package-name column MUST render package names from the current row's `items` in their API-returned order and MUST join multiple names with `、`. + +#### Scenario: Order contains multiple purchased packages + +- **GIVEN** an order response whose `items` contains package names `正式套餐` and `加油包33` +- **WHEN** the order is rendered in the order list +- **THEN** `资产标识符` MUST be positioned between `订单编号` and `购买套餐名称` +- **AND** the `购买套餐名称` column MUST display `正式套餐、加油包33` +- **AND** the order-number column MUST retain its existing navigation behavior + +#### Scenario: Order has no available package names + +- **GIVEN** an order response with `items=null`, an empty item list, or item records without usable names +- **WHEN** the order is rendered in the order list +- **THEN** the `购买套餐名称` column MUST display the standard placeholder diff --git a/openspec/changes/add-order-list-purchased-package-names/tasks.md b/openspec/changes/add-order-list-purchased-package-names/tasks.md new file mode 100644 index 0000000..306a4e1 --- /dev/null +++ b/openspec/changes/add-order-list-purchased-package-names/tasks.md @@ -0,0 +1,10 @@ +## 1. Implementation + +- [x] 1.1 Place `资产标识符` after order number and add the purchased-package-name column immediately after it in the order-list column chooser. +- [x] 1.2 Render package names from `Order.items` in API-returned order, separating multiple values with `、`. +- [x] 1.3 Render a placeholder for null, empty, or unnamed order items without altering the order-number link behavior. + +## 2. Verification + +- [x] 2.1 Verify a single item renders its package name and multiple items render `套餐A、套餐B`. +- [x] 2.2 Run targeted format, type, and lint checks. diff --git a/src/components/business/UpdateRealnameStatusDialog.vue b/src/components/business/UpdateRealnameStatusDialog.vue index 4e47b63..82e59e7 100644 --- a/src/components/business/UpdateRealnameStatusDialog.vue +++ b/src/components/business/UpdateRealnameStatusDialog.vue @@ -3,7 +3,6 @@ v-model="dialogVisible" title="手动更新卡实名状态" width="30%" - modal-class="asset-information-dialog" @closed="handleDialogClosed" > diff --git a/src/components/device/RealnamePolicyDialog.vue b/src/components/device/RealnamePolicyDialog.vue index 4cc9c31..6877213 100644 --- a/src/components/device/RealnamePolicyDialog.vue +++ b/src/components/device/RealnamePolicyDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="设置实名认证策略" width="40%" - modal-class="asset-information-dialog" > diff --git a/src/components/device/SwitchCardDialog.vue b/src/components/device/SwitchCardDialog.vue index 9e327be..3666ac7 100644 --- a/src/components/device/SwitchCardDialog.vue +++ b/src/components/device/SwitchCardDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="切换SIM卡" width="40%" - modal-class="asset-information-dialog" @close="handleClose" >
diff --git a/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue b/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue index f50f138..92f8c87 100644 --- a/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="套餐流量详单" width="900px" - modal-class="asset-information-dialog" destroy-on-close >
diff --git a/src/views/asset-management/asset-information/components/dialogs/OrderHistoryDialog.vue b/src/views/asset-management/asset-information/components/dialogs/OrderHistoryDialog.vue index 8d6c183..d4f8aed 100644 --- a/src/views/asset-management/asset-information/components/dialogs/OrderHistoryDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/OrderHistoryDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="往期订单" width="60%" - modal-class="asset-information-dialog" destroy-on-close >
diff --git a/src/views/asset-management/asset-information/components/dialogs/PackageRechargeDialog.vue b/src/views/asset-management/asset-information/components/dialogs/PackageRechargeDialog.vue index d732633..e7a8537 100644 --- a/src/views/asset-management/asset-information/components/dialogs/PackageRechargeDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/PackageRechargeDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="套餐充值" width="40%" - modal-class="asset-information-dialog" @closed="handleDialogClosed" > diff --git a/src/views/asset-management/asset-information/components/dialogs/SpeedLimitDialog.vue b/src/views/asset-management/asset-information/components/dialogs/SpeedLimitDialog.vue index 16b1e6b..04a2785 100644 --- a/src/views/asset-management/asset-information/components/dialogs/SpeedLimitDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/SpeedLimitDialog.vue @@ -5,7 +5,7 @@ width="500px" :lock-scroll="true" :z-index="4000" - modal-class="asset-information-dialog speed-limit-modal" + modal-class="speed-limit-modal" > diff --git a/src/views/asset-management/asset-information/components/dialogs/SwitchModeDialog.vue b/src/views/asset-management/asset-information/components/dialogs/SwitchModeDialog.vue index a3a774a..827b894 100644 --- a/src/views/asset-management/asset-information/components/dialogs/SwitchModeDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/SwitchModeDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="设置切卡模式" width="45%" - modal-class="asset-information-dialog" > diff --git a/src/views/asset-management/asset-information/components/dialogs/WiFiConfigDialog.vue b/src/views/asset-management/asset-information/components/dialogs/WiFiConfigDialog.vue index 70bf42d..26a8e35 100644 --- a/src/views/asset-management/asset-information/components/dialogs/WiFiConfigDialog.vue +++ b/src/views/asset-management/asset-information/components/dialogs/WiFiConfigDialog.vue @@ -3,7 +3,6 @@ v-model="visible" title="设置WiFi" width="40%" - modal-class="asset-information-dialog" :append-to-body="true" > diff --git a/src/views/asset-management/asset-information/composables/useAssetInfo.ts b/src/views/asset-management/asset-information/composables/useAssetInfo.ts index fd34e27..fd57211 100644 --- a/src/views/asset-management/asset-information/composables/useAssetInfo.ts +++ b/src/views/asset-management/asset-information/composables/useAssetInfo.ts @@ -30,6 +30,9 @@ const NULLABLE_REALTIME_CARD_FIELDS = new Set([ 'last_card_status_check_at' ]) +// 详情接口是绑定卡实名时间的唯一来源;实时状态接口不应覆盖或保留旧值。 +const DETAIL_ONLY_BOUND_CARD_FIELDS = new Set(['real_name_at']) + /** * 格式化数据大小(MB -> GB/MB) */ @@ -60,10 +63,13 @@ const mergeAssetBoundCards = ( ): AssetBoundCard[] => realtimeCards.map((realtimeCard) => { const existingCard = existingCards.find((card) => card.iccid === realtimeCard.iccid) - if (!existingCard) return realtimeCard + if (!existingCard) { + return { ...realtimeCard, real_name_at: null } + } const mergedCard = { ...existingCard } as unknown as Record for (const [key, value] of Object.entries(realtimeCard)) { + if (DETAIL_ONLY_BOUND_CARD_FIELDS.has(key)) continue if (value !== undefined && (value !== null || NULLABLE_REALTIME_CARD_FIELDS.has(key))) { mergedCard[key] = value } diff --git a/src/views/asset-management/asset-information/index.vue b/src/views/asset-management/asset-information/index.vue index ca1e49c..ca8e75a 100644 --- a/src/views/asset-management/asset-information/index.vue +++ b/src/views/asset-management/asset-information/index.vue @@ -1653,112 +1653,3 @@ background: #ffffff; } - - diff --git a/src/views/order-management/order-list/index.vue b/src/views/order-management/order-list/index.vue index 684011d..70b2a23 100644 --- a/src/views/order-management/order-list/index.vue +++ b/src/views/order-management/order-list/index.vue @@ -507,12 +507,13 @@ const columnOptions = computed(() => { const options = [ { label: '订单编号', prop: 'order_no' }, + { label: '资产标识符', prop: 'asset_identifier' }, + { label: '购买套餐名称', prop: 'purchased_package_names' }, { label: '买家手机号', prop: 'buyer_phone' }, { label: '买家昵称', prop: 'buyer_nickname' }, { label: '订单类型', prop: 'order_type' }, { label: '资产类型', prop: 'asset_type' }, { label: '买家类型', prop: 'buyer_type' }, - { label: '资产标识符', prop: 'asset_identifier' }, { label: '订单渠道', prop: 'purchase_role' }, { label: '购买备注', prop: 'purchase_remark' }, { label: '是否代购', prop: 'is_purchase_on_behalf' }, @@ -727,6 +728,14 @@ return `¥${(amount / 100).toFixed(2)}` } + const formatPurchasedPackageNames = (order: Order): string => { + const packageNames = (order.items || []) + .map((item) => (item.package_name || '').trim()) + .filter(Boolean) + + return packageNames.join('、') || '-' + } + // 获取支付状态标签类型 const getPaymentStatusType = ( status: PaymentStatus @@ -847,6 +856,20 @@ ) } }, + { + prop: 'asset_identifier', + label: '资产标识符', + width: 180, + showOverflowTooltip: true, + formatter: (row: Order) => row.asset_identifier || '-' + }, + { + prop: 'purchased_package_names', + label: '购买套餐名称', + minWidth: 180, + showOverflowTooltip: true, + formatter: (row: Order) => formatPurchasedPackageNames(row) + }, { prop: 'buyer_phone', label: '买家手机号', @@ -911,13 +934,6 @@ width: 180, formatter: (row: Order) => (row.expires_at ? formatDateTime(row.expires_at) : '-') }, - { - prop: 'asset_identifier', - label: '资产标识符', - width: 180, - showOverflowTooltip: true, - formatter: (row: Order) => row.asset_identifier || '-' - }, { prop: 'purchase_role', label: '订单渠道',