Files
SecMPS/doc/设计文档/KMS钥匙柜适配器详细设计文档_任务清单.md

330 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# KMS 钥匙柜适配器 — 任务清单
> **基准文档**: `doc/设计文档/KMS钥匙柜适配器详细设计文档.md` v2.1
> **分支**: gateway-dev
> **原则**: 严格按照设计文档执行,严禁无中生有。网关/Vol.Pro 改动放倒数第二步,联调放最后。
---
## Phase K0: 项目骨架(预计 15min
### K0.1 创建适配器项目
- [ ]`gateway/src/` 下执行 `dotnet new classlib -n IntegrationGateway.Adapters.Kms -f net8.0`
- [ ] 删除自动生成的 `Class1.cs`
- [ ] 添加项目引用:`dotnet add reference ../IntegrationGateway.Core/IntegrationGateway.Core.csproj`
- [ ] 将项目加入解决方案:`dotnet sln add`
### K0.2 Host 引用适配器
- [ ] `dotnet add Host reference Adapters.Kms`
### K0.3 编译验证
- [ ] `dotnet build` → 0 错误
> **K0 提交点**: `PhaseK0_scaffold — Kms适配器项目骨架就绪`
---
## Phase K1: KmsModels — 数据模型(预计 1h
### K1.1 认证模型
- [ ] 创建 `KmsModels.cs`
- [ ] 添加 `KmsTokenResponse { Code, Token, Msg }`
### K1.2 第三方接口响应模型2.18.X
- [ ] `KmsOpenerListResponse { Code, Msg, Rows }`
- [ ] `KmsLocker { LockerId, LockerName, LockerCode, LockholeList }`
- [ ] `KmsLockhole { LockholeSort, OpenerId, OpenerName, OpenerType, OpenerState }`
- [ ] `KmsWarningListResponse { Code, Msg, Total, Rows }`
- [ ] `KmsWarning { Uuid, LockerName, LockholeSort, OpenerName, Type, WarningTime, Remark, StaffName }`
- [ ] `KmsRecordListResponse { Code, Msg, Total, Rows }`
- [ ] `KmsRecord { Uuid, LockerName, LockholeSort, OpenerName, StaffName, BorrowTime, ReturnTime, Type }`
### K1.3 标准接口响应模型2.3-2.17
- [ ] `KmsHandoverInfo` — 交接记录
- [ ] `KmsPermissionListResponse` + `KmsPermission` — 授权记录
- [ ] `KmsStaffListResponse` + `KmsStaff` — 员工
- [ ] `KmsLockerListResponse` + `KmsLockerInfo` — 柜体
- [ ] `KmsLockholeListResponse` + `KmsLockholeInfo` — 锁孔
- [ ] `KmsOpenerListResponse2` + `KmsOpenerInfo` — 钥匙
- [ ] `KmsStaffOpenerListResponse` + `KmsStaffOpener` — 员工可借
- [ ] `KmsRemotePermissionRequest` — 远程授权请求(联调时确认字段)
### K1.4 编译验证
- [ ] `dotnet build` → 0 错误DTO 引用 Core 的 `StandardDevice`/`StandardAlarm` 等确认无编译错误)
> **K1 提交点**: `PhaseK1_models — KmsModels.cs 完整定义全部 15 个 DTO`
---
## Phase K2: KmsAuthHelper — 认证(预计 30min
### K2.1 创建 KmsAuthHelper.cs
- [ ] 构造函数:接收 `HttpClient`, `baseUrl`, `clientId`, `clientSecret`
- [ ] 属性:`_token` (string?), `_tokenExpiry` (DateTime)
- [ ] 依赖:`System.Text.Json`, `System.Net.Http.Json`
### K2.2 GetTokenAsync
- [ ] POST `/prod-api/getToken?clientId=xx&clientSecret=yy`
- [ ] 检查 `resp.EnsureSuccessStatusCode()`
- [ ] 反序列化 `KmsTokenResponse`
- [ ] 校验 `Code == 200`
- [ ] 缓存 Token过期时间 = `UtcNow.AddMinutes(25)`30 分钟效期5 分钟余量)
### K2.3 GetAuthenticatedClientAsync
- [ ] 调用 `GetTokenAsync()`
- [ ] 创建新 `HttpClient``BaseAddress = _baseUrl`
- [ ] 设置 Header `Authorization: Bearer {token}`
- [ ] 返回 client
### K2.4 Invalidate
- [ ] `_token = null` 强制下次重新获取
### K2.5 编译验证
- [ ] `dotnet build` → 0 错误
> **K2 提交点**: `PhaseK2_auth — KmsAuthHelper Bearer Token 认证就绪`
---
## Phase K3: KmsAdapter 核心方法(预计 1.5h
### K3.1 类定义与构造函数
- [ ] `public class KmsAdapter : IHasFlatDevices, IHasAlarms`
- [ ] 字段:`_http`, `_auth` (KmsAuthHelper), `_limiter` (RateLimiter(5))
- [ ] 属性:`AdapterCode`, `DisplayName`, `Capabilities { HasFlatDevices=true, HasAlarms=true }`
- [ ] 构造函数:注入 `httpClient`, `baseUrl`, `clientId`, `clientSecret`
### K3.2 InitializeAsync
- [ ] `await _auth.GetTokenAsync()`
### K3.3 HealthCheckAsync2.18.1
- [ ] POST `/prod-api/heartBeat` (空 body `{}`)
- [ ] 返回 `resp.IsSuccessStatusCode`
- [ ] 异常捕获返回 false
### K3.4 GetDevicesAsync2.18.4 — 柜体+锁孔 → StandardDevice
- [ ] `await _limiter.WaitAsync()`
- [ ] POST `/prod-api/getOpenerList` (body `{}`)
- [ ] 反序列化 `KmsOpenerListResponse`
- [ ] 遍历 `Rows`
- 每个 `KmsLocker``MapLockerToDevice`父设备SourceId=`locker_{LockerId}`
- 每个 `KmsLockhole``MapLockholeToDevice`子设备ParentSourceId=`locker_{LockerId}`
- [ ] IsOnline 判断:`OpenerState == "在位"` → true
- [ ] Extra 字典:`{ openerId, openerType, openerState }` / `{ lockerCode, lockholeCount }`
- [ ] 返回 `PagedResult<StandardDevice>`
### K3.5 GetAlarmsAsync2.18.7 — 告警列表 → StandardAlarm
- [ ] `await _limiter.WaitAsync()`
- [ ] POST `/prod-api/getWarningList` (body `{}`)
- [ ] 反序列化 `KmsWarningListResponse`
- [ ] 映射:`AlarmId=uuid`, `Title="{lockerName} 锁孔{lockholeSort}: {openerName}"`, `Status=Type==1?"未确认":"已结束"`, `Level="普通"`
- [ ] 返回 `PagedResult<StandardAlarm>`
### K3.6 ConfirmAlarmAsync / EndAlarmAsync
- [ ] `ConfirmAlarmAsync`: POST `/prod-api/kms/warning/confirm/{alarmId}`
- [ ] `EndAlarmAsync`: 留空实现KMS 第三方接口不提供结束告警)
### K3.7 编译验证
- [ ] `dotnet build` → 0 错误
> **K3 提交点**: `PhaseK3_adapter_core — KmsAdapter 核心4方法就绪(HealthCheck/GetDevices/GetAlarms/Confirm)`
---
## Phase K4: KmsAdapter 扩展方法(预计 1h
### K4.1 GetBorrowRecordsAsync2.18.6
- [ ] POST `/prod-api/getRecordList`
- [ ] 参数:`from`, `to` DateTime?(联调时确认请求体格式)
- [ ] 返回 `PagedResult<KmsRecord>`
### K4.2 GetPermissionListAsync2.18.5
- [ ] POST `/prod-api/getPermissionList`
- [ ] 参数:`from`, `to` DateTime?
- [ ] 返回 `PagedResult<KmsPermission>`
### K4.3 BatchSyncStaffAsync2.18.3
- [ ] POST `/prod-api/batchSyncStaff`
- [ ] 请求体:`new { staff = staffList }`
- [ ] `resp.EnsureSuccessStatusCode()`
### K4.4 BatchDeleteStaffAsync2.18.2
- [ ] POST `/prod-api/batchDeleteStaff`
- [ ] 请求体:`List<string>` (staffUuid 数组)
- [ ] `resp.EnsureSuccessStatusCode()`
### K4.5 RemoteAuthorizeAsync2.4.3
- [ ] POST `/prod-api/kms/permission/remote`
- [ ] 请求体:`KmsRemotePermissionRequest`(联调确认字段)
### K4.6 ThirdPlatLoginAsync2.18.8
- [ ] POST `/thirdPlatlogin?username={username}`
- [ ] 处理 302 重定向:返回 `Location` header 或响应体
- [ ] 超时设置 15s
### K4.7 编译验证
- [ ] `dotnet build` → 0 错误
> **K4 提交点**: `PhaseK4_adapter_ext — 6个扩展方法全部就绪(记录/同步/授权/登录)`
---
## Phase K5: 配置与注册(预计 15min
### K5.1 KmsConfig POCO
- [ ]`Program.cs` 同级新增 `KmsConfig`
- [ ] 属性:`InstanceName?`, `BaseUrl`, `ClientId`, `ClientSecret`
### K5.2 appsettings.json
- [ ] 新增 `KMS` 数组配置段
- [ ] 配置项:`InstanceName`, `BaseUrl`, `ClientId`, `ClientSecret`
### K5.3 Program.cs 注册
- [ ] `var kmsList = app.Configuration.GetSection("KMS").Get<List<KmsConfig>>() ?? new();`
- [ ] foreach 注册 `KmsAdapter("KMS:{InstanceName}", http, baseUrl, clientId, clientSecret)`
- [ ] 适配器编码加入 `adapterTypes` 拼接
### K5.4 编译验证
- [ ] `dotnet build` → 0 错误
> **K5 提交点**: `PhaseK5_config — KMS多实例配置+Program.cs注册就绪`
---
## Phase K6: 编译与自测(预计 15min
### K6.1 全量编译
- [ ] `dotnet build` → 0 错误(确认 KMS 适配器不引入外部依赖)
### K6.2 启动测试
- [ ] `dotnet run` 启动网关
- [ ] 检查控制台输出:`[Gateway] N 个适配器已注册: Owl:main,MC4:31ku,KMS:main`
- [ ] 确认 KMS 初始化失败时打印错误但不阻塞
> **K6 提交点**: `PhaseK6_build — 网关全量编译通过 KMS适配器热加载不阻塞启动`
---
## Phase K7: 网关核心与 Host 扩展(预计 1.5h)⚠️ 倒数第二步
> **说明**: 此阶段按设计文档附录 B 新增 Core 能力接口 + B 组路由,遵循网关设计原则 §3.4。
### K7.1 新增 IAcceptsControl 接口
- [ ] 创建 `Core/Abstractions/IAcceptsControl.cs`
- [ ] 方法:`Task<ControlResult> SendControlAsync(sourceDeviceId, command, parameters)`
- [ ] 新增 `Core/Models/ControlResult.cs``{ Success, Message }`
### K7.2 新增 IHasBusinessLogs 接口
- [ ] 创建 `Core/Abstractions/IHasBusinessLogs.cs`
- [ ] 方法:`Task<PagedResult<BusinessLogEntry>> GetBusinessLogsAsync(logType, from, to, page, size, filters)`
- [ ] 新增 `Core/Models/BusinessLogEntry.cs``{ LogId, LogType, DeviceSourceId, StaffName, Description, CreatedAt, Extra }`
### K7.3 新增 IAcceptsDataSync 接口
- [ ] 创建 `Core/Abstractions/IAcceptsDataSync.cs`
- [ ] 方法:`Task<SyncResult> SyncDataAsync(dataType, items)`
- [ ] 方法:`Task<SyncResult> DeleteDataAsync(dataType, ids)`
- [ ] 新增 `Core/Models/SyncResult.cs``{ SuccessCount, FailCount, Message }`
### K7.4 KmsAdapter 实现新接口
- [ ] `KmsAdapter` 增加 `: IAcceptsControl, IHasBusinessLogs, IAcceptsDataSync`
- [ ] `SendControlAsync`:调 `RemoteAuthorizeAsync`command="open" 时调 `/kms/permission/remote`
- [ ] `GetBusinessLogsAsync`:按 logType 分发到 `GetBorrowRecordsAsync` / `GetPermissionListAsync` / 交接记录
- [ ] `SyncDataAsync`dataType="staff" 时调 `BatchSyncStaffAsync`
- [ ] `DeleteDataAsync`dataType="staff" 时调 `BatchDeleteStaffAsync`
### K7.5 Program.cs 新增 B 组路由
- [ ] `POST /api/gateway/control/{adapter}``IAcceptsControl.SendControlAsync`
- [ ] `GET /api/gateway/logs/{adapter}``IHasBusinessLogs.GetBusinessLogsAsync`
- [ ] `POST /api/gateway/sync/{adapter}``IAcceptsDataSync.SyncDataAsync`
- [ ] `DELETE /api/gateway/sync/{adapter}``IAcceptsDataSync.DeleteDataAsync`
### K7.6 编译验证
- [ ] `dotnet build` → 0 错误
> **K7 提交点**: `PhaseK7_gateway — 3个新Core接口+4条B路由+KmsAdapter多接口实现`
---
## Phase K8: Vol.Pro 管理端配套(预计 1h 倒数第二步
### K8.1 数据字典补充
- [ ] 管理端 → 字典管理 → 设备种类新增:"智能钥匙柜" / "钥匙位"
### K8.2 前端操作列扩展
- [ ] 编辑 `web.vite/src/views/warehouse/device_manager/base_device.vue`
- [ ] `onInited` 的 render 函数中增加 `DeviceGroup==='门禁设备'` 分支
- [ ] 显示 "开门" 按钮(调用网关 B8
- [ ] 显示 "权限" 下拉菜单(永久授权/临时授权/取消授权)
### K8.3 前端 API 调用
- [ ] `fetch()` 调网关 `http://localhost:5100/api/gateway/control/KMS:main`
- [ ] 请求体:`{ sourceDeviceId, command: "open", parameters: { openerId, staffId } }`
### K8.4 编译验证
- [ ] `npm run dev` → 无编译错误
> **K8 提交点**: `PhaseK8_volpro — 字典+前端操作按钮就绪`
---
## Phase K9: 联调验证(预计 3h 最后
> **前置条件**: KMS 服务端可访问,已分配 clientId/clientSecret
### K9.1 认证联调
- [ ] 网关启动 → KmsAdapter.InitializeAsync 成功获取 Token
- [ ] Token 过期自动刷新验证
- [ ] 错误 clientSecret → 网关控制台打印初始化失败日志
### K9.2 设备同步联调2.18.4
- [ ] `/api/gateway/health` 返回 KMS 适配器在线
- [ ] `/api/gateway/devices?adapter=KMS:main` 返回柜体+锁孔设备树
- [ ] 管理端 base_device 列表显示 KMS 设备AdapterCode=KMS:main
### K9.3 告警同步联调2.18.7
- [ ] `/api/gateway/alarms/KMS:main` 返回告警列表
- [ ] 管理端 iot_alarm 表有记录
### K9.4 远程控制联调2.4.3
- [ ] `/api/gateway/control/KMS:main` → 远程开门 → KMS 端锁孔门开
### K9.5 记录查询联调2.18.6
- [ ] `/api/gateway/logs/KMS:main?logType=borrow` 返回借还记录
### K9.6 员工同步联调2.18.3
- [ ] `/api/gateway/sync/KMS:main` → 批量同步员工成功
### K9.7 异常场景
- [ ] KMS 服务离线 → `/api/gateway/health` 中 KMS 返回 unhealthy
- [ ] KMS 恢复 → 下次心跳自动变 healthy
- [ ] 并发请求超过 5 QPS → 限流生效不崩溃
### K9.8 验收
- [ ] 网关 + Vol.Pro + KMS 三端数据一致
- [ ] 管理端可查看 KMS 设备树、告警
- [ ] 前端可远程开门
> **K9 提交点**: `PhaseK9_integration — 全链路联调通过`
---
## 任务总览
| Phase | 内容 | 文件数 | 预计 |
|:---:|------|:---:|:---:|
| K0 | 项目骨架 | 2 | 15min |
| K1 | KmsModels 全部 DTO | 1 | 1h |
| K2 | KmsAuthHelper | 1 | 30min |
| K3 | KmsAdapter 核心方法 | 1 | 1.5h |
| K4 | KmsAdapter 扩展方法 | 1 | 1h |
| K5 | 配置与注册 | 3 | 15min |
| K6 | 编译自测 | — | 15min |
| K7 | 网关 Core + Host 扩展 | 6 | 1.5h |
| K8 | Vol.Pro 管理端配套 | 2 | 1h |
| K9 | 联调验证 | — | 3h |
| **合计** | — | **17** | **~10h** |
---
> **版本**: 1.0 / 2025-05-19 / 严格按照 `KMS钥匙柜适配器详细设计文档.md` v2.1 制订