This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# Design: 新增运营报表模块并迁移时间筛选参数
|
||||
|
||||
## Context
|
||||
|
||||
- 接口文档 `docs/产品迭代8月份/前端接口简版汇总.md` 只给出指标中文名,未给出 JSON 字段名;`默认模块.openapi.json` 不包含 `operations-reports`。
|
||||
- 项目已有 ECharts 封装(`useChart` / `ArtLineChart` / `ArtBarChart`)与导出任务轮询(`useAsyncTaskPolling` + `ExportTaskService`),应复用而非新建。
|
||||
- 其余列表的时间参数迁移属于参数重命名,不改变页面交互。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
- Goals: 报表页可用、参数迁移后筛选生效、导出复用既有异步任务链路。
|
||||
- Non-Goals: 不改动后端、不新增后端字段定义;不重构既有导出任务中心。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 指标字段以「防御性可选类型 + 集中列配置」实现
|
||||
|
||||
由于接口未提供字段名,`operationsReport.ts` 的指标字段统一声明为可选,并保留 `[key: string]: unknown` 索引签名;所有列定义集中在 `src/views/operations-reports/constants.ts`。后端字段名如与推断不同,只需改一处常量即可,不改模板与请求逻辑。
|
||||
|
||||
- 比率/卡均类指标:`number | null`,`null` 渲染为 `-`,否则固定两位小数。
|
||||
- 汇总响应的 `totals` 用于「全部」分组与合计行;`has_snapshot=false` 时展示空态。
|
||||
|
||||
### 趋势图使用项目既有 ECharts 体系
|
||||
|
||||
`OperationsTrendChart.vue` 基于 `useChart` 初始化,props 接收 `categories` 与多 `series`(含 `type`/`yAxisIndex` 以支持比率走次坐标轴),`watch` 深度监听后 `setOption`,卸载时 dispose。
|
||||
|
||||
### 导出复用异步任务轮询
|
||||
|
||||
导出接口仅返回任务信息(`task_id/task_no/status/...`)。页面调用 `useAsyncTaskPolling`(`fetchTask` = `ExportTaskService.getExportTaskDetail`)轮询,终态后提供下载;403 透传为无权限提示。每个页面使用独立 `storageKey` 避免互相串扰。
|
||||
|
||||
### 路由与访问控制
|
||||
|
||||
在 `asyncRoutes` 新增顶层 `/operations-reports`(`component: RoutesAlias.Home`)与两个子路由;`meta.allowedUserTypes` 限制为超管/平台(沿用现有权限门禁机制)。菜单标题使用中文字面量,与现有静态业务页保持一致。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 指标字段名未经后端确认 → 通过集中常量降低风险,联调时单点修正。
|
||||
- 报表页可能返回大量行 → 首版不做虚拟滚动,依赖后端分页/汇总;后续按需优化。
|
||||
@@ -0,0 +1,27 @@
|
||||
# Change: 新增运营报表模块并迁移时间筛选参数
|
||||
|
||||
## Why
|
||||
|
||||
后端新增「运营报表」接口(设备激活汇总/趋势/导出、套餐续费汇总/趋势/导出),前端目前既没有对应 API 封装也没有任何页面。同时,多个列表接口的时间筛选参数统一变更为 `start_time`/`end_time`(RFC3339 带时区、闭区间),旧参数(`created_at_start/end`、`expires_from/to`、`start_date/end_date`)将返回 `1001`,前端必须同步迁移,否则相关页面筛选会失效。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增 `OperationsReportsService` API 模块及对应类型定义,封装 4 个查询接口与 2 个导出接口。
|
||||
- 新增顶层菜单「运营报表」,含「设备激活报表」「套餐续费报表」两个子页;每页提供时间/分组筛选、汇总表格、趋势图与异步导出。
|
||||
- 运营报表仅超级管理员/平台账号可访问,其他账号返回 `403`。
|
||||
- 换货单列表、资产分配记录、代理充值订单、临期资产列表时间筛选参数迁移为 `start_time`/`end_time`。
|
||||
- 新增临期资产导出接口 `POST /api/admin/expiring-assets/export`(复用列表筛选参数 + `format: 'xlsx'`,异步任务)。
|
||||
- 汇总比率、卡均保留两位小数,分母为零或无快照时显示 `-`;无快照时展示空态。
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs: `operations-reports`(新增)、`time-filter-conventions`(新增)
|
||||
- Affected code:
|
||||
- `src/api/modules/operationsReports.ts`(新增)、`src/api/modules/index.ts`
|
||||
- `src/types/api/operationsReport.ts`(新增)、`src/types/api/index.ts`
|
||||
- `src/views/operations-reports/activation/index.vue`、`src/views/operations-reports/renewal/index.vue`、`src/views/operations-reports/components/OperationsTrendChart.vue`、`src/views/operations-reports/constants.ts`(新增)
|
||||
- `src/router/routesAlias.ts`、`src/router/routes/asyncRoutes.ts`
|
||||
- `src/api/modules/exchange.ts`、`src/views/asset-management/exchange-management/index.vue`
|
||||
- `src/types/api/card.ts`、`src/views/asset-management/record-management/asset-assign/index.vue`
|
||||
- `src/types/api/agentRecharge.ts`、`src/views/finance/agent-recharge/index.vue`
|
||||
- `src/types/api/asset.ts`、`src/api/modules/asset.ts`、`src/views/asset-management/expiring-assets/index.vue`
|
||||
@@ -0,0 +1,57 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 运营报表 API 服务
|
||||
|
||||
系统 SHALL 提供 `OperationsReportsService` 封装运营报表 6 个接口:
|
||||
|
||||
- 查询设备激活汇总 `GET /api/admin/operations-reports/activation-summary`
|
||||
- 查询设备激活趋势 `GET /api/admin/operations-reports/activation-trend`
|
||||
- 导出设备激活汇总 `POST /api/admin/operations-reports/activation-summary/export`
|
||||
- 查询套餐续费汇总 `GET /api/admin/operations-reports/package-renewal-summary`
|
||||
- 查询套餐续费趋势 `GET /api/admin/operations-reports/package-renewal-trend`
|
||||
- 导出套餐续费汇总 `POST /api/admin/operations-reports/package-renewal-summary/export`
|
||||
|
||||
查询参数 SHALL 使用 `start_time`/`end_time`(RFC3339 秒级带时区)与 `group_by`;趋势查询额外支持 `granularity`(`day|month`,默认 `day`)。导出请求 SHALL 携带 `format`(`xlsx`)。
|
||||
|
||||
#### Scenario: 查询设备激活汇总
|
||||
|
||||
- **WHEN** 调用 `OperationsReportsService.getActivationSummary({ start_time, end_time, group_by })`
|
||||
- **THEN** 返回包含 `group_by`、`group_name`、`has_snapshot`、`snapshot_dates`、`items`、`totals` 的响应
|
||||
|
||||
#### Scenario: 导出设备激活汇总
|
||||
|
||||
- **WHEN** 调用 `OperationsReportsService.exportActivationSummary({ format: 'xlsx', start_time, end_time, group_by })`
|
||||
- **THEN** 返回包含 `task_id`、`task_no`、`status`、`status_name`、`message` 的异步任务信息
|
||||
|
||||
### Requirement: 运营报表页面
|
||||
|
||||
系统 SHALL 提供顶层菜单「运营报表」及两个子页「设备激活报表」「套餐续费报表」。每页 SHALL 包含时间范围与分组筛选、汇总表格、趋势图和导出按钮。
|
||||
|
||||
#### Scenario: 查询汇总并渲染表格
|
||||
|
||||
- **WHEN** 用户选择时间范围与分组后点击查询
|
||||
- **THEN** 请求对应汇总接口并以表格展示各分组指标与合计行
|
||||
|
||||
#### Scenario: 渲染趋势图
|
||||
|
||||
- **WHEN** 汇总数据加载成功
|
||||
- **THEN** 趋势图按 `granularity`(日/月)以时间点为横轴展示关键指标曲线
|
||||
|
||||
#### Scenario: 导出报表
|
||||
|
||||
- **WHEN** 用户点击导出并成功创建异步任务
|
||||
- **THEN** 前端轮询任务状态,任务完成后可下载文件
|
||||
|
||||
### Requirement: 运营报表访问控制与空态
|
||||
|
||||
运营报表 SHALL 仅对超级管理员/平台账号开放,其他账号访问 SHALL 返回 `403`。比率与卡均指标 SHALL 保留两位小数;分母为零时返回 `null`,页面显示 `-`。无快照时 `has_snapshot=false`、`totals=null`、`items=[]`,页面 SHALL 展示空态而非报错。
|
||||
|
||||
#### Scenario: 无快照
|
||||
|
||||
- **WHEN** 汇总响应 `has_snapshot` 为 `false`
|
||||
- **THEN** 页面展示空态
|
||||
|
||||
#### Scenario: 比率分母为零
|
||||
|
||||
- **WHEN** `activation_rate` 或 `renewal_rate` 为 `null`
|
||||
- **THEN** 表格对应单元格显示 `-`
|
||||
@@ -0,0 +1,34 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 列表时间筛选参数统一
|
||||
|
||||
以下列表接口的时间筛选参数 SHALL 统一为 `start_time`/`end_time`(RFC3339 秒级、闭区间),前端不得再发送旧参数:
|
||||
|
||||
- 换货单列表 `GET /api/admin/exchanges`(由 `created_at_start`/`created_at_end` 迁移)
|
||||
- 资产分配记录 `GET /api/admin/asset-allocation-records`(由 `created_at_start`/`created_at_end` 迁移)
|
||||
- 代理充值订单 `GET /api/admin/agent-recharges`(由 `start_date`/`end_date` 迁移,取消按日自动补齐首尾秒)
|
||||
- 临期资产列表 `GET /api/admin/expiring-assets`(由 `expires_from`/`expires_to` 迁移)
|
||||
|
||||
#### Scenario: 换货单列表时间筛选
|
||||
|
||||
- **WHEN** 用户选择创建时间范围并搜索
|
||||
- **THEN** 请求参数为 `start_time`/`end_time`,且不包含 `created_at_start`/`created_at_end`
|
||||
|
||||
#### Scenario: 代理充值订单时间筛选
|
||||
|
||||
- **WHEN** 用户选择时间范围并搜索或导出
|
||||
- **THEN** 请求参数为 `start_time`/`end_time`,且不包含 `start_date`/`end_date`
|
||||
|
||||
#### Scenario: 临期资产列表时间筛选
|
||||
|
||||
- **WHEN** 用户选择预计到期时间范围并搜索
|
||||
- **THEN** 请求参数为 `start_time`/`end_time`,且不包含 `expires_from`/`expires_to`
|
||||
|
||||
### Requirement: 临期资产导出
|
||||
|
||||
系统 SHALL 提供 `POST /api/admin/expiring-assets/export`,复用临期资产列表筛选参数并携带 `format: 'xlsx'`,返回异步导出任务信息;前端 SHALL 通过现有导出任务接口轮询并在完成后下载。
|
||||
|
||||
#### Scenario: 导出临期资产
|
||||
|
||||
- **WHEN** 用户在临期资产页面点击导出
|
||||
- **THEN** 创建异步导出任务并轮询状态,完成后可下载 xlsx 文件
|
||||
@@ -0,0 +1,35 @@
|
||||
## 1. 运营报表 API 与类型
|
||||
|
||||
- [x] 1.1 新增 `src/types/api/operationsReport.ts`(查询、汇总、趋势、导出任务类型)
|
||||
- [x] 1.2 在 `src/types/api/index.ts` 导出新类型
|
||||
- [x] 1.3 新增 `src/api/modules/operationsReports.ts`(6 个接口方法)
|
||||
- [x] 1.4 在 `src/api/modules/index.ts` 注册 `OperationsReportsService`
|
||||
|
||||
## 2. 运营报表页面
|
||||
|
||||
- [x] 2.1 新增 `src/views/operations-reports/constants.ts`(分组选项与指标列配置)
|
||||
- [x] 2.2 新增 `src/views/operations-reports/components/OperationsTrendChart.vue`(多系列趋势图)
|
||||
- [x] 2.3 新增「设备激活报表」页面(筛选 + 汇总表格 + 趋势图 + 导出)
|
||||
- [x] 2.4 新增「套餐续费报表」页面(筛选 + 汇总表格 + 趋势图 + 导出)
|
||||
|
||||
## 3. 路由与菜单
|
||||
|
||||
- [x] 3.1 `routesAlias.ts` 新增两个页面别名
|
||||
- [x] 3.2 `asyncRoutes.ts` 新增顶层「运营报表」菜单(含权限限制)
|
||||
|
||||
## 4. 时间筛选参数迁移
|
||||
|
||||
- [x] 4.1 换货单列表 `created_at_start/end` -> `start_time/end_time`(类型 + 页面)
|
||||
- [x] 4.2 资产分配记录 `created_at_start/end` -> `start_time/end_time`(类型 + 页面)
|
||||
- [x] 4.3 代理充值订单 `start_date/end_date` -> `start_time/end_time`(类型 + 页面,含导出参数)
|
||||
- [x] 4.4 临期资产列表 `expires_from/to` -> `start_time/end_time`(类型 + 页面)
|
||||
|
||||
## 5. 临期资产导出
|
||||
|
||||
- [x] 5.1 `AssetService.exportExpiringAssets`(POST /api/admin/expiring-assets/export)
|
||||
- [x] 5.2 临期资产页面新增「导出」按钮(筛选参数 + `format: 'xlsx'` + 异步任务轮询下载)
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- [x] 6.1 运行 `eslint`、`stylelint`、`vue-tsc --noEmit`、`vite build --mode production` 均通过
|
||||
- [x] 6.2 运行 `openspec validate add-operations-reports-and-time-filters --strict` 通过
|
||||
@@ -0,0 +1,23 @@
|
||||
# Change: 调整运营报表展示并补齐导出场景
|
||||
|
||||
## Why
|
||||
|
||||
运营报表首版将「汇总数据」标题与趋势图放在报表页内,信息层级冗余且与仪表台分析页重复;同时导出管理缺少临期资产、设备激活情况报表、套餐续费情况报表三个导出场景,且佣金/套餐真流量场景命名与实际业务口径不一致。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 运营报表两个页面移除「汇总数据」标题,仅保留数据快照、导出状态与导出/下载操作。
|
||||
- 运营报表两个页面移除趋势图卡片与「统计粒度」筛选,不再请求趋势接口。
|
||||
- 在仪表台分析页(`/dashboard/analysis`)新增「设备激活趋势」「套餐续费趋势」组件,占位与门禁与运营报表一致(超级管理员/平台账号);统计粒度改为下拉选择(按日/按月),并支持时间范围与刷新。
|
||||
- 导出管理新增 3 个导出场景:`expiring_asset`(临期资产)、`operations_activation`(设备激活情况报表)、`operations_renewal`(套餐续费情况报表)。
|
||||
- 修正场景显示名称:`commission_record` → 佣金明细、`package_traffic_alert` → 套餐真流量达量预警。
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs: `operations-reports`(修改)、`export-task-management`(新增/修改)
|
||||
- Affected code:
|
||||
- `src/views/operations-reports/activation/index.vue`、`src/views/operations-reports/renewal/index.vue`
|
||||
- `src/views/dashboard/analysis/index.vue`、`src/views/dashboard/analysis/widget/OperationsActivationTrend.vue`、`src/views/dashboard/analysis/widget/OperationsRenewalTrend.vue`(新增)
|
||||
- `src/types/api/exportTask.ts`、`src/config/constants/exportTask.ts`
|
||||
- `src/router/routesAlias.ts`、`src/router/routes/asyncRoutes.ts`
|
||||
- `src/locales/langs/zh.json`、`src/locales/langs/en.json`
|
||||
@@ -0,0 +1,37 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Additional Export Task Scenes
|
||||
|
||||
The admin frontend SHALL support three additional export task scenes: `expiring_asset`(临期资产)、`operations_activation`(设备激活情况报表)、`operations_renewal`(套餐续费情况报表)。每个场景 SHALL 有独立的导出任务列表子页,页面固定查询该场景任务(`GET /api/admin/export-tasks` with `scene=<scene>`),并提供 `export_task:<scene>:detail` / `export_task:<scene>:download` 权限配置。
|
||||
|
||||
#### Scenario: Open expiring asset export task page
|
||||
|
||||
- **GIVEN** 用户打开「导出临期资产」页面
|
||||
- **WHEN** 页面查询导出任务列表
|
||||
- **THEN** 系统 MUST call `GET /api/admin/export-tasks` with `scene=expiring_asset`
|
||||
|
||||
#### Scenario: Open operations report export task pages
|
||||
|
||||
- **GIVEN** 用户打开「导出设备激活情况报表」或「导出套餐续费情况报表」页面
|
||||
- **WHEN** 页面查询导出任务列表
|
||||
- **THEN** 系统 MUST call `GET /api/admin/export-tasks` with `scene=operations_activation` 或 `scene=operations_renewal`
|
||||
|
||||
#### Scenario: Gate new scene actions
|
||||
|
||||
- **WHEN** 任一新增场景页面渲染详情与下载操作
|
||||
- **THEN** 系统 MUST 使用对应场景的 `export_task:<scene>:detail` 与 `export_task:<scene>:download` 权限码
|
||||
|
||||
### Requirement: Export Scene Display Names
|
||||
|
||||
导出任务创建弹窗与导出任务列表 SHALL 按最新业务口径展示场景名称:`commission_record` 显示为「佣金明细」(原「佣金记录」),`package_traffic_alert` 显示为「套餐真流量达量预警」(原「套餐真流量预警」);新增场景依次显示为「临期资产」「设备激活情况报表」「套餐续费情况报表」。
|
||||
|
||||
#### Scenario: Show renamed scene names
|
||||
|
||||
- **WHEN** 导出弹窗以 `scene=commission_record` 打开
|
||||
- **THEN** 弹窗 MUST 显示「佣金明细」
|
||||
- **AND** 以 `scene=package_traffic_alert` 打开时 MUST 显示「套餐真流量达量预警」
|
||||
|
||||
#### Scenario: Show new scene names
|
||||
|
||||
- **WHEN** 导出弹窗以 `scene=operations_activation` 打开
|
||||
- **THEN** 弹窗 MUST 显示「设备激活情况报表」
|
||||
@@ -0,0 +1,31 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 运营报表趋势分析
|
||||
|
||||
系统 SHALL 在仪表台分析页(`/dashboard/analysis`)以「设备激活趋势」「套餐续费趋势」两个组件展示运营报表趋势数据。每个组件 SHALL 提供时间范围选择、统计粒度下拉(按日/按月)与刷新操作,并复用 `OperationsTrendChart` 以时间点为横轴渲染关键指标曲线。两个组件 SHALL 仅对超级管理员/平台账号可见。
|
||||
|
||||
#### Scenario: 展示激活趋势
|
||||
|
||||
- **WHEN** 用户在仪表台分析页展开「设备激活趋势」组件并选择时间范围
|
||||
- **THEN** 请求 `GET /api/admin/operations-reports/activation-trend` 并按所选 `granularity`(日/月)渲染多系列曲线
|
||||
|
||||
#### Scenario: 切换统计粒度
|
||||
|
||||
- **WHEN** 用户将统计粒度从「按日」切换为「按月」
|
||||
- **THEN** 组件以 `granularity=month` 重新请求趋势接口并刷新图表
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 运营报表页面
|
||||
|
||||
系统 SHALL 提供顶层菜单「运营报表」及两个子页「设备激活报表」「套餐续费报表」。每页 SHALL 包含时间范围与分组筛选、数据快照信息、汇总表格与导出按钮;页面 SHALL NOT 展示「汇总数据」标题,也 SHALL NOT 在页面内渲染趋势图或提供统计粒度筛选。
|
||||
|
||||
#### Scenario: 查询汇总并渲染表格
|
||||
|
||||
- **WHEN** 用户选择时间范围与分组后点击查询
|
||||
- **THEN** 请求对应汇总接口并以表格展示各分组指标与合计行
|
||||
|
||||
#### Scenario: 导出报表
|
||||
|
||||
- **WHEN** 用户点击导出并成功创建异步任务
|
||||
- **THEN** 前端轮询任务状态,任务完成后可下载文件
|
||||
@@ -0,0 +1,24 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. 运营报表页面调整
|
||||
|
||||
- [x] 1.1 移除 `activation/index.vue`、`renewal/index.vue` 表头「汇总数据」标题(保留数据快照与导出操作)
|
||||
- [x] 1.2 移除报表页趋势图卡片、趋势相关导入/状态/请求及 `granularity` 搜索项
|
||||
- [x] 1.3 清理报表页趋势相关样式(`.report-toolbar`、`.report-title` 及 `.report-snapshot` 的 margin)
|
||||
|
||||
## 2. 趋势分析迁入仪表台分析页
|
||||
|
||||
- [x] 2.1 新增 `widget/OperationsActivationTrend.vue`、`widget/OperationsRenewalTrend.vue`(时间范围 + 统计粒度下拉 + 刷新,复用 `OperationsTrendChart`)
|
||||
- [x] 2.2 在 `views/dashboard/analysis/index.vue` 注册两个趋势组件,门禁使用 `isPlatformAccount`
|
||||
|
||||
## 3. 导出场景补齐
|
||||
|
||||
- [x] 3.1 `ExportTaskScene` 新增 `expiring_asset` / `operations_activation` / `operations_renewal`
|
||||
- [x] 3.2 `EXPORT_TASK_SCENE_CONFIG` 新增三个场景配置,并修正 `commission_record`→佣金明细、`package_traffic_alert`→套餐真流量达量预警
|
||||
- [x] 3.3 `routesAlias.ts` 与 `asyncRoutes.ts` 新增三个导出任务列表子路由
|
||||
- [x] 3.4 `zh.json` / `en.json` 新增导出场景菜单标题并同步更新命名
|
||||
|
||||
## 4. 验证
|
||||
|
||||
- [x] 4.1 `npx eslint --fix`、`npx stylelint ... --fix`、`npx vue-tsc --noEmit`、`npx vite build --mode production`
|
||||
- [x] 4.2 `npx openspec validate update-operations-reports-trend-and-export-scenes --strict`
|
||||
@@ -0,0 +1,41 @@
|
||||
## Context
|
||||
|
||||
- 核销申请弹窗 `ApplicationFormDialog.vue` 同时服务于两处入口:账单列表页传 `presetBill`(含 `debtor_snapshot`),申请列表页传 `application`(`EmployeeCollectionApplication` 不含 `debtor_snapshot`)。
|
||||
- 收款方式接口 `GET /api/admin/employee-collection-payment-methods` 支持 `keyword/page/page_size/enabled`;账单接口支持 `source_type/source_no/status/customer_id/created_from/created_to` 与 `page/page_size`。
|
||||
- 「我的佣金」三页签为同一文件 `my-commission/index.vue`,接口均以 `shop_id` 作路径参数;超管账号无 `shop_id`,现有逻辑直接提示「未关联店铺」并 return。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
- Goals:弹窗数据可筛选、可分页、交互体验一致;代办原因语义准确;超管可查看任意店铺的佣金数据。
|
||||
- Non-Goals:不改动后端接口契约(仅使用现有查询参数);不重构账单列表页与申请列表页。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 抽屉替代对话框
|
||||
使用 `ElDrawer`(`direction="rtl"`,宽度适配表单内容),保留原有表单校验、`destroy-on-close` 语义与底部操作按钮;关闭时沿用既有重置逻辑。
|
||||
|
||||
### 收款方式远程搜索
|
||||
改为 `ElSelect` + `filterable` + `remote`,请求 `getPaymentMethods({ page: 1, page_size: 20, keyword, enabled: true })`;输入经防抖后请求,并以请求序号丢弃过期响应,避免竞态。编辑场景需缓存已选项,保证不在首屏结果内时仍能回显名称。
|
||||
|
||||
### 核销账单候选筛选与分页
|
||||
沿用 `EmployeeCollectionBillQueryParams`,默认 `page_size=20`;新增与账单列表页一致的筛选表单,「店铺」映射 `customer_id` 并用 `ShopService.getShops` 远程搜索。已选账单与核销金额使用独立于当前页的集合维护,翻页/筛选不清空,核销合计覆盖所有已选账单。
|
||||
|
||||
### 代办原因判定
|
||||
`isActing` 改为「当前账号 `user_type === 1` 且存在非本人负责的所选账单」。责任员工取所选账单 `debtor_snapshot.account_id`,缺失时回退 `debtor_account_id`;未选择账单或无法取得责任员工信息时,超管视为代办并要求填写。
|
||||
|
||||
### 我的佣金全局店铺选择
|
||||
页面顶部新增 `ElSelect`,仅 `userStore.info.user_type === 1` 时展示,选项经 `ShopService.getShops` 远程搜索。`currentShopId = isSuperAdmin ? selectedShopId : userStore.info?.shop_id`;切换店铺时重置分页并刷新概览与当前页签。超管未选择时展示选择提示,而非阻断。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 账单候选分页后,用户可能因筛选条件过窄而看不到目标账单;通过保留筛选条件与已选集合降低影响。
|
||||
- 代办判定依赖 `debtor_snapshot` / `debtor_account_id` 数据完整性;数据缺失时按「代办必填」处理,偏保守但符合合规要求。
|
||||
|
||||
## Migration
|
||||
|
||||
- 无数据迁移。行为变化:超管本人办理核销申请不再要求填写代办原因。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 账单接口是否支持按 `shop_id` 过滤;现有类型仅有 `customer_id`,若后续新增需同步 `EmployeeCollectionBillQueryParams`。
|
||||
- 超管在「提现资料」页签提交/替换资格时,是否应使用所选店铺 `shop_id`(预期为是)。
|
||||
@@ -0,0 +1,23 @@
|
||||
# Change: 核销申请弹窗体验优化与超管按店铺查看我的佣金
|
||||
|
||||
## Why
|
||||
|
||||
创建/修改核销申请弹窗的收款方式与核销账单候选各一次性拉取 100 条且无筛选,数据量大时难以定位;弹窗为居中对话框,账单筛选与表单内容在长列表中体验不佳;代办原因仅以「是否超管」判定,超管为本人办理时仍被强制填写,与「本人办理无需代办原因」的业务语义不符。
|
||||
|
||||
同时「我的佣金」页面所有接口均以当前账号 `shop_id` 作为路径参数,超级管理员账号没有 `shop_id`,进入页面即被提示「未关联店铺」且无法查看任何数据。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 核销申请弹窗由居中 `ElDialog` 调整为右侧滑出抽屉。
|
||||
- 收款方式改为远程搜索下拉:按 `keyword` 搜索,默认拉取 20 条(不再固定 100 条),仅展示启用项。
|
||||
- 核销账单候选列表:默认按 20 条分页加载(不再固定 100 条),新增按来源、来源单号、核销状态、店铺、起止时间的筛选表单,筛选变化后回到第 1 页,翻页保持已选账单。
|
||||
- 代办原因(`acting_reason`)判定改为「超级管理员且所选账单责任员工非本人」:当所选账单的 `debtor_snapshot.account_id` 不等于当前登录账号 `id`(或未选择账单 / 无责任员工信息)时展示且必填;所选账单全部归属于当前登录账号时不展示、不提交该字段。**BREAKING**:超管本人办理不再强制填写代办原因。
|
||||
- 「我的佣金」页面顶部为超级管理员新增全局店铺下拉(远程搜索店铺),选中店铺后三个页签(佣金明细 / 提现记录 / 提现资料)均以所选 `shop_id` 调用接口;非超级管理员不展示该下拉,继续使用自身 `shop_id`。
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs: `employee-collection`、`commission-management`
|
||||
- Affected code:
|
||||
- `src/views/finance/employee-collection/applications/components/ApplicationFormDialog.vue`
|
||||
- `src/views/commission-management/my-commission/index.vue`
|
||||
- `src/types/api/employeeCollection.ts`(如需补充账单候选查询字段类型)
|
||||
@@ -0,0 +1,28 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 超级管理员按店铺查看我的佣金
|
||||
「我的佣金」页面 MUST 为超级管理员(`user_type` 为 `1`,其账号无 `shop_id`)在页面顶部提供全局店铺选择下拉,选项 MUST 通过店铺列表接口远程搜索获取。选中店铺后,佣金概览与三个页签(佣金明细、提现记录、提现资料)的接口 MUST 使用所选 `shop_id`;切换店铺 MUST 刷新概览与当前页签数据。非超级管理员 MUST NOT 展示该下拉,且 MUST 继续使用当前账号自身的 `shop_id`。超级管理员未选择店铺时,页面 MUST 展示选择店铺的提示,MUST NOT 以「未关联店铺」为由阻止其使用。
|
||||
|
||||
#### Scenario: 超管选择店铺后查看数据
|
||||
- **GIVEN** 超级管理员进入「我的佣金」页面
|
||||
- **WHEN** 其通过顶部下拉远程搜索并选择一个店铺
|
||||
- **THEN** 佣金概览与当前页签 MUST 以所选 `shop_id` 调用接口
|
||||
- **AND** 切换到其他页签 MUST 继续使用同一 `shop_id`
|
||||
|
||||
#### Scenario: 超管未选择店铺
|
||||
- **GIVEN** 超级管理员进入「我的佣金」页面且尚未选择店铺
|
||||
- **WHEN** 页面初始化
|
||||
- **THEN** 页面 MUST 提示先选择店铺
|
||||
- **AND** MUST NOT 展示「未关联店铺」的阻断提示
|
||||
|
||||
#### Scenario: 非超管不展示店铺下拉
|
||||
- **GIVEN** 当前登录账号不是超级管理员
|
||||
- **WHEN** 其进入「我的佣金」页面
|
||||
- **THEN** 页面 MUST NOT 展示店铺下拉
|
||||
- **AND** MUST 使用自身 `shop_id` 加载数据
|
||||
|
||||
#### Scenario: 切换店铺刷新数据
|
||||
- **GIVEN** 超级管理员已选择店铺并加载数据
|
||||
- **WHEN** 其切换为另一个店铺
|
||||
- **THEN** 前端 MUST 重新加载佣金概览与当前页签列表
|
||||
- **AND** 分页 MUST 重置到第 1 页
|
||||
@@ -0,0 +1,64 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 核销申请弹窗抽屉与收款方式远程搜索
|
||||
创建/修改核销申请弹窗 MUST 以从右侧滑出的抽屉形式呈现,并 MUST 保留表单校验、关闭时重置与底部提交/取消操作。收款方式 MUST 改为远程搜索下拉:请求 MUST 携带 `keyword`、`page_size` 为 `20`、`enabled` 为 `true`,仅展示启用项;输入关键字 MUST 经防抖后发起请求,并发时 MUST 丢弃过期响应。编辑已提交申请时,MUST 能回显并保留当前已选收款方式,即使其不在当前搜索结果内。
|
||||
|
||||
#### Scenario: 打开弹窗
|
||||
- **GIVEN** 用户点击创建或修改核销申请
|
||||
- **WHEN** 弹窗打开
|
||||
- **THEN** 弹窗 MUST 从右侧滑出
|
||||
- **AND** MUST 保留表单字段、校验与底部操作
|
||||
|
||||
#### Scenario: 收款方式远程搜索
|
||||
- **GIVEN** 用户打开收款方式下拉
|
||||
- **WHEN** 输入关键字
|
||||
- **THEN** 前端 MUST 以防抖方式调用收款方式接口,携带 `keyword`、`page_size=20`、`enabled=true`
|
||||
- **AND** 仅展示接口返回的启用项
|
||||
- **AND** 过期请求的响应 MUST NOT 覆盖最新结果
|
||||
|
||||
#### Scenario: 编辑场景回显已选收款方式
|
||||
- **GIVEN** 正在修改的申请已选择某收款方式且其不在首屏搜索结果中
|
||||
- **WHEN** 弹窗初始化
|
||||
- **THEN** 下拉 MUST 回显该收款方式名称
|
||||
- **AND** MUST NOT 因搜索而清空已选值
|
||||
|
||||
### Requirement: 核销账单候选筛选与分页
|
||||
核销申请弹窗的核销账单候选列表 MUST 默认以 `page_size` 为 `20` 加载,MUST NOT 固定请求 100 条。候选列表 MUST 支持按来源(`source_type`)、来源单号(`source_no`)、核销状态(`status`)、店铺(`customer_id`)与创建时间(`created_from` / `created_to`)筛选,店铺筛选 MUST 使用远程搜索。筛选条件变化 MUST 回到第 1 页重新加载。翻页 MUST NOT 清空已选账单与已填核销金额;当前页之外已选账单 MUST 仍计入核销合计并随申请提交。
|
||||
|
||||
#### Scenario: 默认分页加载
|
||||
- **GIVEN** 用户打开核销申请弹窗
|
||||
- **WHEN** 账单候选列表加载
|
||||
- **THEN** 请求 MUST 使用 `page_size=20`
|
||||
- **AND** MUST 提供分页或加载更多入口以访问后续数据
|
||||
|
||||
#### Scenario: 按条件筛选账单
|
||||
- **GIVEN** 用户已打开核销申请弹窗
|
||||
- **WHEN** 其填写来源、来源单号、核销状态、店铺或起止时间中的任意条件
|
||||
- **THEN** 前端 MUST 以对应查询参数从第 1 页重新加载候选账单
|
||||
- **AND** 店铺 MUST 通过远程搜索选择
|
||||
|
||||
#### Scenario: 翻页保持已选
|
||||
- **GIVEN** 用户已在当前页勾选账单并填写核销金额
|
||||
- **WHEN** 其翻页后返回或直接提交
|
||||
- **THEN** 已勾选账单与核销金额 MUST 保持不变
|
||||
- **AND** 核销合计 MUST 包含所有页已选账单
|
||||
|
||||
### Requirement: 代办原因按所选账单责任员工判定
|
||||
核销申请的 `acting_reason` MUST 仅在「当前登录账号为超级管理员(`user_type` 为 `1`)且存在非本人负责的所选账单」时展示并必填。责任员工 MUST 取自账单 `debtor_snapshot.account_id`,缺失时回退 `debtor_account_id`。当所选账单全部归属于当前登录账号时,前端 MUST NOT 展示且 MUST NOT 提交 `acting_reason`;当尚未选择任何账单或无法取得责任员工信息时,超级管理员 MUST 视为代办并要求填写。
|
||||
|
||||
#### Scenario: 超管为他人代办需填原因
|
||||
- **GIVEN** 当前登录账号为超级管理员
|
||||
- **WHEN** 其选择责任员工 `account_id` 不等于当前账号 `id` 的账单
|
||||
- **THEN** 代办原因字段 MUST 展示且必填
|
||||
- **AND** 未填写即提交 MUST 被阻止
|
||||
|
||||
#### Scenario: 超管本人办理无需原因
|
||||
- **GIVEN** 当前登录账号为超级管理员且所选账单全部由其本人负责
|
||||
- **WHEN** 其提交核销申请
|
||||
- **THEN** 代办原因字段 MUST NOT 展示
|
||||
- **AND** 提交载荷 MUST NOT 包含 `acting_reason`
|
||||
|
||||
#### Scenario: 非超管不判定代办
|
||||
- **GIVEN** 当前登录账号不是超级管理员
|
||||
- **WHEN** 其创建或重新提交核销申请
|
||||
- **THEN** 代办原因字段 MUST NOT 展示
|
||||
@@ -0,0 +1,23 @@
|
||||
## 1. 核销申请弹窗
|
||||
|
||||
- [x] 1.1 弹窗由 `ElDialog` 改为右侧 `ElDrawer`,保留表单校验、关闭重置与底部提交/取消操作
|
||||
- [x] 1.2 收款方式改为远程搜索下拉:携带 `keyword`、`page_size=20`、`enabled=true`,防抖并发且丢弃过期响应
|
||||
- [x] 1.3 核销账单候选默认按 20 条分页加载,新增来源 / 来源单号 / 核销状态 / 店铺 / 起止时间筛选表单
|
||||
- [x] 1.4 店铺筛选使用远程搜索(复用账单列表页 `customer_id` + `ShopService.getShops` 范式)
|
||||
- [x] 1.5 筛选条件变化回到第 1 页;翻页保持已选账单与已填核销金额
|
||||
- [x] 1.6 代办原因按所选账单责任员工判定(超管且非本人时展示并必填,本人办理不展示不提交)
|
||||
|
||||
## 2. 我的佣金
|
||||
|
||||
- [x] 2.1 页面顶部新增超管可见的全局店铺下拉(远程搜索,复用 `ShopService.getShops`)
|
||||
- [x] 2.2 `currentShopId` 改为超管取所选店铺、非超管取自身 `shop_id`
|
||||
- [x] 2.3 超管未选择店铺时展示选择提示,不再以「未关联店铺」阻断
|
||||
- [x] 2.4 三个页签(佣金明细 / 提现记录 / 提现资料)与概览均使用所选 `shop_id`
|
||||
- [x] 2.5 切换店铺时重置分页并刷新概览与当前页签数据
|
||||
|
||||
## 3. 验证
|
||||
|
||||
- [x] 3.1 改动文件 `npx eslint` 通过(必要时 `--fix`)
|
||||
- [x] 3.2 `npx vue-tsc --noEmit` 通过
|
||||
- [x] 3.3 `npx vite build --mode production` 通过
|
||||
- [x] 3.4 `npx openspec validate update-writeoff-application-and-superadmin-commission --strict` 通过
|
||||
Reference in New Issue
Block a user