Files
junhong_cmp_fiber/docs/7月迭代/需求02-H5流程配置.md
2026-07-13 12:01:18 +09:00

212 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 需求02H5 流程顺序配置化
---
## 背景
H5 用户进入后:绑定手机号 → 充值 → 实名(当前顺序写死)
需求:允许**按资产个体**配置充值和实名的顺序,支持后台单条或批量改。
---
## 流程图
### 图一H5 登录后资产视角判断与策略读取
```mermaid
flowchart TD
A[用户扫码 / 输入虚拟号] --> B[解析 identifier]
B --> C{资产类型}
C -->|card| D{该卡是否绑定设备?}
D -->|否 独立卡| E[卡视角\n读 IotCard.realname_policy]
D -->|是| F[设备视角\n读 Device.realname_policy\n卡自身策略忽略]
C -->|device| F
E --> G{realname_policy}
F --> G
G -->|none| H[无需实名\n直接进充值页]
G -->|before_order| I[先进实名页\n实名完成后才能充值]
G -->|after_order| J[先进充值页\n充值完成后提示实名]
```
### 图二H5 充值/购买前的策略拦截逻辑
```mermaid
flowchart TD
A[用户发起充值/购买] --> B[读取 resolved.Asset.RealnamePolicy]
B --> C{策略是 before_order?}
C -->|否| D[放行,正常创建订单]
C -->|是| E{当前资产 RealNameStatus == 1?}
E -->|已实名| D
E -->|未实名| F[返回 CodeNeedRealname\nH5 跳转实名页]
```
### 图三GetEffectiveRealnamePolicy 取值逻辑
```mermaid
flowchart TD
A[GetEffectiveRealnamePolicy\ncard, device] --> B{device != nil?}
B -->|是| C[返回 device.RealnamePolicy]
B -->|否| D{card != nil?}
D -->|是| E[返回 card.RealnamePolicy]
D -->|否| F[返回 none]
```
---
## 资产类型与策略归属
系统有两类资产:**独立卡** 和 **设备**
| 资产类型 | realname_policy 归属 | H5 视角 |
|---------|---------------------|---------|
| 独立卡(无设备绑定) | 卡自身的 `realname_policy` | 卡视角 |
| 设备 | 设备自身的 `realname_policy` | 设备视角 |
| 设备下的卡 | **设备**的 `realname_policy`(卡自身策略无效) | 设备视角 |
**关键规则**:设备下的卡无法以卡视角独立登录 H5登录后自动进入设备视角因此实名流程策略由设备决定卡自身的 `realname_policy` 字段对 H5 流程无影响(但字段保留,仅作记录)。
该逻辑已在 `internal/service/asset/service.go:GetEffectiveRealnamePolicy()` 实现:设备不为 nil 时取设备策略,否则取卡策略。
---
## 当前字段状态
两个模型都已有 `realname_policy` 字段,无需迁移:
```go
// internal/model/iot_card.go
RealnamePolicy string `gorm:"column:realname_policy;type:varchar(20);default:'after_order';not null;
comment:实名认证策略(none=无需实名,before_order=先实名后充值/购买,after_order=先充值/购买后实名)"`
// internal/model/device.go
RealnamePolicy string `gorm:"column:realname_policy;type:varchar(20);default:'after_order';not null;
comment:实名认证策略(none=无需实名,before_order=先实名后充值/购买,after_order=先充值/购买后实名)"`
```
值含义:
- `none` — 无需实名
- `before_order` — 先实名后充值
- `after_order` — 先充值后实名(**当前默认**
---
## 后端实现
### 1. 单条修改接口(已有,无需新建)
```
PATCH /api/admin/assets/:identifier/realname-mode
```
该接口已在 `internal/handler/admin/asset.go:UpdateRealnamePolicy()` 实现,通过 identifier 自动解析资产类型,卡和设备都走这里,**不需要再建卡专属或设备专属路由**。
请求体(已有 DTO
```go
type UpdateAssetRealnamePolicyRequest struct {
RealnamePolicy string `json:"realname_policy" validate:"required,oneof=none before_order after_order"
description:"实名策略 (none:无需实名, before_order:先实名后充值, after_order:先充值后实名)"`
}
```
### 2. 新增批量修改接口(需新建)
卡和设备分开批量接口,因为两者在后台是不同的列表页。
#### 2a. 批量修改卡实名策略
```
POST /admin/iot-cards/batch-update-realname-policy
```
请求体:
```go
type BatchUpdateIotCardRealnamePolicy struct {
IotCardIDs []uint `json:"iot_card_ids" validate:"required,min=1" description:"卡ID列表"`
RealnamePolicy string `json:"realname_policy" validate:"required,oneof=none before_order after_order"
description:"实名策略 (none:无需实名, before_order:先实名后充值, after_order:先充值后实名)"`
}
```
Service`UPDATE tb_iot_cards SET realname_policy = ? WHERE id IN (...)`,逐条写审计日志。
#### 2b. 批量修改设备实名策略
```
POST /admin/devices/batch-update-realname-policy
```
请求体:
```go
type BatchUpdateDeviceRealnamePolicy struct {
DeviceIDs []uint `json:"device_ids" validate:"required,min=1" description:"设备ID列表"`
RealnamePolicy string `json:"realname_policy" validate:"required,oneof=none before_order after_order"
description:"实名策略 (none:无需实名, before_order:先实名后充值, after_order:先充值后实名)"`
}
```
Service`UPDATE tb_devices SET realname_policy = ? WHERE id IN (...)`,逐条写审计日志。
### 3. 全局默认值(兜底)
新建卡/设备时默认 `after_order`,通过 GORM default 标签保证,不需要读 `tb_system_config`
---
## 前端对接
### 卡列表页
"操作"列或批量操作下拉增加"设置实名策略"
- **单条**:弹框选策略 → `PATCH /api/admin/assets/{iccid}/realname-mode`
- **批量**:勾选多条 → 批量操作 → "设置实名策略" → `POST /admin/iot-cards/batch-update-realname-policy`
> 注意:设备下的卡即使在卡列表中修改了策略,对 H5 流程也无效H5 取设备策略)。建议在卡列表展示"所属设备"列,提示运营该卡已属于某设备,实名策略需到设备处修改。
### 设备列表页
"操作"列或批量操作下拉增加"设置实名策略"
- **单条**:弹框选策略 → `PATCH /api/admin/assets/{sn}/realname-mode`
- **批量**:勾选多条 → 批量操作 → "设置实名策略" → `POST /admin/devices/batch-update-realname-policy`
### 字段展示
卡列表/详情、设备列表/详情均展示"实名策略"字段:
| realname_policy | 展示文案 |
|----------------|---------|
| `none` | 无需实名 |
| `before_order` | 先实名后充值 |
| `after_order` | 先充值后实名 |
### H5 侧C端
H5 读取资产初始化接口返回的 `realname_policy` 字段,决定先跳充值页还是先跳实名页。
- 独立卡登录 → 读卡的 `realname_policy`
- 设备/设备下的卡登录 → 读设备的 `realname_policy`
该逻辑由 `GetEffectiveRealnamePolicy()` 统一处理H5 无需区分资产类型,直接用接口返回值即可。
---
## 实施范围汇总
| 项目 | 状态 | 说明 |
|------|------|------|
| `IotCard.realname_policy` 字段 | ✅ 已有 | 无需迁移 |
| `Device.realname_policy` 字段 | ✅ 已有 | 无需迁移 |
| 单条修改接口 | ✅ 已有 | `PATCH /api/admin/assets/:identifier/realname-mode` |
| `GetEffectiveRealnamePolicy()` | ✅ 已有 | 设备视角取设备策略 |
| H5 充值前校验 | ✅ 已有 | `client_wallet.go` 已正确读取 |
| 批量修改卡接口 | ❌ 待建 | `POST /admin/iot-cards/batch-update-realname-policy` |
| 批量修改设备接口 | ❌ 待建 | `POST /admin/devices/batch-update-realname-policy` |
| 后台卡列表操作入口 | ❌ 待建(前端) | 单条+批量 |
| 后台设备列表操作入口 | ❌ 待建(前端) | 单条+批量 |