fix(HEL-221): 按确认样图实现情绪周期左右等高与夜间提示

桌面分析区固定 600px 并 stretch 对齐,评分构成在剩余高度内分配;夜间 tooltip 使用指定深色对比度,图表按容器尺寸重绘且不随视口拉满整页。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总工
2026-08-28 15:01:22 +00:00
co-authored by Cursor multica-agent
parent 8a5e78f022
commit 213f735f6a
5 changed files with 265 additions and 10 deletions
+73 -6
View File
@@ -1011,9 +1011,9 @@
border-radius: 6px;
background: var(--r2-ink);
background: var(--sentiment-tooltip-bg);
color: var(--text-inverse);
color: var(--sentiment-tooltip-fg);
font-size: 11px;
@@ -1021,6 +1021,8 @@
}
.sentiment-chart-tooltip b {
color: inherit;
font-weight: 700;
}
@@ -1568,10 +1570,6 @@
#sentimentCycleView .sentiment-component-item {
padding: 4px 0px;
}
#sentimentCycleView .sentiment-component-item small {
display: none;
}
}
@media (min-width: 768px) {
@@ -1764,3 +1762,72 @@
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 1024px) {
#sentimentCycleView .redesigned-emotion-grid {
align-items: stretch;
height: var(--sentiment-analysis-height);
max-height: var(--sentiment-analysis-height);
overflow: hidden;
}
.redesigned-sentiment-view .sentiment-analysis-main,
.redesigned-sentiment-view .sentiment-analysis-rail {
align-self: stretch;
height: 100%;
min-height: 0px;
}
.redesigned-sentiment-view .sentiment-trend-panel {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0px;
}
.redesigned-sentiment-view .sentiment-chart-shell {
flex: 1 1 auto;
height: auto;
min-height: 0px;
}
.redesigned-sentiment-view .sentiment-chart-shell canvas {
height: 100%;
}
.redesigned-sentiment-view .sentiment-cycle-summary {
flex: 0 0 auto;
}
.redesigned-sentiment-view .sentiment-components-panel {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-height: 0px;
}
.redesigned-sentiment-view .sentiment-component-list {
display: flex;
flex: 1 1 auto;
flex-direction: column;
justify-content: space-evenly;
min-height: 0px;
}
}
+38 -4
View File
@@ -1,10 +1,39 @@
let sentimentChartAnimationFrame = null;
let sentimentChartResizeObserver = null;
let sentimentChartLastSize = "";
window.XiaobaiPageModules.register("sentiment", ["sentimentCycleView"], {
bind: bindSentimentEvents,
enter: ["loadSentiment"],
});
function sentimentChartSizeKey(target) {
if (!target) return "";
const rect = target.getBoundingClientRect();
return `${Math.round(rect.width)}x${Math.round(rect.height)}x${window.devicePixelRatio || 1}`;
}
function observeSentimentTrendChart() {
const shell = document.querySelector("#sentimentCycleView .sentiment-chart-shell");
if (!shell) return;
if (!sentimentChartResizeObserver) {
sentimentChartResizeObserver = new ResizeObserver(() => {
if (sentimentChartAnimationFrame) return;
if (state.activeView !== "sentimentCycleView") return;
const rows = state.sentimentHistory?.rows;
if (!rows?.length) return;
const current = document.querySelector("#sentimentCycleView .sentiment-chart-shell");
const nextKey = sentimentChartSizeKey(current);
if (!nextKey || nextKey === sentimentChartLastSize) return;
drawSentimentTrendChart(rows, 1);
});
} else {
sentimentChartResizeObserver.disconnect();
}
sentimentChartLastSize = sentimentChartSizeKey(shell);
sentimentChartResizeObserver.observe(shell);
}
async function loadSentimentHistory(force = false) {
if (!state.dashboard || state.sentimentLoading) return;
const key = `${elements.tradeDate.value}:${state.sentimentRange}`;
@@ -126,6 +155,7 @@ function animateSentimentTrendChart(rows) {
if (sentimentChartAnimationFrame) cancelAnimationFrame(sentimentChartAnimationFrame);
if (!motionEnabled()) {
drawSentimentTrendChart(rows, 1);
observeSentimentTrendChart();
return;
}
const startedAt = performance.now();
@@ -135,7 +165,10 @@ function animateSentimentTrendChart(rows) {
const progress = 1 - (1 - rawProgress) ** 3;
drawSentimentTrendChart(rows, progress);
if (rawProgress < 1) sentimentChartAnimationFrame = requestAnimationFrame(frame);
else sentimentChartAnimationFrame = null;
else {
sentimentChartAnimationFrame = null;
observeSentimentTrendChart();
}
};
sentimentChartAnimationFrame = requestAnimationFrame(frame);
}
@@ -144,9 +177,9 @@ function drawSentimentTrendChart(rows, progress = 1) {
const canvas = document.querySelector("#sentimentTrendChart");
if (!canvas || !rows.length || state.activeView !== "sentimentCycleView") return;
const rect = canvas.getBoundingClientRect();
if (!rect.width) return;
const width = Math.max(320, rect.width);
const height = Math.max(220, rect.height);
if (rect.width < 8 || rect.height < 8) return;
const width = rect.width;
const height = rect.height;
const ratio = window.devicePixelRatio || 1;
canvas.width = Math.round(width * ratio);
canvas.height = Math.round(height * ratio);
@@ -258,6 +291,7 @@ function drawSentimentTrendChart(rows, progress = 1) {
const dateText = displayCompactDate(row.trade_date).slice(5);
context.fillText(dateText, x(index), height - padding.bottom + 10);
});
sentimentChartLastSize = sentimentChartSizeKey(canvas.closest(".sentiment-chart-shell"));
}
function bindSentimentChartTooltip(rows) {
+5
View File
@@ -210,6 +210,9 @@
--pool-table-max-height: calc(var(--content-height) - var(--topbar-height) - var(--page-pad-y) - var(--page-pad-y) - var(--card-gap));
--sentiment-history-max-height: 510px;
--sentiment-history-min-height: 220px;
--sentiment-analysis-height: 600px;
--sentiment-tooltip-bg: var(--text-primary);
--sentiment-tooltip-fg: var(--text-inverse);
--primary-share: 1.45fr;
--secondary-share: .75fr;
--mobile-nav-height: 64px;
@@ -505,6 +508,8 @@
--chart-repair: #e2ad58;
--chart-ma-10: #d39a45;
--chart-ma-20: #9aa5af;
--sentiment-tooltip-bg: #26293e;
--sentiment-tooltip-fg: #e8eaed;
--on-action: #101418;
--warning-line: #6d5a38;
--warning-line-strong: #66502d;