|
@@ -101,6 +101,50 @@ export const STAGE_ICON_OPTIONS = [
|
|
|
|
|
|
|
|
const STORAGE_KEY = 'aidop_s8_stage_config';
|
|
const STORAGE_KEY = 'aidop_s8_stage_config';
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 模块卡「正常」绿色默认显示值(自然数)。
|
|
|
|
|
+ * 当后端尚未提供真实"正常工单 / 运行中工单"字段时使用。
|
|
|
|
|
+ * 任务来源:S8-DASHBOARD-MODULE-TRICOLOR-SEMANTICS-1
|
|
|
|
|
+ */
|
|
|
|
|
+export const DEFAULT_NORMAL_WORK_ORDER_COUNT = 20;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 从模块原始指标派生三色业务数字(自然数字符串)。
|
|
|
|
|
+ * 语义恒等:warningCount + seriousCount = totalExceptionCount。
|
|
|
|
|
+ * 绿色 = 正常工单数(暂用集中默认值兜底)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 兜底策略:
|
|
|
|
|
+ * 1. total / red / yellow 均经过 safeNonNegInt 归一;
|
|
|
|
|
+ * 2. red 不超过 total;
|
|
|
|
|
+ * 3. 当 yellow + red 不等于 total(API 缺字段或脏数据)→ yellow 改为 total - red;
|
|
|
|
|
+ * 4. 全部缺失 → red=0, yellow=0;
|
|
|
|
|
+ * 5. 绿色统一使用 DEFAULT_NORMAL_WORK_ORDER_COUNT,待后端返回真实正常工单数后再接入。
|
|
|
|
|
+ */
|
|
|
|
|
+export function buildModuleTriColorStats(input: {
|
|
|
|
|
+ total?: number | null;
|
|
|
|
|
+ red?: number | null;
|
|
|
|
|
+ yellow?: number | null;
|
|
|
|
|
+}): { green: string; yellow: string; red: string } {
|
|
|
|
|
+ const total = safeNonNegInt(input.total);
|
|
|
|
|
+ let red = Math.min(safeNonNegInt(input.red), total);
|
|
|
|
|
+ let yellow = safeNonNegInt(input.yellow);
|
|
|
|
|
+ if (yellow + red !== total) {
|
|
|
|
|
+ yellow = Math.max(0, total - red);
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ green: String(DEFAULT_NORMAL_WORK_ORDER_COUNT),
|
|
|
|
|
+ yellow: String(yellow),
|
|
|
|
|
+ red: String(red),
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function safeNonNegInt(value: number | null | undefined): number {
|
|
|
|
|
+ if (value === null || value === undefined) return 0;
|
|
|
|
|
+ const n = Number(value);
|
|
|
|
|
+ if (!Number.isFinite(n) || n < 0) return 0;
|
|
|
|
|
+ return Math.floor(n);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function deepClone<T>(value: T): T {
|
|
function deepClone<T>(value: T): T {
|
|
|
return JSON.parse(JSON.stringify(value));
|
|
return JSON.parse(JSON.stringify(value));
|
|
|
}
|
|
}
|
|
@@ -146,11 +190,13 @@ function defaultConfigFromCard(card: StageCardPreviewData): StageCardConfigItem
|
|
|
statusLabel: card.statusLabel,
|
|
statusLabel: card.statusLabel,
|
|
|
showStatusLabel: card.showStatusLabel ?? true,
|
|
showStatusLabel: card.showStatusLabel ?? true,
|
|
|
showProgress: card.showProgress ?? true,
|
|
showProgress: card.showProgress ?? true,
|
|
|
- values: {
|
|
|
|
|
- green: card.value,
|
|
|
|
|
- yellow: card.value,
|
|
|
|
|
- red: card.value,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ values: card.values
|
|
|
|
|
+ ? { ...card.values }
|
|
|
|
|
+ : {
|
|
|
|
|
+ green: card.value,
|
|
|
|
|
+ yellow: card.value,
|
|
|
|
|
+ red: card.value,
|
|
|
|
|
+ },
|
|
|
valueLabels: {
|
|
valueLabels: {
|
|
|
green: '正常',
|
|
green: '正常',
|
|
|
yellow: '关注',
|
|
yellow: '关注',
|
|
@@ -257,7 +303,9 @@ export function useS8StageConfig() {
|
|
|
title: config.title,
|
|
title: config.title,
|
|
|
icon,
|
|
icon,
|
|
|
value: config.values[tone] || card.value,
|
|
value: config.values[tone] || card.value,
|
|
|
- values: { ...config.values },
|
|
|
|
|
|
|
+ // S8-DASHBOARD-MODULE-TRICOLOR-SEMANTICS-1:实时业务三色数字(card.values)优先于
|
|
|
|
|
+ // localStorage 中可能残留的旧 stage 配置(10.0 / 0% / 3.2h),保证「关注 + 严重 = 异常总数」。
|
|
|
|
|
+ values: card.values ? { ...card.values } : { ...config.values },
|
|
|
valueLabels: config.valueLabels ? { ...config.valueLabels } : { green: '正常', yellow: '关注', red: '严重' },
|
|
valueLabels: config.valueLabels ? { ...config.valueLabels } : { green: '正常', yellow: '关注', red: '严重' },
|
|
|
metricLabel: config.metricLabel,
|
|
metricLabel: config.metricLabel,
|
|
|
healthRate: clampPercent(config.healthRates[tone] ?? card.healthRate),
|
|
healthRate: clampPercent(config.healthRates[tone] ?? card.healthRate),
|