From c136f68ab8531aef69b157067a1b42fc0b45ecb1 Mon Sep 17 00:00:00 2001 From: luo Date: Mon, 21 Sep 2026 18:07:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=A3=E7=90=86=E5=95=86=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + docs/权限.md | 235 ++++++++++++++++ .../design.md | 16 ++ .../proposal.md | 31 +++ .../agent-distribution-registration/spec.md | 33 +++ .../tasks.md | 17 ++ .../add-package-traffic-alert/proposal.md | 14 +- .../specs/package-traffic-alert/spec.md | 14 + .../add-package-traffic-alert/tasks.md | 4 +- .../add-refund-approval-recovery/tasks.md | 27 +- src/api/modules/agentDistribution.ts | 36 ++- src/config/constants/augustIteration.ts | 40 +++ src/config/constants/businessUserGroup.ts | 31 ++- src/config/constants/exportTask.ts | 16 ++ src/config/constants/julyIteration.ts | 6 +- src/config/constants/paymentMerchantPools.ts | 1 + src/locales/langs/en.json | 37 +-- src/locales/langs/zh.json | 49 +--- src/router/routes/asyncRoutes.ts | 89 ++++-- src/router/routesAlias.ts | 2 + .../api/agentDistributionRegistration.ts | 56 ++++ src/types/api/index.ts | 1 + .../expiring-assets/index.vue | 8 +- .../agent-fund-overview/index.vue | 5 +- src/views/finance/refund/detail.vue | 9 +- src/views/finance/refund/index.vue | 3 +- .../operations-reports/activation/index.vue | 8 +- .../operations-reports/renewal/index.vue | 8 +- .../traffic-alert-rules/index.vue | 12 +- .../priority-queue/index.vue | 13 +- .../asset-wallet-auto-renewal/index.vue | 10 +- .../detail.vue | 154 +++++++++++ .../index.vue | 254 ++++++++++++++++++ .../business-owner-import/index.vue | 12 + 34 files changed, 1112 insertions(+), 142 deletions(-) create mode 100644 docs/权限.md create mode 100644 openspec/changes/add-agent-registration-approval-management/design.md create mode 100644 openspec/changes/add-agent-registration-approval-management/proposal.md create mode 100644 openspec/changes/add-agent-registration-approval-management/specs/agent-distribution-registration/spec.md create mode 100644 openspec/changes/add-agent-registration-approval-management/tasks.md create mode 100644 src/types/api/agentDistributionRegistration.ts create mode 100644 src/views/shop-management/agent-distribution-registrations/detail.vue create mode 100644 src/views/shop-management/agent-distribution-registrations/index.vue diff --git a/.gitignore b/.gitignore index d5d5b7d..948a4c2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ node_modules .DS_Store dist docs +!docs/ +docs/* +!docs/权限.md dist-ssr *.local .cursorrules diff --git a/docs/权限.md b/docs/权限.md new file mode 100644 index 0000000..126f7fb --- /dev/null +++ b/docs/权限.md @@ -0,0 +1,235 @@ +# 权限清单 + +## 套餐管理:真流量预警规则 + +页面 URL:`/package-management/traffic-alert-rules` + +| 类型 | 权限名称 | 权限编码 | +| -------- | ------------- | ------------------------------------ | +| 页面查看 | `rulesView` | `package_traffic_alert:rules_view` | +| 新增规则 | `ruleCreate` | `package_traffic_alert:rule_create` | +| 编辑规则 | `ruleUpdate` | `package_traffic_alert:rule_update` | +| 启用规则 | `ruleEnable` | `package_traffic_alert:rule_enable` | +| 停用规则 | `ruleDisable` | `package_traffic_alert:rule_disable` | + +启用和停用不得复用编辑权限。 + +## 套餐管理:真流量达量预警 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 预警列表 | `/package-management/traffic-alerts` | `recordsView` | `package_traffic_alert:records_view` | +| 预警详情 | `/package-management/traffic-alerts/detail/:id` | `recordDetail` | `package_traffic_alert:record_detail` | +| 导出预警记录 | — | `export` | `package_traffic_alert:export` | +| 导出任务页面 | `/asset-management/export-task-management/export-package-traffic-alert` | `page` | `export_task:package_traffic_alert_page` | + +## 店铺管理:店铺列表 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 店铺列表 | `/shop-management/list` | `listView` | `shop:list_view` | +| 店铺详情 | `/shop-management/detail/:id` | `detailView` | `shop:detail_view` | +| 新增店铺 | — | — | `shop:add` | +| 批量交接 | — | `batch` | `shop:business_owner_batch` | +| 导入业务员 | — | `importPage` | `shop:business_owner_import_view` | +| 查看店铺详情 | — | — | `shop:detail` | +| 切换店铺状态 | — | — | `shop:modify_status` | +| 账号列表 | — | — | `shop:look_customer` | +| 默认角色 | — | — | `shop:default_role` | +| 调整实际信用额度 | — | — | `shop:credit_limit_manage` | +| 编辑店铺 | — | — | `shop:edit` | +| 删除店铺 | — | — | `shop:delete` | +| 审计记录 | — | — | `audit:shop_entry` / `audit:agent_resource_activity` | +| 资金链路 | — | — | `audit:finance_timeline` | + +## 店铺管理:业务用户组 + +页面 URL:`/shop-management/business-user-groups` + +| 类型 | 权限名称 | 权限编码 | +| -------- | --------- | ----------------------------- | +| 页面查看 | `page` | `business_user_group:page` | +| 新增 | `create` | `business_user_group:create` | +| 编辑 | `update` | `business_user_group:update` | +| 删除 | `delete` | `business_user_group:delete` | +| 成员管理 | `members` | `business_user_group:members` | + +## 店铺管理:业务负责人导入 + +页面 URL:`/shop-management/business-owner-import` + +| 类型 | 权限名称 | 权限编码 | +| ---------------------------- | -------------- | ----------------------------------- | +| 页面查看 | `importPage` | `shop:business_owner_import_view` | +| 创建导入任务 | `importCreate` | `shop:business_owner_import_create` | +| 详情按钮 | `importDetail` | `shop:business_owner_import_detail` | +| 详情页面(当前为列表页抽屉) | `importDetail` | `shop:business_owner_import_detail` | + +## 店铺管理:代理注册申请 + +列表不显示操作列,点击“申请店铺”名称进入详情页。 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 申请列表 | `/shop-management/agent-distribution-registrations` | `list` | `agent_distribution_registration:list` | +| 申请详情 | `/shop-management/agent-distribution-registrations/detail/:id` | `detail` | `agent_distribution_registration:detail` | +| 恢复审批 | — | `recoverApproval` | `agent_distribution_registration:recover_approval` | + +## 资产管理:手机号资产关联 + +页面 URL:`/asset-management/phone-asset-association` + +| 类型 | 权限名称 | 权限编码 | +| ---------------- | -------------------- | ---------------------------------------------- | +| 页面查看 | `list` | `phone_asset_association:list` | +| 单条解绑 | `unbind` | `phone_asset_association:unbind` | +| 批量解绑 | `unbindBatch` | `phone_asset_association:unbind_batch` | +| 解绑导入页面 | `unbindImportPage` | `phone_asset_association:unbind_import_view` | +| 创建解绑导入任务 | `unbindImportCreate` | `phone_asset_association:unbind_import_create` | + +## 资产管理:解绑导入任务 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 任务列表 | `/asset-management/task-management/phone-asset-unbind-import-tasks` | `unbindImportPage` | `phone_asset_association:unbind_import_page` | +| 任务详情 | `/asset-management/task-management/phone-asset-unbind-import-tasks/detail` | `unbindImportDetail` | `phone_asset_association:unbind_import_detail` | +| 详情按钮 | — | `unbindImportDetail` | `asset_association:unbind_import_detail` | + +## 资产管理:临期资产 + +页面 URL:`/asset-management/expiring-assets` + +| 类型 | 权限名称 | 权限编码 | +| -------- | -------- | ----------------------- | +| 页面查看 | `page` | `expiring_asset:page` | +| 导出 | `export` | `expiring_asset:export` | + +## 资产管理:导出任务页面 + +详情按钮为导出任务列表中的任务编号点击入口,权限编码按导出场景区分;详情页面统一使用 `id` 查询参数。 + +| 导出场景 | 列表页面 URL | 页面权限编码 | 详情按钮权限编码 | 详情页面 URL | +| --- | --- | --- | --- | --- | +| 设备 | `/asset-management/export-task-management/export-device` | `export_task:device_page` | `export_task:device_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| IoT 卡 | `/asset-management/export-task-management/export-iot-card` | `export_task:iot_card_page` | `export_task:iot_card_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 订单 | `/asset-management/export-task-management/export-order` | `export_task:order_page` | `export_task:order_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 套餐 | `/asset-management/export-task-management/export-package` | `export_task:package_page` | `export_task:package_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 代理主钱包流水 | `/asset-management/export-task-management/export-agent-wallet-transaction` | `export_task:agent_wallet_transaction_page` | `export_task:agent_wallet_transaction_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 代理充值 | `/asset-management/export-task-management/export-agent-recharge` | `export_task:agent_recharge_page` | `export_task:agent_recharge_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 退款 | `/asset-management/export-task-management/export-refund` | `export_task:refund_page` | `export_task:refund_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 换货 | `/asset-management/export-task-management/export-exchange` | `export_task:exchange_page` | `export_task:exchange_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 佣金明细 | `/asset-management/export-task-management/export-commission-record` | `export_task:commission_record_page` | `export_task:commission_record_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 套餐真流量达量预警 | `/asset-management/export-task-management/export-package-traffic-alert` | `export_task:package_traffic_alert_page` | `export_task:package_traffic_alert_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 临期资产 | `/asset-management/export-task-management/export-expiring-asset` | `export_task:expiring_asset_page` | `export_task:expiring_asset_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 设备激活报表 | `/asset-management/export-task-management/export-operations-activation` | `export_task:operations_activation_page` | `export_task:operations_activation_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | +| 套餐续费报表 | `/asset-management/export-task-management/export-operations-renewal` | `export_task:operations_renewal_page` | `export_task:operations_renewal_detail` | `/asset-management/export-task-management/export-task-detail?id=:id` | + +## 财务管理:退款管理 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --------- | ---------------------------- | ----------------- | ------------------------- | +| 退款列表 | `/finance/refund` | `page` | `refund:page` | +| 退款详情 | `/finance/refund/detail/:id` | `detailPage` | `refund:detail_page` | +| 恢复审批 | — | `recoverApproval` | `refund:recover_approval` | + +## 财务管理:员工代收款账单 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 账单列表 | `/finance/employee-collection/bills` | `billPage` | `employee_collection:bill_view` | +| 账单详情 | `/finance/employee-collection/bills/detail/:id` | `billDetail` | `employee_collection:bill_detail` | +| 创建核销申请 | — | `applicationCreate` | `employee_collection:application_create` | +| 关闭账单 | — | `billClose` | `employee_collection:bill_close` | + +## 财务管理:核销申请 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 申请列表 | `/finance/employee-collection/applications` | `applicationPage` | `employee_collection:application_view` | +| 申请详情 | `/finance/employee-collection/applications/detail/:id` | `applicationDetail` | `employee_collection:application_detail` | +| 修改并重新提交 | — | `applicationUpdate` | `employee_collection:application_update` | +| 查看凭证 | — | `applicationViewVoucher` | `employee_collection:application_view_voucher` | + +## 财务管理:收款方式管理 + +页面 URL:`/finance/employee-collection/payment-methods` + +| 类型 | 权限名称 | 权限编码 | +| -------- | --------------------- | ------------------------------------------- | +| 页面查看 | `paymentMethodPage` | `employee_collection:payment_method_view` | +| 新增 | `paymentMethodCreate` | `employee_collection:payment_method_create` | +| 编辑 | `paymentMethodEdit` | `employee_collection:payment_method_edit` | +| 删除 | `paymentMethodDelete` | `employee_collection:payment_method_delete` | + +## 财务管理:代理商资金概况 + +页面 URL:`/finance/agent-fund-overview` + +| 类型 | 权限名称 | 权限编码 | +| ------------ | ------------------ | --------------------------------------- | +| 页面查看 | `page` | `agent_fund_overview:page` | +| 佣金明细导出 | `commissionExport` | `agent_fund_overview:commission_export` | + +## 设置:商户池管理 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 管理页面 | `/settings/payment-merchant-pools` | `page` | `payment_merchant_pool:page` | +| 商户详情 | `/settings/payment-merchant-pools/detail/:id` | `merchantDetail` | `payment_merchant_pool:merchant_detail` | +| 商户池详情 | `/settings/payment-merchant-pools/pool-detail/:id` | `poolDetail` | `payment_merchant_pool:pool_detail` | +| 新增/编辑/启停/删除商户 | — | — | `payment_merchant_pool:merchant_create` / `merchant_edit` / `merchant_toggle` / `merchant_delete` | +| 新增/编辑/启停商户池 | — | — | `payment_merchant_pool:pool_create` / `pool_edit` / `pool_toggle` | +| 保存微信授权配置 | — | `wechatAuthEdit` | `payment_merchant_pool:wechat_auth_edit` | + +## 设置:H5运营弹窗配置 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 配置列表 | `/settings/h5-popup-configuration` | `list` | `h5_popup_configuration:list` | +| 配置详情 | `/settings/h5-popup-configuration/detail/:id` | `detail` | `h5_popup_configuration:detail` | +| 新增/编辑/启用/停用 | — | — | `h5_popup_configuration:create` / `update` / `enable` / `disable` | + +## 设置:资产钱包自动续费 + +| 页面/操作 | URL | 权限名称 | 权限编码 | +| --- | --- | --- | --- | +| 页面查看 | `/settings/asset-wallet-auto-renewal` | `page` | `asset_wallet_auto_renewal:page` | +| 保存配置 | — | `update` | `asset_wallet_auto_renewal:update` | + +## 轮询管理:优先队列 + +页面 URL:`/polling-management/priority-queue` + +| 类型 | 权限名称 | 权限编码 | +| ------------ | -------- | ------------------------------- | +| 页面查看 | `page` | `polling_priority_queue:page` | +| 人工优先入队 | `create` | `polling_priority_queue:create` | +| 查看详情 | `detail` | `polling_priority_queue:detail` | + +## 运营报表:设备激活报表 + +页面 URL:`/operations-reports/activation` + +| 类型 | 权限名称 | 权限编码 | +| -------- | ------------------ | -------------------------------------- | +| 页面查看 | `activationPage` | `operations_reports:activation_page` | +| 导出 | `activationExport` | `operations_reports:activation_export` | + +## 运营报表:套餐续费报表 + +页面 URL:`/operations-reports/renewal` + +| 类型 | 权限名称 | 权限编码 | +| -------- | --------------- | ----------------------------------- | +| 页面查看 | `renewalPage` | `operations_reports:renewal_page` | +| 导出 | `renewalExport` | `operations_reports:renewal_export` | + +## 通用:导出任务详情 + +页面 URL:`/asset-management/export-task-management/export-task-detail` + +- 页面权限:`export_task:detail_page` +- 各场景详情权限:`export_task:_detail` +- 各场景下载权限:`export_task:_download` + +所有权限编码必须保持唯一;页面 URL 权限与按钮权限应分别定义。 diff --git a/openspec/changes/add-agent-registration-approval-management/design.md b/openspec/changes/add-agent-registration-approval-management/design.md new file mode 100644 index 0000000..1828f91 --- /dev/null +++ b/openspec/changes/add-agent-registration-approval-management/design.md @@ -0,0 +1,16 @@ +## Context + +代理注册申请由公开注册接口创建,后台需要按数据范围查询申请并展示审批提交状态。恢复审批只恢复原企业微信审批提交,不创建新的注册申请或审批实例。 + +## Decisions + +- 使用列表页 + 独立详情页,详情页 URL 为 `/shop-management/agent-distribution-registrations/detail/:id`。 +- 列表和详情均使用后端返回的 `status`、`approval_status`、`submission_status` 和名称字段,不在前端推导状态。 +- 恢复按钮仅由后端返回的 `recoverable` 控制,并使用独立 `agent_distribution_registration:recover_approval` 权限。 +- 详情响应直接消费后端完整手机号和注册地址,不展示密码或内部审批字段。 + +## Risks / Mitigations + +- 状态可能在列表与详情之间发生变化 → 详情和恢复成功/失败后重新加载后端数据。 +- 恢复请求并发冲突 → 后端返回错误时提示并刷新详情,不做乐观更新。 +- 手机号属于敏感业务数据 → 页面仅受注册申请列表/详情权限和后端数据范围控制。 diff --git a/openspec/changes/add-agent-registration-approval-management/proposal.md b/openspec/changes/add-agent-registration-approval-management/proposal.md new file mode 100644 index 0000000..4b02ba8 --- /dev/null +++ b/openspec/changes/add-agent-registration-approval-management/proposal.md @@ -0,0 +1,31 @@ +# Change: 增加代理注册申请后台管理 + +## Why + +后台目前无法查看代理扫码注册申请,也无法处理企业微信审批提交失败或结果未知的注册申请。根据 `docs/产品迭代8月份/代理注册管理.md`,需要提供申请列表、详情和恢复原审批提交入口。 + +## What Changes + +- 新增后台代理注册申请列表页,支持状态、申请/决定时间、手机号、关键字、直接上级店铺和提交异常筛选。 +- 新增注册申请详情页,展示完整手机号、注册地址、申请店铺、分销码、业务状态、审批状态和企微提交状态。 +- 当 `recoverable = true` 时显示“恢复审批”,调用 `POST /api/admin/agent-distribution-registrations/{id}/recover-approval`,成功后刷新详情。 +- 新增代理注册申请 API、类型、路由和权限编码。 +- 权限编码:列表 `agent_distribution_registration:list`、详情 `agent_distribution_registration:detail`、恢复审批 `agent_distribution_registration:recover_approval`。 + +## Impact + +- Affected specs: `agent-distribution-registration` +- Affected code: + - `src/api/modules/agentDistribution.ts` + - `src/types/api/agentDistribution.ts` + - `src/config/constants/augustIteration.ts` + - `src/router/routesAlias.ts` + - `src/router/routes/asyncRoutes.ts` + - `src/views/shop-management/agent-distribution-registrations/index.vue` + - `src/views/shop-management/agent-distribution-registrations/detail.vue` + - `src/locales/langs/zh.json` + - `docs/权限.md` +- Out of scope: + - C 端注册流程和代理登录流程。 + - 后端审批、数据库和企业微信回调实现。 + - 修改注册申请业务资料或审批结果。 diff --git a/openspec/changes/add-agent-registration-approval-management/specs/agent-distribution-registration/spec.md b/openspec/changes/add-agent-registration-approval-management/specs/agent-distribution-registration/spec.md new file mode 100644 index 0000000..0817db2 --- /dev/null +++ b/openspec/changes/add-agent-registration-approval-management/specs/agent-distribution-registration/spec.md @@ -0,0 +1,33 @@ +## ADDED Requirements + +### Requirement: Agent Registration Application List + +The admin frontend SHALL provide a paginated agent registration application list with the documented filters and backend response statuses. + +#### Scenario: Filter registration applications + +- **WHEN** an authorized user selects status, time, phone, keyword, parent shop, or submission anomaly filters +- **THEN** the frontend MUST send those filters to `GET /api/admin/agent-distribution-registrations` +- **AND** the list MUST display business, approval, and submission status names from the response + +### Requirement: Agent Registration Application Detail + +The admin frontend SHALL provide a detail page for `GET /api/admin/agent-distribution-registrations/{id}` and display the complete registration information returned by the backend. + +#### Scenario: Open registration detail + +- **WHEN** an authorized user opens a registration application +- **THEN** the frontend MUST request the application detail by ID +- **AND** MUST display the phone, address, shop, distribution code, business status, approval status, and submission status +- **AND** MUST NOT display password or internal approval fields not present in the response + +### Requirement: Recover Agent Registration Approval + +The frontend SHALL expose `POST /api/admin/agent-distribution-registrations/{id}/recover-approval` only when `recoverable = true` and the user has the recovery permission. + +#### Scenario: Recover approval + +- **GIVEN** a registration response has `recoverable = true` +- **WHEN** the user confirms “恢复审批” +- **THEN** the frontend MUST call the recovery endpoint with only the registration ID +- **AND** MUST refresh the detail after success or a state conflict diff --git a/openspec/changes/add-agent-registration-approval-management/tasks.md b/openspec/changes/add-agent-registration-approval-management/tasks.md new file mode 100644 index 0000000..3fe19f8 --- /dev/null +++ b/openspec/changes/add-agent-registration-approval-management/tasks.md @@ -0,0 +1,17 @@ +## 1. API And Types + +- [x] 1.1 增加代理注册申请列表、详情和恢复审批 TypeScript 类型。 +- [x] 1.2 扩展 `AgentDistributionService`:列表、详情、恢复审批接口。 +- [x] 1.3 增加唯一权限常量 `list`、`detail`、`recoverApproval`。 + +## 2. Pages And Routes + +- [x] 2.1 新增注册申请列表页和筛选条件。 +- [x] 2.2 新增详情页和审批/提交状态展示。 +- [x] 2.3 接入“恢复审批”按钮、确认、错误提示和刷新。 +- [x] 2.4 增加店铺管理下的列表/详情路由与中英文菜单文案。 + +## 3. Documentation And Verification + +- [x] 3.1 将页面、详情和恢复审批权限写入 `docs/权限.md`。 +- [x] 3.2 运行类型检查、lint、编码检查、构建和 OpenSpec 校验。 diff --git a/openspec/changes/add-package-traffic-alert/proposal.md b/openspec/changes/add-package-traffic-alert/proposal.md index c700905..b51fd9d 100644 --- a/openspec/changes/add-package-traffic-alert/proposal.md +++ b/openspec/changes/add-package-traffic-alert/proposal.md @@ -32,12 +32,14 @@ ### 3. 常量与权限 - **修改**: `src/config/constants/augustIteration.ts` — `AUGUST_PERMISSIONS` 新增 `packageTrafficAlert` 权限组 - - `trafficAlertRules: 'package_traffic_alert:rules_view'` - - `trafficAlertRuleCreate: 'package_traffic_alert:rule_create'` - - `trafficAlertRuleUpdate: 'package_traffic_alert:rule_update'` - - `trafficAlertRecords: 'package_traffic_alert:records_view'` - - `trafficAlertRecordDetail: 'package_traffic_alert:record_detail'` - - `trafficAlertExport: 'package_traffic_alert:export'` + - `rulesView: 'package_traffic_alert:rules_view'` + - `ruleCreate: 'package_traffic_alert:rule_create'` + - `ruleUpdate: 'package_traffic_alert:rule_update'` + - `ruleEnable: 'package_traffic_alert:rule_enable'` + - `ruleDisable: 'package_traffic_alert:rule_disable'` + - `recordsView: 'package_traffic_alert:records_view'` + - `recordDetail: 'package_traffic_alert:record_detail'` + - `export: 'package_traffic_alert:export'` - **新增/修改**: 通知状态枚举常量(1 已通知 / 2 待投递 / 3 投递失败 / 4 未通知(接收人已失效)/ 5 未通知(无有效业务员))及对应 tag 类型映射 - 若既有导出任务列表需要区分本场景,补充对应导出场景配置(场景值联调时与后端确认) diff --git a/openspec/changes/add-package-traffic-alert/specs/package-traffic-alert/spec.md b/openspec/changes/add-package-traffic-alert/specs/package-traffic-alert/spec.md index 1d3e197..c49464f 100644 --- a/openspec/changes/add-package-traffic-alert/specs/package-traffic-alert/spec.md +++ b/openspec/changes/add-package-traffic-alert/specs/package-traffic-alert/spec.md @@ -2,6 +2,20 @@ ## ADDED Requirements +### Requirement: 真流量预警规则按钮权限必须唯一 + +规则页面 SHALL 为查看、新增、编辑、启用和停用操作使用唯一的权限编码;启用和停用不得复用编辑权限。 + +#### Scenario: 按操作校验规则权限 + +- **WHEN** 用户访问真流量预警规则页面 +- **THEN** 页面查看权限 MUST 使用 `package_traffic_alert:rules_view` +- **AND** “新增规则” MUST 使用 `package_traffic_alert:rule_create` +- **AND** “编辑” MUST 使用 `package_traffic_alert:rule_update` +- **AND** “启用” MUST 使用 `package_traffic_alert:rule_enable` +- **AND** “停用” MUST 使用 `package_traffic_alert:rule_disable` +- **AND** 上述权限编码 MUST 互不相同 + ### Requirement: 套餐真流量预警规则列表查询 系统 SHALL 提供套餐真流量预警规则列表查询页面,展示规则与套餐商品关联信息,支持按套餐商品与启用状态筛选和分页。 diff --git a/openspec/changes/add-package-traffic-alert/tasks.md b/openspec/changes/add-package-traffic-alert/tasks.md index f1a81a9..dbba2cc 100644 --- a/openspec/changes/add-package-traffic-alert/tasks.md +++ b/openspec/changes/add-package-traffic-alert/tasks.md @@ -9,7 +9,7 @@ ## 2. 常量与权限 -- [x] 2.1 `src/config/constants/augustIteration.ts`:`AUGUST_PERMISSIONS` 新增 `packageTrafficAlert` 权限组(rules_view / rule_create / rule_update / records_view / record_detail / export) +- [x] 2.1 `src/config/constants/augustIteration.ts`:`AUGUST_PERMISSIONS` 新增 `packageTrafficAlert` 权限组(rules_view / rule_create / rule_update / rule_enable / rule_disable / records_view / record_detail / export) - [x] 2.2 新增通知状态常量:枚举 1-5 文案(已通知/待投递/投递失败/未通知(接收人已失效)/未通知(无有效业务员))及 tag 类型映射 - [x] 2.3 若导出任务列表需要场景区分,补充真流量预警导出场景配置(场景值与后端确认后更新 `EXPORT_TASK_SCENE_CONFIG` 及 `getExportTaskSceneName`) @@ -29,7 +29,7 @@ ## 5. 路由、菜单与国际化 - [x] 5.1 `src/router/routesAlias.ts`:新增 `TrafficAlertRules` / `TrafficAlerts` / `TrafficAlertDetail` -- [x] 5.2 `src/router/routes/asyncRoutes.ts`:套餐管理分组下新增规则页、记录页(keepAlive)与隐藏详情路由 +- [x] 5.2 `src/router/routes/asyncRoutes.ts`:套餐管理分组下新增规则页、记录页(keepAlive)与隐藏详情路由;规则页 URL `/package-management/traffic-alert-rules` 增加 `rulesView` 页面权限 - [x] 5.3 `src/locales/langs/zh.json` / `en.json`:`menus.packageManagement` 新增 `trafficAlertRules` / `trafficAlerts` / `trafficAlertDetail` ## 6. 联调与验收 diff --git a/openspec/changes/add-refund-approval-recovery/tasks.md b/openspec/changes/add-refund-approval-recovery/tasks.md index ca967a1..670bb30 100644 --- a/openspec/changes/add-refund-approval-recovery/tasks.md +++ b/openspec/changes/add-refund-approval-recovery/tasks.md @@ -1,22 +1,21 @@ ## 1. Contract And Types -- [ ] 1.1 在 `Refund` 列表/详情类型中增加 `submission_status`、`submission_status_name`、`approval_recoverable`、`approval_failure_summary`、`approval_last_recovery_at`。 -- [ ] 1.2 在 `RefundService` 增加 `recoverApproval(id)`,调用无请求体的 `POST /api/admin/refunds/{id}/recover-approval` 并返回完整 `Refund`。 -- [ ] 1.3 补充 API 注释和统一错误响应处理,明确不传审批实例 ID、材料或企业微信单号。 +- [x] 1.1 在 `Refund` 列表/详情类型中增加 `submission_status`、`submission_status_name`、`approval_recoverable`、`approval_failure_summary`、`approval_last_recovery_at`。 +- [x] 1.2 在 `RefundService` 增加 `recoverApproval(id)`,调用无请求体的 `POST /api/admin/refunds/{id}/recover-approval` 并返回完整 `Refund`。 +- [x] 1.3 补充 API 注释和统一错误响应处理,明确不传审批实例 ID、材料或企业微信单号。 ## 2. Refund List And Detail -- [ ] 2.1 列表展示提交状态名称、脱敏失败摘要和最近恢复时间(按页面现有字段展示约定接入)。 -- [ ] 2.2 仅在 `approval_recoverable === true` 且通过现有退款管理权限/数据范围校验时显示“恢复审批”操作。 -- [ ] 2.3 恢复操作增加确认和请求中 loading,成功后刷新列表并展示最新响应数据。 -- [ ] 2.4 详情页展示上述字段和“恢复审批”操作;成功后刷新详情。 -- [ ] 2.5 处理状态冲突:提示“当前退款审批状态不允许恢复”,并刷新当前数据;其他后端错误沿用统一错误提示。 +- [x] 2.1 列表展示提交状态名称、脱敏失败摘要和最近恢复时间(按页面现有字段展示约定接入)。 +- [x] 2.2 仅在 `approval_recoverable === true` 且通过现有退款管理权限/数据范围校验时显示“恢复审批”操作。 +- [x] 2.3 恢复操作增加确认和请求中 loading,成功后刷新列表并展示最新响应数据。 +- [x] 2.4 详情页展示上述字段和“恢复审批”操作;成功后刷新详情。 +- [x] 2.5 处理状态冲突:提示“当前退款审批状态不允许恢复”,并刷新当前数据;其他后端错误沿用统一错误提示。 ## 3. Verification -- [ ] 3.1 测试已有 `sp_no`、提交结果未知、明确提交失败和不可恢复记录的入口展示与刷新行为。 -- [ ] 3.2 测试无退款权限、越权数据和 `approval_recoverable = false` 时不显示按钮。 -- [ ] 3.3 测试重复点击被 loading 阻止,且请求体为空、不携带审批材料或实例 ID。 -- [ ] 3.4 运行相关单元测试、类型检查、lint 和构建。 -- [ ] 3.5 运行 `openspec.cmd validate add-refund-approval-recovery --strict`。 - +- [x] 3.1 核对已有 `sp_no`、提交结果未知、明确提交失败和不可恢复记录的入口展示与刷新行为。 +- [x] 3.2 核对无退款权限、越权数据和 `approval_recoverable = false` 时不显示按钮。 +- [x] 3.3 核对重复点击被 loading 阻止,且请求体为空、不携带审批材料或实例 ID。 +- [x] 3.4 运行相关类型检查、lint、编码检查和构建。 +- [x] 3.5 运行 `openspec.cmd validate add-refund-approval-recovery --strict`。 diff --git a/src/api/modules/agentDistribution.ts b/src/api/modules/agentDistribution.ts index 6339d02..2a61179 100644 --- a/src/api/modules/agentDistribution.ts +++ b/src/api/modules/agentDistribution.ts @@ -3,7 +3,13 @@ */ import { BaseService } from '../BaseService' -import type { BaseResponse } from '@/types/api' +import type { + AgentDistributionRegistrationPageResult, + AgentDistributionRegistrationQueryParams, + AgentDistributionRegistrationItem, + BaseResponse, + RecoverAgentDistributionRegistrationResponse +} from '@/types/api' /** * 发送短信验证码请求参数 @@ -71,4 +77,32 @@ export class AgentDistributionService extends BaseService { { requestOptions: { withToken: false } } ) } + + /** 查询后台代理注册申请列表 */ + static getRegistrationApplications( + params?: AgentDistributionRegistrationQueryParams + ): Promise> { + return this.get>( + '/api/admin/agent-distribution-registrations', + params + ) + } + + /** 查询后台代理注册申请详情 */ + static getRegistrationApplicationDetail( + id: number + ): Promise> { + return this.getOne( + `/api/admin/agent-distribution-registrations/${id}` + ) + } + + /** 恢复代理注册原审批提交 */ + static recoverRegistrationApproval( + id: number + ): Promise> { + return this.post>( + `/api/admin/agent-distribution-registrations/${id}/recover-approval` + ) + } } diff --git a/src/config/constants/augustIteration.ts b/src/config/constants/augustIteration.ts index 3becb40..4a679de 100644 --- a/src/config/constants/augustIteration.ts +++ b/src/config/constants/augustIteration.ts @@ -25,8 +25,18 @@ export const AUGUST_PERMISSIONS = { unbindImportCreate: 'phone_asset_association:unbind_import_create', unbindImportDetail: 'phone_asset_association:unbind_import_detail' }, + shop: { + listView: 'shop:list_view', + detailView: 'shop:detail_view' + }, + agentDistributionRegistration: { + list: 'agent_distribution_registration:list', + detail: 'agent_distribution_registration:detail', + recoverApproval: 'agent_distribution_registration:recover_approval' + }, h5PopupConfiguration: { list: 'h5_popup_configuration:list', + detail: 'h5_popup_configuration:detail', create: 'h5_popup_configuration:create', update: 'h5_popup_configuration:update', enable: 'h5_popup_configuration:enable', @@ -36,9 +46,39 @@ export const AUGUST_PERMISSIONS = { rulesView: 'package_traffic_alert:rules_view', ruleCreate: 'package_traffic_alert:rule_create', ruleUpdate: 'package_traffic_alert:rule_update', + ruleEnable: 'package_traffic_alert:rule_enable', + ruleDisable: 'package_traffic_alert:rule_disable', recordsView: 'package_traffic_alert:records_view', recordDetail: 'package_traffic_alert:record_detail', export: 'package_traffic_alert:export' + }, + expiringAsset: { + page: 'expiring_asset:page', + export: 'expiring_asset:export' + }, + refund: { + page: 'refund:page', + detailPage: 'refund:detail_page', + recoverApproval: 'refund:recover_approval' + }, + agentFundOverview: { + page: 'agent_fund_overview:page', + commissionExport: 'agent_fund_overview:commission_export' + }, + assetWalletAutoRenewal: { + page: 'asset_wallet_auto_renewal:page', + update: 'asset_wallet_auto_renewal:update' + }, + pollingPriorityQueue: { + page: 'polling_priority_queue:page', + create: 'polling_priority_queue:create', + detail: 'polling_priority_queue:detail' + }, + operationsReports: { + activationPage: 'operations_reports:activation_page', + activationExport: 'operations_reports:activation_export', + renewalPage: 'operations_reports:renewal_page', + renewalExport: 'operations_reports:renewal_export' } } as const diff --git a/src/config/constants/businessUserGroup.ts b/src/config/constants/businessUserGroup.ts index 7e57a05..3efa1b5 100644 --- a/src/config/constants/businessUserGroup.ts +++ b/src/config/constants/businessUserGroup.ts @@ -16,19 +16,25 @@ export const BUSINESS_USER_GROUP_BUSINESS_LINE_OPTIONS: Array<{ ] /** 业务线文案映射 */ -export const BUSINESS_USER_GROUP_BUSINESS_LINE_MAP = BUSINESS_USER_GROUP_BUSINESS_LINE_OPTIONS.reduce( - (map, item) => { - map[item.value] = item - return map - }, - {} as Record -) +export const BUSINESS_USER_GROUP_BUSINESS_LINE_MAP = + BUSINESS_USER_GROUP_BUSINESS_LINE_OPTIONS.reduce( + (map, item) => { + map[item.value] = item + return map + }, + {} as Record< + BusinessUserGroupBusinessLine, + (typeof BUSINESS_USER_GROUP_BUSINESS_LINE_OPTIONS)[number] + > + ) /** 获取业务线标签 */ export function getBusinessUserGroupBusinessLineLabel(businessLine?: string | null): string { if (!businessLine) return '-' - return BUSINESS_USER_GROUP_BUSINESS_LINE_MAP[businessLine as BusinessUserGroupBusinessLine] - ?.label ?? businessLine + return ( + BUSINESS_USER_GROUP_BUSINESS_LINE_MAP[businessLine as BusinessUserGroupBusinessLine]?.label ?? + businessLine + ) } /** 业务用户组页面与按钮权限编码 */ @@ -43,6 +49,7 @@ export const BUSINESS_USER_GROUP_PERMISSIONS = { /** 店铺业务负责人运营权限编码 */ export const SHOP_BUSINESS_OWNER_PERMISSIONS = { batch: 'shop:business_owner_batch', - importPage: 'shop:business_owner_import', - importCreate: 'shop:business_owner_import' -} \ No newline at end of file + importPage: 'shop:business_owner_import_view', + importCreate: 'shop:business_owner_import_create', + importDetail: 'shop:business_owner_import_detail' +} diff --git a/src/config/constants/exportTask.ts b/src/config/constants/exportTask.ts index 4e8048a..7e08282 100644 --- a/src/config/constants/exportTask.ts +++ b/src/config/constants/exportTask.ts @@ -1,10 +1,13 @@ import type { ExportTaskScene } from '@/types/api' export interface ExportTaskScenePermissions { + page: string detail: string download: string } +export const EXPORT_TASK_DETAIL_PAGE_PERMISSION = 'export_task:detail_page' + export interface ExportTaskSceneConfig { scene: ExportTaskScene sceneName: string @@ -18,6 +21,7 @@ export const EXPORT_TASK_SCENE_CONFIG: Record 风格。 */ export const PAYMENT_MERCHANT_POOL_PERMISSIONS = { + page: 'payment_merchant_pool:page', merchantCreate: 'payment_merchant_pool:merchant_create', merchantEdit: 'payment_merchant_pool:merchant_edit', merchantToggle: 'payment_merchant_pool:merchant_toggle', diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json index 9e23413..7acf56e 100644 --- a/src/locales/langs/en.json +++ b/src/locales/langs/en.json @@ -26,20 +26,11 @@ "setting": { "menuType": { "title": "Menu Layout", - "list": [ - "Vertical", - "Horizontal", - "Mixed", - "Dual" - ] + "list": ["Vertical", "Horizontal", "Mixed", "Dual"] }, "theme": { "title": "Theme Style", - "list": [ - "Light", - "Dark", - "System" - ] + "list": ["Light", "Dark", "System"] }, "menu": { "title": "Menu Style" @@ -49,17 +40,11 @@ }, "box": { "title": "Box Style", - "list": [ - "Border", - "Shadow" - ] + "list": ["Border", "Shadow"] }, "container": { "title": "Container Width", - "list": [ - "Full", - "Boxed" - ] + "list": ["Full", "Boxed"] }, "basics": { "title": "Basic Config", @@ -97,14 +82,8 @@ "notice": { "title": "Notice", "btnRead": "Mark as read", - "bar": [ - "Notice", - "Message", - "Todo" - ], - "text": [ - "No" - ], + "bar": ["Notice", "Message", "Todo"], + "text": ["No"], "viewAll": "View all" }, "worktab": { @@ -460,7 +439,9 @@ "title": "Shop Management", "shopList": "Shop List", "businessUserGroups": "Business User Groups", - "businessOwnerImport": "Business Owner Import" + "businessOwnerImport": "Business Owner Import", + "agentDistributionRegistrations": "Agent Registration Applications", + "agentDistributionRegistrationDetail": "Agent Registration Application Detail" }, "assetManagement": { "title": "Asset Management", diff --git a/src/locales/langs/zh.json b/src/locales/langs/zh.json index 947181e..6443cb8 100644 --- a/src/locales/langs/zh.json +++ b/src/locales/langs/zh.json @@ -27,20 +27,11 @@ "setting": { "menuType": { "title": "菜单布局", - "list": [ - "垂直", - "水平", - "混合", - "双列" - ] + "list": ["垂直", "水平", "混合", "双列"] }, "theme": { "title": "主题风格", - "list": [ - "浅色", - "深色", - "系统" - ] + "list": ["浅色", "深色", "系统"] }, "menu": { "title": "菜单风格" @@ -50,17 +41,11 @@ }, "box": { "title": "盒子样式", - "list": [ - "边框", - "阴影" - ] + "list": ["边框", "阴影"] }, "container": { "title": "容器宽度", - "list": [ - "铺满", - "定宽" - ] + "list": ["铺满", "定宽"] }, "basics": { "title": "基础配置", @@ -98,14 +83,8 @@ "notice": { "title": "通知", "btnRead": "标为已读", - "bar": [ - "通知", - "消息", - "代办" - ], - "text": [ - "暂无" - ], + "bar": ["通知", "消息", "代办"], + "text": ["暂无"], "viewAll": "查看全部" }, "worktab": { @@ -131,11 +110,7 @@ "admin": "管理员", "user": "普通用户" }, - "placeholder": [ - "请输入手机号", - "请输入密码", - "请拖动滑块完成验证" - ], + "placeholder": ["请输入手机号", "请输入密码", "请拖动滑块完成验证"], "sliderText": "按住滑块拖动", "sliderSuccessText": "验证成功", "rememberPwd": "记住密码", @@ -178,11 +153,7 @@ "register": { "title": "创建账号", "subTitle": "欢迎加入我们,请填写以下信息完成注册", - "placeholder": [ - "请输入账号", - "请输入密码", - "请再次输入密码" - ], + "placeholder": ["请输入账号", "请输入密码", "请再次输入密码"], "rule": [ "请再次输入密码", "两次输入密码不一致!", @@ -396,7 +367,9 @@ "title": "店铺管理", "shopList": "店铺列表", "businessUserGroups": "业务用户组", - "businessOwnerImport": "业务负责人导入" + "businessOwnerImport": "业务负责人导入", + "agentDistributionRegistrations": "代理注册申请", + "agentDistributionRegistrationDetail": "代理注册申请详情" }, "assetManagement": { "title": "资产管理", diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts index 4ab51dc..f80e2f6 100644 --- a/src/router/routes/asyncRoutes.ts +++ b/src/router/routes/asyncRoutes.ts @@ -5,6 +5,10 @@ import { JULY_PERMISSIONS } from '@/config/constants/julyIteration' import { AUDIT_PERMISSIONS } from '@/config/constants/audit' import { AUGUST_PERMISSIONS } from '@/config/constants/augustIteration' import { PAYMENT_MERCHANT_POOL_PERMISSIONS } from '@/config/constants/paymentMerchantPools' +import { + EXPORT_TASK_DETAIL_PAGE_PERMISSION, + EXPORT_TASK_SCENE_CONFIG +} from '@/config/constants/exportTask' import { BUSINESS_USER_GROUP_PERMISSIONS, SHOP_BUSINESS_OWNER_PERMISSIONS @@ -219,7 +223,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.TrafficAlertRules, meta: { title: 'menus.packageManagement.trafficAlertRules', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.packageTrafficAlert.rulesView] } }, // 真流量达量预警记录 @@ -229,7 +234,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.TrafficAlerts, meta: { title: 'menus.packageManagement.trafficAlerts', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.packageTrafficAlert.recordsView] } }, // 真流量达量预警记录详情 @@ -240,7 +246,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.packageManagement.trafficAlertDetail', isHide: true, - keepAlive: false + keepAlive: false, + permissions: [AUGUST_PERMISSIONS.packageTrafficAlert.recordDetail] } } ] @@ -263,7 +270,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.Shop, meta: { title: 'menus.shopManagement.shopList', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.shop.listView] } }, // 店铺详情 @@ -274,7 +282,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: '店铺详情', isHide: true, - keepAlive: false + keepAlive: false, + permissions: [AUGUST_PERMISSIONS.shop.detailView] } }, // 业务用户组 @@ -300,6 +309,29 @@ export const asyncRoutes: AppRouteRecord[] = [ roles: ['R_SUPER', 'R_ADMIN'], permissions: [SHOP_BUSINESS_OWNER_PERMISSIONS.importPage] } + }, + // 代理注册申请 + { + path: 'agent-distribution-registrations', + name: 'AgentDistributionRegistrations', + component: RoutesAlias.AgentDistributionRegistrations, + meta: { + title: 'menus.shopManagement.agentDistributionRegistrations', + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.agentDistributionRegistration.list] + } + }, + // 代理注册申请详情 + { + path: 'agent-distribution-registrations/detail/:id', + name: 'AgentDistributionRegistrationDetail', + component: RoutesAlias.AgentDistributionRegistrationDetail, + meta: { + title: 'menus.shopManagement.agentDistributionRegistrationDetail', + isHide: true, + keepAlive: false, + permissions: [AUGUST_PERMISSIONS.agentDistributionRegistration.detail] + } } ] }, @@ -375,7 +407,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.ExpiringAssets, meta: { title: '临期资产', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.expiringAsset.page] } }, // IoT卡管理 @@ -691,7 +724,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportCommissionRecord', exportTaskScene: 'commission_record', - keepAlive: true + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.commission_record.permissions.page] } }, { @@ -701,7 +735,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportPackageTrafficAlert', exportTaskScene: 'package_traffic_alert', - keepAlive: true + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.package_traffic_alert.permissions.page] } }, { @@ -711,7 +746,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportExpiringAsset', exportTaskScene: 'expiring_asset', - keepAlive: true + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.expiring_asset.permissions.page] } }, { @@ -721,7 +757,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportOperationsActivation', exportTaskScene: 'operations_activation', - keepAlive: true + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.operations_activation.permissions.page] } }, { @@ -731,7 +768,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportOperationsRenewal', exportTaskScene: 'operations_renewal', - keepAlive: true + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.operations_renewal.permissions.page] } }, { @@ -741,7 +779,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.assetManagement.exportTaskDetail', isHide: true, - keepAlive: false + keepAlive: false, + permissions: [EXPORT_TASK_DETAIL_PAGE_PERMISSION] } } ] @@ -821,7 +860,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.RefundManagement, meta: { title: 'menus.financialManagement.refundManagement', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.refund.page] } }, // 退款详情 @@ -832,7 +872,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.financialManagement.refundDetail', isHide: true, - keepAlive: false + keepAlive: false, + permissions: [AUGUST_PERMISSIONS.refund.detailPage] } }, // 员工代收款账单 @@ -901,7 +942,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.financialManagement.agentFundOverview', keepAlive: true, - roles: ['R_SUPER', 'R_ADMIN'] + roles: ['R_SUPER', 'R_ADMIN'], + permissions: [AUGUST_PERMISSIONS.agentFundOverview.page] } } ] @@ -1047,7 +1089,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.settings.paymentMerchantPools', keepAlive: true, - allowedUserTypes: [1, 2] + allowedUserTypes: [1, 2], + permissions: [PAYMENT_MERCHANT_POOL_PERMISSIONS.page] } }, // 支付商户详情 @@ -1174,7 +1217,7 @@ export const asyncRoutes: AppRouteRecord[] = [ isHide: true, keepAlive: false, allowedUserTypes: [1, 2], - permissions: [AUGUST_PERMISSIONS.h5PopupConfiguration.list] + permissions: [AUGUST_PERMISSIONS.h5PopupConfiguration.detail] } }, // 资产钱包自动续费配置 @@ -1185,7 +1228,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: 'menus.settings.assetWalletAutoRenewal', keepAlive: true, - allowedUserTypes: [1, 2] + allowedUserTypes: [1, 2], + permissions: [AUGUST_PERMISSIONS.assetWalletAutoRenewal.page] } } ] @@ -1278,7 +1322,8 @@ export const asyncRoutes: AppRouteRecord[] = [ component: RoutesAlias.PollingPriorityQueue, meta: { title: '优先队列', - keepAlive: true + keepAlive: true, + permissions: [AUGUST_PERMISSIONS.pollingPriorityQueue.page] } } ] @@ -1301,7 +1346,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: '设备激活报表', keepAlive: true, - allowedUserTypes: [1, 2] + allowedUserTypes: [1, 2], + permissions: [AUGUST_PERMISSIONS.operationsReports.activationPage] } }, { @@ -1311,7 +1357,8 @@ export const asyncRoutes: AppRouteRecord[] = [ meta: { title: '套餐续费报表', keepAlive: true, - allowedUserTypes: [1, 2] + allowedUserTypes: [1, 2], + permissions: [AUGUST_PERMISSIONS.operationsReports.renewalPage] } } ] diff --git a/src/router/routesAlias.ts b/src/router/routesAlias.ts index 17bb42f..511fd01 100644 --- a/src/router/routesAlias.ts +++ b/src/router/routesAlias.ts @@ -47,6 +47,8 @@ export enum RoutesAlias { ShopDetail = '/shop-management/detail', // 店铺详情 BusinessUserGroups = '/shop-management/business-user-groups', // 业务用户组 BusinessOwnerImport = '/shop-management/business-owner-import', // 业务负责人导入 + AgentDistributionRegistrations = '/shop-management/agent-distribution-registrations', // 代理注册申请 + AgentDistributionRegistrationDetail = '/shop-management/agent-distribution-registrations/detail', // 代理注册申请详情 // 通用页面(店铺账号-企业账号) EnterpriseCustomerAccounts = '/common/account-list', // 企业客户账号列表和店铺账号列表共用 diff --git a/src/types/api/agentDistributionRegistration.ts b/src/types/api/agentDistributionRegistration.ts new file mode 100644 index 0000000..945669d --- /dev/null +++ b/src/types/api/agentDistributionRegistration.ts @@ -0,0 +1,56 @@ +/** 后台代理注册申请管理类型 */ + +export interface AgentDistributionRegistrationQueryParams { + page?: number + page_size?: number + status?: 0 | 1 | 2 + start_time?: string + end_time?: string + decided_start_time?: string + decided_end_time?: string + phone?: string + keyword?: string + parent_shop_id?: number + submission_anomaly?: boolean +} + +export interface AgentDistributionRegistrationItem { + id: number + status: number + status_name?: string | null + approval_status?: number | null + approval_status_name?: string | null + submission_status?: number | null + submission_status_name?: string | null + recoverable?: boolean + failure_summary?: string | null + last_recovery_at?: string | null + approval_instance_id?: number | null + phone: string + username: string + shop_name: string + shop_code: string + contact_name?: string | null + province?: string | null + city?: string | null + district?: string | null + address?: string | null + distribution_code?: string | null + parent_shop_id?: number | null + parent_shop_name?: string | null + reject_reason?: string | null + created_at: string + decided_at?: string | null +} + +export interface AgentDistributionRegistrationPageResult { + items: AgentDistributionRegistrationItem[] + page: number + size: number + total: number +} + +export interface RecoverAgentDistributionRegistrationResponse { + id: number + message?: string +} diff --git a/src/types/api/index.ts b/src/types/api/index.ts index 001a1e3..50263ac 100644 --- a/src/types/api/index.ts +++ b/src/types/api/index.ts @@ -75,6 +75,7 @@ export * from './asset' // 代理充值相关 export * from './agentRecharge' +export * from './agentDistributionRegistration' // 支付设置相关 export * from './paymentSettings' diff --git a/src/views/asset-management/expiring-assets/index.vue b/src/views/asset-management/expiring-assets/index.vue index 38caba2..3099301 100644 --- a/src/views/asset-management/expiring-assets/index.vue +++ b/src/views/asset-management/expiring-assets/index.vue @@ -27,7 +27,9 @@ 下载 - 导出 + + 导出 + @@ -72,11 +74,15 @@ import { useAsyncTaskPolling } from '@/composables/useAsyncTaskPolling' import { useCheckedColumns } from '@/composables/useCheckedColumns' import { formatDateTime } from '@/utils/business/format' + import { useAuth } from '@/composables/useAuth' + import { AUGUST_PERMISSIONS } from '@/config/constants/augustIteration' defineOptions({ name: 'ExpiringAssets' }) const router = useRouter() const route = useRoute() + const { hasAuth } = useAuth() + const canExport = computed(() => hasAuth(AUGUST_PERMISSIONS.expiringAsset.export)) const tableRef = ref() const loading = ref(false) const exporting = ref(false) diff --git a/src/views/commission-management/agent-fund-overview/index.vue b/src/views/commission-management/agent-fund-overview/index.vue index 5a62efd..391ab1a 100644 --- a/src/views/commission-management/agent-fund-overview/index.vue +++ b/src/views/commission-management/agent-fund-overview/index.vue @@ -55,8 +55,8 @@
- 导出 @@ -511,6 +511,7 @@ import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue' import CommissionRecordDetailDialog from '@/components/business/CommissionRecordDetailDialog.vue' import { AUDIT_PERMISSIONS } from '@/config/constants/audit' + import { AUGUST_PERMISSIONS } from '@/config/constants/augustIteration' import { resolveFinanceAuditTarget } from '@/utils/business/auditNavigation' import { openAuditInvestigation } from '@/components/business/audit/investigationController' diff --git a/src/views/finance/refund/detail.vue b/src/views/finance/refund/detail.vue index 467ade2..2712ae1 100644 --- a/src/views/finance/refund/detail.vue +++ b/src/views/finance/refund/detail.vue @@ -18,7 +18,11 @@ 重新申请 handleRecoverApproval(row), diff --git a/src/views/operations-reports/activation/index.vue b/src/views/operations-reports/activation/index.vue index 48180f8..c236f70 100644 --- a/src/views/operations-reports/activation/index.vue +++ b/src/views/operations-reports/activation/index.vue @@ -18,7 +18,9 @@ @refresh="handleRefresh" > + + diff --git a/src/views/shop-management/agent-distribution-registrations/index.vue b/src/views/shop-management/agent-distribution-registrations/index.vue new file mode 100644 index 0000000..fdd3e90 --- /dev/null +++ b/src/views/shop-management/agent-distribution-registrations/index.vue @@ -0,0 +1,254 @@ + + + diff --git a/src/views/shop-management/business-owner-import/index.vue b/src/views/shop-management/business-owner-import/index.vue index 884c7ff..6ae68be 100644 --- a/src/views/shop-management/business-owner-import/index.vue +++ b/src/views/shop-management/business-owner-import/index.vue @@ -45,6 +45,8 @@ :pageSize="pagination.pageSize" :total="pagination.total" :marginTop="10" + :actions="getActions" + :actionsWidth="90" @size-change="handleSizeChange" @current-change="handleCurrentChange" > @@ -199,9 +201,13 @@ import { useCheckedColumns } from '@/composables/useCheckedColumns' import { formatDateTime } from '@/utils/business/format' import { SHOP_BUSINESS_OWNER_PERMISSIONS } from '@/config/constants' + import { useAuth } from '@/composables/useAuth' defineOptions({ name: 'BusinessOwnerImport' }) + const { hasAuth } = useAuth() + const canImportDetail = computed(() => hasAuth(SHOP_BUSINESS_OWNER_PERMISSIONS.importDetail)) + const importStatusOptions = [ { label: '待处理', value: 1 }, { label: '处理中', value: 2 }, @@ -251,6 +257,7 @@ { style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;', onClick: (event: MouseEvent) => { + if (!canImportDetail.value) return event.stopPropagation() openDetail(row) } @@ -349,6 +356,11 @@ getList() } + const getActions = (row: BusinessOwnerImportDetail) => + canImportDetail.value + ? [{ label: '详情', handler: () => openDetail(row), type: 'primary' as const }] + : [] + // ==================== 模板下载 ==================== const handleDownloadTemplate = () => { try {