fix: merge B-157 and B-158 shell review blockers

Keep 1024-1439 broken/seal metrics in the detail panel, fold desktop admin actions into the ellipsis menu, and fit the 13-column limit pool at 1600 without hiding the data date.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
MS-01-Codex
2026-08-20 02:19:04 +08:00
co-authored by Cursor multica-agent
parent e778c883db
commit bb67085dd4
15 changed files with 334 additions and 158 deletions
+5 -5
View File
@@ -1178,14 +1178,14 @@ button.account-role-badge:focus-visible {
}
@media (min-width: 1280px) and (max-width: 1510px) {
.account-role-badge span {
display: none;
.app-header .header-command-group .account-role-badge span {
display: inline;
}
.account-role-badge {
min-width: 27px;
.app-header .header-command-group .account-role-badge {
min-width: 0;
justify-content: center;
justify-content: flex-start;
}
}
+40 -16
View File
@@ -1,11 +1,15 @@
/* Canonical CSS owner: cards. Historical layers consolidated 2026-08-02. */
.stock-name {
font-weight: 700;
font-size: var(--fs-table);
font-weight: 600;
}
.stock-code {
color: var(--text-muted);
color: var(--text-3);
font-size: var(--fs-aux);
font-variant-numeric: tabular-nums;
}
@@ -49,25 +53,37 @@
}
.streak-pill {
background: var(--coral-soft);
color: var(--coral);
font-weight: 700;
display: inline-flex;
align-items: center;
min-height: 24px;
justify-content: center;
padding: 2px 8px;
min-width: 30px;
border-radius: 4px;
height: 20px;
padding: 0 7px;
border-radius: 999px;
background: var(--up-soft);
color: var(--up);
font-size: var(--fs-caption);
font-weight: 600;
white-space: nowrap;
}
.streak-pill.high {
background: var(--up);
color: #fff;
}
.outcome-tag {
display: inline-flex;
@@ -253,21 +269,29 @@
}
.sname {
font-weight: 700;
font-weight: 600;
font-size: 13px;
font-size: var(--fs-table);
}
.scode {
font-size: 11px;
font-size: var(--fs-aux);
color: var(--faint);
color: var(--text-3);
margin-left: 6px;
margin-left: 0;
font-weight: 400;
}
.stock-cell {
display: flex;
flex-direction: column;
line-height: 1.3;
}
.muted {
color: var(--faint);
}
+1 -1
View File
@@ -1010,7 +1010,7 @@ textarea {
@media (min-width: 768px) {
.header-menu-button {
display: none;
display: inline-flex;
}
}
+19 -9
View File
@@ -14,13 +14,13 @@
.data-table th.sort-asc::after {
content: " ↑";
color: var(--blue);
color: var(--accent);
}
.data-table th.sort-desc::after {
content: " ↓";
color: var(--blue);
color: var(--accent);
}
.data-table tbody tr td {
@@ -114,9 +114,9 @@
text-align: left;
height: 42px;
height: 40px;
padding: 8px 11px;
padding: 0 12px;
border-right: 0px;
@@ -214,7 +214,9 @@
.data-table .stock-name {
color: var(--text-primary);
font-weight: 700;
font-size: var(--fs-table);
font-weight: 600;
}
.main-grid > .table-frame {
@@ -278,9 +280,9 @@
}
.main-grid .data-table thead th {
height: 34px;
height: 36px;
padding: 6px 10px;
padding: 0 12px;
}
.main-grid .data-table tbody td {
@@ -339,8 +341,16 @@
margin-left: 3px;
}
.tbl thead th.sorted .arr {
color: var(--blue);
.tbl thead th.sorted,
.data-table thead th.sorted,
.data-table thead th.sort-asc,
.data-table thead th.sort-desc {
color: var(--accent);
}
.tbl thead th.sorted .arr,
.data-table thead th.sorted .arr {
color: var(--accent);
}
.tbl tbody td {
+24 -14
View File
@@ -89,7 +89,10 @@ function renderDashboard() {
const { meta, overview, ladders, sectors } = state.dashboard;
animateMetric("tapeUp", overview.up_count, (value) => Math.round(value));
animateMetric("tapeDown", overview.down_count, (value) => Math.round(value));
setText("tapeLimit", `${overview.limit_up_count} / 跌停 ${overview.limit_down_count}`);
animateMetric("tapeLimit", overview.limit_up_count, (value) => `${Math.round(value)}`);
animateMetric("tapeLimitDown", overview.limit_down_count, (value) => `${Math.round(value)}`);
animateMetric("detailBroken", overview.broken_count, (value) => `${Math.round(value)}`);
animateMetric("detailSealRate", overview.seal_rate, (value) => `${formatNumber(value, 1)}%`);
animateMetric("tapeAmount", overview.amount_billion, (value) => `${formatNumber(value, 1)} 亿`);
animateMetric("limitUpMetric", overview.limit_up_count, (value) => `${Math.round(value)}`);
animateMetric("limitDownMetric", overview.limit_down_count, (value) => `${Math.round(value)}`);
@@ -98,22 +101,29 @@ function renderDashboard() {
animateMetric("amountMetric", overview.amount_billion, (value) => `${formatNumber(value, 1)} 亿`);
setText("dataDateMetric", dashboardDataTimestamp(meta));
animateMetric("sentimentScore", overview.sentiment_score, (value) => Math.round(value));
setText("sentimentText", sentimentLabel(overview.sentiment_score));
const sentimentChip = document.querySelector("#sentimentText");
if (sentimentChip) {
const label = sentimentLabel(overview.sentiment_score);
sentimentChip.classList.toggle("is-hot", label === "情绪高涨");
sentimentChip.classList.toggle("is-strong", label === "情绪偏强");
sentimentChip.classList.toggle("is-cold", label === "情绪冰点" || label === "情绪偏");
}
animateMetric("detailSentimentScore", overview.sentiment_score, (value) => Math.round(value));
const moodLabel = sentimentLabel(overview.sentiment_score);
setText("sentimentText", moodLabel);
setText("detailSentimentText", moodLabel);
document.querySelectorAll("#sentimentText, #detailSentimentText").forEach((sentimentChip) => {
sentimentChip.classList.toggle("is-hot", moodLabel === "情绪高涨");
sentimentChip.classList.toggle("is-strong", moodLabel === "情绪偏");
sentimentChip.classList.toggle("is-cold", moodLabel === "情绪冰点" || moodLabel === "情绪偏弱");
});
const pageSubtitle = document.querySelector("#currentPageSubtitle");
const activePage = window.XiaobaiPages?.get(state.activeView);
if (pageSubtitle && activePage?.id !== "mentorView") {
const groupLabel = activePage?.group === "market"
? "市场复盘"
: activePage?.group === "personal" ? "个人" : "智能工具";
if (pageSubtitle) {
const dateText = displayCompactDate(meta.trade_date);
pageSubtitle.textContent = dateText === "--" ? groupLabel : `${groupLabel} · ${dateText}`;
if (activePage?.id === "mentorView") {
pageSubtitle.textContent = dateText === "--"
? "与不同交易思维模型持续对话 · 数据日期 --"
: `与不同交易思维模型持续对话 · 数据日期 ${dateText}`;
} else {
const groupLabel = activePage?.group === "market"
? "市场复盘"
: activePage?.group === "personal" ? "个人" : "智能工具";
pageSubtitle.textContent = dateText === "--" ? groupLabel : `${groupLabel} · ${dateText}`;
}
}
updateSentimentGauge(overview.sentiment_score);
setText("updatedAt", `${dashboardSourceLabel(meta)} · 更新 ${formatTimestamp(meta.updated_at)}`);
+79 -50
View File
@@ -187,12 +187,6 @@ body.sidebar-collapsed .nav-group + .nav-group {
.metric {
border-top: 1px solid var(--line);
}
.metric-wide {
display: flex;
grid-column: span 2;
}
}
@media (max-width: 860px) {
@@ -228,10 +222,6 @@ body.sidebar-collapsed .nav-group + .nav-group {
grid-template-columns: repeat(3, 1fr);
}
.metric-wide {
grid-column: auto;
}
.metric {
padding: 10px;
}
@@ -262,10 +252,6 @@ body.sidebar-collapsed .nav-group + .nav-group {
grid-template-columns: repeat(2, 1fr);
}
.metric-wide {
grid-column: 1 / -1;
}
.section-title-group {
align-items: flex-start;
@@ -311,10 +297,6 @@ body.sidebar-collapsed .nav-group + .nav-group {
.overview-strip {
grid-template-columns: minmax(210px, 1.3fr) repeat(5, minmax(90px, 0.7fr));
}
.overview-strip .metric-wide {
display: none;
}
}
@media (max-width: 767px) {
@@ -644,10 +626,6 @@ body.sidebar-collapsed .app-main {
padding: 0px 8px;
}
.overview-strip .metric-wide {
display: none;
}
.overview-strip .metric:nth-of-type(n+4) {
display: none;
}
@@ -662,14 +640,6 @@ body.sidebar-collapsed .app-main {
padding: 8px;
}
.overview-strip[data-overview-expanded="true"] .metric-wide {
min-height: 54px;
display: flex;
border-bottom: 1px solid var(--border);
}
.overview-strip[data-overview-expanded="true"] .metric:nth-of-type(n) {
min-height: 54px;
@@ -770,10 +740,6 @@ body.sidebar-collapsed .app-main {
display: flex;
}
.overview-strip .metric-wide {
display: none;
}
.overview-strip .metric:nth-of-type(n+5) {
display: none;
}
@@ -892,7 +858,7 @@ body.sidebar-collapsed .app-main {
padding: 0px 10px;
border-radius: 7px;
border-radius: var(--radius-md);
font-size: 12.5px;
@@ -1452,7 +1418,7 @@ body.sidebar-collapsed .module-nav .nav-group + .nav-group {
border: 0px;
border-radius: 7px;
border-radius: var(--radius-md);
background: transparent;
@@ -2719,10 +2685,6 @@ body.sidebar-collapsed .status-bar {
padding: 0px;
}
.overview-strip .metric-wide {
display: none;
}
.overview-strip .metric:nth-of-type(n+4) {
display: none;
}
@@ -3216,11 +3178,6 @@ body.sidebar-collapsed .status-bar {
display: flex;
}
body.mobile-shell .overview-strip .metric-wide,
body.mobile-shell .overview-toggle {
display: none;
}
body.mobile-shell .workspace-view,
body.mobile-shell .workspace-view.page:not(#heavenView),
body.mobile-shell:is([data-active-view]) .workspace-view.active-view {
@@ -3367,7 +3324,8 @@ body.sidebar-collapsed .status-bar {
color: var(--down);
}
.tape-metric .metric-value.warning {
.tape-metric .metric-value.warning,
.tape-detail-item .warning {
color: var(--warn);
}
@@ -3380,7 +3338,8 @@ body.sidebar-collapsed .status-bar {
pointer-events: none;
}
.tape-sentiment .sentiment-text {
.tape-sentiment .sentiment-text,
.tape-detail-item .sentiment-text {
display: inline-flex;
align-items: center;
height: 18px;
@@ -3394,17 +3353,20 @@ body.sidebar-collapsed .status-bar {
line-height: 18px;
}
.tape-sentiment .sentiment-text.is-hot {
.tape-sentiment .sentiment-text.is-hot,
.tape-detail-item .sentiment-text.is-hot {
background: var(--up-soft);
color: var(--up);
}
.tape-sentiment .sentiment-text.is-strong {
.tape-sentiment .sentiment-text.is-strong,
.tape-detail-item .sentiment-text.is-strong {
background: var(--accent-soft);
color: var(--accent);
}
.tape-sentiment .sentiment-text.is-cold {
.tape-sentiment .sentiment-text.is-cold,
.tape-detail-item .sentiment-text.is-cold {
background: var(--down-soft);
color: var(--down);
}
@@ -3479,11 +3441,13 @@ body.sidebar-collapsed .status-bar {
}
.app-header .header-actions {
position: relative;
display: flex;
flex: 0 0 auto;
align-items: center;
gap: 6px;
margin-left: 0;
overflow: visible;
}
.app-header .header-date-group {
@@ -3675,3 +3639,68 @@ body.sidebar-collapsed .status-bar {
}
}
@media (min-width: 768px) {
.app-header .header-menu-button {
display: inline-flex;
}
.app-header .header-command-group {
position: absolute;
top: calc(100% + 8px);
right: 0;
z-index: 60;
display: none;
flex-direction: column;
align-items: stretch;
gap: 6px;
width: 240px;
padding: 8px;
overflow: visible;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--surface);
box-shadow: var(--shadow-float);
}
.app-header .header-command-group.is-open {
display: flex;
}
.app-header .header-command-group .command-button,
.app-header .header-command-group .account-button {
width: 100%;
justify-content: flex-start;
}
.app-header .header-command-group .account-menu-shell {
display: flex;
flex-direction: column;
align-items: stretch;
width: 100%;
}
.app-header .header-command-group .account-role-badges {
display: flex;
flex-wrap: wrap;
min-height: 0;
}
.app-header .header-command-group .account-dropdown {
left: 0;
right: auto;
}
}
body[data-active-view="heavenView"] .app-header .overview-strip,
body[data-active-view="heavenView"] .app-header .overview-strip[data-overview-expanded="true"],
body.mobile-shell[data-active-view="heavenView"] .app-header .overview-strip,
body.mobile-shell[data-active-view="heavenView"] .app-header .overview-strip[data-overview-expanded="true"] {
display: none;
flex: 0 0 0;
width: 0;
min-width: 0;
height: 0;
min-height: 0;
overflow: hidden;
}
+24 -9
View File
@@ -56,11 +56,32 @@
updateSidebarControl();
}
function pageGroupLabel(page) {
return page?.group === "market"
? "市场复盘"
: page?.group === "personal" ? "个人" : "智能工具";
}
function writePageSubtitle(viewId) {
const pageSubtitle = document.querySelector("#currentPageSubtitle");
if (!pageSubtitle) return;
const page = registry.get(viewId);
const dateText = options.tradeDate?.() || "";
const hasDate = Boolean(dateText) && dateText !== "--";
if (viewId === "mentorView") {
pageSubtitle.textContent = hasDate
? `与不同交易思维模型持续对话 · 数据日期 ${dateText}`
: "与不同交易思维模型持续对话 · 数据日期 --";
return;
}
const groupLabel = pageGroupLabel(page);
pageSubtitle.textContent = hasDate ? `${groupLabel} · ${dateText}` : groupLabel;
}
function syncNavigation(viewId) {
const page = registry.get(viewId);
const navigationId = page?.navigation_alias || viewId;
const marketView = page?.group === "market";
const previousActiveView = document.body.dataset.activeView;
document.body.dataset.activeView = viewId;
const mobileGroup = document.querySelector("#mobilePageGroup");
const mobileTitle = document.querySelector("#mobilePageTitle");
@@ -72,13 +93,7 @@
if (mobileTitle) mobileTitle.textContent = page?.title || "小白复盘";
const pageTitle = document.querySelector("#currentPageTitle");
if (pageTitle) pageTitle.textContent = page?.title || "小白复盘";
const pageSubtitle = document.querySelector("#currentPageSubtitle");
if (pageSubtitle && previousActiveView !== viewId) {
const groupLabel = page?.group === "market"
? "市场复盘"
: page?.group === "personal" ? "个人" : "智能工具";
pageSubtitle.textContent = groupLabel;
}
writePageSubtitle(viewId);
document.querySelectorAll(".module-tab").forEach((button) => {
button.classList.toggle("active", button.dataset.view === navigationId);
button.classList.toggle(
@@ -216,7 +231,7 @@
if (expanded) toggleHeaderCommandMenu(false);
});
document.addEventListener("click", (event) => {
if (!event.target.closest(".header-actions")) toggleHeaderCommandMenu(false);
if (!event.target.closest("#headerCommandGroup, #headerMenuButton")) toggleHeaderCommandMenu(false);
if (!event.target.closest(".overview-strip")) setOverviewExpanded(false);
});
document.addEventListener("keydown", (event) => {