SecMPS统一问题清单+修复方案: 18项问题 4阶段F1-F4 25文件~9h
This commit is contained in:
56
doc/设计文档/SecMPS统一问题清单20260603.md
Normal file
56
doc/设计文档/SecMPS统一问题清单20260603.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# SecMPS 统一问题清单 2026-06-03
|
||||||
|
|
||||||
|
> **版本**: 1.0
|
||||||
|
> **日期**: 2026-06-03
|
||||||
|
> **范围**: gateway / VolPro (api_sqlsugar) / web.vite / warehouse / owl_zlmediakit
|
||||||
|
> **来源**: 项目深度审计 + 规则引擎方案审查
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P0 — 阻塞性(影响功能完整性,必须修复)
|
||||||
|
|
||||||
|
| 编号 | 类别 | 问题 | 影响 | 方案 |
|
||||||
|
|:---:|:---:|------|------|------|
|
||||||
|
| P0-1 | 规则引擎 | RealtimePollJob 空壳 — IoT 实时值从未持久化,规则引擎无历史数据源 | 规则无法追溯历史趋势 | 在此 Job 实现轮询→写入 iot_devicedata,或合并到 RuleEngineJob |
|
||||||
|
| P0-2 | 网关 | A1 自注册未调用 — `GatewayClientFactory.RegisterAsync` 已定义但 Program.cs 从未执行 | 网关启动后不向 Vol.Pro 注册 | `InitializeAllAsync()` 后遍历适配器调 A1 |
|
||||||
|
| P0-3 | 安全 | B 组路由零认证 — 14+ 条路由无任何认证 | 内网未授权客户端可操控设备、查视频流 | 生产环境绑定 `127.0.0.1`,或加 `X-Gateway-Key` 中间件 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P1 — 重要(影响性能、安全、可靠性)
|
||||||
|
|
||||||
|
| 编号 | 类别 | 问题 | 影响 | 方案 |
|
||||||
|
|:---:|:---:|------|------|------|
|
||||||
|
| P1-1 | 性能 | 逐设备 B4 调用 — 规则引擎按设备逐个调 B4 | 规则引擎 90% 时间耗在网络往返 | 新增 `POST /realtime/{adapter}/batch` 批量接口 |
|
||||||
|
| P1-2 | 性能 | 级联离线标记逐条 UPDATE — HeartbeatMonitorJob 对每台设备单独更新 | 设备多时慢且无事务 | 一条 SQL: `UPDATE base_device SET IsOnline='离线' WHERE GatewayNodeId=@id` |
|
||||||
|
| P1-3 | 安全 | Token/密码明文存储 — appsettings.json 明文且被复制到 bin/ | 源码泄露 = 凭据泄露 | 环境变量覆盖 + `.gitignore bin` |
|
||||||
|
| P1-4 | 可维护 | 前端硬编码网关地址 — `const GW = 'http://localhost:5100'` | 部署时需逐文件修改 | 统一用 `window.apiConfig.gatewayUrl` |
|
||||||
|
| P1-5 | 规则引擎 | DeviceId→(AdapterCode, SourceId) 解析缺失 | 规则引擎无法直接调网关 B4 | 批量查 base_device 建映射表 |
|
||||||
|
| P1-6 | 规则引擎 | ValueId 语义模糊 — 字典绑定但无对应实体表 | "变量"选的是什么不明确 | 新建 `warehouse_variable` 表 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P2 — 改善(影响排错效率、维护成本)
|
||||||
|
|
||||||
|
| 编号 | 类别 | 问题 | 影响 | 方案 |
|
||||||
|
|:---:|:---:|------|------|------|
|
||||||
|
| P2-1 | 代码质量 | 静默异常吞噬 — 适配器 `catch { return false; }` | 离线不知道原因 | `catch(Exception ex)` + STDERR 输出 |
|
||||||
|
| P2-2 | 规则引擎 | 阈值抖动 — 温度反复跳变时规则频繁触发→恢复 | 空调反复开关,告警洪水 | hysteresis 滞后窗 |
|
||||||
|
| P2-3 | 规则引擎 | 冷却期粒度 — Cooldown 在规则级,OR 组合不该整体冷却 | 冷却期过宽 | 冷却期下沉到条件表或基于"上次触发值"去重 |
|
||||||
|
| P2-4 | 可维护 | warehouse 端 console.log 残留 — 30+ 处开发日志 | 生产环境噪声 | vite.config.ts 移除非生产日志 |
|
||||||
|
| P2-5 | 可维护 | 双端 gateway API 重复封装 | 维护两份 | 统一到 web.vite/src/api/gateway.js |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P3 — 优化(影响开发体验、仓库整洁)
|
||||||
|
|
||||||
|
| 编号 | 类别 | 问题 | 影响 | 方案 |
|
||||||
|
|:---:|:---:|------|------|------|
|
||||||
|
| P3-1 | 规则引擎 | 动作执行阻塞 — `ExecuteActionsAsync` 串行等待 B5 响应 | 一条规则卡住全部阻塞 | `Task.WhenAll` + 5s 超时 |
|
||||||
|
| P3-2 | 文档 | bin 目录残留配置 | 仓库体积 + 凭据泄露 | `.gitignore` 加 `**/bin/` |
|
||||||
|
| P3-3 | 开发 | 网关无 Swagger | 调试需手动 curl | `AddEndpointsApiExplorer` + `MapSwagger` |
|
||||||
|
| P3-4 | 文档 | 设计文档与代码路由数不一致 | 架构文档过时 | 每次 Phase 同步更新 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **总计**: 18 项 — P0: 3 / P1: 6 / P2: 5 / P3: 4
|
||||||
280
doc/设计文档/SecMPS统一问题清单20260603修复方案.md
Normal file
280
doc/设计文档/SecMPS统一问题清单20260603修复方案.md
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
# SecMPS 统一问题清单 2026-06-03 修复方案
|
||||||
|
|
||||||
|
> **版本**: 1.0
|
||||||
|
> **日期**: 2026-06-03
|
||||||
|
> **基准**: `SecMPS统一问题清单20260603.md`
|
||||||
|
> **原则**: 按优先级逐项修复,每项修复后编译验证;涉及网关/Vol.Pro 改动的放一组批量提交
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 修复总览
|
||||||
|
|
||||||
|
| 阶段 | 优先级 | 涉及项目 | 文件数 | 预计 |
|
||||||
|
|:---:|:---:|------|:---:|:---:|
|
||||||
|
| F1 | P0-1 ~ P0-3 | gateway + Vol.Pro | 5 | 2h |
|
||||||
|
| F2 | P1-1 ~ P1-6 | gateway + Vol.Pro + 库表 + 前端 | 8 | 4h |
|
||||||
|
| F3 | P2-1 ~ P2-5 | gateway + warehouse | 8 | 2h |
|
||||||
|
| F4 | P3-1 ~ P3-4 | gateway + 文档 | 4 | 1h |
|
||||||
|
| **合计** | — | 4 项目 | **25** | **~9h** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 F1: P0 阻塞项修复(预计 2h)
|
||||||
|
|
||||||
|
#### F1.1 [P0-1] RealtimePollJob 填充实现
|
||||||
|
|
||||||
|
- [ ] 编辑 `api_sqlsugar/Warehouse/Services/RealtimePollJob.cs`
|
||||||
|
- [ ] 注入 `GatewayClient` + `Ibase_deviceRepository`
|
||||||
|
- [ ] `Execute()` 中:
|
||||||
|
1. 查询在线 MC4 网关 (`gateway_nodes WHERE IsOnline=在线 AND AdapterTypes LIKE '%MC4%'`)
|
||||||
|
2. 查对应设备列表 (`base_device WHERE DeviceGroup='IoT设备' AND IsOnline=在线`)
|
||||||
|
3. 对每个设备调 `GatewayClient.GetRealtimeAsync(gwBaseUrl, adapterCode, sourceId)`
|
||||||
|
4. 结果写入 `iot_devicedata` 表(INSERT 新记录)
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
#### F1.2 [P0-2] 网关 A1 自注册
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/Program.cs`
|
||||||
|
- [ ] 在 `registry.InitializeAllAsync()` 后加入:
|
||||||
|
```csharp
|
||||||
|
var nodeCode = gwCfg["NodeCode"] ?? "gw-default";
|
||||||
|
var nodeToken = gwCfg["NodeToken"] ?? "";
|
||||||
|
var adapterTypes = string.Join(",", registry.All.Select(a => a.AdapterCode));
|
||||||
|
await clientFactory.RegisterAsync(nodeCode, nodeToken, adapterTypes, volProUrl);
|
||||||
|
```
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
#### F1.3 [P0-3] B 组路由认证
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/Program.cs`
|
||||||
|
- [ ] 在 `app.UseCors()` 之后添加中间件:
|
||||||
|
```csharp
|
||||||
|
var gatewayKey = gwCfg["GatewayKey"];
|
||||||
|
if (!string.IsNullOrEmpty(gatewayKey))
|
||||||
|
{
|
||||||
|
app.Use(async (context, next) => {
|
||||||
|
var key = context.Request.Headers["X-Gateway-Key"].FirstOrDefault();
|
||||||
|
if (key == gatewayKey || context.Request.Path == "/") { await next(); }
|
||||||
|
else { context.Response.StatusCode = 401; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [ ] appsettings.json Gateway 段新增 `"GatewayKey": null`
|
||||||
|
- [ ] Vol.Pro 端 `GatewayClient` 所有 HTTP 请求头自动附加 `X-Gateway-Key`
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
> **F1 提交点**: `Fix-P0: RealtimePollJob+A1自注册+B组认证`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 F2: P1 重要项修复(预计 4h)
|
||||||
|
|
||||||
|
#### F2.1 [P1-1] 网关新增批量实时值接口
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/Program.cs`
|
||||||
|
- [ ] 新增 B4-batch 路由:
|
||||||
|
```csharp
|
||||||
|
app.MapPost("/api/gateway/realtime/{adapter}/batch", async (string adapter, BatchRealtimeRequest req) =>
|
||||||
|
{
|
||||||
|
var a = registry.FindByCode<IHasPoints>(adapter);
|
||||||
|
if (a == null) return Results.NotFound();
|
||||||
|
var results = new Dictionary<string, List<PointValue>>();
|
||||||
|
foreach (var deviceId in req.DeviceIds ?? new())
|
||||||
|
results[deviceId] = await a.GetRealtimeValuesAsync(deviceId);
|
||||||
|
return Results.Ok(results);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
- [ ] 新增 `record BatchRealtimeRequest(List<string>? DeviceIds);`
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
#### F2.2 [P1-2] 批量级联离线标记
|
||||||
|
|
||||||
|
- [ ] 编辑 `api_sqlsugar/Warehouse/Services/HeartbeatMonitorJob.cs`
|
||||||
|
- [ ] 替换逐条 `UpdateAsync` 为:
|
||||||
|
```csharp
|
||||||
|
context.Repository.DbContext.Db.Ado.ExecuteCommand(
|
||||||
|
"UPDATE base_device SET IsOnline='离线' WHERE GatewayNodeId=@id AND IsOnline='在线'",
|
||||||
|
new { id = node.GatewayNodeId });
|
||||||
|
```
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
#### F2.3 [P1-3] 凭据安全化
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/appsettings.json`
|
||||||
|
- `NodeToken` → `null`, 加注释 "生产环境由 SECMPS_GATEWAY_TOKEN 环境变量注入"
|
||||||
|
- Owl `Password` → `""`, 加注释
|
||||||
|
- KMS `ClientSecret` → `""`, 加注释
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/Program.cs`
|
||||||
|
- `gwCfg["NodeToken"]` → `Environment.GetEnvironmentVariable("SECMPS_GATEWAY_TOKEN") ?? gwCfg["NodeToken"]`
|
||||||
|
- [ ] 编辑 `.gitignore` → 加 `**/bin/`、`**/obj/`
|
||||||
|
- [ ] `git rm -r --cached gateway/src/IntegrationGateway.Host/bin/`
|
||||||
|
|
||||||
|
#### F2.4 [P1-4] 前端网关地址统一化
|
||||||
|
|
||||||
|
- [ ] 编辑 `web.vite/public/index.html` 的 `window.apiConfig` → 加 `gatewayUrl: 'http://localhost:5100'`
|
||||||
|
- [ ] 编辑 `web.vite/src/views/warehouse/device_manager/base_device.vue`
|
||||||
|
- `const GW = 'http://localhost:5100'` → `const GW = window.apiConfig.gatewayUrl || 'http://localhost:5100'`
|
||||||
|
- [ ] 编辑 `warehouse/src/api/gateway.ts`
|
||||||
|
- `const GW_BASE = 'http://localhost:5100'` → 读取 `window.apiConfig.gatewayUrl`
|
||||||
|
- [ ] 编辑 `warehouse/index.html` 的 `window.apiConfig` → 加 `gatewayUrl`
|
||||||
|
|
||||||
|
#### F2.5 [P1-5] 规则引擎增加 DeviceId 映射
|
||||||
|
|
||||||
|
- [ ] 在规则引擎实现方案中增加 `BuildDeviceMappingAsync` 方法:
|
||||||
|
```csharp
|
||||||
|
var deviceIds = rules.SelectMany(r => r.Conditions).Select(c => c.DeviceId).Distinct();
|
||||||
|
var devices = await _deviceRepo.FindAsync(d => deviceIds.Contains(d.DeviceId));
|
||||||
|
var map = devices.ToDictionary(d => d.DeviceId, d => (d.AdapterCode, d.SourceId));
|
||||||
|
```
|
||||||
|
- [ ] 后续调网关时用 `map[cond.DeviceId]` 拼装 URL
|
||||||
|
|
||||||
|
#### F2.6 [P1-6] 新建 warehouse_variable 表
|
||||||
|
|
||||||
|
- [ ] 执行 SQL:
|
||||||
|
```sql
|
||||||
|
CREATE TABLE warehouse_variable (
|
||||||
|
VariableId INT IDENTITY PRIMARY KEY,
|
||||||
|
DeviceId INT NOT NULL,
|
||||||
|
VariableName NVARCHAR(255), -- 温度/湿度/人数
|
||||||
|
PointIndex INT DEFAULT 0, -- MC4 pointIndex
|
||||||
|
Unit NVARCHAR(50), -- ℃/%/人
|
||||||
|
SortOrder INT DEFAULT 0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
- [ ] 在 Vol.Pro 代码生成器选择 `warehouse_variable`,生成全套 CRUD 代码
|
||||||
|
- [ ] 管理端字典 "变量列表" 绑定到 `warehouse_variable.VariableName`
|
||||||
|
- [ ] 规则条件/动作的 `ValueId` 下拉框改为从 `warehouse_variable` 查询(JOIN `base_device.DeviceId`)
|
||||||
|
|
||||||
|
> **F2 提交点**: `Fix-P1: B4-batch+批量离线+凭据安全+前端地址+DeviceId映射+变量表`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 F3: P2 改善项修复(预计 2h)
|
||||||
|
|
||||||
|
#### F3.1 [P2-1] 适配器异常日志
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Adapters.Owl/OwlAdapter.cs`
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Adapters.MC4/Mc4Adapter.cs`
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Adapters.Kms/KmsAdapter.cs`
|
||||||
|
- [ ] 所有 `catch { return false; }` → `catch (Exception ex) { Console.Error.WriteLine($"[{AdapterCode}] HealthCheck: {ex.Message}"); return false; }`
|
||||||
|
- [ ] `dotnet build` → 0 错误
|
||||||
|
|
||||||
|
#### F3.2 [P2-2] 规则引擎滞后窗
|
||||||
|
|
||||||
|
- [ ] 在 `warehouse_rulecondition` 表新增字段:
|
||||||
|
```sql
|
||||||
|
ALTER TABLE warehouse_rulecondition ADD
|
||||||
|
RecoveryThreshold_Numeric DECIMAL(18,2) NULL, -- 恢复阈值(下界)
|
||||||
|
RecoveryThreshold_Switch NVARCHAR(50) NULL; -- 恢复开关状态
|
||||||
|
```
|
||||||
|
- [ ] `RuleEngineService.EvaluateCondition` 中加逻辑:
|
||||||
|
```csharp
|
||||||
|
bool wasTriggered = cond.LastTriggered.HasValue;
|
||||||
|
if (wasTriggered)
|
||||||
|
return Compare(actualValue, "大于等于", cond.RecoveryThreshold_Numeric);
|
||||||
|
else
|
||||||
|
return Compare(actualValue, cond.CompareOperator, cond.TargetValue_Number);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### F3.3 [P2-3] 条件级冷却
|
||||||
|
|
||||||
|
- [ ] `warehouse_rulecondition` 表新增 `LastTriggered DATETIME NULL`、`LastTriggerValue DECIMAL(18,2) NULL`
|
||||||
|
- [ ] `RuleEngineService.EvaluateCondition` 中:
|
||||||
|
- 如果 `DateTime.Now - cond.LastTriggered < rule.CooldownSec` → 跳过此条件
|
||||||
|
- 触发时更新 `LastTriggered` 和 `LastTriggerValue`
|
||||||
|
|
||||||
|
#### F3.4 [P2-4] 生产环境移除 console.log
|
||||||
|
|
||||||
|
- [ ] 编辑 `warehouse/vite.config.ts`
|
||||||
|
```typescript
|
||||||
|
build: {
|
||||||
|
terserOptions: { compress: { drop_console: true } }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [ ] 开发环境保留 `console.log`(仅 build 时移除)
|
||||||
|
- [ ] `npm run build` → 确认无 console.log 残留
|
||||||
|
|
||||||
|
#### F3.5 [P2-5] 统一 gateway API 封装
|
||||||
|
|
||||||
|
- [ ] 复制 `warehouse/src/api/gateway.ts` → `web.vite/src/api/gateway.js`
|
||||||
|
- 修改 `GW_BASE` 为 `window.apiConfig.gatewayUrl || 'http://localhost:5100'`
|
||||||
|
- [ ] `web.vite/src/views/warehouse/device_manager/base_device.vue`
|
||||||
|
- 删除内联 `const GW =` + `fetch()` → 改为 `import { gwGet, gwPost } from '@/api/gateway.js'`
|
||||||
|
- 所有 `fetch(\`\${GW}/api/gateway/...\`)` → `gwGet(...)` / `gwPost(...)`
|
||||||
|
|
||||||
|
> **F3 提交点**: `Fix-P2: 异常日志+滞后窗+条件冷却+console清理+API统一`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 阶段 F4: P3 优化项(预计 1h)
|
||||||
|
|
||||||
|
#### F4.1 [P3-1] 规则引擎并发动作执行
|
||||||
|
|
||||||
|
- [ ] 在规则引擎实现方案的 `ExecuteActionsAsync` 中:
|
||||||
|
```csharp
|
||||||
|
var tasks = actions.Select(a => ExecuteSingleActionAsync(a, rule));
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
|
||||||
|
async Task ExecuteSingleActionAsync(Action a, Rule r) {
|
||||||
|
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||||
|
try { await DoAction(a, r, cts.Token); }
|
||||||
|
catch (OperationCanceledException) { Log($"[RuleEngine] 动作超时: {a.id}"); }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### F4.2 [P3-2] 清理 bin/obj + .gitignore
|
||||||
|
|
||||||
|
- [ ] `.gitignore` 追加规则(如未在 F2.3 中完成):
|
||||||
|
```
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
|
gateway/src/IntegrationGateway.Host/bin/
|
||||||
|
api_sqlsugar/**/bin/
|
||||||
|
```
|
||||||
|
- [ ] `git rm -r --cached` 所有 bin/obj 目录
|
||||||
|
|
||||||
|
#### F4.3 [P3-3] 网关 Swagger
|
||||||
|
|
||||||
|
- [ ] 编辑 `gateway/src/IntegrationGateway.Host/Program.cs`:
|
||||||
|
```csharp
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
// ...
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
```
|
||||||
|
- [ ] 浏览器访问 `http://localhost:5100/swagger` 验证
|
||||||
|
|
||||||
|
#### F4.4 [P3-4] 同步设计文档路由数
|
||||||
|
|
||||||
|
- [ ] 编辑 `doc/设计文档/对接网关设计文档.md` → 路由表从 14 条更新为当前实际数
|
||||||
|
- [ ] 确认以下设计文档一致: 对接网关设计文档、规则引擎方案、KMS 设计文档
|
||||||
|
|
||||||
|
> **F4 提交点**: `Fix-P3: 并发动作+清理bin+Swagger+文档同步`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 任务总览
|
||||||
|
|
||||||
|
| 编号 | 问题 | 涉及文件 | 预计 |
|
||||||
|
|:---:|------|------|:---:|
|
||||||
|
| P0-1 | RealtimePollJob 空壳 | RealtimePollJob.cs | 1h |
|
||||||
|
| P0-2 | A1 自注册 | Program.cs | 30min |
|
||||||
|
| P0-3 | B 组认证 | Program.cs + appsettings | 30min |
|
||||||
|
| P1-1 | B4-batch | Program.cs | 30min |
|
||||||
|
| P1-2 | 批量离线 | HeartbeatMonitorJob.cs | 20min |
|
||||||
|
| P1-3 | 凭据安全 | appsettings + .gitignore + bin | 20min |
|
||||||
|
| P1-4 | 前端地址 | base_device.vue + gateway.ts | 20min |
|
||||||
|
| P1-5 | DeviceId 映射 | RuleEngineService | 30min |
|
||||||
|
| P1-6 | 变量表 | SQL + 代码生成 + 前端 | 1h |
|
||||||
|
| P2-1 | 异常日志 | OwlAdapter + MC4Adapter + KmsAdapter | 20min |
|
||||||
|
| P2-2 | 滞后窗 | SQL + RuleEngineService | 30min |
|
||||||
|
| P2-3 | 条件冷却 | SQL + RuleEngineService | 20min |
|
||||||
|
| P2-4 | console 清理 | vite.config.ts | 10min |
|
||||||
|
| P2-5 | API 统一 | gateway.js + base_device.vue | 30min |
|
||||||
|
| P3-1 | 并发动作 | RuleEngineService | 15min |
|
||||||
|
| P3-2 | bin 清理 | .gitignore + git rm | 5min |
|
||||||
|
| P3-3 | Swagger | Program.cs | 10min |
|
||||||
|
| P3-4 | 文档同步 | 设计文档 | 15min |
|
||||||
|
|
||||||
|
> **总计**: 18 项 / 25 文件 / ~9h
|
||||||
Reference in New Issue
Block a user