5.3 KiB
5.3 KiB
需求10:Gateway 手动卡限速
状态:待评审 已确认边界:本期只提供手动设置/取消限速;Gateway 最终对象始终是卡,统一使用
cardNo。
一、范围
本期提供一个统一的后台能力:对一张实际联网卡设置或取消限速。
- 单卡资产:使用
IotCard.ICCID作为cardNo。 - 设备资产:查询
tb_device_sim_binding.is_current=true的当前绑定卡,再使用该卡 ICCID。 speed_kbps > 0表示设置限速;speed_kbps = 0表示取消限速。- 内部业务单位固定为
kbps,前端也按kbps输入和展示。
本期不做:
- 套餐限速字段或套餐编辑页限速配置。
- 套餐激活、到期、续费、停机、切卡后的自动限速或自动取消。
- 设备 IMEI 限速。
- “Gateway 当前实际限速”查询展示。上游未提供查询接口时,页面只能展示最近一次本系统操作记录。
取消限速仍调用同一个 Gateway 方法。speed_kbps=0 是本系统语义,Gateway 所需的取消报文仅在 Infrastructure 适配器中转换,不散落在 Handler、Service 或前端。
二、流程
sequenceDiagram
actor User as 平台员工
participant Web as 资产详情页
participant API as SpeedLimit Application
participant DB as PostgreSQL
participant Resolver as 当前卡解析器
participant Gateway as Gateway Adapter
User->>Web: 输入限速值或点击取消
Web->>API: asset identifier + speed_kbps + request_id
API->>Resolver: 解析实际 cardNo
Resolver-->>API: ICCID 或无当前卡错误
API->>DB: 创建或复用限速操作记录
API->>Gateway: SetSpeedLimit(cardNo, speedKbps)
Gateway-->>API: 成功或失败
API->>DB: 写结果、错误摘要和操作审计
API-->>Web: 返回本次操作结果
设备不存在当前绑定卡时,接口返回业务错误并记录失败原因;绝不把设备 IMEI、设备 ID 或空字符串发送给 Gateway。
三、应用端口与数据
// GatewaySpeedLimitPort 设置或取消卡限速。
// speedKbps=0 表示取消,具体上游参数由适配器转换。
type GatewaySpeedLimitPort interface {
SetSpeedLimit(ctx context.Context, cardNo string, speedKbps int) error
}
// SpeedLimitCardResolver 将卡或设备资产解析为实际联网卡 ICCID。
type SpeedLimitCardResolver interface {
ResolveCardNo(ctx context.Context, assetType string, assetID uint) (string, error)
}
新建操作记录表,既用于审计,也用于同一 request_id 的幂等重试:
CREATE TABLE tb_gateway_speed_limit_operation (
id BIGSERIAL PRIMARY KEY,
request_id VARCHAR(64) NOT NULL,
asset_type VARCHAR(20) NOT NULL,
asset_id BIGINT NOT NULL,
card_no VARCHAR(100) NOT NULL,
desired_speed_kbps INT NOT NULL,
status INT NOT NULL DEFAULT 1,
error_summary TEXT NOT NULL DEFAULT '',
operator_id BIGINT NOT NULL,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX uq_gateway_speed_limit_operation_request
ON tb_gateway_speed_limit_operation(request_id);
CREATE INDEX idx_gateway_speed_limit_operation_asset
ON tb_gateway_speed_limit_operation(asset_type, asset_id, created_at DESC);
状态:1=处理中, 2=成功, 3=失败。同一 request_id 重试时,任务、操作人、资产和目标限速一致才返回或继续原记录;不一致返回冲突。Gateway 网络超时后允许使用相同目标值重试,因为 SetSpeedLimit 是“设为目标状态”的幂等操作。
四、接口与前端
POST /api/admin/assets/{identifier}/speed-limit
{
"request_id": "01JZ...",
"speed_kbps": 1024
}
speed_kbps必须为整数且大于等于 0。- 取消操作提交
speed_kbps=0,不新增第二个取消接口。 - 后端根据
identifier解析资产类型和数据范围,前端不得传cardNo、设备 ID 或资产类型作为权威依据。
资产详情页提供两个独立命令:
- 数字输入框加“保存”用于设置限速,单位固定显示
kbps。 - 取消按钮用于提交
speed_kbps=0,并使用确认弹窗避免误操作。
设备详情页显示“当前使用卡 ICCID”。没有当前卡时禁用两个命令并展示后端返回的原因。页面可展示最近一次操作的目标限速、结果、操作人和时间,但不能把该记录描述为 Gateway 的实时状态。
五、审计与人工验收
每次请求记录:资产类型/ID、最终 cardNo、目标 speed_kbps、设置或取消、操作人、request_id、Gateway 结果和脱敏错误摘要。
人工验收覆盖:
- 单卡按 ICCID 设置限速。
- 设备按
is_current=true的绑定卡设置限速,请求中不出现设备 IMEI。 - 设备无当前卡时拒绝调用 Gateway。
speed_kbps=0经同一 Gateway 方法取消限速。- 同一
request_id重试不重复生成操作记录;不同请求复用 ID 返回冲突。 - Gateway 失败记录错误并允许相同目标值重试。
上线前置条件:Gateway 提供设置和取消所需的最终报文字段约定。业务层只保持 cardNo + speedKbps 契约。