fix(hub): archive trade row selection by exchange+id

Use composite trade key so Gate accounts with duplicate trade IDs no longer highlight two rows at once.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-11 20:01:20 +08:00
parent a87234f627
commit 3ef0750ea9
2 changed files with 42 additions and 18 deletions
+41 -17
View File
@@ -58,7 +58,7 @@
let tradingDay = ""; let tradingDay = "";
let selected = null; let selected = null;
let trades = []; let trades = [];
let selectedTradeId = null; let selectedTradeKey = null;
let timeframe = "15m"; let timeframe = "15m";
let chart = null; let chart = null;
let candleSeries = null; let candleSeries = null;
@@ -229,6 +229,23 @@
return exKey ? exchangeLabel(exKey) : "—"; return exKey ? exchangeLabel(exKey) : "—";
} }
function tradeRowKey(tr) {
if (!tr) return "";
const exKey = String(tr.exchange_key || "").toLowerCase();
const tid = tr.trade_id != null ? tr.trade_id : tr.id;
if (!exKey || tid == null || tid === "") return "";
return exKey + ":" + String(tid);
}
function findTradeByKey(key) {
if (!key) return null;
return (
dailyTrades.find(function (t) {
return tradeRowKey(t) === String(key);
}) || null
);
}
function applyTagSelectStyle(sel) { function applyTagSelectStyle(sel) {
if (!sel) return; if (!sel) return;
const v = sel.value || ""; const v = sel.value || "";
@@ -272,7 +289,7 @@
}); });
if (!tr) return; if (!tr) return;
selected = { exchange_key: tr.exchange_key, symbol: tr.symbol }; selected = { exchange_key: tr.exchange_key, symbol: tr.symbol };
selectedTradeId = String(tr.trade_id || tr.id); selectedTradeKey = tradeRowKey(tr);
await loadSymbolTradesForChart(tr.exchange_key, tr.symbol); await loadSymbolTradesForChart(tr.exchange_key, tr.symbol);
} }
@@ -589,9 +606,9 @@
function pickAnchorTrade() { function pickAnchorTrade() {
if (!trades.length) return null; if (!trades.length) return null;
if (selectedTradeId != null) { if (selectedTradeKey) {
const hit = trades.find(function (t) { const hit = trades.find(function (t) {
return String(t.trade_id || t.id) === String(selectedTradeId); return tradeRowKey(t) === selectedTradeKey;
}); });
if (hit) return hit; if (hit) return hit;
} }
@@ -721,10 +738,10 @@
const multi = sorted.length > 1; const multi = sorted.length > 1;
const out = []; const out = [];
sorted.forEach(function (row, idx) { sorted.forEach(function (row, idx) {
const tid = String(row.trade_id || row.id); const rowKey = tradeRowKey(row);
const parts = buildTradeMarkers(row, candles, tf, { const parts = buildTradeMarkers(row, candles, tf, {
labelSuffix: multi ? String(idx + 1) : "", labelSuffix: multi ? String(idx + 1) : "",
highlight: tid === String(selectedTradeId), highlight: rowKey === selectedTradeKey,
}); });
out.push.apply(out, parts); out.push.apply(out, parts);
}); });
@@ -937,7 +954,7 @@
return; return;
} }
selected = { exchange_key: exKey, symbol: sym }; selected = { exchange_key: exKey, symbol: sym };
selectedTradeId = String(tr.trade_id || tr.id); selectedTradeKey = tradeRowKey(tr);
renderTrades(); renderTrades();
setChartOpen(true); setChartOpen(true);
await loadSymbolTradesForChart(exKey, sym); await loadSymbolTradesForChart(exKey, sym);
@@ -960,14 +977,17 @@
.map(function (t) { .map(function (t) {
const tid = t.trade_id || t.id; const tid = t.trade_id || t.id;
const exKey = String(t.exchange_key || "").toLowerCase(); const exKey = String(t.exchange_key || "").toLowerCase();
const rowKey = tradeRowKey(t);
const tag = t.behavior_tag || ""; const tag = t.behavior_tag || "";
const sick = tag === "sick"; const sick = tag === "sick";
const active = String(tid) === String(selectedTradeId) ? " is-active" : ""; const active = rowKey && rowKey === selectedTradeKey ? " is-active" : "";
const rev = reviewMark(t); const rev = reviewMark(t);
return ( return (
'<tr class="archive-trade-row' + '<tr class="archive-trade-row' +
active + active +
(sick ? " archive-trade-sick" : "") + (sick ? " archive-trade-sick" : "") +
'" data-key="' +
esc(rowKey) +
'" data-id="' + '" data-id="' +
tid + tid +
'" data-ex="' + '" data-ex="' +
@@ -1051,13 +1071,11 @@
btn.addEventListener("click", function (ev) { btn.addEventListener("click", function (ev) {
ev.stopPropagation(); ev.stopPropagation();
const row = btn.closest(".archive-trade-row"); const row = btn.closest(".archive-trade-row");
const tid = btn.getAttribute("data-id"); const rowKey = row && row.getAttribute("data-key");
const tr = dailyTrades.find(function (t) { const tr = findTradeByKey(rowKey);
return String(t.trade_id || t.id) === String(tid);
});
if (tr) void openTradeChart(tr); if (tr) void openTradeChart(tr);
else if (row) { else if (rowKey) {
selectedTradeId = tid; selectedTradeKey = rowKey;
renderTrades(); renderTrades();
} }
}); });
@@ -1096,7 +1114,8 @@
setStatus(j.detail || j.msg || "删除失败"); setStatus(j.detail || j.msg || "删除失败");
return; return;
} }
if (String(selectedTradeId) === String(tradeId)) selectedTradeId = null; const deletedKey = String(exchangeKey || "").toLowerCase() + ":" + String(tradeId);
if (selectedTradeKey === deletedKey) selectedTradeKey = null;
await loadDailyTrades(); await loadDailyTrades();
setStatus("已移除 1 笔档案记录"); setStatus("已移除 1 笔档案记录");
} }
@@ -1106,7 +1125,9 @@
if (!exKey) return; if (!exKey) return;
const body = { behavior_tag: tag || "", note: note != null ? note : undefined }; const body = { behavior_tag: tag || "", note: note != null ? note : undefined };
if (note == null) { if (note == null) {
const row = elTrades.querySelector('.archive-trade-row[data-id="' + tradeId + '"]'); const row = elTrades.querySelector(
'.archive-trade-row[data-id="' + tradeId + '"][data-ex="' + exKey + '"]'
);
const inp = row && row.querySelector(".archive-note-input"); const inp = row && row.querySelector(".archive-note-input");
body.note = inp ? inp.value : ""; body.note = inp ? inp.value : "";
} }
@@ -1116,7 +1137,10 @@
body: JSON.stringify(body), body: JSON.stringify(body),
}); });
const tr = dailyTrades.find(function (t) { const tr = dailyTrades.find(function (t) {
return String(t.trade_id || t.id) === String(tradeId); return (
String(t.trade_id || t.id) === String(tradeId) &&
String(t.exchange_key || "").toLowerCase() === String(exKey).toLowerCase()
);
}); });
if (tr) { if (tr) {
tr.behavior_tag = body.behavior_tag; tr.behavior_tag = body.behavior_tag;
+1 -1
View File
@@ -584,7 +584,7 @@
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script> <script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
<script src="/assets/chart_draw.js?v=20260609-market-day-split"></script> <script src="/assets/chart_draw.js?v=20260609-market-day-split"></script>
<script src="/assets/chart.js?v=20260609-market-day-split"></script> <script src="/assets/chart.js?v=20260609-market-day-split"></script>
<script src="/assets/archive.js?v=20260612-archive-chart-row"></script> <script src="/assets/archive.js?v=20260612-trade-row-key"></script>
<script src="/assets/funds.js?v=20260609-hub-funds-fold"></script> <script src="/assets/funds.js?v=20260609-hub-funds-fold"></script>
<script src="/assets/dashboard.js?v=20260612-dash-monitor-count"></script> <script src="/assets/dashboard.js?v=20260612-dash-monitor-count"></script>
<script src="/assets/ai_review_render.js?v=3"></script> <script src="/assets/ai_review_render.js?v=3"></script>