fix(ui): light-theme badges, PnL colors, and journal detail across four exchanges

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-05 13:16:29 +08:00
parent 1b51f73ecd
commit e30d24173f
6 changed files with 187 additions and 124 deletions
+3 -31
View File
@@ -231,7 +231,7 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
</style>
<link rel="stylesheet" href="/static/instance_theme.css?v=5">
<link rel="stylesheet" href="/static/instance_theme.css?v=6">
</head>
<body data-page="{{ page }}">
@@ -900,6 +900,7 @@
</div>
</div>
<script src="/static/instance_ui.js?v=1"></script>
<script src="/static/ai_review_render.js?v=1"></script>
<script src="/static/form_submit_guard.js?v=2"></script>
<script>
@@ -1018,36 +1019,7 @@ function formatJournalExitOneLine(o){
}
function openJournalDetail(id){
const o = journalCache[id];
if(!o){ return; }
const moodTags = (o.mood_issues || []).join(",") || "无";
const detail = [
`币种/周期:${o.coin || "-"} ${o.tf || "-"}`,
`开仓时间:${o.open_datetime || "-"}`,
`平仓时间:${o.close_datetime || "-"}`,
`持仓时长:${o.hold_duration || "-"}`,
`盈亏:${o.pnl || "-"}U`,
`开仓类型:${o.entry_reason || "无"}`,
`平仓/离场:${formatJournalExitOneLine(o)}`,
`预期RR${o.expect_rr || "-"}`,
`实际RR${o.real_rr || "-"}`,
`保本后盯盘:${o.post_breakeven_stare || "-"}`,
`占用时新开仓:${o.new_trade_while_occupied || "-"}`,
`心态标签:${moodTags}`,
`备注:${o.note || "无"}`,
].join("\n");
document.getElementById("detailTitle").innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
setDetailBodyPlain(detail);
const imgEl = document.getElementById("detailImage");
if(o.image){
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
setDetailModalFullscreen(false);
document.getElementById("detailModal").style.display = "flex";
InstanceUI.openJournalDetailModal(id, journalCache, formatJournalExitOneLine);
}
function openReviewDetail(id, fullscreen){
+3 -31
View File
@@ -231,7 +231,7 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
</style>
<link rel="stylesheet" href="/static/instance_theme.css?v=5">
<link rel="stylesheet" href="/static/instance_theme.css?v=6">
</head>
<body data-page="{{ page }}">
@@ -900,6 +900,7 @@
</div>
</div>
<script src="/static/instance_ui.js?v=1"></script>
<script src="/static/ai_review_render.js?v=1"></script>
<script src="/static/form_submit_guard.js?v=2"></script>
<script>
@@ -1018,36 +1019,7 @@ function formatJournalExitOneLine(o){
}
function openJournalDetail(id){
const o = journalCache[id];
if(!o){ return; }
const moodTags = (o.mood_issues || []).join(",") || "无";
const detail = [
`币种/周期:${o.coin || "-"} ${o.tf || "-"}`,
`开仓时间:${o.open_datetime || "-"}`,
`平仓时间:${o.close_datetime || "-"}`,
`持仓时长:${o.hold_duration || "-"}`,
`盈亏:${o.pnl || "-"}U`,
`开仓类型:${o.entry_reason || "无"}`,
`平仓/离场:${formatJournalExitOneLine(o)}`,
`预期RR${o.expect_rr || "-"}`,
`实际RR${o.real_rr || "-"}`,
`保本后盯盘:${o.post_breakeven_stare || "-"}`,
`占用时新开仓:${o.new_trade_while_occupied || "-"}`,
`心态标签:${moodTags}`,
`备注:${o.note || "无"}`,
].join("\n");
document.getElementById("detailTitle").innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
setDetailBodyPlain(detail);
const imgEl = document.getElementById("detailImage");
if(o.image){
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
setDetailModalFullscreen(false);
document.getElementById("detailModal").style.display = "flex";
InstanceUI.openJournalDetailModal(id, journalCache, formatJournalExitOneLine);
}
function openReviewDetail(id, fullscreen){
+3 -31
View File
@@ -268,7 +268,7 @@
.stats-split-row{grid-template-columns:1fr}
}
</style>
<link rel="stylesheet" href="/static/instance_theme.css?v=5">
<link rel="stylesheet" href="/static/instance_theme.css?v=6">
</head>
<body data-page="{{ page }}">
@@ -869,6 +869,7 @@
</div>
</div>
<script src="/static/instance_ui.js?v=1"></script>
<script src="/static/ai_review_render.js?v=1"></script>
<script src="/static/form_submit_guard.js?v=2"></script>
<script>
@@ -1022,36 +1023,7 @@ function formatJournalExitOneLine(o){
}
function openJournalDetail(id){
const o = journalCache[id];
if(!o){ return; }
const moodTags = (o.mood_issues || []).join(",") || "无";
const detail = [
`币种/周期:${o.coin || "-"} ${o.tf || "-"}`,
`开仓时间:${o.open_datetime || "-"}`,
`平仓时间:${o.close_datetime || "-"}`,
`持仓时长:${o.hold_duration || "-"}`,
`盈亏:${o.pnl || "-"}U`,
`开仓类型:${o.entry_reason || "无"}`,
`平仓/离场:${formatJournalExitOneLine(o)}`,
`预期RR${o.expect_rr || "-"}`,
`实际RR${o.real_rr || "-"}`,
`保本后盯盘:${o.post_breakeven_stare || "-"}`,
`占用时新开仓:${o.new_trade_while_occupied || "-"}`,
`心态标签:${moodTags}`,
`备注:${o.note || "无"}`,
].join("\n");
document.getElementById("detailTitle").innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
setDetailBodyPlain(detail);
const imgEl = document.getElementById("detailImage");
if(o.image){
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
setDetailModalFullscreen(false);
document.getElementById("detailModal").style.display = "flex";
InstanceUI.openJournalDetailModal(id, journalCache, formatJournalExitOneLine);
}
function openReviewDetail(id, fullscreen){
+3 -31
View File
@@ -231,7 +231,7 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
</style>
<link rel="stylesheet" href="/static/instance_theme.css?v=5">
<link rel="stylesheet" href="/static/instance_theme.css?v=6">
</head>
<body data-page="{{ page }}">
@@ -909,6 +909,7 @@
</div>
</div>
<script src="/static/instance_ui.js?v=1"></script>
<script src="/static/ai_review_render.js?v=1"></script>
<script src="/static/form_submit_guard.js?v=2"></script>
<script>
@@ -1027,36 +1028,7 @@ function formatJournalExitOneLine(o){
}
function openJournalDetail(id){
const o = journalCache[id];
if(!o){ return; }
const moodTags = (o.mood_issues || []).join(",") || "无";
const detail = [
`币种/周期:${o.coin || "-"} ${o.tf || "-"}`,
`开仓时间:${o.open_datetime || "-"}`,
`平仓时间:${o.close_datetime || "-"}`,
`持仓时长:${o.hold_duration || "-"}`,
`盈亏:${o.pnl || "-"}U`,
`开仓类型:${o.entry_reason || "无"}`,
`平仓/离场:${formatJournalExitOneLine(o)}`,
`预期RR${o.expect_rr || "-"}`,
`实际RR${o.real_rr || "-"}`,
`保本后盯盘:${o.post_breakeven_stare || "-"}`,
`占用时新开仓:${o.new_trade_while_occupied || "-"}`,
`心态标签:${moodTags}`,
`备注:${o.note || "无"}`,
].join("\n");
document.getElementById("detailTitle").innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
setDetailBodyPlain(detail);
const imgEl = document.getElementById("detailImage");
if(o.image){
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
setDetailModalFullscreen(false);
document.getElementById("detailModal").style.display = "flex";
InstanceUI.openJournalDetailModal(id, journalCache, formatJournalExitOneLine);
}
function openReviewDetail(id, fullscreen){
+81
View File
@@ -337,6 +337,87 @@ html[data-theme="light"] .detail-modal .panel-image {
border-color: #b8c8d8 !important;
}
html[data-theme="light"] .detail-modal .panel-close {
background: #f6f9fc !important;
color: #4a6078 !important;
border: 1px solid #b8c8d8 !important;
}
/* ── 交易记录:方向 / 结果徽章(浅底描边,避免黑底块)── */
html[data-theme="light"] .badge.direction-long,
html[data-theme="light"] .direction-long {
background: rgba(8, 122, 80, 0.1) !important;
color: #087a50 !important;
border: 1px solid rgba(8, 122, 80, 0.28) !important;
font-weight: 600 !important;
}
html[data-theme="light"] .badge.direction-short,
html[data-theme="light"] .direction-short {
background: rgba(192, 48, 48, 0.08) !important;
color: #b03030 !important;
border: 1px solid rgba(192, 48, 48, 0.25) !important;
font-weight: 600 !important;
}
html[data-theme="light"] .badge.profit {
background: rgba(8, 122, 80, 0.1) !important;
color: #087a50 !important;
border: 1px solid rgba(8, 122, 80, 0.28) !important;
font-weight: 600 !important;
}
html[data-theme="light"] .badge.loss {
background: rgba(192, 48, 48, 0.08) !important;
color: #b03030 !important;
border: 1px solid rgba(192, 48, 48, 0.25) !important;
font-weight: 600 !important;
}
html[data-theme="light"] .badge.miss {
background: rgba(180, 130, 20, 0.1) !important;
color: #8a6200 !important;
border: 1px solid rgba(180, 130, 20, 0.28) !important;
font-weight: 600 !important;
}
html[data-theme="light"] .badge.direction {
background: rgba(0, 110, 154, 0.08) !important;
color: #006e9a !important;
border: 1px solid rgba(0, 110, 154, 0.22) !important;
}
html[data-theme="light"] .table-del,
html[data-theme="light"] button.table-del {
background: #fff5f5 !important;
color: #b03030 !important;
border: 1px solid rgba(176, 48, 48, 0.28) !important;
}
html[data-theme="light"] .pos-breakeven-badge {
background: rgba(8, 122, 80, 0.1) !important;
color: #087a50 !important;
border: 1px solid rgba(8, 122, 80, 0.25) !important;
}
/* ── 实时持仓 / 行情:浮盈亏涨跌色 ── */
html[data-theme="light"] .price-up,
html[data-theme="light"] .pos-value.price-up {
color: #087a50 !important;
font-weight: 600 !important;
}
html[data-theme="light"] .price-down,
html[data-theme="light"] .pos-value.price-down {
color: #c03030 !important;
font-weight: 600 !important;
}
html[data-theme="light"] .journal-detail-meta {
color: #1a2838 !important;
line-height: 1.65 !important;
}
html[data-theme="light"] .journal-card .form-grid label,
html[data-theme="light"] .journal-card .sub {
color: #4a6078 !important;
+94
View File
@@ -0,0 +1,94 @@
/**
* 四所实例共用 UI复盘详情盈亏着色等
*/
(function (global) {
"use strict";
function escapeHtml(s) {
return String(s == null ? "" : s)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function pnlClassFromValue(val) {
const n = Number(String(val == null ? "" : val).replace(/[^\d.-]/g, ""));
if (!Number.isFinite(n) || n === 0) return "";
return n > 0 ? "pnl-profit" : "pnl-loss";
}
function formatPnlSpan(val, suffix) {
const sfx = suffix == null ? "U" : suffix;
const cls = pnlClassFromValue(val);
const text = escapeHtml(val == null || val === "" ? "-" : val) + sfx;
return cls ? `<span class="${cls}">${text}</span>` : text;
}
function buildJournalDetailHtml(o, formatExitLine) {
const moodTags =
Array.isArray(o.mood_issues) && o.mood_issues.length
? o.mood_issues.join(",")
: o.mood_issues || "无";
const exitText =
typeof formatExitLine === "function" ? formatExitLine(o) : o.exit_reason || "无";
const lines = [
`币种/周期:${escapeHtml(o.coin || "-")} ${escapeHtml(o.tf || "-")}`,
`开仓时间:${escapeHtml(o.open_datetime || "-")}`,
`平仓时间:${escapeHtml(o.close_datetime || "-")}`,
`持仓时长:${escapeHtml(o.hold_duration || "-")}`,
`盈亏:${formatPnlSpan(o.pnl)}`,
`开仓类型:${escapeHtml(o.entry_reason || "无")}`,
`平仓/离场:${escapeHtml(exitText)}`,
`预期RR${escapeHtml(o.expect_rr || "-")}`,
`实际RR${escapeHtml(o.real_rr || "-")}`,
`保本后盯盘:${escapeHtml(o.post_breakeven_stare || "-")}`,
`占用时新开仓:${escapeHtml(o.new_trade_while_occupied || "-")}`,
`心态标签:${escapeHtml(moodTags)}`,
`备注:${escapeHtml(o.note || "无")}`,
];
return lines.join("<br>");
}
function setJournalDetailBody(o, formatExitLine) {
const body = document.getElementById("detailBody");
if (!body) return;
body.classList.remove("md-review");
body.classList.add("journal-detail-meta");
body.innerHTML = buildJournalDetailHtml(o, formatExitLine);
}
function openJournalDetailModal(id, journalCache, formatExitLine) {
const o = journalCache && journalCache[id];
if (!o) return;
const titleEl = document.getElementById("detailTitle");
if (titleEl) {
titleEl.innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
}
setJournalDetailBody(o, formatExitLine);
const imgEl = document.getElementById("detailImage");
if (imgEl) {
if (o.image) {
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
}
if (typeof setDetailModalFullscreen === "function") {
setDetailModalFullscreen(false);
}
const modal = document.getElementById("detailModal");
if (modal) modal.style.display = "flex";
}
global.InstanceUI = {
escapeHtml: escapeHtml,
pnlClassFromValue: pnlClassFromValue,
formatPnlSpan: formatPnlSpan,
buildJournalDetailHtml: buildJournalDetailHtml,
setJournalDetailBody: setJournalDetailBody,
openJournalDetailModal: openJournalDetailModal,
};
})(typeof window !== "undefined" ? window : globalThis);