feat: auto sick tag in archive from journal mood issues

内照明心同步时匹配实例复盘情绪标签,自动标注犯病并锁定标签;中控不再手动选犯病。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-07 01:12:47 +08:00
parent 2a3d264c8f
commit d7fa596e68
5 changed files with 218 additions and 26 deletions
+12
View File
@@ -7126,6 +7126,18 @@ body.funds-fullscreen-open {
color: var(--text);
font-size: 0.75rem;
}
.archive-tag-fixed {
display: inline-block;
padding: 4px 8px;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 600;
}
.archive-tag-fixed.is-tag-sick {
color: var(--red);
border: 1px solid color-mix(in srgb, var(--red) 45%, var(--border-soft));
background: color-mix(in srgb, var(--red) 14%, var(--inset-surface));
}
.archive-tag-select.is-tag-sick {
color: var(--red);
border-color: color-mix(in srgb, var(--red) 45%, var(--border-soft));
+40 -24
View File
@@ -1230,7 +1230,8 @@
const tid = t.trade_id || t.id;
const exKey = String(t.exchange_key || "").toLowerCase();
const rowKey = tradeRowKey(t);
const tag = t.behavior_tag || "";
const journalSick = !!t.behavior_tag_from_journal;
const tag = journalSick ? "sick" : (t.behavior_tag || "");
const sick = tag === "sick";
const active = rowKey && rowKey === selectedTradeKey ? " is-active" : "";
const rev = reviewMark(t);
@@ -1283,21 +1284,23 @@
"<td>" +
fmtFeeStat(t.exchange_commission_usdt) +
"</td>" +
'<td><select class="archive-tag-select" data-id="' +
tid +
'" data-ex="' +
esc(exKey) +
'">' +
'<option value=""' +
(tag === "" ? " selected" : "") +
">—</option>" +
'<option value="sick"' +
(tag === "sick" ? " selected" : "") +
">犯病</option>" +
'<option value="emotion"' +
(tag === "emotion" ? " selected" : "") +
">情绪</option>" +
"</select></td>" +
(journalSick
? '<td><span class="archive-tag-fixed is-tag-sick" title="实例复盘已勾选情绪标签">犯病</span></td>'
: '<td><select class="archive-tag-select" data-id="' +
tid +
'" data-ex="' +
esc(exKey) +
'">' +
'<option value=""' +
(tag === "" ? " selected" : "") +
">—</option>" +
'<option value="sick"' +
(tag === "sick" ? " selected" : "") +
">犯病</option>" +
'<option value="emotion"' +
(tag === "emotion" ? " selected" : "") +
">情绪</option>" +
"</select></td>") +
'<td><input class="archive-note-input" data-id="' +
tid +
'" data-ex="' +
@@ -1366,10 +1369,17 @@
inp.addEventListener("change", function () {
const row = inp.closest(".archive-trade-row");
const tagSel = row && row.querySelector(".archive-tag-select");
const tr = findTradeByKey(row && row.getAttribute("data-key"));
const tag =
tr && tr.behavior_tag_from_journal
? "sick"
: tagSel
? tagSel.value
: "";
saveOverlay(
inp.getAttribute("data-id"),
inp.getAttribute("data-ex"),
tagSel ? tagSel.value : "",
tag,
inp.value
);
});
@@ -1398,7 +1408,19 @@
async function saveOverlay(tradeId, exchangeKey, tag, note) {
const exKey = exchangeKey || (selected && selected.exchange_key);
if (!exKey) return;
const body = { behavior_tag: tag || "", note: note != null ? note : undefined };
const tr = dailyTrades.find(function (t) {
return (
String(t.trade_id || t.id) === String(tradeId) &&
String(t.exchange_key || "").toLowerCase() === String(exKey).toLowerCase()
);
});
if (tr && tr.behavior_tag_from_journal && tag != null && String(tag) !== "sick") {
return;
}
const body = {
behavior_tag: tr && tr.behavior_tag_from_journal ? "sick" : tag || "",
note: note != null ? note : undefined,
};
if (note == null) {
const row = elTrades.querySelector(
'.archive-trade-row[data-id="' + tradeId + '"][data-ex="' + exKey + '"]'
@@ -1411,12 +1433,6 @@
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const tr = dailyTrades.find(function (t) {
return (
String(t.trade_id || t.id) === String(tradeId) &&
String(t.exchange_key || "").toLowerCase() === String(exKey).toLowerCase()
);
});
if (tr) {
tr.behavior_tag = body.behavior_tag;
tr.note = body.note;