setShowPlateNumbers({ batch: 'All', model: 'All', location: 'All', source: 'asset', title: '资产概览' })}>
@@ -66,7 +66,7 @@ export function SummaryMetrics({
+
运营概览
diff --git a/src/modules/assets/history/AssetHistorySection.tsx b/src/modules/assets/history/AssetHistorySection.tsx
index 7f45019..0a5e82f 100644
--- a/src/modules/assets/history/AssetHistorySection.tsx
+++ b/src/modules/assets/history/AssetHistorySection.tsx
@@ -69,18 +69,17 @@ export function AssetHistorySection({ subject, onSubjects }: { subject: string |
{mode === 'monthly' && ({ value: String(y), label: `${y}年` }))} onChange={value => { setYear(Number(value)); setDetails(null); }} />}
{data && { setSelected(value); setDetails(null); }} options={data.points.map(p => ({ value: p.period, label: p.label, detail: p.state === 'RECONSTRUCTED' ? '估算' : p.state === 'LIVE' ? '实时' : p.state === 'ARCHIVED' ? '归档' : p.state === 'FUTURE' ? '未来' : p.state === 'MISSING' ? '缺失' : HISTORY_STATE_LABELS[p.state] }))} />}
- 月末 17:00
+ 月末 17:00
{loading && !data ?
正在加载资产历史趋势…
: !data ?
{error || '暂无可用数据'}
: <>
{error &&
{error} · 保留上次查询结果
}
-
数量(台)
- { const p = chart.find(p => p.label === String(state?.activeLabel)); if (p) setSelected(p.period); }}>
+ { const p = chart.find(p => p.label === String(state?.activeLabel)); if (p) setSelected(p.period); }}>
-
+
{
const item = payload?.[0]?.payload as HistoryPoint | undefined;
const values = item && displayHistoryCounts(item);
@@ -92,16 +91,19 @@ export function AssetHistorySection({ subject, onSubjects }: { subject: string |
-
运营数库存数资产总数
+
运营数库存数资产总数台
{point &&
-
{mode === 'annual' || point.state === 'LIVE' ? point.label : `${point.label}末`}{HISTORY_STATE_LABELS[point.state]}{point.asOf && }
-
{([['total', '总数'], ['inventory', '库存'], ['operating', '运营']] as const).map(([key, label]) =>
{label}(台){displayHistoryCounts(point)?.[key]?.toLocaleString() ?? (point.reconstruction && key === 'total' ? '待核实' : '—')}
)}
+
{mode === 'annual' || point.state === 'LIVE' ? point.label : `${point.label}末`}{HISTORY_STATE_LABELS[point.state]}
+
{([['total', '总数'], ['inventory', '库存'], ['operating', '运营']] as const).map(([key, label]) =>
{label}{displayHistoryCounts(point)?.[key]?.toLocaleString() ?? (point.reconstruction && key === 'total' ? '待核实' : '—')}
)}
{hasComparison ?
{point.comparisonLabel}{(['total', 'inventory', 'operating'] as const).map(key => {
const difference = displayHistoryDifference(point, key);
return 0 ? 'asset-history-increase' : difference != null && difference < 0 ? 'asset-history-decrease' : ''}>{difference != null ? signedCount(difference) : '—'};
- })}
:
{point.comparisonLabel}
}
+ })}
: null}
+
+
{point.asOf && }{!hasComparison && {point.comparisonLabel}}
+ {mode === 'monthly' &&
}
+
}
- {point && mode === 'monthly' &&
}
历史库存状态快照缺失,核对中,暂不展示。
>}
{details &&
}
diff --git a/src/modules/assets/history/history.css b/src/modules/assets/history/history.css
index 7bc74fe..980a651 100644
--- a/src/modules/assets/history/history.css
+++ b/src/modules/assets/history/history.css
@@ -1,41 +1,43 @@
-.asset-history { --history-blue:#1559e8; margin:8px 0 16px; padding:16px; border:1px solid #e6edf5; border-radius:20px; background:#fff; color:#142b4e; box-shadow:0 5px 24px rgb(22 53 90 / 3%); }
-.asset-history button,.asset-history-dialog button { cursor:pointer; }
+.asset-history { --history-blue:#1559e8; --history-ink:#142b4e; --history-muted:#62748b; --history-border:#e3ebf5; margin:0; padding:16px; border:1px solid var(--history-border); border-radius:16px; background:#fff; color:var(--history-ink); box-shadow:0 2px 12px rgb(22 53 90 / 3%); }
+.asset-history button,.asset-history-dialog button { cursor:pointer; touch-action:manipulation; }
.asset-history button:disabled,.asset-history-dialog button:disabled { cursor:default; opacity:.45; }
-.asset-history button:focus-visible,.asset-history select:focus-visible,.asset-history-dialog :is(button,input,select):focus-visible { outline:2px solid #2563eb; outline-offset:3px; }
-.asset-history-header { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:12px; }
-.asset-history-header h2 { margin:0; font-size:20px; font-weight:750; letter-spacing:-.5px; }
-.asset-history-modes { display:flex; gap:2px; background:#eef3fa; border:1px solid #e7edf6; border-radius:11px; padding:3px; }
-.asset-history-modes button { padding:7px 20px; min-height:34px; border-radius:8px; font-size:13px; font-weight:600; transition:background .15s,color .15s,box-shadow .15s; color:#64748b; }
-.asset-history-modes button[aria-pressed=true] { background:#fff; color:#1559e8; box-shadow:0 1px 4px #193c6920, inset 0 0 0 1px #dce7f5; }
-.asset-history-toolbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:8px 0 4px; font-size:12px; color:#64748b; }
+.asset-history button:focus-visible,.asset-history-dialog :is(button,input,select):focus-visible { outline:2px solid #2563eb; outline-offset:3px; }
+.asset-history-header { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; }
+.asset-history-header h2 { margin:0; font-size:18px; font-weight:700; letter-spacing:-.4px; }
+.asset-history-modes { display:flex; gap:2px; background:#f0f4f9; border-radius:10px; padding:0 3px; }
+.asset-history-modes button { position:relative; isolation:isolate; min-width:52px; min-height:44px; padding:8px 14px; font-size:13px; font-weight:600; color:var(--history-muted); transition:color .16s; }
+.asset-history-modes button::before { content:""; position:absolute; inset:5px 0; z-index:-1; border-radius:7px; transition:background .16s,box-shadow .16s; }
+.asset-history-modes button[aria-pressed=true] { color:var(--history-blue); }
+.asset-history-modes button[aria-pressed=true]::before { background:#fff; box-shadow:0 1px 4px #193c691a,0 0 0 1px #e0e8f3; }
+.asset-history-toolbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:4px 0 0; color:var(--history-muted); font-size:12px; }
.asset-history-toolbar>span { margin-left:auto; }
-.asset-history-toolbar .asset-history-annual-note { margin-left:0; margin-right:auto; }
-.asset-history-refresh { display:grid; place-items:center; padding:8px; border-radius:8px; color:#7c8da5; transition:background .15s,color .15s; }
+.asset-history-refresh { display:grid; place-items:center; min-width:44px; min-height:44px; padding:8px; border-radius:8px; color:var(--history-muted); transition:background .16s,color .16s; }
.asset-history-warning { margin:8px 0; font-size:12px; line-height:1.7; color:#74613a; background:#fff9ec; padding:9px 12px; border-radius:9px; }
-.asset-history-warning button,.asset-history-empty button { color:#1559e8; text-decoration:underline; padding:6px; }
-.asset-history-unit { font-size:12px; color:#64748b; margin:6px 0 0; }
-.asset-history-chart { height:200px; width:100%; min-width:0; }
-.asset-history-tooltip { background:#fff; border:1px solid #dce5ef; border-radius:10px; padding:10px 12px; box-shadow:0 4px 16px #142b4e15; font-size:12px; }
+.asset-history-warning button,.asset-history-empty button { color:var(--history-blue); text-decoration:underline; padding:6px; }
+.asset-history-chart { height:180px; width:100%; min-width:0; }
+.asset-history-tooltip { background:#fff; border:1px solid var(--history-border); border-radius:10px; padding:10px 12px; box-shadow:0 4px 16px #142b4e15; font-size:12px; }
.asset-history-tooltip p { margin-top:4px; }
-.asset-history-legend { display:flex; justify-content:center; flex-wrap:wrap; gap:22px; color:#64748b; font-size:12px; margin:6px 0; }
-.asset-history-legend span { display:flex; align-items:center; gap:7px; }
-.asset-history-legend i { display:inline-block; height:11px; width:11px; border-radius:2px; }
+.asset-history-legend { display:flex; justify-content:center; align-items:center; flex-wrap:wrap; gap:16px; color:var(--history-muted); font-size:12px; line-height:18px; margin:2px 0 8px; }
+.asset-history-legend span { display:flex; align-items:center; gap:6px; }
+.asset-history-legend i { display:inline-block; height:8px; width:8px; border-radius:2px; }
.asset-history-legend .operating { background:#347df5; }.asset-history-legend .inventory { background:#9ed1fa; }
-.asset-history-legend .total { width:20px; height:2px; background:#132e57; }
-.asset-history-selected { margin-top:8px; display:grid; grid-template-columns:90px minmax(0,1fr); align-items:center; gap:0 10px; padding:10px 14px; background:linear-gradient(115deg,#f3f7fe,#edf5ff); border:1px solid #e7effb; border-radius:12px; }
+.asset-history-legend .total { position:relative; width:16px; height:2px; background:#132e57; }
+.asset-history-legend .total::after { content:""; position:absolute; top:-2px; left:6px; width:6px; height:6px; border:2px solid #132e57; border-radius:50%; background:white; }
+.asset-history-legend .asset-history-unit { padding-left:8px; border-left:1px solid var(--history-border); }
+.asset-history-selected { display:grid; grid-template-columns:94px minmax(0,1fr); align-items:center; gap:0 8px; padding:10px 12px 0; background:#f2f7ff; border:1px solid #e4edfa; border-radius:10px; }
.asset-history-selected-heading { display:flex; flex-direction:column; align-items:flex-start; gap:3px; min-width:0; }
-.asset-history-selected-heading>strong { color:#1559e8; font-size:17px; font-weight:750; }
-.asset-history-selected-heading>span,.asset-history-selected-heading>time { color:#64748b; font-size:11px; }
+.asset-history-selected-heading>strong { color:var(--history-blue); font-size:18px; line-height:24px; font-weight:700; }
+.asset-history-selected-heading>span { color:var(--history-muted); font-size:12px; line-height:18px; }
.asset-history-counts { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); }
-.asset-history-counts>div { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; min-width:0; border-right:1px solid #d4e2f4; }
-.asset-history-counts>div:last-child { border:0; }
-.asset-history-counts>div>span { color:#64748b; font-size:12px; }
-.asset-history-counts strong { font-size:23px; font-weight:750; line-height:1.2; font-variant-numeric:tabular-nums; }
+.asset-history-counts>div { display:flex; flex-direction:column; align-items:center; gap:3px; min-width:0; border-left:1px solid #dce7f6; }
+.asset-history-counts>div>span { color:var(--history-muted); font-size:12px; line-height:18px; }
+.asset-history-counts strong { font-size:24px; font-weight:700; line-height:28px; letter-spacing:-.4px; font-variant-numeric:tabular-nums; }
.asset-history-increase { color:#bf2f30; }.asset-history-decrease { color:#14864a; }
-.asset-history-selected>p { grid-column:1 / -1; color:#64748b; font-size:11px; text-align:center; padding-top:6px; }
-.asset-history-detail-button { display:flex; width:100%; align-items:center; justify-content:space-between; min-height:44px; padding:8px 12px; margin-top:8px; border:1px solid #dce8f8; border-radius:10px; background:#f7faff; color:#18385d; font-size:14px; font-weight:600; }
-.asset-history-footnote { display:flex; align-items:center; flex-wrap:wrap; gap:6px; color:#64748b; font-size:11px; margin-top:8px; }
-.asset-history-empty { padding:32px 12px; text-align:center; font-size:13px; color:#64748b; }
+.asset-history-selected-footer { grid-column:1/-1; display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:8px; border-top:1px solid #e0eaf8; min-height:44px; }
+.asset-history-point-meta { display:flex; flex-wrap:wrap; gap:2px 12px; color:var(--history-muted); font-size:12px; line-height:18px; }
+.asset-history-detail-button { display:flex; flex-shrink:0; align-items:center; justify-content:space-between; gap:4px; min-height:44px; padding:8px 0 8px 8px; color:var(--history-blue); font-size:12px; font-weight:600; border-radius:6px; transition:color .16s,background .16s; }
+.asset-history-footnote { color:var(--history-muted); font-size:12px; line-height:18px; margin-top:8px; }
+.asset-history-empty { padding:32px 12px; text-align:center; font-size:13px; color:var(--history-muted); }
.asset-history-overlay { position:fixed; inset:0; z-index:120; background:#0c1e3b66; display:flex; justify-content:center; align-items:center; padding:24px; }
.asset-history-dialog { display:flex; flex-direction:column; width:min(980px,100%); max-height:88dvh; border-radius:18px; background:white; color:#183454; box-shadow:0 24px 64px #142b4e30; overflow:hidden; outline:none; }
.asset-history-dialog>header { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:20px 22px; border-bottom:1px solid #e6edf5; }
@@ -58,12 +60,12 @@
.asset-history-dialog footer { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:12px 22px; border-top:1px solid #e6edf5; color:#64748b; font-size:12px; }
.asset-history-dialog footer>div { display:flex; gap:8px; }.asset-history-dialog footer button { padding:9px; border:1px solid #dce5f0; border-radius:7px; }
@media(max-width:640px) {
- .asset-history { padding:12px; border-radius:16px; }
- .asset-history-header h2 { font-size:18px; }.asset-history-modes button { padding:7px 15px; min-height:38px; }
- .asset-history-toolbar { gap:6px; }.asset-history-toolbar>span { font-size:10px; }
- .asset-history-chart { height:170px; }
- .asset-history-selected { grid-template-columns:72px minmax(0,1fr); gap:0 6px; padding:8px 10px; }.asset-history-selected-heading { gap:2px; }.asset-history-selected-heading>span,.asset-history-selected-heading>time { font-size:10px; }
- .asset-history-counts strong { font-size:21px; }.asset-history-counts>div>span { font-size:11px; }
+ .asset-history { padding:12px; border-radius:14px; }
+ .asset-history-header h2 { font-size:17px; }
+ .asset-history-chart { height:140px; }
+ .asset-history-selected { grid-template-columns:84px minmax(0,1fr); padding:8px 10px 0; gap:0 6px; }
+ .asset-history-counts strong { font-size:22px; line-height:26px; }
+ .asset-history-point-meta { flex-direction:column; gap:0; }
.asset-history-overlay { padding:10px; }.asset-history-dialog { max-height:94dvh; border-radius:14px; }
.asset-history-dialog>header { padding:14px; }.asset-history-dialog h2 { font-size:16px; }.asset-history-detail-tools { padding:12px 14px; }
.asset-history-detail-note { padding:10px 14px; }.asset-history-dialog :is(input,select) { font-size:16px; }.asset-history-dialog footer { padding:12px 14px; }
@@ -79,31 +81,18 @@
}
@media(min-width:900px) {
- .asset-history-controls { display:flex; align-items:center; flex-wrap:wrap; gap:8px 24px; }
+ .asset-history-controls { display:flex; align-items:center; gap:24px; flex-wrap:wrap; }
.asset-history-header { flex:1; gap:16px; }
.asset-history-toolbar { margin:0; }
- .asset-history-selected { display:grid; grid-template-columns:minmax(150px,1fr) 3fr; align-items:center; gap:0 18px; }
- .asset-history-selected-heading { display:grid; grid-template-columns:auto 1fr; align-items:center; gap:2px 12px; margin:0; }
- .asset-history-selected-heading>strong { grid-row:span 2; }
- .asset-history-selected-heading>span,.asset-history-selected-heading>time { grid-column:2; }
- .asset-history-selected>p { grid-column:1 / -1; }
+ .asset-history-selected { grid-template-columns:minmax(150px,1fr) 3fr; gap:0 16px; }
+ .asset-history-selected-heading { flex-direction:row; align-items:center; gap:12px; }
}
-@media(max-width:640px) {
- .asset-history-modes button,.asset-history-refresh { min-height:44px; }
- .asset-history-refresh { min-width:44px; }
- .asset-history-toolbar { gap:4px; }
-}
-
-.asset-history-comparison { grid-column:1 / -1; display:grid; grid-template-columns:90px minmax(0,1fr); gap:10px; align-items:center; margin-top:6px; padding-top:6px; border-top:1px solid #d4e2f4; font-size:11px; color:#64748b; }
+.asset-history-comparison { grid-column:1/-1; display:grid; grid-template-columns:94px minmax(0,1fr); gap:8px; align-items:center; margin-top:8px; padding-top:6px; border-top:1px solid #dce7f6; font-size:12px; color:var(--history-muted); }
.asset-history-comparison>div { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); text-align:center; font-size:13px; font-weight:600; }
-@media(min-width:900px) {
- .asset-history-comparison { grid-template-columns:minmax(150px,1fr) 3fr; gap:18px; }
-}
-@media(max-width:640px) {
- .asset-history-comparison { grid-template-columns:72px minmax(0,1fr); gap:6px; }
-}
+@media(min-width:900px) { .asset-history-comparison { grid-template-columns:minmax(150px,1fr) 3fr; gap:16px; } }
+@media(max-width:640px) { .asset-history-comparison { grid-template-columns:84px minmax(0,1fr); gap:6px; } }
-.asset-history-select { display:inline-flex; align-items:center; justify-content:space-between; gap:12px; min-width:76px; min-height:36px; padding:7px 11px; border:1px solid #dce5f1; border-radius:9px; background:#fff; color:#254365; font-size:13px; font-weight:550; box-shadow:0 1px 2px #173c6310; transition:border-color .15s,box-shadow .15s; }
+.asset-history-select { display:inline-flex; align-items:center; justify-content:space-between; gap:12px; min-width:76px; min-height:44px; padding:7px 11px; border:1px solid #dce5f1; border-radius:8px; background:#fff; color:#254365; font-size:13px; font-weight:550; box-shadow:0 1px 2px #173c6310; transition:border-color .15s,box-shadow .15s; }
.asset-history-select[data-state=open] { border-color:#8fb4f2; box-shadow:0 0 0 3px #dbeaff80; }
.asset-history-select-icon { color:#8b9db5; display:flex; transition:transform .15s; }
.asset-history-select[data-state=open] .asset-history-select-icon { transform:rotate(180deg); }
@@ -115,17 +104,19 @@
.asset-history-option-detail { margin-left:auto; color:#7b8da5; font-size:11px; font-weight:400; }
.asset-history-option-check { position:absolute; right:9px; display:flex; color:#2563eb; }
.asset-history-select-scroll { display:flex; align-items:center; justify-content:center; height:24px; color:#7b8da5; }
-.asset-history-detail-button>svg { padding:3px; width:24px; height:24px; border-radius:7px; background:#eaf2ff; color:#527eb7; }
+.asset-history-detail-button>svg { flex-shrink:0; }
@media(hover:hover) {
- .asset-history-modes button:not([aria-pressed=true]):hover { color:#1559e8; background:#e5edf9; }
+ .asset-history-modes button:not([aria-pressed=true]):hover::before { background:#e5edf9; }
.asset-history-select:hover { border-color:#adc5e8; }
.asset-history-refresh:hover { color:#2563eb; background:#eef5ff; }
- .asset-history-detail-button:hover { background:#eef5ff; border-color:#bcd3f3; }
+ .asset-history-detail-button:hover { color:#103eaa; background:#e9f1ff; }
}
@media(max-width:640px) {
.asset-history-select { min-height:44px; padding:8px 10px; font-size:12px; gap:10px; }
.asset-history-select-option { min-height:44px; }
}
@media(prefers-reduced-motion:reduce) {
- .asset-history-modes button,.asset-history-select,.asset-history-select-icon,.asset-history-refresh { transition:none; }
+ .asset-history-modes button,.asset-history-modes button::before,.asset-history-select,.asset-history-select-icon,.asset-history-refresh,.asset-history-detail-button { transition:none; }
}
+
+.asset-history :is(.asset-history-select,.asset-history-refresh,.asset-history-detail-button):active { background:#e6effe; }