|
@@ -182,7 +182,7 @@ import S8MonitoringModulesGrid from './components/S8MonitoringModulesGrid.vue';
|
|
|
import S8MonitoringCategoryGrid, { type CategoryGridCardData } from './components/S8MonitoringCategoryGrid.vue';
|
|
import S8MonitoringCategoryGrid, { type CategoryGridCardData } from './components/S8MonitoringCategoryGrid.vue';
|
|
|
import S8MonitoringEditToolbar from './components/S8MonitoringEditToolbar.vue';
|
|
import S8MonitoringEditToolbar from './components/S8MonitoringEditToolbar.vue';
|
|
|
import S8MonitoringStageConfigDrawer from './components/S8MonitoringStageConfigDrawer.vue';
|
|
import S8MonitoringStageConfigDrawer from './components/S8MonitoringStageConfigDrawer.vue';
|
|
|
-import { useS8StageConfig, buildModuleTriColorStats } from './useS8StageConfig';
|
|
|
|
|
|
|
+import { useS8StageConfig, buildModuleTriColorStats, DEFAULT_NORMAL_WORK_ORDER_COUNT } from './useS8StageConfig';
|
|
|
import { useS8CategoryConfig } from './useS8CategoryConfig';
|
|
import { useS8CategoryConfig } from './useS8CategoryConfig';
|
|
|
import { useS9DeptConfig } from './useS9DeptConfig';
|
|
import { useS9DeptConfig } from './useS9DeptConfig';
|
|
|
import { useS8UnsavedLayoutEditGuard } from './useS8UnsavedLayoutEditGuard';
|
|
import { useS8UnsavedLayoutEditGuard } from './useS8UnsavedLayoutEditGuard';
|
|
@@ -212,7 +212,7 @@ const numberFormatter = new Intl.NumberFormat('zh-CN');
|
|
|
|
|
|
|
|
const STAGE_META_FALLBACK: ReadonlyArray<StageMeta> = [
|
|
const STAGE_META_FALLBACK: ReadonlyArray<StageMeta> = [
|
|
|
{ code: 'S1', title: '销售评审', icon: Checked, metricLabel: '累计监控单量', valueMode: 'total' },
|
|
{ code: 'S1', title: '销售评审', icon: Checked, metricLabel: '累计监控单量', valueMode: 'total' },
|
|
|
- { code: 'S2', title: '计划排产', icon: TrendCharts, metricLabel: '异常频率 / 百单', valueMode: 'frequency' },
|
|
|
|
|
|
|
+ { code: 'S2', title: '计划排产', icon: TrendCharts, metricLabel: '累计异常数', valueMode: 'total' },
|
|
|
{ code: 'S3', title: '物料备料', icon: ShoppingBag, metricLabel: '累计异常数量', valueMode: 'total' },
|
|
{ code: 'S3', title: '物料备料', icon: ShoppingBag, metricLabel: '累计异常数量', valueMode: 'total' },
|
|
|
{ code: 'S4', title: '生产制造', icon: Tools, metricLabel: '平均处理时长', valueMode: 'avgHours' },
|
|
{ code: 'S4', title: '生产制造', icon: Tools, metricLabel: '平均处理时长', valueMode: 'avgHours' },
|
|
|
{ code: 'S5', title: '质量检测', icon: DataAnalysis, metricLabel: '异常关闭率', valueMode: 'closeRate' },
|
|
{ code: 'S5', title: '质量检测', icon: DataAnalysis, metricLabel: '异常关闭率', valueMode: 'closeRate' },
|
|
@@ -502,15 +502,19 @@ function buildStageCard(
|
|
|
const total = Math.max(module?.total ?? summaryItem?.total ?? 0, 0);
|
|
const total = Math.max(module?.total ?? summaryItem?.total ?? 0, 0);
|
|
|
const red = Math.max(module?.red ?? summaryItem?.red ?? 0, 0);
|
|
const red = Math.max(module?.red ?? summaryItem?.red ?? 0, 0);
|
|
|
const yellow = Math.max(module?.yellow ?? summaryItem?.yellow ?? 0, 0);
|
|
const yellow = Math.max(module?.yellow ?? summaryItem?.yellow ?? 0, 0);
|
|
|
- const green = Math.max(module?.green ?? summaryItem?.green ?? Math.max(total - red - yellow, 0), 0);
|
|
|
|
|
const timeout = Math.max(summaryItem?.timeout ?? 0, 0);
|
|
const timeout = Math.max(summaryItem?.timeout ?? 0, 0);
|
|
|
- const healthRate = total > 0 ? Math.round((green / total) * 100) : 0;
|
|
|
|
|
const closeRate = clampPercent(module?.closeRate ?? 0);
|
|
const closeRate = clampPercent(module?.closeRate ?? 0);
|
|
|
const frequency = module?.frequency ?? 0;
|
|
const frequency = module?.frequency ?? 0;
|
|
|
const avgProcessHours = module?.avgProcessHours ?? 0;
|
|
const avgProcessHours = module?.avgProcessHours ?? 0;
|
|
|
const tone: 'green' | 'yellow' | 'red' = red > 0 ? 'red' : yellow > 0 ? 'yellow' : 'green';
|
|
const tone: 'green' | 'yellow' | 'red' = red > 0 ? 'red' : yellow > 0 ? 'yellow' : 'green';
|
|
|
const title = stripModulePrefix(module?.moduleLabel || summaryItem?.moduleLabel || meta.title, meta.code) || meta.title;
|
|
const title = stripModulePrefix(module?.moduleLabel || summaryItem?.moduleLabel || meta.title, meta.code) || meta.title;
|
|
|
const anomalyCount = red + yellow;
|
|
const anomalyCount = red + yellow;
|
|
|
|
|
+ // S8-MODULE-CARD-SEMANTICS-FIX-1A:
|
|
|
|
|
+ // - 健康度块改为「闭环率」,数值取 closeRate(与 wide-meter 蓝条一致);
|
|
|
|
|
+ // - 三色进度条分母统一为 normal + yellow + red(normal 暂用 DEFAULT_NORMAL_WORK_ORDER_COUNT),
|
|
|
|
|
+ // 不再用异常总数 total(不含正常底数会导致绿色永远 0);
|
|
|
|
|
+ // - 均时接入真实 API avgProcessHours,不再写死 0h。
|
|
|
|
|
+ const normal = DEFAULT_NORMAL_WORK_ORDER_COUNT;
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
code: meta.code,
|
|
code: meta.code,
|
|
@@ -521,15 +525,16 @@ function buildStageCard(
|
|
|
// S8-DASHBOARD-MODULE-TRICOLOR-SEMANTICS-1:三色数字(绿正常 / 黄关注 / 红严重)
|
|
// S8-DASHBOARD-MODULE-TRICOLOR-SEMANTICS-1:三色数字(绿正常 / 黄关注 / 红严重)
|
|
|
// 全部为自然数;warning + serious = 异常总数;绿色暂用 DEFAULT_NORMAL_WORK_ORDER_COUNT。
|
|
// 全部为自然数;warning + serious = 异常总数;绿色暂用 DEFAULT_NORMAL_WORK_ORDER_COUNT。
|
|
|
values: buildModuleTriColorStats({ total: anomalyCount, red, yellow }),
|
|
values: buildModuleTriColorStats({ total: anomalyCount, red, yellow }),
|
|
|
- healthRate,
|
|
|
|
|
|
|
+ healthRate: closeRate,
|
|
|
statusLabel: timeout > 0 ? `${timeout} 超时` : `${anomalyCount} 异常`,
|
|
statusLabel: timeout > 0 ? `${timeout} 超时` : `${anomalyCount} 异常`,
|
|
|
- progress: toProgress(green, yellow, red, total),
|
|
|
|
|
|
|
+ progress: toProgress(normal, yellow, red),
|
|
|
tone,
|
|
tone,
|
|
|
wide: meta.wide ?? false,
|
|
wide: meta.wide ?? false,
|
|
|
cardSpan: meta.wide ? 2 : 1,
|
|
cardSpan: meta.wide ? 2 : 1,
|
|
|
minHeight: meta.wide ? 196 : 176,
|
|
minHeight: meta.wide ? 196 : 176,
|
|
|
wideRate: closeRate,
|
|
wideRate: closeRate,
|
|
|
- wideRateLabel: `关闭率 ${formatPercent(closeRate, closeRate > 0 && closeRate < 10 ? 1 : 0)}`,
|
|
|
|
|
|
|
+ wideRateLabel: `闭环率 ${formatPercent(closeRate, closeRate > 0 && closeRate < 10 ? 1 : 0)} / 均时 ${formatHours(avgProcessHours)}`,
|
|
|
|
|
+ avgProcessHours,
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -556,14 +561,16 @@ function formatStageValue(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function toProgress(green: number, yellow: number, red: number, total: number) {
|
|
|
|
|
- if (total <= 0) {
|
|
|
|
|
|
|
+// S8-MODULE-CARD-SEMANTICS-FIX-1A:分母统一为 green(normal) + yellow + red,不再用异常总数。
|
|
|
|
|
+function toProgress(green: number, yellow: number, red: number) {
|
|
|
|
|
+ const denominator = green + yellow + red;
|
|
|
|
|
+ if (denominator <= 0) {
|
|
|
return { green: 0, yellow: 0, red: 0 };
|
|
return { green: 0, yellow: 0, red: 0 };
|
|
|
}
|
|
}
|
|
|
return {
|
|
return {
|
|
|
- green: (green / total) * 100,
|
|
|
|
|
- yellow: (yellow / total) * 100,
|
|
|
|
|
- red: (red / total) * 100,
|
|
|
|
|
|
|
+ green: (green / denominator) * 100,
|
|
|
|
|
+ yellow: (yellow / denominator) * 100,
|
|
|
|
|
+ red: (red / denominator) * 100,
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|