From 39b135fa364af75ef66d7d9961397e8da773d076 Mon Sep 17 00:00:00 2001 From: AdamGao Date: Wed, 2 Sep 2026 18:14:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8C=81=E4=BB=93):=20strategy-positions?= =?UTF-8?q?=20=E8=BF=94=E5=9B=9E=20values=20=E6=8C=89=E5=BD=93=E5=89=8D=20?= =?UTF-8?q?configSchema=20=E8=BF=87=E6=BB=A4=EF=BC=88=E9=98=B2=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E6=94=B6=E7=AA=84=E5=90=8E=E6=AE=8B=E7=95=99=E9=94=AE?= =?UTF-8?q?=E6=B7=B7=E5=85=A5=E5=B1=95=E7=A4=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/position/PositionManager.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/position/PositionManager.js b/src/position/PositionManager.js index 2371b7d..e5b93db 100644 --- a/src/position/PositionManager.js +++ b/src/position/PositionManager.js @@ -84,6 +84,14 @@ export class PositionManager { const shareMap = new Map(dataset.map((d) => [d.code, d.shares])); const holdingMap = new Map(holdings.map((h) => [h.code, h.holdingId])); // code → holdingId const valuesMap = new Map(holdings.map((h) => [h.code, h.values ?? null])); // R-013:code → 自定义字段值 + // R-013 防御(2026-09-02 小修):展示层按该策略当前 configSchema 过滤 values 键 —— + // 字段定义收窄/删除后,行内残留的旧键(如曾与网格同款的 grid_*)不随持仓返回、不在表格显示; + // 编辑保存以过滤后值为基底 → 覆盖写回时残留键自然被清除(数据层收敛,不动写路径语义)。 + const schemaKeys = new Set((this.getStrategySchema(strategyId) ?? []).map((f) => f.key)); + const cleanValues = (raw) => { + if (!raw || typeof raw !== 'object' || schemaKeys.size === 0) return null; // 无字段定义 → 无值 + return Object.fromEntries(Object.entries(raw).filter(([k]) => schemaKeys.has(k))); + }; // R-010 Q4:批量取各 holding 的关联委托(查最后一笔成交价) const holdingIds = [...new Set(holdings.map((h) => h.holdingId).filter((x) => x != null))]; const tradesByHolding = new Map(); @@ -108,7 +116,7 @@ export class PositionManager { // getOrdersByHolding 已按 insert_ts DESC,第一条即最新 lastTradePrice = +filled[0].tradedPrice; } - return { ...p, shares, holdingId, avgPrice, lastTradePrice, values: valuesMap.get(p.code) ?? null }; // R-013 + return { ...p, shares, holdingId, avgPrice, lastTradePrice, values: cleanValues(valuesMap.get(p.code)) }; // R-013(展示层按 schema 过滤) }) .filter(Boolean); }