From 91d7d4c21fac3def18329bfc0ac51e443f2defdb Mon Sep 17 00:00:00 2001 From: sexygoat <1538832180@qq.com> Date: Wed, 15 Apr 2026 11:54:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/DESIGN-SYSTEM.md | 53 +- docs/BREAKING_CHANGES_asset_identifier(1).md | 265 ++++++++ docs/前端接口变更通知.md | 129 ++++ src/api/assets.ts | 210 +++++- src/api/commission.ts | 106 ++- src/api/withdrawal.ts | 18 +- src/components/SimplePicker.vue | 2 +- src/components/Skeleton.vue | 36 +- src/pages/agent-system/asset-detail/index.vue | 46 +- src/pages/agent-system/asset-search/index.vue | 53 +- src/pages/agent-system/asset-wallet/index.vue | 225 ++++--- src/pages/agent-system/assets/index.vue | 227 +++---- .../agent-system/change-password/index.vue | 360 ++++------- .../agent-system/commission-center/index.vue | 293 ++++----- .../agent-system/enterprise-cards/index.vue | 291 +++------ .../agent-system/enterprise-devices/index.vue | 239 ++----- src/pages/agent-system/home/index.vue | 603 +++++++++--------- src/pages/agent-system/index.vue | 36 +- src/pages/agent-system/packages/index.vue | 4 +- src/pages/agent-system/withdraw/index.vue | 363 ++++------- src/pages/common/login/index.vue | 12 +- src/static/icons/佣金中心.png | Bin 0 -> 145640 bytes src/static/icons/修改密码.png | Bin 0 -> 111617 bytes src/static/icons/授权卡列表.png | Bin 0 -> 117376 bytes src/static/icons/授权设备列表.png | Bin 0 -> 89754 bytes src/static/icons/提现管理.png | Bin 0 -> 176913 bytes src/static/icons/资产列表.png | Bin 0 -> 139634 bytes src/static/icons/退出登录.png | Bin 0 -> 112148 bytes src/static/styles/theme.scss | 26 +- src/utils/request/index.ts | 8 + 30 files changed, 1863 insertions(+), 1742 deletions(-) create mode 100644 docs/BREAKING_CHANGES_asset_identifier(1).md create mode 100644 docs/前端接口变更通知.md create mode 100644 src/static/icons/佣金中心.png create mode 100644 src/static/icons/修改密码.png create mode 100644 src/static/icons/授权卡列表.png create mode 100644 src/static/icons/授权设备列表.png create mode 100644 src/static/icons/提现管理.png create mode 100644 src/static/icons/资产列表.png create mode 100644 src/static/icons/退出登录.png diff --git a/.claude/DESIGN-SYSTEM.md b/.claude/DESIGN-SYSTEM.md index 1e1194a..b034c42 100644 --- a/.claude/DESIGN-SYSTEM.md +++ b/.claude/DESIGN-SYSTEM.md @@ -39,54 +39,57 @@ Based on analysis: **SaaS (General) + B2B Service** ## 🌈 Color Palette -### Brand Colors (Xiaomi-Inspired) +### Brand Colors (Blue Theme) ```scss // Primary Brand Colors ---brand-orange: #ff6700; // Primary CTA, hover states ---brand-orange-light: #ff8533; // Lighter variant ---brand-orange-dark: #e65a00; // Pressed states ---brand-gray: #333333; // Headings, important text ---brand-gray-light: #757575; // Secondary text +--brand-primary: #1677ff; // Primary CTA, hover states +--brand-primary-light: #4096ff; // Lighter variant +--brand-primary-dark: #0958d9; // Pressed states +--brand-secondary: #1e293b; // Dark Gray (headings) +--brand-accent: #ffffff; // White (emphasis) ``` ### Semantic Colors (Light Mode) ```scss // Primary Theme Colors ---theme-primary: #ff6700; // Orange (Trust + Energy) ---theme-secondary: #ff8533; // Lighter Orange ---theme-accent: #333333; // Dark Gray +--theme-primary: #1677ff; // Blue (Trust + Energy) +--theme-secondary: #1e293b; // Dark Gray +--theme-accent: #ffffff; // White // Status Colors ---theme-success: #3ed268; // Green (Success states) ---theme-warning: #e68815; // Amber (Warnings) ---theme-error: #d31638; // Red (Errors) +--theme-success: #52c41a; // Green (Success states) +--theme-warning: #faad14; // Amber (Warnings) +--theme-error: #ff4d4f; // Red (Errors) +--theme-info: #1677ff; // Info (same as primary) // Text Hierarchy ---theme-main-color: #4c484f; // Primary text (slate-900 equivalent) ---theme-content-color: #6b6569; // Body text (slate-700) ---theme-tips-color: #8a8486; // Secondary text (slate-500) ---theme-light-color: #bd9e84; // Muted text (beige) ---theme-disabled-color: #dce0eb; // Disabled states +--theme-main-color: #212121; // Primary text +--theme-content-color: #666666; // Body text +--theme-tips-color: #999999; // Secondary text +--theme-light-color: #cccccc; // Muted text +--theme-disabled-color: #f5f5f5; // Disabled states // Backgrounds ---theme-bg-color: #ffffff; // Main background ---theme-bg-color-secondary: #faf8f7; // Card backgrounds ---theme-bg-gradient-start: #c5dfdf; ---theme-bg-gradient-end: #bd9e84; +--theme-bg-color: #fafafa; // Main background +--theme-bg-color-secondary: #ffffff; // Card backgrounds +--theme-bg-gradient-start: #1677ff; +--theme-bg-gradient-end: #4096ff; // Borders ---theme-border-color: #c5dfdf; // Borders, dividers +--theme-border-color: #e8e8e8; // Borders, dividers ``` ### Dark Mode Colors ```scss .theme-dark { - --theme-primary: #3c9cff; // Blue (better for dark mode) - --theme-success: #5ac725; - --theme-warning: #f9ae3d; + --brand-primary: #4b9cff; // Blue (lighter for dark mode) + --brand-primary-light: #69b1ff; + --brand-primary-dark: #1668dc; + --theme-success: #73d13d; + --theme-warning: #ffc53d; --theme-error: #f56c6c; // Text (High Contrast Required) diff --git a/docs/BREAKING_CHANGES_asset_identifier(1).md b/docs/BREAKING_CHANGES_asset_identifier(1).md new file mode 100644 index 0000000..eab1c33 --- /dev/null +++ b/docs/BREAKING_CHANGES_asset_identifier(1).md @@ -0,0 +1,265 @@ +# 接口变化说明:资产标识符规范化 + 历史订单 + 导入必填 + +> **涉及提案**: +> - `asset-identifier-standardization`(BREAKING) +> - `asset-historical-orders`(新增接口) +> - `import-mandatory-virtual-no`(行为变更) +> +> **影响范围**:B 端资产操作、设备管理、订单创建、IoT 卡 / 设备导入 + +--- + +## 1. 资产操作接口路由变更 + +**变更前**:路径参数为数据库主键 ID,需同时传 `asset_type` +**变更后**:路径参数统一为资产标识符(ICCID 或 VirtualNo),系统内部自动识别资产类型 + +| 旧路由 | 新路由 | +|---|---| +| `GET /api/admin/assets/:asset_type/:id/realtime-status` | `GET /api/admin/assets/:identifier/realtime-status` | +| `POST /api/admin/assets/:asset_type/:id/refresh` | `POST /api/admin/assets/:identifier/refresh` | +| `GET /api/admin/assets/:asset_type/:id/packages` | `GET /api/admin/assets/:identifier/packages` | +| `GET /api/admin/assets/:asset_type/:id/current-package` | `GET /api/admin/assets/:identifier/current-package` | +| `GET /api/admin/assets/:asset_type/:id/wallet` | `GET /api/admin/assets/:identifier/wallet` | +| `GET /api/admin/assets/:asset_type/:id/wallet/transactions` | `GET /api/admin/assets/:identifier/wallet/transactions` | +| `PATCH /api/admin/assets/:asset_type/:id/polling-status` | `PATCH /api/admin/assets/:identifier/polling-status` | +| `POST /api/admin/assets/device/:device_id/stop` | `POST /api/admin/assets/:identifier/stop` | +| `POST /api/admin/assets/card/:iccid/stop` | `POST /api/admin/assets/:identifier/stop`(已合并) | +| `POST /api/admin/assets/device/:device_id/start` | `POST /api/admin/assets/:identifier/start` | +| `POST /api/admin/assets/card/:iccid/start` | `POST /api/admin/assets/:identifier/start`(已合并) | +| `PATCH /api/admin/devices/:id/deactivate` | `PATCH /api/admin/assets/:identifier/deactivate` | +| `PATCH /api/admin/iot-cards/:id/deactivate` | `PATCH /api/admin/assets/:identifier/deactivate`(已合并) | + +**注意事项:** +- `:identifier` 只接受 ICCID 或 VirtualNo(全局唯一标识符) +- `stop` / `start` / `deactivate` 已合并为统一接口,系统内部按资产类型自动分支处理,前端无需区分卡和设备 +- IMEI / SN / MSISDN 仍可用于 `GET /api/admin/assets/resolve/:identifier` 搜索,但不适用于操作接口 + +--- + +## 2. 设备管理接口路由变更 + +**变更前**:路径参数为数据库主键 ID +**变更后**:路径参数改为 VirtualNo(虚拟号) + +| 旧路由 | 新路由 | +|---|---| +| `DELETE /api/admin/devices/:id` | `DELETE /api/admin/devices/:virtual_no` | +| `GET /api/admin/devices/:id/cards` | `GET /api/admin/devices/:virtual_no/cards` | +| `POST /api/admin/devices/:id/cards` | `POST /api/admin/devices/:virtual_no/cards` | +| `DELETE /api/admin/devices/:id/cards/:cardId` | `DELETE /api/admin/devices/:virtual_no/cards/:iccid` | + +**注意事项:** +- 解绑卡接口第二段路径参数从 `cardId`(数据库 ID)改为 `iccid`(ICCID 字符串) + +--- + +## 3. 创建订单接口请求体变更 + +### B 端:`POST /api/admin/orders` + +**请求体字段变化:** + +| 字段 | 旧 | 新 | 说明 | +|---|---|---|---| +| `order_type` | 必填 | **废弃** | 系统根据 `identifier` 解析结果自动填入 | +| `iot_card_id` | 单卡购买必填 | **废弃** | 改用 `identifier` | +| `device_id` | 设备购买必填 | **废弃** | 改用 `identifier` | +| `identifier` | — | **必填** | ICCID 或 VirtualNo,最长 100 字符 | +| `package_ids` | 必填 | 不变 | — | +| `payment_method` | 必填 | 不变 | — | + +**变更后请求体示例:** + +```json +{ + "identifier": "8986XXXXXXXXXXXXXXXX",[前端接口变更通知.md](%E5%89%8D%E7%AB%AF%E6%8E%A5%E5%8F%A3%E5%8F%98%E6%9B%B4%E9%80%9A%E7%9F%A5.md) + "package_ids": [5], + "payment_method": "wallet" +} +``` + +### C 端:`POST /api/c/v1/orders/create` + +同 B 端,废弃 `order_type` / `iot_card_id` / `device_id`,统一使用 `identifier`。C 端原本已有此字段,行为不变。 + +--- + +## 4. 订单列表接口新增过滤参数 + +### `GET /api/admin/orders` + +新增可选查询参数: + +| 参数 | 类型 | 说明 | +|---|---|---| +| `identifier` | string | 按资产标识符精确过滤,匹配订单的 `asset_identifier` 快照字段 | + +**示例:** + +``` +GET /api/admin/orders?identifier=8986XXXXXXXXXXXXXXXX +GET /api/admin/orders?identifier=DEV-001 +``` + +--- + +## 5. 响应结构新增字段 + +### `OrderResponse`(所有订单相关接口响应) + +| 新增字段 | 类型 | 说明 | +|---|---|---| +| `asset_identifier` | string | 下单时资产的标识符快照,资产删除后仍可读 | +| `asset_type` | string | 资产类型:`single_card` 或 `device` | + +### `AssetResolveResponse`(`GET /api/admin/assets/resolve/:identifier`) + +| 新增字段 | 类型 | 说明 | +|---|---|---| +| `identifier` | string | 原样回传本次查询所用的标识符 | + +--- + +## 6. 新增业务规则 + +### 已绑设备的卡不可单独购买套餐 + +- **触发条件**:IoT 卡的 `is_standalone = false`(已绑定设备) +- **影响接口**:所有套餐购买入口(B 端后台、C 端 H5) +- **返回错误**: + +```json +{ + "code": 40001, + "msg": "该卡已绑定设备,请前往设备页面购买套餐" +} +``` + +--- + +--- + +## 7. 新增接口:资产历史订单 + +> **来源提案**:`asset-historical-orders` + +### `GET /api/admin/assets/:identifier/orders` + +查询某资产本代历史订单,可选通过换货链追溯前代(最多10代)。 + +**路径参数:** + +| 参数 | 说明 | +|---|---| +| `identifier` | 资产标识符(ICCID 或 VirtualNo) | + +**查询参数:** + +| 参数 | 类型 | 必填 | 说明 | +|---|---|---|---| +| `page` | int | 否 | 页码,默认 1 | +| `page_size` | int | 否 | 每页条数,默认 20,最大 100 | +| `include_previous` | bool | 否 | 是否追溯换货前代,默认 false | + +**响应示例:** + +```json +{ + "code": 0, + "data": { + "current_generation": { + "generation": 2, + "identifier": "VNO-001", + "asset_type": "card", + "total": 3, + "page": 1, + "page_size": 20, + "items": [ + { + "order_no": "ORD-20250101-001", + "order_type": "single_card", + "payment_status": 2, + "payment_status_text": "已支付", + "total_amount": 9900, + "payment_method": "wallet", + "paid_at": "2025-01-01T10:00:00Z", + "generation": 2, + "items": [ + { + "package_name": "30天1GB套餐", + "quantity": 1, + "unit_price": 9900, + "amount": 9900 + } + ], + "created_at": "2025-01-01T09:58:00Z" + } + ] + }, + "previous_generations": [ + { + "generation": 1, + "identifier": "VNO-000", + "asset_type": "card", + "exchange_no": "EX-20241201-001", + "exchanged_at": "2024-12-01T10:00:00Z", + "total": 1, + "items": [...] + } + ], + "truncated": false + } +} +``` + +**注意事项:** +- `previous_generations` 仅在 `include_previous=true` 时返回,否则字段不存在 +- `truncated: true` 表示换货链超过 10 代,已截断,前代数据不完整 +- 前代订单每代最多返回 20 条(不分页) +- 依赖提案一(`asset-identifier-standardization`)中的 `Order.asset_identifier` 快照字段 + +--- + +## 8. 行为变更:导入接口 virtual_no 必填 + +> **来源提案**:`import-mandatory-virtual-no`(无 Schema 结构变化,仅行为变更) + +### `POST /api/admin/iot-cards/import` — BREAKING + +| 场景 | 旧行为 | 新行为 | +|---|---|---| +| Excel 缺少 `virtual_no` 列 | 正常导入,卡的 `virtual_no` 存空字符串 | **整批失败**,任务状态=失败,错误:"Excel 文件缺少 virtual_no 列,请使用最新模板" | +| 某行 `virtual_no` 为空 | 该行导入成功 | 该行计入 `fail_count`,`failed_items` 含原因:"虚拟号(virtual_no)不能为空" | +| `virtual_no` 重复 | 无变化 | 无变化 | + +> IoT 卡导入 Excel 模板**必须新增 `virtual_no` 列**,否则全批失败。 + +### `POST /api/admin/devices/import` — 统计语义变更 + +| 场景 | 旧行为 | 新行为 | +|---|---|---| +| 某行 `virtual_no` 为空 | 计入 `skip_count`,无失败详情 | 计入 `fail_count`,`failed_items` 含原因:"设备虚拟号(virtual_no)不能为空" | + +> 前端若有"跳过了 N 行设备"的提示文案,需同步调整为失败处理逻辑。 + +--- + +## 前端迁移清单 + +### asset-identifier-standardization(必须改) +- [ ] 将 `/assets/:asset_type/:id/` 系列 URL 改为 `/assets/:identifier/`,传 ICCID 或 VirtualNo +- [ ] 停复机不再区分卡/设备,统一调 `/assets/:identifier/stop` 和 `/assets/:identifier/start` +- [ ] 停用不再区分 `/iot-cards/:id/deactivate` 和 `/devices/:id/deactivate`,统一调 `/assets/:identifier/deactivate` +- [ ] 设备管理接口将 `/:id` 改为 `/:virtual_no`,解绑卡将 `/:cardId` 改为 `/:iccid` +- [ ] 创建订单请求体移除 `order_type`、`iot_card_id`、`device_id`,改传 `identifier` +- [ ] 订单列表可通过 `?identifier=xxx` 过滤指定资产的历史订单 +- [ ] 展示订单详情时可直接读取 `asset_identifier` 字段,无需额外查询资产 + +### asset-historical-orders(新功能) +- [ ] 资产详情页接入 `GET /api/admin/assets/:identifier/orders` 展示历史订单 +- [ ] 换货资产可通过 `?include_previous=true` 追溯前代购买记录 + +### import-mandatory-virtual-no(需同步) +- [ ] 更新 IoT 卡导入 Excel 模板,必须包含 `virtual_no` 列 +- [ ] 导入结果展示逻辑:设备导入"跳过行"统计移至"失败行",并展示原因 diff --git a/docs/前端接口变更通知.md b/docs/前端接口变更通知.md new file mode 100644 index 0000000..9f78043 --- /dev/null +++ b/docs/前端接口变更通知.md @@ -0,0 +1,129 @@ +前端接口变更通知 + +背景 & 原因 + +平台需要展示代理的\*\*预充值钱包(主钱包)\*\*余额与流水,原来这部分数据完全不可见。同时,代理的佣金相关接口散落在 /my/ 路径下,与平台统一的 /shops/:id/ 资源路径存在职责重叠,本次统一收拢到 /shops/ 下。 + + +--- + +一、BREAKING CHANGE — 必须迁移 + + +1. 概况列表接口改造 + +┌──────────────┬──────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────┐ │ │ 旧 │ 新 │ ├──────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤ │ 路径 │ GET /api/admin/shops/commission-summary │ GET /api/admin/shops/fund-summary │ ├──────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤ │ 入参 │ 完全相同(page, page_size, shop_name, username) │ 无变化 │ ├──────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤ │ 响应新增字段 │ — │ main_balance(预充值余额,分)main_frozen_balance(预充值冻结余额,分) │ ├──────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────┤ │ 响应删除字段 │ — │ 无 │ └──────────────┴──────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────┘ + +旧响应 items 字段(已废弃 DTO ShopCommissionSummaryItem)→ 新 DTO ShopFundSummaryItem: + +{ "shop_id": 1, "shop_name": "代理A", "shop_code": "A001", "username": "agent_a", "phone": "138xxxx", + +* "main_balance": 200000, // 新增:预充值钱包余额(分) +* "main_frozen_balance": 0, // 新增:预充值冻结余额(分,当前均为0) "total_commission": 50000, "withdrawn_commission": 10000, "unwithdraw_commission": 30000, "frozen_commission": 5000, "withdrawing_commission": 5000, "available_commission": 30000, "created_at": "2025-01-01T00:00:00Z" } + +▎ 操作:把所有调用 /commission-summary 的地方改为 /fund-summary,同时在 UI 上新增"预充值余额"列。 + + +--- + + +2. 废弃的 /my/ 接口 — 全部删除,必须切换 + +┌────────────────────────────────┬─────────────────────────────────────────────┬─────────────────────────────────────────────┐ │ 废弃路由 │ 替代路由 │ 变化 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ GET /my/commission-summary │ GET /shops/fund-summary │ 见上方,返回结构有变化 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ GET /my/withdrawal-requests │ GET /shops/{shop_id}/withdrawal-requests │ 入参、响应完全一致,只需把 shop_id 放进路径 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ GET /my/commission-records │ GET /shops/{shop_id}/commission-records │ 入参、响应完全一致,只需把 shop_id 放进路径 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ GET /my/commission-stats │ GET /shops/{shop_id}/commission-stats │ 见下方详情 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ GET /my/commission-daily-stats │ GET /shops/{shop_id}/commission-daily-stats │ 见下方详情 │ ├────────────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┤ │ POST /my/withdrawal-requests │ POST /shops/{shop_id}/withdrawal-requests │ 见下方详情 │ └────────────────────────────────┴─────────────────────────────────────────────┴─────────────────────────────────────────────┘ + +▎ 旧 /my/ 接口已从服务端完全删除,调用会 404。 + + +--- + +二、新增接口详情 + +GET /api/admin/shops/{shop_id}/commission-stats + +替代 GET /my/commission-stats + +入参(Query): + +┌────────────┬────────┬──────────────────┐ │ 参数 │ 类型 │ 说明 │ ├────────────┼────────┼──────────────────┤ │ start_time │ string │ 开始时间(可选) │ ├────────────┼────────┼──────────────────┤ │ end_time │ string │ 结束时间(可选) │ └────────────┴────────┴──────────────────┘ + +▎ 旧接口的 shop_id query 参数已去掉,改为路径参数 {shop_id} + +响应(无变化): { "total_amount": 50000, "cost_diff_amount": 30000, "one_time_amount": 20000, "cost_diff_percent": 600, "one_time_percent": 400, "total_count": 15, "cost_diff_count": 10, "one_time_count": 5 } + + +--- + +GET /api/admin/shops/{shop_id}/commission-daily-stats + +替代 GET /my/commission-daily-stats + +入参(Query): + +┌────────────┬────────┬───────────────────────────────────┐ │ 参数 │ 类型 │ 说明 │ ├────────────┼────────┼───────────────────────────────────┤ │ start_date │ string │ 开始日期 YYYY-MM-DD(可选) │ ├────────────┼────────┼───────────────────────────────────┤ │ end_date │ string │ 结束日期 YYYY-MM-DD(可选) │ ├────────────┼────────┼───────────────────────────────────┤ │ days │ int │ 查询天数,默认30,最大365(可选) │ └────────────┴────────┴───────────────────────────────────┘ + +响应(无变化): \[ { "date": "2025-04-08", "total_amount": 10000, "total_count": 3 }, { "date": "2025-04-07", "total_amount": 5000, "total_count": 2 } \] + + +--- + +POST /api/admin/shops/{shop_id}/withdrawal-requests + +替代 POST /my/withdrawal-requests + +Body(无变化): { "amount": 10000, "withdrawal_method": "alipay", "account_name": "张三", "account_number": "138xxxx" } + +权限变化(重要): + +* 仅代理账号可调用,平台账号调用返回 403 仅代理商用户可发起提现 +* 只能为自己的 shop_id 提现,topLevel 代理不能替下级提现,否则返回 403 仅可为本人店铺发起提现 + + +--- + +GET /api/admin/shops/{shop_id}/main-wallet/transactions ✨ 全新 + +预充值钱包流水列表(此前无此功能) + +入参(Query): + +┌──────────────────┬────────┬────────────────────────────────────────────────────────────────────────┐ │ 参数 │ 类型 │ 说明 │ ├──────────────────┼────────┼────────────────────────────────────────────────────────────────────────┤ │ page │ int │ 页码,默认1 │ ├──────────────────┼────────┼────────────────────────────────────────────────────────────────────────┤ │ page_size │ int │ 每页数量,默认20,最大100 │ ├──────────────────┼────────┼────────────────────────────────────────────────────────────────────────┤ │ transaction_type │ string │ 交易类型过滤:recharge(充值入账)/ deduct(套餐扣款)/ refund(退款) │ ├──────────────────┼────────┼────────────────────────────────────────────────────────────────────────┤ │ start_date │ string │ 开始日期 YYYY-MM-DD │ ├──────────────────┼────────┼────────────────────────────────────────────────────────────────────────┤ │ end_date │ string │ 结束日期 YYYY-MM-DD │ └──────────────────┴────────┴────────────────────────────────────────────────────────────────────────┘ + +响应: { "items": \[ { "id": 1, "transaction_type": "recharge", "transaction_subtype": "", "amount": 50000, "balance_before": 150000, "balance_after": 200000, "remark": "线下充值", "created_at": "2025-04-08T10:00:00Z" } \], "total": 3, "page": 1, "size": 20 } + +▎ amount 正数为入账,负数为扣款,单位:分 + + +--- + +三、数据权限说明(前端需了解) + +两种角色访问同一套接口,后端自动过滤数据: + +┌──────────┬─────────────────────────┬──────────────────────────────────────────┐ │ 角色 │ /shops/fund-summary │ /shops/{shop_id}/... │ ├──────────┼─────────────────────────┼──────────────────────────────────────────┤ │ 平台账号 │ 返回所有代理店铺 │ 可查任意 shop_id │ ├──────────┼─────────────────────────┼──────────────────────────────────────────┤ │ 代理账号 │ 返回自己 + 所有下级店铺 │ 只能查自己和下级的 shop_id,其他返回 403 │ └──────────┴─────────────────────────┴──────────────────────────────────────────┘ + +提现操作额外限制:代理账号只能为自己的 shop_id 发起提现,即使是上级代理也不能替下级操作。 + + +--- + +四、变更全景图 + +变更前 变更后 ────────────────────────────────────────────────────────────────────── GET /shops/commission-summary → GET /shops/fund-summary ★ 改路径 + 新增字段 GET /shops/:id/withdrawal-requests GET /shops/:id/withdrawal-requests (不变) GET /shops/:id/commission-records GET /shops/:id/commission-records (不变) → GET /shops/:id/commission-stats ★ 新增 → GET /shops/:id/commission-daily-stats ★ 新增 → POST /shops/:id/withdrawal-requests ★ 新增 → GET /shops/:id/main-wallet/transactions ★ 新增(全新功能) + +GET /my/commission-summary × 已删除 GET /my/withdrawal-requests × 已删除 GET /my/commission-records × 已删除 GET /my/commission-stats × 已删除 GET /my/commission-daily-stats × 已删除 POST /my/withdrawal-requests × 已删除 + + +--- + +五、前端改造核实清单 + +* 将 GET /shops/commission-summary → 改为 GET /shops/fund-summary,UI 新增"预充值余额"列 +* 代理侧"我的余额概览"调用改为 GET /shops/fund-summary(不再有独立的 /my/commission-summary) +* 代理侧"提现记录"改为 GET /shops/{自己shopID}/withdrawal-requests +* 代理侧"佣金明细"改为 GET /shops/{自己shopID}/commission-records +* 代理侧"佣金统计"改为 GET /shops/{自己shopID}/commission-stats(去掉 query 里的 shop_id) +* 代理侧"每日统计"改为 GET /shops/{自己shopID}/commission-daily-stats(去掉 query 里的 shop_id) +* 代理侧"发起提现"改为 POST /shops/{自己shopID}/withdrawal-requests(shop_id 进路径,body 不变) +* 新建"预充值钱包流水"页面,调用 GET /shops/{shopID}/main-wallet/transactions + +\ diff --git a/src/api/assets.ts b/src/api/assets.ts index 44b0c63..b948391 100644 --- a/src/api/assets.ts +++ b/src/api/assets.ts @@ -1,7 +1,7 @@ /** * 资产模块 API */ -import { get, post } from '@/utils/request' +import { get, post, patch } from '@/utils/request' /** * 资产类型 @@ -139,13 +139,22 @@ export interface HistoryRecord { } /** - * 操作参数 + * 操作参数 (旧版,使用 ID) + * @deprecated 使用 AssetOperationParams 代替 */ export interface OperationParams { id: string reason?: string } +/** + * 操作参数 (新版,使用 identifier) + */ +export interface AssetOperationParams { + identifier: string + reason?: string +} + /** * 资产解析 (智能识别) * GET /api/admin/assets/resolve/:identifier @@ -156,7 +165,8 @@ export function resolveAsset(identifier: string) { /** * 获取资产详情 - * GET /api/admin/assets/:type/:id + * GET /api/admin/assets/:identifier (已废弃 type/id 格式) + * @deprecated 使用 identifier 代替,路由: GET /api/admin/assets/:identifier */ export function getAssetDetail(type: AssetType, id: string) { return get(`/api/admin/assets/${type}/${id}`) @@ -164,7 +174,7 @@ export function getAssetDetail(type: AssetType, id: string) { /** * 获取卡片详情 - * GET /api/admin/cards/:id + * @deprecated 请使用 resolveAsset 通过 ICCID 查询 */ export function getCardDetail(id: string) { return get(`/api/admin/cards/${id}`) @@ -172,10 +182,11 @@ export function getCardDetail(id: string) { /** * 获取设备详情 - * GET /api/admin/devices/:id + * GET /api/admin/devices/:virtual_no + * @param virtualNo 设备虚拟号 */ -export function getDeviceDetail(id: string) { - return get(`/api/admin/devices/${id}`) +export function getDeviceDetail(virtualNo: string) { + return get(`/api/admin/devices/${virtualNo}`) } /** @@ -243,10 +254,11 @@ export interface AssetRealtimeStatus { /** * 获取资产实时状态 - * GET /api/admin/assets/:asset_type/:id/realtime-status + * GET /api/admin/assets/:identifier/realtime-status + * @param identifier ICCID 或 VirtualNo */ -export function getAssetRealtimeStatus(assetType: AssetType, id: number) { - return get(`/api/admin/assets/${assetType}/${id}/realtime-status`) +export function getAssetRealtimeStatus(identifier: string) { + return get(`/api/admin/assets/${identifier}/realtime-status`) } /** @@ -275,41 +287,44 @@ export interface AssetPackage { /** * 获取资产套餐列表 - * GET /api/admin/assets/:asset_type/:id/packages + * GET /api/admin/assets/:identifier/packages + * @param identifier ICCID 或 VirtualNo */ -export function getAssetPackages(assetType: AssetType, id: number, params?: { page?: number, page_size?: number }) { +export function getAssetPackages(identifier: string, params?: { page?: number, page_size?: number }) { return get<{ items: AssetPackage[] page: number page_size: number total: number - }>(`/api/admin/assets/${assetType}/${id}/packages`, { params }) + }>(`/api/admin/assets/${identifier}/packages`, { params }) } /** * 获取当前生效套餐 - * GET /api/admin/assets/:asset_type/:id/current-package + * GET /api/admin/assets/:identifier/current-package + * @param identifier ICCID 或 VirtualNo */ -export function getCurrentPackage(assetType: AssetType, id: number) { - return get(`/api/admin/assets/${assetType}/${id}/current-package`) +export function getCurrentPackage(identifier: string) { + return get(`/api/admin/assets/${identifier}/current-package`) } /** * 获取资产历史记录 - * GET /api/admin/assets/:type/:id/history + * GET /api/admin/assets/:identifier/history + * @param identifier ICCID 或 VirtualNo */ -export function getAssetHistory(type: AssetType, id: string, params?: { page?: number, pageSize?: number }) { +export function getAssetHistory(identifier: string, params?: { page?: number, pageSize?: number }) { return get<{ list: HistoryRecord[] total: number page: number pageSize: number - }>(`/api/admin/assets/${type}/${id}/history`, { params }) + }>(`/api/admin/assets/${identifier}/history`, { params }) } /** * 停用卡片 - * POST /api/admin/cards/:id/stop + * @deprecated 使用 stopAsset 代替,路由: POST /api/admin/assets/:identifier/stop */ export function stopCard(data: OperationParams) { return post(`/api/admin/cards/${data.id}/stop`, { @@ -319,7 +334,7 @@ export function stopCard(data: OperationParams) { /** * 启用卡片 - * POST /api/admin/cards/:id/start + * @deprecated 使用 startAsset 代替,路由: POST /api/admin/assets/:identifier/start */ export function startCard(data: OperationParams) { return post(`/api/admin/cards/${data.id}/start`, { @@ -329,21 +344,23 @@ export function startCard(data: OperationParams) { /** * 停用设备 - * POST /api/admin/devices/:id/stop + * POST /api/admin/devices/:virtual_no/stop + * @param virtualNo 设备虚拟号 */ -export function stopDevice(data: OperationParams) { - return post(`/api/admin/devices/${data.id}/stop`, { - data: { reason: data.reason }, +export function stopDevice(virtualNo: string, reason?: string) { + return post(`/api/admin/devices/${virtualNo}/stop`, { + data: { reason }, }) } /** * 启用设备 - * POST /api/admin/devices/:id/start + * POST /api/admin/devices/:virtual_no/start + * @param virtualNo 设备虚拟号 */ -export function startDevice(data: OperationParams) { - return post(`/api/admin/devices/${data.id}/start`, { - data: { reason: data.reason }, +export function startDevice(virtualNo: string, reason?: string) { + return post(`/api/admin/devices/${virtualNo}/start`, { + data: { reason }, }) } @@ -367,7 +384,7 @@ export interface DeviceStopResponse { /** * 设备停机 (批量停机设备下所有已实名卡) - * POST /api/admin/assets/device/:device_id/stop + * @deprecated 使用 stopAsset 代替,路由: POST /api/admin/assets/:identifier/stop */ export function stopDeviceAsset(deviceId: number) { return post(`/api/admin/assets/device/${deviceId}/stop`) @@ -375,7 +392,7 @@ export function stopDeviceAsset(deviceId: number) { /** * 设备复机 (批量复机设备下所有已实名卡) - * POST /api/admin/assets/device/:device_id/start + * @deprecated 使用 startAsset 代替,路由: POST /api/admin/assets/:identifier/start */ export function startDeviceAsset(deviceId: number) { return post(`/api/admin/assets/device/${deviceId}/start`) @@ -383,7 +400,7 @@ export function startDeviceAsset(deviceId: number) { /** * 单卡停机 (通过ICCID) - * POST /api/admin/assets/card/:iccid/stop + * @deprecated 使用 stopAsset 代替,路由: POST /api/admin/assets/:identifier/stop */ export function stopCardByIccid(iccid: string) { return post(`/api/admin/assets/card/${iccid}/stop`) @@ -391,8 +408,135 @@ export function stopCardByIccid(iccid: string) { /** * 单卡复机 (通过ICCID) - * POST /api/admin/assets/card/:iccid/start + * @deprecated 使用 startAsset 代替,路由: POST /api/admin/assets/:identifier/start */ export function startCardByIccid(iccid: string) { return post(`/api/admin/assets/card/${iccid}/start`) } + +/** + * 统一停机接口 (卡/设备) + * POST /api/admin/assets/:identifier/stop + * @param identifier ICCID 或 VirtualNo + * @param reason 停机原因 + */ +export function stopAsset(identifier: string, reason?: string) { + return post(`/api/admin/assets/${identifier}/stop`, { + data: { reason }, + }) +} + +/** + * 统一复机接口 (卡/设备) + * POST /api/admin/assets/:identifier/start + * @param identifier ICCID 或 VirtualNo + * @param reason 复机原因 + */ +export function startAsset(identifier: string, reason?: string) { + return post(`/api/admin/assets/${identifier}/start`, { + data: { reason }, + }) +} + +/** + * 统一停用接口 (卡/设备) + * POST /api/admin/assets/:identifier/deactivate + * @param identifier ICCID 或 VirtualNo + */ +export function deactivateAsset(identifier: string) { + return post(`/api/admin/assets/${identifier}/deactivate`) +} + +/** + * 资产钱包信息 + * GET /api/admin/assets/:identifier/wallet + * @param identifier ICCID 或 VirtualNo + */ +export function getAssetWallet(identifier: string) { + return get<{ + available_balance: number + frozen_balance: number + total_balance: number + }>(`/api/admin/assets/${identifier}/wallet`) +} + +/** + * 资产钱包交易记录 + * GET /api/admin/assets/:identifier/wallet/transactions + * @param identifier ICCID 或 VirtualNo + */ +export function getAssetWalletTransactions(identifier: string, params?: { page?: number, page_size?: number }) { + return get<{ + items: Array<{ + id: number + type: string + amount: number + balance_after: number + remark?: string + created_at: string + }> + page: number + page_size: number + total: number + }>(`/api/admin/assets/${identifier}/wallet/transactions`, { params }) +} + +/** + * 更新资产轮询状态 + * PATCH /api/admin/assets/:identifier/polling-status + * @param identifier ICCID 或 VirtualNo + */ +export function updatePollingStatus(identifier: string, enable: boolean) { + return patch(`/api/admin/assets/${identifier}/polling-status`, { + data: { enable_polling: enable }, + }) +} + +/** + * 资产历史订单 + * GET /api/admin/assets/:identifier/orders + * @param identifier ICCID 或 VirtualNo + * @param params 查询参数 + */ +export function getAssetOrders(identifier: string, params?: { + page?: number + page_size?: number + include_previous?: boolean +}) { + return get<{ + current_generation: { + generation: number + identifier: string + asset_type: string + total: number + page: number + page_size: number + items: Array<{ + order_no: string + order_type: string + payment_status: number + payment_status_text: string + total_amount: number + payment_method: string + paid_at?: string + generation: number + items: Array<{ + package_name: string + quantity: number + unit_price: number + amount: number + }> + created_at: string + }> + } + previous_generations?: Array<{ + generation: number + identifier: string + asset_type: string + exchange_no: string + exchanged_at: string + total: number + }> + truncated?: boolean + }>(`/api/admin/assets/${identifier}/orders`, { params }) +} diff --git a/src/api/commission.ts b/src/api/commission.ts index a29740b..7f98077 100644 --- a/src/api/commission.ts +++ b/src/api/commission.ts @@ -4,7 +4,29 @@ import { get, post } from '@/utils/request' /** - * 佣金概览 + * 资金概览 (代理端主页用) + * GET /api/admin/shops/fund-summary + */ +export interface FundSummary { + shop_id: number + shop_name: string + shop_code: string + username: string + phone: string + main_balance: number // 预充值钱包余额(分) + main_frozen_balance: number // 预充值冻结余额(分) + total_commission: number // 累计佣金(分) + available_commission: number // 可提现佣金(分) + frozen_commission: number // 冻结佣金(分) + unwithdraw_commission: number // 未提现佣金(分) + withdrawing_commission: number // 提现中金额(分) + withdrawn_commission: number // 已提现佣金(分) + created_at: string +} + +/** + * 佣金概览 (旧接口,仅保留类型定义) + * @deprecated 使用 FundSummary 代替 */ export interface CommissionSummary { shop_id: number @@ -67,24 +89,47 @@ export interface CommissionRecordsParams { } /** - * 佣金统计查询参数 + * 佣金统计查询参数 (新接口,shop_id 在路径中) */ export interface CommissionStatsParams { - shop_id?: number start_time?: string end_time?: string } /** - * 每日佣金统计查询参数 + * 每日佣金统计查询参数 (新接口,shop_id 在路径中) */ export interface DailyCommissionStatsParams { - shop_id?: number start_date?: string // YYYY-MM-DD end_date?: string // YYYY-MM-DD days?: number // 查询天数(默认30,最大365) } +/** + * 预充值钱包交易记录 + */ +export interface WalletTransaction { + id: number + transaction_type: string // 交易类型: recharge | deduct | refund + transaction_subtype: string + amount: number // 金额(分),正数为入账,负数为扣款 + balance_before: number // 余额变动前(分) + balance_after: number // 余额变动后(分) + remark?: string // 备注 + created_at: string // 创建时间 +} + +/** + * 预充值钱包交易列表参数 + */ +export interface WalletTransactionsParams { + page?: number + page_size?: number + transaction_type?: string // 交易类型: recharge | deduct | refund + start_date?: string // YYYY-MM-DD + end_date?: string // YYYY-MM-DD +} + /** * 列表响应 */ @@ -95,34 +140,63 @@ export interface ListResponse { total: number } +/** + * 获取资金概览 (代理端主页用) + * GET /api/admin/shops/fund-summary + */ +export function getFundSummary() { + return get<{ items: FundSummary[] }>('/api/admin/shops/fund-summary').then(res => res.items?.[0]) +} + /** * 获取我的佣金概览 - * GET /api/admin/my/commission-summary + * @deprecated 使用 getFundSummary 代替 + * GET /api/admin/shops/{shop_id}/commission-summary */ export function getCommissionSummary() { - return get('/api/admin/my/commission-summary') + return get('/api/admin/shops/1/commission-summary') } /** * 获取我的佣金明细 - * GET /api/admin/my/commission-records + * GET /api/admin/shops/{shop_id}/commission-records + * @param shopId 店铺ID */ -export function getCommissionRecords(params?: CommissionRecordsParams) { - return get>('/api/admin/my/commission-records', { params }) +export function getCommissionRecords(shopId: number, params?: CommissionRecordsParams) { + return get>(`/api/admin/shops/${shopId}/commission-records`, { params }) } /** * 获取我的佣金统计 - * GET /api/admin/my/commission-stats + * GET /api/admin/shops/{shop_id}/commission-stats + * @param shopId 店铺ID + * @param params 查询参数 */ -export function getCommissionStats(params?: CommissionStatsParams) { - return get('/api/admin/my/commission-stats', { params }) +export function getCommissionStats(shopId: number, params?: CommissionStatsParams) { + return get(`/api/admin/shops/${shopId}/commission-stats`, { params }) } /** * 获取我的每日佣金统计 - * GET /api/admin/my/commission-daily-stats + * GET /api/admin/shops/{shop_id}/commission-daily-stats + * @param shopId 店铺ID + * @param params 查询参数 */ -export function getCommissionDailyStats(params?: DailyCommissionStatsParams) { - return get('/api/admin/my/commission-daily-stats', { params }) +export function getCommissionDailyStats(shopId: number, params?: DailyCommissionStatsParams) { + return get(`/api/admin/shops/${shopId}/commission-daily-stats`, { params }) +} + +/** + * 获取预充值钱包流水 + * GET /api/admin/shops/{shop_id}/main-wallet/transactions + * @param shopId 店铺ID + * @param params 查询参数 + */ +export function getMainWalletTransactions(shopId: number, params?: WalletTransactionsParams) { + return get<{ + items: WalletTransaction[] + total: number + page: number + size: number + }>(`/api/admin/shops/${shopId}/main-wallet/transactions`, { params }) } diff --git a/src/api/withdrawal.ts b/src/api/withdrawal.ts index e5ec73b..9747eb9 100644 --- a/src/api/withdrawal.ts +++ b/src/api/withdrawal.ts @@ -74,16 +74,20 @@ export interface ListResponse { /** * 发起提现申请 - * POST /api/admin/my/withdrawal-requests + * POST /api/admin/shops/{shop_id}/withdrawal-requests + * @param shopId 店铺ID + * @param data 提现申请参数 */ -export function createWithdrawal(data: WithdrawalCreateParams) { - return post('/api/admin/my/withdrawal-requests', { data }) +export function createWithdrawal(shopId: number, data: WithdrawalCreateParams) { + return post(`/api/admin/shops/${shopId}/withdrawal-requests`, { data }) } /** - * 获取我的提现记录 - * GET /api/admin/my/withdrawal-requests + * 获取提现记录 + * GET /api/admin/shops/{shop_id}/withdrawal-requests + * @param shopId 店铺ID + * @param params 查询参数 */ -export function getWithdrawalRecords(params?: WithdrawalListParams) { - return get>('/api/admin/my/withdrawal-requests', { params }) +export function getWithdrawalRecords(shopId: number, params?: WithdrawalListParams) { + return get>(`/api/admin/shops/${shopId}/withdrawal-requests`, { params }) } diff --git a/src/components/SimplePicker.vue b/src/components/SimplePicker.vue index 1030610..f4d9072 100644 --- a/src/components/SimplePicker.vue +++ b/src/components/SimplePicker.vue @@ -176,7 +176,7 @@ function selectOption(index: number) { } .simple-picker-item-active .simple-picker-item-text { - color: var(--brand-color, #ff6700); + color: var(--brand-primary, #1677ff); font-weight: 600; } diff --git a/src/components/Skeleton.vue b/src/components/Skeleton.vue index 0f3ad22..ad324ce 100644 --- a/src/components/Skeleton.vue +++ b/src/components/Skeleton.vue @@ -2,27 +2,35 @@ - - - - - + + + + + + + + + - - - + + + - - + + - - + + + + + + @@ -30,8 +38,8 @@ - - + + diff --git a/src/pages/agent-system/asset-detail/index.vue b/src/pages/agent-system/asset-detail/index.vue index 981d133..1aff7ac 100644 --- a/src/pages/agent-system/asset-detail/index.vue +++ b/src/pages/agent-system/asset-detail/index.vue @@ -1,13 +1,13 @@ @@ -459,7 +449,7 @@ function viewWallet() { {{ currentPackage.package_name || '-' }} - + 已用: {{ currentPackage.virtual_used_mb || 0 }}MB / 总量: {{ currentPackage.virtual_limit_mb || 0 }}MB @@ -546,7 +536,7 @@ function viewWallet() { transition-all duration-200 active:opacity-80 " - @click="stopAsset" + @click="handleStopAsset" > @@ -562,7 +552,7 @@ function viewWallet() { transition-all duration-200 active:opacity-80 " - @click="startAsset" + @click="handleStartAsset" > diff --git a/src/pages/agent-system/asset-search/index.vue b/src/pages/agent-system/asset-search/index.vue index a996e25..874a868 100644 --- a/src/pages/agent-system/asset-search/index.vue +++ b/src/pages/agent-system/asset-search/index.vue @@ -17,7 +17,7 @@ // 套餐列表 const packageList = ref([]) // 是否展开套餐列表 - const showPackageList = ref(false) + const showPackageList = ref(true) // 是否为卡片 const isCard = computed(() => assetType.value === 'card') @@ -39,10 +39,11 @@ assetType.value = result.asset_type assetInfo.value = result - // 加载实时状态和当前套餐 - if (result.asset_type && result.asset_id) { - loadRealtimeStatus(result.asset_type, result.asset_id) - loadCurrentPackage(result.asset_type, result.asset_id) + // 加载实时状态和当前套餐 (使用 identifier) + if (searchKeyword.value.trim()) { + loadRealtimeStatus(searchKeyword.value.trim()) + loadCurrentPackage(searchKeyword.value.trim()) + loadPackageList(searchKeyword.value.trim()) } } catch (error : any) { console.error('查询失败:', error) @@ -53,9 +54,9 @@ } // 加载实时状态 - async function loadRealtimeStatus(type : 'card' | 'device', id : number) { + async function loadRealtimeStatus(identifier : string) { try { - const status = await getAssetRealtimeStatus(type, id) + const status = await getAssetRealtimeStatus(identifier) realtimeStatus.value = status } catch (error : any) { console.error('加载实时状态失败:', error) @@ -63,10 +64,10 @@ } // 加载当前套餐 - async function loadCurrentPackage(type : 'card' | 'device', id : number) { + async function loadCurrentPackage(identifier : string) { try { - console.log('开始加载当前套餐:', type, id) - const pkg = await getCurrentPackage(type, id) + console.log('开始加载当前套餐:', identifier) + const pkg = await getCurrentPackage(identifier) console.log('当前套餐数据:', pkg) currentPackage.value = pkg } catch (error : any) { @@ -77,10 +78,10 @@ } // 加载套餐列表 - async function loadPackageList(type : 'card' | 'device', id : number) { + async function loadPackageList(identifier : string) { try { - console.log('开始加载套餐列表:', type, id) - const response = await getAssetPackages(type, id, { page: 1, page_size: 50 }) + console.log('开始加载套餐列表:', identifier) + const response = await getAssetPackages(identifier, { page: 1, page_size: 50 }) console.log('套餐列表数据:', response) packageList.value = response?.items || [] } catch (error : any) { @@ -93,8 +94,8 @@ async function togglePackageList() { showPackageList.value = !showPackageList.value // 第一次展开时加载套餐列表 - if (showPackageList.value && packageList.value.length === 0 && assetType.value && assetInfo.value?.asset_id) { - await loadPackageList(assetType.value, assetInfo.value.asset_id) + if (showPackageList.value && packageList.value.length === 0 && searchKeyword.value.trim()) { + await loadPackageList(searchKeyword.value.trim()) } } @@ -325,9 +326,9 @@ - + - 电话号码 + msisdn {{ cardInfo.msisdn }} @@ -376,7 +377,7 @@ 累计充值 - + ¥{{ cardInfo.accumulated_recharge }} @@ -424,7 +425,7 @@ 本月用量 - + {{ realtimeStatus.current_month_usage_mb !== null && realtimeStatus.current_month_usage_mb !== undefined ? formatDataSize(realtimeStatus.current_month_usage_mb) @@ -495,7 +496,7 @@ {{ currentPackage.package_name }} @@ -564,7 +565,7 @@ {{ pkg.package_name }} (加油包) @@ -697,7 +698,7 @@ 绑定卡数 - + {{ deviceInfo.bound_card_count }} 张 @@ -753,7 +754,7 @@ 累计充值 - + ¥{{ deviceInfo.accumulated_recharge }} @@ -876,7 +877,7 @@ 今日用量 - {{ formatBytes(realtimeStatus.device_realtime.daily_usage) }} + {{ formatBytes(realtimeStatus.device_realtime.daily_usage) }} @@ -1017,7 +1018,7 @@ {{ currentPackage.package_name }} @@ -1086,7 +1087,7 @@ {{ pkg.package_name }} (加油包) diff --git a/src/pages/agent-system/asset-wallet/index.vue b/src/pages/agent-system/asset-wallet/index.vue index 7169aa7..7c55db4 100644 --- a/src/pages/agent-system/asset-wallet/index.vue +++ b/src/pages/agent-system/asset-wallet/index.vue @@ -1,99 +1,99 @@ diff --git a/src/pages/agent-system/assets/index.vue b/src/pages/agent-system/assets/index.vue index a05aeec..63c24c2 100644 --- a/src/pages/agent-system/assets/index.vue +++ b/src/pages/agent-system/assets/index.vue @@ -5,8 +5,7 @@ import type { UserInfo } from '@/api/auth' import { getEnterpriseCards, getEnterpriseDevices } from '@/api/enterprise' import { getCarriers } from '@/api/carrier' import type { CarrierInfo } from '@/api/carrier' -import { stopDeviceAsset, startDeviceAsset, stopCardByIccid, startCardByIccid } from '@/api/assets' -import type { DeviceStopResponse } from '@/api/assets' +import { stopAsset, startAsset } from '@/api/assets' import Skeleton from '@/components/Skeleton.vue' import SimplePicker from '@/components/SimplePicker.vue' import { formatTime, formatDataSize } from '@/utils/format' @@ -404,10 +403,9 @@ async function handleStopDevice(asset: AssetItem, event: Event) { event.stopPropagation() const device = asset.raw as DeviceInfo - const deviceId = device.id || device.device_id - if (!deviceId) { - uni.$u.toast('设备ID不存在') + if (!device.virtual_no) { + uni.$u.toast('设备虚拟号不存在') return } @@ -418,14 +416,13 @@ async function handleStopDevice(asset: AssetItem, event: Event) { if (res.confirm) { uni.showLoading({ title: '停机中...' }) try { - const result = await stopDeviceAsset(Number(deviceId)) + const result = await stopAsset(device.virtual_no) uni.hideLoading() - // 显示停机结果 - const msg = `停机完成\n成功: ${result.success_count}张\n失败: ${result.fail_count}张\n跳过: ${result.skip_count}张` + // 显示停机结果 (统一接口不返回详情,仅提示成功) uni.showModal({ - title: '停机结果', - content: msg, + title: '停机成功', + content: '设备已停机', showCancel: false, success: () => { // 刷新列表 @@ -447,10 +444,9 @@ async function handleStartDevice(asset: AssetItem, event: Event) { event.stopPropagation() const device = asset.raw as DeviceInfo - const deviceId = device.id || device.device_id - if (!deviceId) { - uni.$u.toast('设备ID不存在') + if (!device.virtual_no) { + uni.$u.toast('设备虚拟号不存在') return } @@ -461,7 +457,7 @@ async function handleStartDevice(asset: AssetItem, event: Event) { if (res.confirm) { uni.showLoading({ title: '复机中...' }) try { - await startDeviceAsset(Number(deviceId)) + await startAsset(device.virtual_no) uni.hideLoading() uni.$u.toast('复机成功') // 刷新列表 @@ -494,7 +490,7 @@ async function handleStopCard(asset: AssetItem, event: Event) { if (res.confirm) { uni.showLoading({ title: '停机中...' }) try { - await stopCardByIccid(card.iccid) + await stopAsset(card.iccid) uni.hideLoading() uni.$u.toast('停机成功') // 刷新列表 @@ -527,7 +523,7 @@ async function handleStartCard(asset: AssetItem, event: Event) { if (res.confirm) { uni.showLoading({ title: '复机中...' }) try { - await startCardByIccid(card.iccid) + await startAsset(card.iccid) uni.hideLoading() uni.$u.toast('复机成功') // 刷新列表 @@ -682,135 +678,124 @@ onMounted(async () => { @scroll="onScroll" > - - - - - - - - - - - + + + + + + {{ asset.name }} - - {{ asset.detail }} - + + + {{ asset.type === 'card' ? 'IoT卡' : '设备' }} - - - {{ asset.type === 'card' ? 'IoT卡' : '设备' }} - - - - - - - - - - {{ asset.status }} + + + + {{ asset.detail }} - - - -