From 73ce9af11a5c12a5b9cb66eb6b557b31da4033f8 Mon Sep 17 00:00:00 2001 From: sexygoat <1538832180@qq.com> Date: Sat, 9 May 2026 16:13:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=A3=E7=90=86=E7=B3=BB=E5=88=97?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E5=BA=97=E9=93=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 14 +- .env.development | 4 +- .env.production | 2 +- .../proposal.md | 36 ++ .../asset-package-traffic-display/spec.md | 57 ++ .../tasks.md | 8 + .../proposal.md | 36 ++ .../asset-wallet-transaction-display/spec.md | 57 ++ .../tasks.md | 7 + .../proposal.md | 32 + .../specs/package-management/spec.md | 46 ++ .../tasks.md | 6 + .../proposal.md | 30 + .../specs/shop-series-grant-packages/spec.md | 45 ++ .../tasks.md | 6 + src/types/api/asset.ts | 6 +- .../components/CurrentPackageCard.vue | 37 +- .../components/PackageListCard.vue | 26 +- .../components/WalletTransactionCard.vue | 163 ++++-- .../composables/useAssetInfo.ts | 52 +- .../asset-information/index.vue | 6 + .../package-list/detail.vue | 82 +-- .../package-management/package-list/index.vue | 166 ++++-- .../series-grants/detail.vue | 35 +- .../series-grants/index.vue | 554 +----------------- .../series-grants/packages.vue | 127 ++-- 26 files changed, 833 insertions(+), 807 deletions(-) create mode 100644 openspec/changes/update-asset-package-traffic-display/proposal.md create mode 100644 openspec/changes/update-asset-package-traffic-display/specs/asset-package-traffic-display/spec.md create mode 100644 openspec/changes/update-asset-package-traffic-display/tasks.md create mode 100644 openspec/changes/update-asset-wallet-empty-state-stability/proposal.md create mode 100644 openspec/changes/update-asset-wallet-empty-state-stability/specs/asset-wallet-transaction-display/spec.md create mode 100644 openspec/changes/update-asset-wallet-empty-state-stability/tasks.md create mode 100644 openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/proposal.md create mode 100644 openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/specs/package-management/spec.md create mode 100644 openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/tasks.md create mode 100644 openspec/changes/update-series-grant-package-edit-cost-price-consistency/proposal.md create mode 100644 openspec/changes/update-series-grant-package-edit-cost-price-consistency/specs/shop-series-grant-packages/spec.md create mode 100644 openspec/changes/update-series-grant-package-edit-cost-price-consistency/tasks.md diff --git a/.env b/.env index 8cfed79..0b94fb5 100644 --- a/.env +++ b/.env @@ -1,21 +1,21 @@ # 【通用】环境变量 # 版本号 -VITE_VERSION = 2.4.1.1 +VITE_VERSION=2.4.1.1 # 端口号 -VITE_PORT = 3006 +VITE_PORT=3006 # 网站地址前缀 -VITE_BASE_URL = +VITE_BASE_URL= # API 地址前缀 -VITE_API_URL = https://cmp-api.boss160.cn +VITE_API_URL=https://cmp-api.xm-iot.cn # 权限模式( frontend | backend ) -VITE_ACCESS_MODE = backend +VITE_ACCESS_MODE=backend # 是否打开路由信息 -VITE_OPEN_ROUTE_INFO = false +VITE_OPEN_ROUTE_INFO=false # 锁屏加密密钥 -VITE_LOCK_ENCRYPT_KEY = jfsfjk1938jfj +VITE_LOCK_ENCRYPT_KEY=jfsfjk1938jfj diff --git a/.env.development b/.env.development index 3532770..7e3a2e4 100644 --- a/.env.development +++ b/.env.development @@ -1,10 +1,10 @@ # 【开发】环境变量 # 网站地址前缀 -VITE_BASE_URL = / +VITE_BASE_URL=/ # API 地址前缀 -VITE_API_URL = https://cmp-api.boss160.cn +VITE_API_URL=https://cmp-api.xm-iot.cn # Delete console VITE_DROP_CONSOLE = false diff --git a/.env.production b/.env.production index 049769e..0d728eb 100644 --- a/.env.production +++ b/.env.production @@ -4,7 +4,7 @@ VITE_BASE_URL= # API 地址前缀 -VITE_API_URL=https://cmp-api.boss160.cn +VITE_API_URL=https://cmp-api.xm-iot.cn # Delete console VITE_DROP_CONSOLE=true diff --git a/openspec/changes/update-asset-package-traffic-display/proposal.md b/openspec/changes/update-asset-package-traffic-display/proposal.md new file mode 100644 index 0000000..035f900 --- /dev/null +++ b/openspec/changes/update-asset-package-traffic-display/proposal.md @@ -0,0 +1,36 @@ +# Change: 更新资产详情套餐流量展示口径 + +## Why + +当前资产详情页中的“当前生效套餐”和“套餐列表”已经接入 `real_total_mb`、`real_used_mb`、`virtual_used_mb` 与 `enable_virtual_data`,但非平台账号的展示口径与最新业务说明不一致: + +- 总量应始终使用 `real_total_mb` +- 已使用应按 `enable_virtual_data` 在 `virtual_used_mb` 与 `real_used_mb` 之间切换 +- 剩余与进度条应基于同一套已使用值重新计算 + +如果不统一这套规则,代理账号和企业账号会在同一资产详情页内看到错误的剩余流量和进度占比,影响运营判断。 + +## What Changes + +- 新增资产详情套餐流量展示规范,覆盖: + - “当前生效套餐”卡片 + - “套餐列表”中的流量列 +- 明确非平台/非超级管理员账号(`user_type` 不为 `1`/`2`)的展示规则: + - 总量使用 `real_total_mb` + - 已使用在 `enable_virtual_data=true` 时使用 `virtual_used_mb`,否则使用 `real_used_mb` + - 剩余 = 总量 - 已使用 + - 进度条 = 已使用 / 总量 +- 明确超级管理员和平台用户(`user_type` 为 `1`/`2`)继续保留当前的真流量/虚流量双口径展示 +- 不修改后端接口路径、响应字段或权限模型 + +## Impact + +- Affected specs: + - `asset-package-traffic-display` +- Affected code: + - `src/views/asset-management/asset-information/components/CurrentPackageCard.vue` + - `src/views/asset-management/asset-information/components/PackageListCard.vue` + - `src/views/asset-management/asset-information/composables/useAssetInfo.ts` +- Dependencies: + - `GET /api/admin/assets/:identifier/current-package` + - 资产详情页套餐列表接口继续返回 `real_total_mb`、`real_used_mb`、`virtual_used_mb`、`enable_virtual_data` diff --git a/openspec/changes/update-asset-package-traffic-display/specs/asset-package-traffic-display/spec.md b/openspec/changes/update-asset-package-traffic-display/specs/asset-package-traffic-display/spec.md new file mode 100644 index 0000000..88c174a --- /dev/null +++ b/openspec/changes/update-asset-package-traffic-display/specs/asset-package-traffic-display/spec.md @@ -0,0 +1,57 @@ +## ADDED Requirements + +### Requirement: Non-Platform Asset Package Traffic Display + +The asset information page SHALL use a unified traffic display formula for non-platform users in both the current package card and the package list. + +#### Scenario: Current package uses virtual usage when virtual data is enabled + +- **GIVEN** 当前登录账号的 `user_type` 不是 `1` 或 `2` +- **AND** “当前生效套餐”返回的 `enable_virtual_data` 为 `true` +- **WHEN** 页面渲染“当前生效套餐”的流量信息 +- **THEN** 系统 MUST 使用 `real_total_mb` 作为总量 +- **AND** 系统 MUST 使用 `virtual_used_mb` 作为已使用 +- **AND** 系统 MUST 按 `real_total_mb - virtual_used_mb` 计算剩余 +- **AND** 系统 MUST 按 `virtual_used_mb / real_total_mb` 计算进度条百分比 + +#### Scenario: Current package uses real usage when virtual data is disabled + +- **GIVEN** 当前登录账号的 `user_type` 不是 `1` 或 `2` +- **AND** “当前生效套餐”返回的 `enable_virtual_data` 为 `false` +- **WHEN** 页面渲染“当前生效套餐”的流量信息 +- **THEN** 系统 MUST 使用 `real_total_mb` 作为总量 +- **AND** 系统 MUST 使用 `real_used_mb` 作为已使用 +- **AND** 系统 MUST 按 `real_total_mb - real_used_mb` 计算剩余 +- **AND** 系统 MUST 按 `real_used_mb / real_total_mb` 计算进度条百分比 + +#### Scenario: Package list uses virtual usage when virtual data is enabled + +- **GIVEN** 当前登录账号的 `user_type` 不是 `1` 或 `2` +- **AND** 套餐列表中的某条记录 `enable_virtual_data` 为 `true` +- **WHEN** 页面渲染该条记录的流量信息 +- **THEN** 系统 MUST 使用 `real_total_mb` 作为总量 +- **AND** 系统 MUST 使用 `virtual_used_mb` 作为已使用 +- **AND** 系统 MUST 按 `real_total_mb - virtual_used_mb` 计算剩余 +- **AND** 系统 MUST 按 `virtual_used_mb / real_total_mb` 计算进度条百分比 + +#### Scenario: Package list uses real usage when virtual data is disabled + +- **GIVEN** 当前登录账号的 `user_type` 不是 `1` 或 `2` +- **AND** 套餐列表中的某条记录 `enable_virtual_data` 为 `false` +- **WHEN** 页面渲染该条记录的流量信息 +- **THEN** 系统 MUST 使用 `real_total_mb` 作为总量 +- **AND** 系统 MUST 使用 `real_used_mb` 作为已使用 +- **AND** 系统 MUST 按 `real_total_mb - real_used_mb` 计算剩余 +- **AND** 系统 MUST 按 `real_used_mb / real_total_mb` 计算进度条百分比 + +### Requirement: Platform And Super Admin Package Traffic Detail + +The asset information page SHALL preserve the existing dual-track traffic display for super admins and platform users. + +#### Scenario: Platform-side users keep real and virtual traffic breakdown + +- **GIVEN** 当前登录账号的 `user_type` 为 `1` 或 `2` +- **WHEN** 页面渲染“当前生效套餐”或“套餐列表”的流量信息 +- **THEN** 系统 MUST 继续展示真流量统计 +- **AND** 系统 MUST 继续展示虚流量统计 +- **AND** 系统 MUST NOT 将该类账号改为单一的“总量 / 已使用 / 剩余”展示口径 diff --git a/openspec/changes/update-asset-package-traffic-display/tasks.md b/openspec/changes/update-asset-package-traffic-display/tasks.md new file mode 100644 index 0000000..b58920d --- /dev/null +++ b/openspec/changes/update-asset-package-traffic-display/tasks.md @@ -0,0 +1,8 @@ +## 1. Implementation + +- [x] 1.1 调整 `CurrentPackageCard.vue` 中非平台/非超级管理员视角的流量展示与进度计算。 +- [x] 1.2 调整 `PackageListCard.vue` 中非平台/非超级管理员视角的流量展示与进度计算。 +- [x] 1.3 对齐 `useAssetInfo.ts` 中由当前生效套餐推导出的流量统计,避免同页展示口径不一致。 +- [x] 1.4 验证 `enable_virtual_data=true` 时,代理账号和企业账号的总量、已使用、剩余、进度条均符合文档。 +- [x] 1.5 验证 `enable_virtual_data=false` 时,代理账号和企业账号的总量、已使用、剩余、进度条均符合文档。 +- [x] 1.6 验证超级管理员与平台用户继续保留真流量/虚流量双口径展示。 diff --git a/openspec/changes/update-asset-wallet-empty-state-stability/proposal.md b/openspec/changes/update-asset-wallet-empty-state-stability/proposal.md new file mode 100644 index 0000000..651d2b7 --- /dev/null +++ b/openspec/changes/update-asset-wallet-empty-state-stability/proposal.md @@ -0,0 +1,36 @@ +# Change: 优化资产信息钱包流水的默认加载与展示稳定性 + +## Why + +当前资产信息页的钱包流水区域存在三个连续问题:默认进入资产详情时没有稳定触发钱包流水查询;前端按 `list/page_size` 解析响应,但后端实际返回 `items/size`,导致接口成功返回后表格仍然不显示;当结果为空时,重复查询还会出现“暂无钱包流水数据”先消失再出现的闪烁。 + +这些问题叠加后,会让用户误以为钱包流水没有被加载、接口无返回,或页面发生异常刷新。需要将默认加载、数据展示和空态刷新体验统一规范。 + +## What Changes + +- 为资产信息页的钱包流水区域新增默认加载规范: + - 资产详情加载完成后应自动请求钱包流水 + - 默认请求参数为 `page=1`、`page_size=20` +- 明确钱包流水区域需兼容后端当前返回结构: + - 使用 `items` 作为流水列表 + - 使用 `page`、`size`、`total` 作为分页信息 +- 明确有数据时必须展示钱包流水表格,不能因为前端字段映射不一致而落入空态 +- 为空结果场景新增稳定性展示规范: + - 当当前已是空态且新结果仍为空时,空态区域应保持连续可见 + - 加载反馈不应通过“先移除空态再重新渲染”的方式呈现 +- 覆盖以下触发路径: + - 资产信息页首次进入或首次加载当前资产 + - 资产信息页顶部再次搜索资产 + - 钱包流水区域内的查询、重置、分页切换、分页尺寸重置等再次拉取 + +## Impact + +- Affected specs: + - `asset-wallet-transaction-display` +- Affected code: + - `src/views/asset-management/asset-information/components/WalletTransactionCard.vue` + - `src/views/asset-management/asset-information/index.vue` + - `src/types/api/asset.ts` +- Dependencies: + - `GET /api/admin/assets/:asset_type/:id/wallet/transactions` + - 钱包流水分页响应以接口返回 `items`、`page`、`size`、`total` 为准 diff --git a/openspec/changes/update-asset-wallet-empty-state-stability/specs/asset-wallet-transaction-display/spec.md b/openspec/changes/update-asset-wallet-empty-state-stability/specs/asset-wallet-transaction-display/spec.md new file mode 100644 index 0000000..6d4a6f2 --- /dev/null +++ b/openspec/changes/update-asset-wallet-empty-state-stability/specs/asset-wallet-transaction-display/spec.md @@ -0,0 +1,57 @@ +## ADDED Requirements + +### Requirement: Wallet Transactions Shall Load And Render Automatically + +The asset information wallet transaction panel SHALL automatically request and render wallet transaction data for the current asset by using the backend response contract returned from the wallet transaction API. + +#### Scenario: Opening an asset information page triggers the default wallet transaction request + +- **GIVEN** 用户进入某个资产的信息页,且当前资产支持直接查看钱包流水 +- **WHEN** 资产详情上下文已完成加载并显示钱包流水区域 +- **THEN** 系统 MUST 自动请求当前资产的钱包流水接口 +- **AND** 请求参数 MUST 默认为 `page=1` 且 `page_size=20` +- **AND** 系统 MUST NOT 要求用户先点击“查询”后才首次拉取钱包流水 + +#### Scenario: Asset search refreshes wallet transactions with default pagination + +- **GIVEN** 用户已经位于资产信息页 +- **WHEN** 用户通过页面顶部搜索重新加载当前资产或切换到另一个资产 +- **THEN** 系统 MUST 为新解析出的当前资产重新请求钱包流水接口 +- **AND** 首次展示该资产的钱包流水时 MUST 使用 `page=1` 且 `page_size=20` + +#### Scenario: Successful wallet transaction response with items renders table rows + +- **GIVEN** 钱包流水接口成功返回 `data.items`,且其中包含一条或多条流水记录 +- **WHEN** 前端接收到该响应 +- **THEN** 系统 MUST 按 `data.items` 渲染钱包流水表格 +- **AND** 系统 MUST 使用 `data.total` 作为总记录数 +- **AND** 系统 MUST 使用 `data.page` 和 `data.size` 同步当前分页状态 +- **AND** 系统 MUST NOT 展示“暂无钱包流水数据”空态 + +### Requirement: Stable Wallet Empty State During Refresh + +The asset information wallet transaction panel SHALL preserve a stable empty-state presentation when repeated requests continue to return no wallet transaction data. + +#### Scenario: Re-searching the same asset still returns no wallet transactions + +- **GIVEN** 用户已经在资产信息页的钱包流水区域看到“暂无钱包流水数据” +- **AND** 当前钱包流水响应数据为 `items=[]`、`page=1`、`size=20` 且 `total=0` +- **WHEN** 用户再次触发资产搜索,且新的钱包流水响应仍然为 `items=[]`、`page=1`、`size=20` 且 `total=0` +- **THEN** 系统 MUST 继续在同一钱包流水区域保持空态展示 +- **AND** 系统 MUST NOT 通过先移除空态内容再重新插入的方式呈现刷新过程 +- **AND** 系统 MUST 将刷新反馈限制在不破坏当前空态布局稳定性的范围内 + +#### Scenario: Wallet filter refresh still returns an empty result + +- **GIVEN** 用户已经在资产信息页的钱包流水区域看到“暂无钱包流水数据” +- **WHEN** 用户在钱包流水区域执行查询、重置或其他会重新拉取流水的操作 +- **AND** 新的响应仍然为 `items=[]`、`page=1`、`size=20` 且 `total=0` +- **THEN** 系统 MUST 保持空态区域连续可见 +- **AND** 系统 MUST NOT 在刷新过程中出现钱包内容区域短暂空白再恢复空态的视觉跳变 + +#### Scenario: First empty response shows the wallet empty state + +- **GIVEN** 用户首次打开某个资产的信息页或首次加载钱包流水 +- **WHEN** 钱包流水响应为 `items=[]`、`page=1`、`size=20` 且 `total=0` +- **THEN** 系统 MUST 展示“暂无钱包流水数据”空态 +- **AND** 系统 MUST 不显示分页控件 diff --git a/openspec/changes/update-asset-wallet-empty-state-stability/tasks.md b/openspec/changes/update-asset-wallet-empty-state-stability/tasks.md new file mode 100644 index 0000000..24cef0e --- /dev/null +++ b/openspec/changes/update-asset-wallet-empty-state-stability/tasks.md @@ -0,0 +1,7 @@ +## 1. Implementation + +- [x] 1.1 调整资产信息页钱包流水卡片的初始化逻辑,确保资产详情首次进入和资产切换后会自动请求钱包流水,默认参数为 `page=1`、`page_size=20`。 +- [x] 1.2 对齐钱包流水接口的实际响应结构,使用 `items` 渲染表格数据,并使用 `page`、`size`、`total` 同步分页状态。 +- [x] 1.3 确保钱包流水接口返回非空 `items` 时,页面正确展示流水表格而不是错误落入空态。 +- [x] 1.4 确保重复搜索同一资产,或在钱包区域内执行查询、重置、分页切换、分页尺寸变化后,如果结果仍为空,空态不会出现“隐藏再显示”的闪烁。 +- [x] 1.5 验证空结果与非空结果两类场景下的钱包流水表格、空态和分页展示行为都符合规范。 diff --git a/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/proposal.md b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/proposal.md new file mode 100644 index 0000000..7b3537f --- /dev/null +++ b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/proposal.md @@ -0,0 +1,32 @@ +# Change: 更新套餐管理中的角色化流量展示与零售价约束 + +## Why + +当前套餐管理列表会向所有账号展示真流量、虚流量和虚流量比例,但最新业务要求代理账号和企业账号不再看到虚流量拆分口径,只保留总量视图,避免暴露不必要的内部计量细节。 + +同时,代理侧“修改零售价”弹窗缺少成本价展示和建议售价上限约束,前端当前也没有把“建议售价的 2 倍”作为输入上限,会导致代理录入超出业务允许范围的零售价。 + +## What Changes + +- 为套餐管理列表补充按账号类型展示流量字段的规则: + - 当 `user_type` 为 `3`(代理账号)或 `4`(企业账号)时,隐藏“虚流量”和“虚流量比例”列 + - 同一视角下,将列表中的“真流量”列文案改为“总流量” + - 该“总流量”继续使用接口返回的 `real_data_mb` 展示 +- 为代理侧“修改零售价”弹窗补充价格展示和校验规则: + - 在“单位:元”提示前展示当前套餐的成本价 + - 展示提示文案:`零售价不能大于建议售价 * 2 = xxx` + - 将零售价输入框最大值设置为同一上限 + - 表单校验阻止提交超过该上限的零售价 +- 不修改套餐管理相关后端接口路径、字段结构或权限模型 + +## Impact + +- Affected specs: + - `package-management` +- Affected code: + - `src/views/package-management/package-list/index.vue` +- Dependencies: + - 套餐列表接口继续返回 `real_data_mb`、`virtual_data_mb`、`suggested_retail_price`、`cost_price` + - 当前登录用户信息继续提供 `user_type` +- Notes: + - 本提案默认“可修改零售价”的套餐记录会返回 `suggested_retail_price`;如果后端允许为空,实施阶段需要补充兜底交互 diff --git a/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/specs/package-management/spec.md b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/specs/package-management/spec.md new file mode 100644 index 0000000..1fc7e93 --- /dev/null +++ b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/specs/package-management/spec.md @@ -0,0 +1,46 @@ +## ADDED Requirements + +### Requirement: 套餐列表流量字段按账号类型展示 + +系统 SHALL 根据当前登录账号类型控制套餐管理列表中的流量相关字段展示。 + +#### Scenario: 代理账号和企业账号隐藏虚流量拆分信息 + +- **GIVEN** 当前登录账号的 `user_type` 为 `3` 或 `4` +- **WHEN** 用户访问套餐管理列表 +- **THEN** 系统显示标签为 `总流量` 的列表列 +- **AND** 该列使用接口返回的 `real_data_mb` 作为展示值 +- **AND** 系统不显示 `虚流量` 列 +- **AND** 系统不显示 `虚流量比例` 列 + +#### Scenario: 其他账号继续显示虚流量拆分信息 + +- **GIVEN** 当前登录账号的 `user_type` 不为 `3` 且不为 `4` +- **WHEN** 用户访问套餐管理列表 +- **THEN** 系统继续显示标签为 `真流量` 的列表列 +- **AND** 系统继续显示 `虚流量` 列 +- **AND** 系统继续显示 `虚流量比例` 列 + +### Requirement: 修改零售价时展示成本价并限制上限 + +系统 SHALL 在“修改零售价”弹窗中展示成本价,并基于建议售价限制可输入和可提交的零售价。 + +#### Scenario: 打开弹窗时展示成本价和上限提示 + +- **GIVEN** 用户具备修改零售价权限 +- **AND** 所选套餐的 `cost_price` 为 `1000` 分 +- **AND** 所选套餐的 `suggested_retail_price` 为 `2000` 分 +- **WHEN** 用户打开“修改零售价”弹窗 +- **THEN** 系统显示该套餐的成本价为 `¥10.00` +- **AND** 系统在“单位:元”提示前展示成本价信息 +- **AND** 系统显示提示 `零售价不能大于建议售价 * 2 = 40.00` +- **AND** 零售价输入框的最大值为 `40.00` + +#### Scenario: 超过建议售价两倍时阻止提交 + +- **GIVEN** 用户具备修改零售价权限 +- **AND** 当前套餐零售价上限为 `40.00` 元 +- **WHEN** 用户输入大于 `40.00` 的零售价并提交 +- **THEN** 系统阻止提交 +- **AND** 系统显示“零售价不能大于建议售价 * 2”对应的校验提示 +- **AND** 系统不得调用修改零售价接口 diff --git a/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/tasks.md b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/tasks.md new file mode 100644 index 0000000..1745bdb --- /dev/null +++ b/openspec/changes/update-package-management-role-based-traffic-and-retail-pricing/tasks.md @@ -0,0 +1,6 @@ +## 1. Implementation + +- [x] 1.1 调整套餐管理列表列配置,对 `user_type` 为 `3` 和 `4` 的账号隐藏“虚流量”“虚流量比例”,并将“真流量”列改名为“总流量” +- [x] 1.2 扩展“修改零售价”弹窗状态,携带并展示成本价与建议售价计算出的零售价上限 +- [x] 1.3 为零售价输入框增加 `suggested_retail_price * 2` 的最大值约束,并在表单校验中阻止超过上限的提交 +- [x] 1.4 验证代理账号、企业账号与其他账号在套餐列表中的流量列展示差异,以及零售价弹窗的上限提示与提交流程 diff --git a/openspec/changes/update-series-grant-package-edit-cost-price-consistency/proposal.md b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/proposal.md new file mode 100644 index 0000000..ca56ae0 --- /dev/null +++ b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/proposal.md @@ -0,0 +1,30 @@ +# Change: 修正代理系列授权套餐编辑中的成本价回填与提交一致性 + +## Why + +当前“代理系列授权套餐列表”页面在编辑已授权套餐时,成本价输入框没有稳定使用列表行中的当前成本价作为初始值;同时,用户修改输入框后,前端提交给 `manageGrantPackages` 接口的 `cost_price` 可能退化为默认值 `0`,会直接把代理授权套餐的成本价错误覆盖。 + +这类问题会导致代理系列授权价格被误改,属于高风险的业务数据错误,需要明确前端在编辑态下的回填来源和提交流程。 + +## What Changes + +- 为代理系列授权中的“编辑授权套餐”交互补充统一规范: + - 编辑弹窗打开时,成本价必须使用当前被编辑套餐记录中的 `cost_price` 回填 + - 该回填行为不能依赖“可选套餐列表”是否已预先加载 + - 用户在输入框中修改后的值,保存时必须按“元转分”写入 `manageGrantPackages` 请求体中的 `cost_price` + - 保存时不得回退为表单默认值 `0`,除非用户实际输入的就是 `0` 且通过业务校验 +- 约束同一能力下多个编辑入口保持一致行为,包括: + - 代理系列授权套餐列表页 + - 代理系列授权页面中的套餐管理弹窗 +- 不修改后端接口路径、字段命名或请求结构 + +## Impact + +- Affected specs: + - `shop-series-grant-packages` +- Affected code: + - `src/views/package-management/series-grants/packages.vue` + - `src/views/package-management/series-grants/index.vue` +- Dependencies: + - `GET /api/admin/shop-series-grants/{id}` 继续返回授权套餐的 `cost_price` + - `PUT /api/admin/shop-series-grants/{id}/packages` 继续接收 `packages[].package_id` 和 `packages[].cost_price` diff --git a/openspec/changes/update-series-grant-package-edit-cost-price-consistency/specs/shop-series-grant-packages/spec.md b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/specs/shop-series-grant-packages/spec.md new file mode 100644 index 0000000..c432d54 --- /dev/null +++ b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/specs/shop-series-grant-packages/spec.md @@ -0,0 +1,45 @@ +## ADDED Requirements + +### Requirement: 编辑授权套餐弹窗必须回填当前成本价 + +系统 SHALL 在编辑代理系列授权中的已授权套餐时,使用当前套餐记录中的成本价作为编辑弹窗的初始值。 + +#### Scenario: 从套餐列表页编辑时回填列表中的成本价 + +- **GIVEN** 用户进入代理系列授权套餐列表页 +- **AND** 某条已授权套餐记录的 `package_id` 为 `10` +- **AND** 该记录当前 `cost_price` 为 `1234` 分 +- **WHEN** 用户点击该记录的“编辑”操作 +- **THEN** 系统打开编辑弹窗 +- **AND** 成本价输入框显示 `12.34` 元 +- **AND** 该回填值来自当前列表行数据而不是表单默认值 + +#### Scenario: 编辑弹窗回填不依赖可选套餐列表预加载 + +- **GIVEN** 用户进入代理系列授权中的套餐编辑入口 +- **AND** 当前页面尚未预先加载 `availablePackages` +- **AND** 被编辑套餐记录当前 `cost_price` 为 `2560` 分 +- **WHEN** 用户打开编辑弹窗 +- **THEN** 系统仍然显示成本价输入框初始值为 `25.60` 元 +- **AND** 系统不得因为 `availablePackages` 为空而将初始值退回为 `0` + +### Requirement: 编辑授权套餐时必须提交用户修改后的成本价 + +系统 SHALL 在保存代理系列授权中的已授权套餐时,将用户当前输入的成本价按“元转分”写入请求体。 + +#### Scenario: 保存编辑后的成本价时按元转分提交 + +- **GIVEN** 用户正在编辑 `package_id` 为 `10` 的已授权套餐 +- **AND** 编辑弹窗中的成本价初始值为 `12.34` 元 +- **WHEN** 用户将成本价修改为 `15.80` 元并点击保存 +- **THEN** 系统调用 `PUT /api/admin/shop-series-grants/{id}/packages` +- **AND** 请求体中的 `packages[0].package_id` 为 `10` +- **AND** 请求体中的 `packages[0].cost_price` 为 `1580` + +#### Scenario: 未清空输入时保存不得提交默认零值 + +- **GIVEN** 用户正在编辑一条已有成本价的授权套餐 +- **AND** 成本价输入框中存在通过表单校验的非零值 +- **WHEN** 用户点击保存 +- **THEN** 系统提交的 `packages[0].cost_price` 必须等于当前输入值换算后的分值 +- **AND** 系统不得提交表单初始化默认值 `0` diff --git a/openspec/changes/update-series-grant-package-edit-cost-price-consistency/tasks.md b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/tasks.md new file mode 100644 index 0000000..15c9c75 --- /dev/null +++ b/openspec/changes/update-series-grant-package-edit-cost-price-consistency/tasks.md @@ -0,0 +1,6 @@ +## 1. Implementation + +- [x] 1.1 调整代理系列授权套餐编辑弹窗的初始化逻辑,确保编辑态优先使用当前授权套餐行中的成本价回填 +- [x] 1.2 消除对 `availablePackages` 预加载状态的错误依赖,保证编辑弹窗在任意入口下都能拿到正确的初始成本价 +- [x] 1.3 调整保存逻辑,确保提交给 `manageGrantPackages` 的 `cost_price` 来自用户当前输入值,并按元转分传递而不是默认 `0` +- [x] 1.4 验证套餐列表页和代理系列授权管理弹窗两个入口在编辑已授权套餐时都能正确回填并提交成本价 diff --git a/src/types/api/asset.ts b/src/types/api/asset.ts index 2de65ea..1007622 100644 --- a/src/types/api/asset.ts +++ b/src/types/api/asset.ts @@ -324,9 +324,11 @@ export interface AssetWalletTransactionItem { * 对应接口:GET /api/admin/assets/:asset_type/:id/wallet/transactions */ export interface AssetWalletTransactionListResponse { - list?: AssetWalletTransactionItem[] | null // 流水列表 + items?: AssetWalletTransactionItem[] | null // 流水列表(当前接口结构) + list?: AssetWalletTransactionItem[] | null // 流水列表(兼容旧结构) page?: number // 当前页码 - page_size?: number // 每页数量 + size?: number // 每页数量(当前接口结构) + page_size?: number // 每页数量(兼容旧结构) total?: number // 总记录数 total_pages?: number // 总页数 } diff --git a/src/views/asset-management/asset-information/components/CurrentPackageCard.vue b/src/views/asset-management/asset-information/components/CurrentPackageCard.vue index 642cf2e..382dbc6 100644 --- a/src/views/asset-management/asset-information/components/CurrentPackageCard.vue +++ b/src/views/asset-management/asset-information/components/CurrentPackageCard.vue @@ -147,49 +147,32 @@