fix(hub): add section icons and color PnL in AI summary table
Show emoji headings for overview, accounts, alerts, and data notes; apply green/red styling to table PnL columns. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3541,6 +3541,20 @@ body.hub-page-ai #page-ai {
|
|||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
border-bottom: 1px solid var(--border-soft);
|
border-bottom: 1px solid var(--border-soft);
|
||||||
}
|
}
|
||||||
|
.ai-md-body.ai-result-md h2:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.ai-md-body.ai-result-md h3 {
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: var(--accent-2, var(--accent));
|
||||||
|
margin: 16px 0 8px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
border-bottom: 1px solid var(--border-soft);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.ai-md-body.ai-result-md h3:first-of-type {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
.ai-result-md h3,
|
.ai-result-md h3,
|
||||||
.ai-result-md h4 {
|
.ai-result-md h4 {
|
||||||
font-size: 0.92rem;
|
font-size: 0.92rem;
|
||||||
@@ -3609,23 +3623,9 @@ body.hub-page-ai #page-ai {
|
|||||||
background: color-mix(in srgb, var(--accent-dim) 35%, transparent);
|
background: color-mix(in srgb, var(--accent-dim) 35%, transparent);
|
||||||
}
|
}
|
||||||
.ai-ac-name {
|
.ai-ac-name {
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 8px;
|
|
||||||
min-width: 9rem;
|
min-width: 9rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.ai-ac-name > span:last-child {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
.ai-ex-icon {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
line-height: 0;
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.ai-ac-remark {
|
.ai-ac-remark {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 0.74rem;
|
font-size: 0.74rem;
|
||||||
@@ -3640,8 +3640,12 @@ body.hub-page-ai #page-ai {
|
|||||||
.ai-ac-warn {
|
.ai-ac-warn {
|
||||||
color: var(--amber, #d4a017);
|
color: var(--amber, #d4a017);
|
||||||
}
|
}
|
||||||
.ai-ac-table .pos,
|
.ai-ac-table .ai-stat-val.pos {
|
||||||
.ai-ac-table .neg {
|
color: var(--green);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.ai-ac-table .ai-stat-val.neg {
|
||||||
|
color: var(--red);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.ai-placeholder {
|
.ai-placeholder {
|
||||||
|
|||||||
@@ -2972,43 +2972,20 @@
|
|||||||
return renderHubMarkdown(text);
|
return renderHubMarkdown(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AI_EX_SVG = {
|
function enhanceHubSummaryMarkdown(md) {
|
||||||
binance:
|
let out = String(md || "");
|
||||||
'<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><rect width="24" height="24" rx="5" fill="#F0B90B"/><path fill="#1E2329" d="M12 4.5l2.2 2.2L12 8.9 9.8 6.7 12 4.5zm0 14.6l2.2-2.2L12 15.1l-2.2 2.2 2.2 2.2zM4.5 12l2.2-2.2L8.9 12l-2.2 2.2L4.5 12zm14.6 0l2.2-2.2L15.1 12l2.2-2.2 2.2 2.2z"/></svg>',
|
out = out.replace(/\*\*今日交易总结(([^)]+))\*\*/g, "# 📋 今日交易总结($1)");
|
||||||
okx:
|
out = out.replace(/\*\*1\.\s*(?:📊\s*)?总览\*\*/g, "## 1. 📊 总览");
|
||||||
'<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><rect width="24" height="24" rx="5" fill="#000"/><rect x="5" y="5" width="6" height="6" fill="#fff"/><rect x="13" y="5" width="6" height="6" fill="#fff"/><rect x="5" y="13" width="6" height="6" fill="#fff"/><rect x="13" y="13" width="6" height="6" fill="#fff"/></svg>',
|
out = out.replace(/\*\*2\.\s*(?:👥\s*)?分户明细\*\*/g, "## 2. 👥 分户明细");
|
||||||
gate:
|
out = out.replace(/\*\*3\.\s*(?:⚠️\s*)?需关注\*\*/g, "## 3. ⚠️ 需关注");
|
||||||
'<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><rect width="24" height="24" rx="5" fill="#2354E6"/><path fill="#fff" d="M7 17V7h4.2c2.2 0 3.6 1.1 3.6 2.9 0 1.2-.6 2.1-1.6 2.5 1.2.4 2 1.4 2 2.8 0 2-1.5 3.1-3.8 3.1H7zm2.5-2.1h1.5c1.1 0 1.7-.5 1.7-1.3s-.6-1.3-1.7-1.3H9.5v2.6zm0-4.4h1.4c1 0 1.5-.4 1.5-1.2s-.5-1.2-1.5-1.2H9.5v2.4z"/></svg>',
|
out = out.replace(/\*\*4\.\s*(?:ℹ️\s*)?数据说明\*\*/g, "## 4. ℹ️ 数据说明");
|
||||||
gate_bot:
|
return out;
|
||||||
'<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><rect width="24" height="24" rx="5" fill="#17E6A1"/><path fill="#102820" d="M7 17V7h4.2c2.2 0 3.6 1.1 3.6 2.9 0 1.2-.6 2.1-1.6 2.5 1.2.4 2 1.4 2 2.8 0 2-1.5 3.1-3.8 3.1H7zm2.5-2.1h1.5c1.1 0 1.7-.5 1.7-1.3s-.6-1.3-1.7-1.3H9.5v2.6zm0-4.4h1.4c1 0 1.5-.4 1.5-1.2s-.5-1.2-1.5-1.2H9.5v2.4z"/></svg>',
|
|
||||||
other:
|
|
||||||
'<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><rect width="24" height="24" rx="5" fill="var(--border-soft)"/><circle cx="12" cy="12" r="3" fill="var(--muted)"/></svg>',
|
|
||||||
};
|
|
||||||
|
|
||||||
function resolveExchangeIconId(key, name) {
|
|
||||||
const k = String(key || "").toLowerCase();
|
|
||||||
const n = String(name || "").toLowerCase();
|
|
||||||
if (k === "gate_bot" || k.includes("gate_bot") || n.includes("趋势") || n.includes("gate_bot"))
|
|
||||||
return "gate_bot";
|
|
||||||
if (k === "binance" || k.includes("binance") || n.includes("币安")) return "binance";
|
|
||||||
if (k === "okx" || k.includes("okx")) return "okx";
|
|
||||||
if (k === "gate" || k.includes("gate") || n.includes("gate")) return "gate";
|
|
||||||
return "other";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hubExchangeIconHtml(key, name) {
|
function aiPnlCellHtml(v, digits) {
|
||||||
const id = resolveExchangeIconId(key, name);
|
const cls = aiPnlClass(v);
|
||||||
const title =
|
const valCls = cls ? ` ai-stat-val ${cls}` : " ai-stat-val";
|
||||||
id === "binance"
|
return `<span class="${valCls.trim()}">${aiPnlSigned(v, digits)}</span>`;
|
||||||
? "Binance"
|
|
||||||
: id === "okx"
|
|
||||||
? "OKX"
|
|
||||||
: id === "gate_bot"
|
|
||||||
? "Gate Bot"
|
|
||||||
: id === "gate"
|
|
||||||
? "Gate"
|
|
||||||
: "";
|
|
||||||
return `<span class="ai-ex-icon ai-ex-${id}" title="${esc(title)}">${AI_EX_SVG[id] || AI_EX_SVG.other}</span>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function aiAccountStatusClass(status) {
|
function aiAccountStatusClass(status) {
|
||||||
@@ -3038,11 +3015,11 @@
|
|||||||
const statusCls = aiAccountStatusClass(ac.status);
|
const statusCls = aiAccountStatusClass(ac.status);
|
||||||
return (
|
return (
|
||||||
"<tr>" +
|
"<tr>" +
|
||||||
`<td class="ai-ac-name">${hubExchangeIconHtml(ac.key, ac.name)}<span>${esc(ac.name || "—")}</span></td>` +
|
`<td class="ai-ac-name">${esc(ac.name || "—")}</td>` +
|
||||||
`<td class="${statusCls}">${esc(ac.status || "—")}</td>` +
|
`<td class="${statusCls}">${esc(ac.status || "—")}</td>` +
|
||||||
`<td class="${aiPnlClass(closedPnl)}">${aiPnlSigned(closedPnl, 2)}</td>` +
|
`<td>${aiPnlCellHtml(closedPnl, 2)}</td>` +
|
||||||
`<td>${Number(ac.closed_count) || 0}</td>` +
|
`<td>${Number(ac.closed_count) || 0}</td>` +
|
||||||
`<td class="${aiPnlClass(floatPnl)}">${aiPnlSigned(floatPnl, 2)}</td>` +
|
`<td>${aiPnlCellHtml(floatPnl, 2)}</td>` +
|
||||||
`<td class="ai-ac-remark">${esc(remark)}</td>` +
|
`<td class="ai-ac-remark">${esc(remark)}</td>` +
|
||||||
"</tr>"
|
"</tr>"
|
||||||
);
|
);
|
||||||
@@ -3052,9 +3029,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderAiSummaryBody(contentMd, snapshot) {
|
function renderAiSummaryBody(contentMd, snapshot) {
|
||||||
const md = String(contentMd || "");
|
const md = enhanceHubSummaryMarkdown(contentMd);
|
||||||
const sec2 = /\*\*2\.\s*分户明细\*\*/;
|
const sec2 = /##\s*2\.\s*👥\s*分户明细/;
|
||||||
const sec3 = /\*\*3\.\s*需关注\*\*/;
|
const sec3 = /##\s*3\.\s*⚠️\s*需关注/;
|
||||||
const i2 = md.search(sec2);
|
const i2 = md.search(sec2);
|
||||||
const i3 = md.search(sec3);
|
const i3 = md.search(sec3);
|
||||||
const tableHtml = renderAiAccountTable(snapshot);
|
const tableHtml = renderAiAccountTable(snapshot);
|
||||||
|
|||||||
@@ -288,6 +288,6 @@
|
|||||||
<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.js?v=20260604-upnl-contracts"></script>
|
<script src="/assets/chart.js?v=20260604-upnl-contracts"></script>
|
||||||
<script src="/assets/ai_review_render.js?v=2"></script>
|
<script src="/assets/ai_review_render.js?v=2"></script>
|
||||||
<script src="/assets/app.js?v=20260606-hub-ai-table"></script>
|
<script src="/assets/app.js?v=20260606-hub-ai-sec"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user