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:
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user