From 85d158dfec727cff7838ca383c8f9dd806b03ddf Mon Sep 17 00:00:00 2001 From: luo Date: Wed, 17 Jun 2026 17:46:04 +0800 Subject: [PATCH] feat: order-export,generation,status --- .../proposal.md | 20 ++++++++ .../specs/asset-information/spec.md | 34 ++++++++++++++ .../tasks.md | 28 +++++++++++ .../add-order-export-scene/proposal.md | 24 ++++++++++ .../specs/export-task-management/spec.md | 35 ++++++++++++++ .../changes/add-order-export-scene/tasks.md | 33 +++++++++++++ .../business/ExportTaskCreateDialog.vue | 3 +- src/types/api/card.ts | 17 +++++++ src/types/api/device.ts | 11 +++++ src/types/api/exportTask.ts | 2 +- .../asset-management/device-list/index.vue | 24 ++++++++++ .../export-task-detail/index.vue | 3 +- .../export-task-list/index.vue | 3 +- .../iot-card-management/index.vue | 24 ++++++++++ .../order-management/order-list/index.vue | 47 +++++++++++++++++-- 15 files changed, 300 insertions(+), 8 deletions(-) create mode 100644 openspec/changes/add-asset-status-generation-display/proposal.md create mode 100644 openspec/changes/add-asset-status-generation-display/specs/asset-information/spec.md create mode 100644 openspec/changes/add-asset-status-generation-display/tasks.md create mode 100644 openspec/changes/add-order-export-scene/proposal.md create mode 100644 openspec/changes/add-order-export-scene/specs/export-task-management/spec.md create mode 100644 openspec/changes/add-order-export-scene/tasks.md diff --git a/openspec/changes/add-asset-status-generation-display/proposal.md b/openspec/changes/add-asset-status-generation-display/proposal.md new file mode 100644 index 0000000..32cecc0 --- /dev/null +++ b/openspec/changes/add-asset-status-generation-display/proposal.md @@ -0,0 +1,20 @@ +# Change: 新增资产业务状态和世代编号字段 + +## Why + +后端已在 IoT 卡和设备的资产详情接口中新增 `asset_status`(业务状态)和 `generation`(资产世代编号)字段,前端需要展示这些字段供运营人员查看。 + +## What Changes + +- 资产信息详情新增 `asset_status` 和 `asset_status_name` 字段,展示业务状态(1:在库, 2:已销售, 3:已换货, 4:已停用) +- 资产信息详情新增 `generation` 字段,展示资产世代编号(初始值1,每次换货转新后+1) +- 相关格式化函数更新以支持新字段 + +## Impact + +- Affected specs: + - `asset-information` +- Affected code: + - `src/views/asset-management/asset-information/types.ts` - AssetInfo 接口 + - `src/views/asset-management/asset-information/components/BasicInfoCard.vue` - 详情展示 + - `src/views/asset-management/asset-information/composables/useAssetFormatters.ts` - 格式化函数 diff --git a/openspec/changes/add-asset-status-generation-display/specs/asset-information/spec.md b/openspec/changes/add-asset-status-generation-display/specs/asset-information/spec.md new file mode 100644 index 0000000..68b32a5 --- /dev/null +++ b/openspec/changes/add-asset-status-generation-display/specs/asset-information/spec.md @@ -0,0 +1,34 @@ +## ADDED Requirements + +### Requirement: Asset Status and Generation Display + +The admin frontend SHALL display `asset_status`, `asset_status_name`, and `generation` fields in the asset information detail page for both IoT cards and devices. + +#### Scenario: Display IoT card asset status and generation + +- **GIVEN** 用户打开 IoT 卡资产信息详情页 +- **WHEN** 后端返回 `asset_status`、`asset_status_name` 和 `generation` 字段 +- **THEN** 页面 MUST display the asset status with appropriate tag type +- **AND** 页面 MUST display the generation number + +#### Scenario: Display device asset status and generation + +- **GIVEN** 用户打开设备资产信息详情页 +- **WHEN** 后端返回 `asset_status`、`asset_status_name` 和 `generation` 字段 +- **THEN** 页面 MUST display the asset status with appropriate tag type +- **AND** 页面 MUST display the generation number + +### Requirement: Asset Status Formatting + +The admin frontend SHALL format asset status values with appropriate labels and tag types. + +#### Scenario: Map asset status to display name + +- **GIVEN** `asset_status` value is 1 +- **THEN** display name MUST be "在库" +- **WHEN** `asset_status` value is 2 +- **THEN** display name MUST be "已销售" +- **WHEN** `asset_status` value is 3 +- **THEN** display name MUST be "已换货" +- **WHEN** `asset_status` value is 4 +- **THEN** display name MUST be "已停用" diff --git a/openspec/changes/add-asset-status-generation-display/tasks.md b/openspec/changes/add-asset-status-generation-display/tasks.md new file mode 100644 index 0000000..60970a4 --- /dev/null +++ b/openspec/changes/add-asset-status-generation-display/tasks.md @@ -0,0 +1,28 @@ +## 1. Proposal Review + +- [ ] 1.1 确认 `asset_status` 字段含义:1:在库, 2:已销售, 3:已换货, 4:已停用 +- [ ] 1.2 确认 `generation` 字段含义:资产世代编号,初始值1,每次换货转新后+1 + +## 2. Type Updates + +- [ ] 2.1 在 `AssetInfo` 接口中添加 `asset_status?: number` +- [ ] 2.2 在 `AssetInfo` 接口中添加 `asset_status_name?: string` +- [ ] 2.3 在 `AssetInfo` 接口中添加 `generation?: number` + +## 3. Formatter Functions + +- [ ] 3.1 在 `useAssetFormatters` 中添加 `getAssetStatusName` 函数(如果不存在) +- [ ] 3.2 在 `useAssetFormatters` 中添加 `getAssetStatusType` 函数(如果不存在) + +## 4. BasicInfoCard Component + +- [ ] 4.1 在卡信息区域添加「业务状态」展示行 +- [ ] 4.2 在卡信息区域添加「资产世代」展示行 +- [ ] 4.3 在设备信息区域添加「业务状态」展示行 +- [ ] 4.4 在设备信息区域添加「资产世代」展示行 + +## 5. Verification + +- [ ] 5.1 验证 IoT 卡详情页正确显示业务状态和世代编号 +- [ ] 5.2 验证设备详情页正确显示业务状态和世代编号 +- [ ] 5.3 验证格式化函数正确处理各状态值 diff --git a/openspec/changes/add-order-export-scene/proposal.md b/openspec/changes/add-order-export-scene/proposal.md new file mode 100644 index 0000000..99143e8 --- /dev/null +++ b/openspec/changes/add-order-export-scene/proposal.md @@ -0,0 +1,24 @@ +# Change: 新增订单导出场景 + +## Why + +导出管理现已支持设备管理和IoT卡管理两个导出场景,需要扩展至订单管理,以便订单列表也能按当前检索条件全量导出。 + +## What Changes + +- 在导出任务中新增 `order` 导出场景支持 +- 导出管理列表的场景筛选中新增「订单管理」选项 +- 订单列表页面新增导出按钮,创建 `scene=order` 的导出任务 +- 订单导出按钮需要权限编码控制 + +## Impact + +- Affected specs: + - `export-task-management` +- Affected code: + - `src/types/api/exportTask.ts` - ExportTaskScene 类型 + - `src/views/asset-management/export-task-management/export-task-list/index.vue` - 场景选项 + - `src/components/business/ExportTaskCreateDialog.vue` - sceneName 映射 + - `src/views/order-management/order-list/index.vue` - 导出按钮 +- Dependencies: + - 依赖后端 export task API 支持 `scene=order` diff --git a/openspec/changes/add-order-export-scene/specs/export-task-management/spec.md b/openspec/changes/add-order-export-scene/specs/export-task-management/spec.md new file mode 100644 index 0000000..82ebb23 --- /dev/null +++ b/openspec/changes/add-order-export-scene/specs/export-task-management/spec.md @@ -0,0 +1,35 @@ +## ADDED Requirements + +### Requirement: Order Export Scene Support + +The system SHALL support `scene="order"` for creating export tasks from the order management list. + +#### Scenario: Create order export task from order management + +- **GIVEN** 用户在订单管理页设置了列表检索条件 +- **AND** 当前用户具备订单导出权限 +- **WHEN** 用户确认创建导出任务 +- **THEN** 系统 MUST submit `scene="order"` +- **AND** 系统 MUST submit the current order list filter conditions as `query` + +### Requirement: Order Export in Export Task List + +The admin frontend SHALL display "订单管理" as a selectable scene option when filtering export tasks. + +#### Scenario: Filter export tasks by order scene + +- **GIVEN** 用户打开导出列表页面 +- **WHEN** 用户选择「订单管理」作为场景筛选条件 +- **THEN** 系统 MUST call `GET /api/admin/export-tasks` with `scene=order` + +## MODIFIED Requirements + +### Requirement: Reusable Export Task Creation Dialog + +The admin frontend already provides a reusable dialog for creating export tasks. This requirement adds the order scene to the scene name mapping. + +#### Scenario: Display order scene name in dialog + +- **GIVEN** 导出弹窗通过 `scene="order"` 打开 +- **WHEN** 弹窗渲染 +- **THEN** 弹窗 MUST display "订单管理" as the scene name diff --git a/openspec/changes/add-order-export-scene/tasks.md b/openspec/changes/add-order-export-scene/tasks.md new file mode 100644 index 0000000..d3c63fd --- /dev/null +++ b/openspec/changes/add-order-export-scene/tasks.md @@ -0,0 +1,33 @@ +## 1. Proposal Review + +- [ ] 1.1 确认订单导出权限编码(如 `orders:export`) +- [ ] 1.2 确认导出任务 scene 值使用 `order` + +## 2. Type Updates + +- [ ] 2.1 在 `ExportTaskScene` 类型中添加 `order` 选项 + +## 3. Export Task List Page + +- [ ] 3.1 在导出列表的场景筛选选项中添加「订单管理」 + +## 4. Export Dialog Component + +- [ ] 4.1 在 `ExportTaskCreateDialog` 的 `sceneName` 映射中添加 `order` → '订单管理' + +## 5. Order List Page + +- [ ] 5.1 在订单列表页添加导出按钮 +- [ ] 5.2 使用 `ExportTaskCreateDialog`,传入 `scene="order"` 和当前筛选条件 +- [ ] 5.3 添加权限控制(按钮需检查 `orders:export` 权限) + +## 6. Permissions And UX + +- [ ] 6.1 导出按钮在无权限时隐藏 +- [ ] 6.2 创建导出任务成功后提示 + +## 7. Verification + +- [ ] 7.1 验证订单列表页可按当前筛选条件创建 `order` 导出任务 +- [ ] 7.2 验证导出管理列表可按场景筛选 `order` 任务 +- [ ] 7.3 验证无权限时导出按钮不显示 diff --git a/src/components/business/ExportTaskCreateDialog.vue b/src/components/business/ExportTaskCreateDialog.vue index 19b0218..ca3f454 100644 --- a/src/components/business/ExportTaskCreateDialog.vue +++ b/src/components/business/ExportTaskCreateDialog.vue @@ -76,7 +76,8 @@ const sceneName = computed(() => { const sceneMap: Record = { device: '设备管理', - iot_card: 'IoT卡管理' + iot_card: 'IoT卡管理', + order: '订单管理' } return sceneMap[props.scene] diff --git a/src/types/api/card.ts b/src/types/api/card.ts index 1b4a511..eb4581e 100644 --- a/src/types/api/card.ts +++ b/src/types/api/card.ts @@ -63,6 +63,14 @@ export interface SimCardProduct { updateTime?: string } +// 网卡业务状态枚举 +export enum AssetStatus { + IN_STOCK = 1, // 在库 + SOLD = 2, // 已销售 + REPLACED = 3, // 已换货 + DISABLED = 4 // 已停用 +} + // 网卡实体 export interface Card { id: string | number @@ -73,6 +81,9 @@ export interface Card { networkType: NetworkType cardType: CardType status: CardStatus + generation?: number // 资产世代编号(初始值1,每次换货转新后+1) + asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用) + asset_status_name?: string // 业务状态名称(中文) // 关联信息 productId?: string | number // 关联商品ID productName?: string @@ -369,6 +380,9 @@ export interface StandaloneIotCard { activation_status: number // 激活状态 (0:未激活, 1:已激活) network_status: number // 网络状态 (0:停机, 1:开机) real_name_status: number // 实名状态 (0:未实名, 1:已实名) + generation?: number // 资产世代编号(初始值1,每次换货转新后+1) + asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用) + asset_status_name?: string // 业务状态名称(中文) batch_no?: string // 批次号 (可选) supplier?: string // 供应商 (可选) shop_id?: number | null // 店铺ID (可选) @@ -515,6 +529,9 @@ export interface IotCardDetailResponse { activation_status: number // 激活状态 (0:未激活, 1:已激活) network_status: number // 网络状态 (0:停机, 1:开机) real_name_status: number // 实名状态 (0:未实名, 1:已实名) + generation?: number // 资产世代编号(初始值1,每次换货转新后+1) + asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用) + asset_status_name?: string // 业务状态名称(中文) batch_no: string // 批次号 supplier: string // 供应商 shop_id: number | null // 店铺ID diff --git a/src/types/api/device.ts b/src/types/api/device.ts index 60189f4..084f3eb 100644 --- a/src/types/api/device.ts +++ b/src/types/api/device.ts @@ -14,6 +14,14 @@ export enum DeviceStatus { DEACTIVATED = 4 // 已停用 } +// 设备业务状态枚举 +export enum DeviceAssetStatus { + IN_STOCK = 1, // 在库 + SOLD = 2, // 已销售 + REPLACED = 3, // 已换货 + DISABLED = 4 // 已停用 +} + // 设备在线状态枚举 export enum DeviceOnlineStatus { UNKNOWN = 0, // 未知 @@ -38,6 +46,9 @@ export interface Device { bound_card_count: number // 已绑定卡数量 status: DeviceStatus // 状态 (1:在库, 2:已分销, 3:已激活, 4:已停用) status_name: string // 状态名称 + generation?: number // 资产世代编号(初始值1,每次换货转新后+1) + asset_status?: DeviceAssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用) + asset_status_name?: string // 业务状态名称(中文) shop_id: number | null // 店铺ID shop_name: string // 店铺名称 batch_no: string // 批次号 diff --git a/src/types/api/exportTask.ts b/src/types/api/exportTask.ts index 68a98a9..2024763 100644 --- a/src/types/api/exportTask.ts +++ b/src/types/api/exportTask.ts @@ -1,6 +1,6 @@ import type { BaseResponse, PaginationParams } from './common' -export type ExportTaskScene = 'device' | 'iot_card' +export type ExportTaskScene = 'device' | 'iot_card' | 'order' export type ExportTaskFormat = 'xlsx' | 'csv' diff --git a/src/views/asset-management/device-list/index.vue b/src/views/asset-management/device-list/index.vue index 4d0c1e3..6fed81a 100644 --- a/src/views/asset-management/device-list/index.vue +++ b/src/views/asset-management/device-list/index.vue @@ -1219,6 +1219,8 @@ { label: '设备类型', prop: 'device_type' }, { label: '状态', prop: 'status' }, { label: '状态名称', prop: 'status_name' }, + { label: '资产世代', prop: 'generation' }, + { label: '业务状态', prop: 'asset_status' }, { label: '激活状态', prop: 'activation_status_name' }, { label: '在线状态', prop: 'online_status' }, { label: '实名策略', prop: 'realname_policy' }, @@ -1527,6 +1529,28 @@ width: 100, formatter: (row: Device) => row.status_name || '-' }, + { + prop: 'generation', + label: '资产世代', + width: 100, + formatter: (row: Device) => row.generation ?? '-' + }, + { + prop: 'asset_status', + label: '业务状态', + width: 100, + formatter: (row: Device) => { + const assetStatusMap: Record = { + 1: { text: '在库', type: 'info' }, + 2: { text: '已销售', type: 'success' }, + 3: { text: '已换货', type: 'warning' }, + 4: { text: '已停用', type: 'danger' } + } + if (row.asset_status == null) return '-' + const status = assetStatusMap[row.asset_status] || { text: '未知', type: 'info' } + return h(ElTag, { type: status.type }, () => status.text) + } + }, { prop: 'activation_status_name', label: '激活状态', diff --git a/src/views/asset-management/export-task-management/export-task-detail/index.vue b/src/views/asset-management/export-task-management/export-task-detail/index.vue index fcf2070..9e2e6f5 100644 --- a/src/views/asset-management/export-task-management/export-task-detail/index.vue +++ b/src/views/asset-management/export-task-management/export-task-detail/index.vue @@ -67,7 +67,8 @@ const getSceneName = (scene?: ExportTaskScene) => { const sceneMap: Record = { device: '设备管理', - iot_card: 'IoT卡管理' + iot_card: 'IoT卡管理', + order: '订单管理' } return scene ? sceneMap[scene] : '-' diff --git a/src/views/asset-management/export-task-management/export-task-list/index.vue b/src/views/asset-management/export-task-management/export-task-list/index.vue index 298e34b..2163021 100644 --- a/src/views/asset-management/export-task-management/export-task-list/index.vue +++ b/src/views/asset-management/export-task-management/export-task-list/index.vue @@ -74,7 +74,8 @@ const sceneOptions = [ { label: '设备管理', value: 'device' }, - { label: 'IoT卡管理', value: 'iot_card' } + { label: 'IoT卡管理', value: 'iot_card' }, + { label: '订单管理', value: 'order' } ] const statusOptions = [ diff --git a/src/views/asset-management/iot-card-management/index.vue b/src/views/asset-management/iot-card-management/index.vue index 7c3b318..86b0f6e 100644 --- a/src/views/asset-management/iot-card-management/index.vue +++ b/src/views/asset-management/iot-card-management/index.vue @@ -1363,6 +1363,8 @@ { label: '运营商', prop: 'carrier_name' }, { label: '卡业务类型', prop: 'card_category' }, { label: '状态', prop: 'status' }, + { label: '资产世代', prop: 'generation' }, + { label: '业务状态', prop: 'asset_status' }, { label: '激活状态', prop: 'activation_status' }, { label: '激活时间', prop: 'activated_at' }, { label: '网络状态', prop: 'network_status' }, @@ -1550,6 +1552,28 @@ return h(ElTag, { type: getStatusType(row.status) }, () => getStatusText(row.status)) } }, + { + prop: 'generation', + label: '资产世代', + width: 100, + formatter: (row: StandaloneIotCard) => row.generation ?? '-' + }, + { + prop: 'asset_status', + label: '业务状态', + width: 100, + formatter: (row: StandaloneIotCard) => { + const assetStatusMap: Record = { + 1: { text: '在库', type: 'info' }, + 2: { text: '已销售', type: 'success' }, + 3: { text: '已换货', type: 'warning' }, + 4: { text: '已停用', type: 'danger' } + } + if (row.asset_status == null) return '-' + const status = assetStatusMap[row.asset_status] || { text: '未知', type: 'info' } + return h(ElTag, { type: status.type }, () => status.text) + } + }, { prop: 'activation_status', label: '激活状态', diff --git a/src/views/order-management/order-list/index.vue b/src/views/order-management/order-list/index.vue index e49fdfb..43bb42f 100644 --- a/src/views/order-management/order-list/index.vue +++ b/src/views/order-management/order-list/index.vue @@ -22,6 +22,9 @@ {{ '创建订单' }} + {{ + '导出' + }} @@ -152,17 +155,17 @@ @@ -237,13 +240,22 @@ :file-key="paymentVoucherFileKey" @close="paymentVoucherFileKey = ''" /> + + +