2b1d7c0b65
The dashboard had several oversized orchestration, component, and CSS files that made product-copy changes and mobile/performance work risky. This refactor preserves behavior while splitting scan terminal CSS, opportunity helpers, future forecast panels, history/detail charts, and probability/model sections into smaller ownership boundaries. Constraint: No user-visible version bump because this batch is architecture and performance cleanup, not a release announcement. Rejected: Rewrite dashboard state management in the same batch | too broad for a safe upload after CSS and component splitting. Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep new component/CSS boundaries instead of moving product copy back into the large dashboard files. Tested: npm run build; npm run test:business; git diff --check Not-tested: Browser visual smoke test after push
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import type { ScanOpportunityRow } from "@/lib/dashboard-types";
|
|
import { formatTemperatureValue } from "@/lib/temperature-utils";
|
|
|
|
export function formatModelSources(row: ScanOpportunityRow, tempSymbol?: string | null) {
|
|
const sources = row.model_cluster_sources || {};
|
|
return Object.entries(sources)
|
|
.filter(([, value]) => value != null && Number.isFinite(Number(value)))
|
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
.map(([name, value]) => ({
|
|
name,
|
|
value: formatTemperatureValue(Number(value), tempSymbol, { digits: 1 }),
|
|
}));
|
|
}
|
|
|
|
export function formatModelClusterRange(
|
|
sources?: Record<string, number | null> | null,
|
|
tempSymbol?: string | null,
|
|
) {
|
|
const values = Object.values(sources || {})
|
|
.map((value) => Number(value))
|
|
.filter((value) => Number.isFinite(value));
|
|
if (!values.length) return "--";
|
|
const low = Math.min(...values);
|
|
const high = Math.max(...values);
|
|
if (Math.abs(low - high) < 0.05) {
|
|
return formatTemperatureValue(low, tempSymbol, { digits: 1 });
|
|
}
|
|
return `${formatTemperatureValue(low, tempSymbol, { digits: 1 })} ~ ${formatTemperatureValue(high, tempSymbol, { digits: 1 })}`;
|
|
}
|
|
|
|
export function getModelSourceSummary(
|
|
row: ScanOpportunityRow,
|
|
locale: string,
|
|
tempSymbol?: string | null,
|
|
) {
|
|
const sources = formatModelSources(row, tempSymbol);
|
|
if (!sources.length) {
|
|
return locale === "en-US"
|
|
? "model cluster pending"
|
|
: "模型集群暂未回传";
|
|
}
|
|
const shown = sources.map((item) => `${item.name} ${item.value}`).join(" / ");
|
|
return locale === "en-US"
|
|
? `all models: ${shown}`
|
|
: `全部模型:${shown}`;
|
|
}
|