feat: 迭代03-05 交易记录接入、行情实时、QMT连接配置、data store 标准化
- R-004 QMT连接配置:多配置管理 + 会话头部快捷切换(03-QMT连接配置) - R-005 WS盘中价格实时更新:服务端中转+缓存+前端轮询(04-WS盘中价格实时更新) - R-006 策略数据 JSON data store 标准化(store.json/market.json/schema.json) - R-007 交易记录接入:当日订单+成交单表合并(委托主行+展开成交明细)、时间段查询(今日/本周/本月+手动起止)、费用计算(佣金费率万m_dCommission+最低5元、印花税卖出万5、过户费双向万0.1) - 架构治理:api 按领域拆分、component 目录、QmtHealthMonitor
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# 迭代 03:技术实现方案
|
||||
|
||||
> 依据:PLAN-003、技术约束-003/008/009、产品约束-005/006、UI约束-001/002
|
||||
|
||||
## 数据模型(settings namespace: one-divine-lot 新增字段 qmtConnections)
|
||||
|
||||
```
|
||||
qmtConnections: {
|
||||
list: [{ id, name, baseUrl, order }], // order 决定列表展示顺序
|
||||
activeId: string, // 当前激活配置 id('' = 无,展示层回退 defaultId/第一条)
|
||||
defaultId: string, // 默认配置 id('' = 无;启动时自动激活的目标)
|
||||
}
|
||||
```
|
||||
|
||||
- id:复用策略 slug 生成逻辑(拼音映射 + 去重),fallback 前缀 qmt-conn;
|
||||
- baseUrl:归一化(trim + 去尾斜杠 + 校验 http(s):// 前缀);
|
||||
- 生效连接解析顺序(getActiveConnection):activeId → defaultId → order 第一条 → null。
|
||||
|
||||
## 关键机制
|
||||
|
||||
1. **启动激活(Q1)**:apply 时 resolveStartupConnection(settings, config)——list 空 → cordis config.qmtBaseUrl 兜底(Q4 不迁移);否则 defaultId → activeId → 第一条;结果直接作为数据源构造参数并打日志。
|
||||
2. **热切换(Q2)**:QmtBridgeRestDataSource 增加 setBaseUrl(url)——baseUrl 为按请求读取的实例字段,改字段即对后续请求生效,无需重建实例、无需重启。
|
||||
3. **删除边界(Q6)**:removeQmtConnection 内处理——被删为激活 → activeId 指向 defaultId(若有效)否则第一条;被删为默认 → defaultId 转移到第一条;删除后为空 → activeId/defaultId 清空;**列表仅剩一条时拒绝删除**(返回约定错误)。
|
||||
4. **测试连接(Q3)**:服务端代理 GET {baseUrl}/health(15s 超时),返回 { ok, latencyMs, status, error };支持传未保存的 baseUrl(表单内先测后存)。
|
||||
5. **头部挂载(Q9)**:client 插件向 slot conversation.session.header.actions 注册 id=odl-qmt-switch、order=-9(内置 PTC 标签 order=-10,并排其后);控件用插件自身 connection RPC 读写配置,不依赖 slot 注入。
|
||||
|
||||
## 服务端 API(POST /odl/api/<method>,webServer 自开路由 · 技术约束-004)
|
||||
|
||||
| 端点 | 入参 | 行为 |
|
||||
|---|---|---|
|
||||
| qmt-connections | - | 返回 { list, activeId, defaultId, active }(active 为生效连接对象) |
|
||||
| qmt-connections/add | { name, baseUrl } | 新增;返回新配置 |
|
||||
| qmt-connections/update | { id, name, baseUrl } | 编辑;若改的是激活配置且 baseUrl 变化 → 编排 setBaseUrl |
|
||||
| qmt-connections/remove | { id } | 删除(含边界处理);生效连接变化 → 编排 setBaseUrl;仅剩一条时报错 |
|
||||
| qmt-connections/activate | { id } | 激活(写 activeId)+ setBaseUrl |
|
||||
| qmt-connections/set-default | { id } | 设默认(写 defaultId) |
|
||||
| qmt-connections/test | { baseUrl } 或 { id } | 代理 /health,返回可达性与延迟 |
|
||||
|
||||
## 客户端
|
||||
|
||||
- **QmtConnectionChip.jsx(新增)**:chip `QMT: <激活配置名> ▾` + 自实现下拉菜单(绝对定位 + 外点关闭;激活项勾选);点选 → activate 端点 → toast 反馈 + 本地状态刷新。
|
||||
- **SettingsSection.jsx(改)**:第三个子 tab「QMT 连接配置」;配置列表(名称/地址/激活与默认徽标)+ 行内操作(激活 / 设为默认 / 编辑 / 测试 / 删除)+ 新增与编辑表单 + 删除确认弹窗(复用 ConfirmDialog)+ Toast 反馈。
|
||||
- **client/index.js(改)**:注册头部 slot;其余 tab 注册不动。
|
||||
|
||||
## 安装与构建
|
||||
|
||||
服务端直接改 src;客户端 bundle 走既有 tsdown + wrap 构建(技术约束-005/006);安装用 dsh plugin add(技术约束-007)。cordis.patch.yml 不改动(Q4)。
|
||||
|
||||
## 实施事实(2026-08-29)
|
||||
|
||||
- **改动文件**:src/settings.js(schema + 9 个 QMT 函数段)、src/data-source/qmt-bridge-rest.js(setBaseUrl)、src/index.js(启动解析 + dataSource 注入 api)、src/api.js(7 个 qmt-connections 端点 + testQmtConnection 代理 + activate/update/remove 热切换编排)、src/client/index.js(头部 slot 注册 odl-qmt-switch order=-9)、src/client/views/QmtConnectionChip.jsx(新增)、src/client/views/SettingsSection.jsx(第三个子 tab QmtConnectionsSettings,追加于文件尾)。cordis.patch.yml 未改动。
|
||||
- **构建**:pnpm run build 一次通过(服务端 ESM 14 文件 + 客户端 CJS bundle 69.60kB + wrap 65907 bytes);node --check 服务端全通过;bundle 内已核对 chip 与端点调用代码。
|
||||
- **安装方式更正**:profile(~/.dsh/profiles/web)中插件为 link 符号链接指向工作区,工作区 lib/ 即宿主加载产物,构建后无需再执行 dsh plugin add(技术约束-007 补充事实:link 安装形态下构建即生效)。
|
||||
- **数据层单测**:14 项断言全部通过(mock settings scope):新增归一化去尾斜杠、order 排序、新增不自动激活、空激活态回退第一条、非法地址拒绝、激活/默认写入、生效连接解析、编辑激活配置地址、删除标记返回、删激活/默认→转移第一条并激活、禁删最后一条、空列表回退 cordis、启动激活默认(覆盖上次激活)、启动解析回写 activeId。
|
||||
- **生效条件**:线上宿主进程(GUI http://127.0.0.1:3080)启动时已加载旧 lib(qmt-connections 端点 404 证实),需重启 DSH Web 或重载插件后新代码生效。
|
||||
Reference in New Issue
Block a user