docs(迭代07/08): 交易记录本地存储 + 策略持仓展开全量文档 + 需求归档(R-009/R-010)

- PLAN-008/PLAN-009 计划(已完成)
- 迭代 07/08 四件套(目标/技术方案/验收标准/复盘)
- 设计约束:数据存储设计 §10/§10.1、技术约束-012/013、产品约束-008
- R-009/R-010 需求归档(含二次定稿:手动归属、Q4 成本价/成交价)
- 需求池索引同步
This commit is contained in:
2026-09-02 01:21:10 +08:00
parent 859938c4f1
commit 2aacd8a25d
16 changed files with 821 additions and 6 deletions
@@ -0,0 +1,71 @@
# 技术实现方案:08-策略持仓行展开关联交易记录(Holding → 交易汇总)
> 依据:PLAN-009 需求:R-010(Q1-Q3 定稿)| 设计约束:技术约束-012、技术约束-011(测试隔离)
## 技术选型
- 复用 R-009 的 holding_id 关联(trade_orders.holding_id);
- 服务端:strategy-positions 附加 holding_id + trades/by-holding 端点;
- 前端:StrategyTab 持仓行展开(懒加载内嵌汇总表)。
## 数据流
```
策略持仓 tab
load() → strategy-positions(每行含 holding_id
用户点击持仓行 → 展开 → trades/by-holding?holdingId=13 → 委托汇总列表
懒加载:不展开不请求
```
## 实现细节
### 1. PositionManager.getStrategyPositions 附加 holding_id
```js
async getStrategyPositions(strategyId) {
const [positions, dataset, holdings] = await Promise.all([
this.getAllPositions(),
this.storage.getDataset(strategyId),
this.storage.getCurrentHoldings(strategyId), // 含 holding_id
]);
const shareMap = new Map(dataset.map(d => [d.code, d.shares]));
const holdingMap = new Map(holdings.map(h => [h.code, h.holdingId]));
return positions.map(p => {
const shares = shareMap.get(p.code) ?? 0;
return shares > 0 ? { ...p, shares, holdingId: holdingMap.get(p.code) ?? null } : null;
}).filter(Boolean);
}
```
### 2. SqliteStore.getOrdersByHolding
```js
getOrdersByHolding(holdingId) {
this.init();
return this.db.prepare(
'SELECT * FROM trade_orders WHERE holding_id=? ORDER BY insert_ts DESC'
).all(holdingId).map(r => this._mapOrderRow(r));
}
```
### 3. api/trades.jstrades/by-holding 端点
```js
case 'trades/by-holding':
return await storage.getTradeOrdersByHolding(args.holdingId);
```
### 4. StrategyTab 展开 UI
- 持仓行加展开箭头(类似交易记录 tab);
- 展开时调 trades/by-holding,内嵌小表格显示委托汇总:
时间 / 方向 / 状态 / 委托量 / 成交量 / 均价 / 金额 / 费用;
- 只显示委托汇总(ORDER_STATUS 中文映射复用);
- 懒加载:展开时才请求,折叠清空。
## 涉及设计约束
| 约束 | 内容 |
|---|---|
| 技术约束-012 | 数据存储遵循数据存储设计.md(复用 trade_orders.holding_id |
| 技术约束-011 | 测试用独立数据目录(ODL_TEST_DATA_DIR |