diff --git a/doc/设计文档/KMS钥匙柜适配器详细设计文档_任务清单.md b/doc/设计文档/KMS钥匙柜适配器详细设计文档_任务清单.md new file mode 100644 index 0000000..0bafb9a --- /dev/null +++ b/doc/设计文档/KMS钥匙柜适配器详细设计文档_任务清单.md @@ -0,0 +1,329 @@ +# 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 HealthCheckAsync(2.18.1) +- [ ] POST `/prod-api/heartBeat` (空 body `{}`) +- [ ] 返回 `resp.IsSuccessStatusCode` +- [ ] 异常捕获返回 false + +### K3.4 GetDevicesAsync(2.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` + +### K3.5 GetAlarmsAsync(2.18.7 — 告警列表 → StandardAlarm) +- [ ] `await _limiter.WaitAsync()` +- [ ] POST `/prod-api/getWarningList` (body `{}`) +- [ ] 反序列化 `KmsWarningListResponse` +- [ ] 映射:`AlarmId=uuid`, `Title="{lockerName} 锁孔{lockholeSort}: {openerName}"`, `Status=Type==1?"未确认":"已结束"`, `Level="普通"` +- [ ] 返回 `PagedResult` + +### 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 GetBorrowRecordsAsync(2.18.6) +- [ ] POST `/prod-api/getRecordList` +- [ ] 参数:`from`, `to` DateTime?(联调时确认请求体格式) +- [ ] 返回 `PagedResult` + +### K4.2 GetPermissionListAsync(2.18.5) +- [ ] POST `/prod-api/getPermissionList` +- [ ] 参数:`from`, `to` DateTime? +- [ ] 返回 `PagedResult` + +### K4.3 BatchSyncStaffAsync(2.18.3) +- [ ] POST `/prod-api/batchSyncStaff` +- [ ] 请求体:`new { staff = staffList }` +- [ ] `resp.EnsureSuccessStatusCode()` + +### K4.4 BatchDeleteStaffAsync(2.18.2) +- [ ] POST `/prod-api/batchDeleteStaff` +- [ ] 请求体:`List` (staffUuid 数组) +- [ ] `resp.EnsureSuccessStatusCode()` + +### K4.5 RemoteAuthorizeAsync(2.4.3) +- [ ] POST `/prod-api/kms/permission/remote` +- [ ] 请求体:`KmsRemotePermissionRequest`(联调确认字段) + +### K4.6 ThirdPlatLoginAsync(2.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>() ?? 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 SendControlAsync(sourceDeviceId, command, parameters)` +- [ ] 新增 `Core/Models/ControlResult.cs`:`{ Success, Message }` + +### K7.2 新增 IHasBusinessLogs 接口 +- [ ] 创建 `Core/Abstractions/IHasBusinessLogs.cs` +- [ ] 方法:`Task> 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 SyncDataAsync(dataType, items)` +- [ ] 方法:`Task 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 制订