|
|
@@ -28,6 +28,26 @@ const monitorObjects = ref<S8MonitorObjectOption[]>([]);
|
|
|
const drawerOpen = ref(false);
|
|
|
const editingRow = ref<S8WatchRuleConfigRow | null>(null);
|
|
|
|
|
|
+// S8-WATCH-RULE-CONFIG-CONSISTENCY-FIX-1 / t1-seed-rule-list-display-align:
|
|
|
+// SeedData 60 条规则 paramsJson 不携带 objectLabel/metricLabel/thresholdDisplay/unit;
|
|
|
+// 列表层做派生 fallback,让"已有规则"和"新建配置"展示口径一致。
|
|
|
+// 派生顺序(与 parseRuleBizFields 一致):
|
|
|
+// objectLabel:paramsJson.objectLabel → monitorObjects[objectType] → 静态 fallback map → watchObjectType 原值 → '未配置'
|
|
|
+// metricLabel:paramsJson.metricLabel → EXCEPTION_TYPE_NAME_MAP[exceptionTypeCode] → exceptionTypeCode → '未配置'
|
|
|
+// thresholdDisplay:paramsJson.thresholdDisplay → summarizeBizCondition 派生 → '未配置'
|
|
|
+// 仅展示层;不写 DB;不调后端。
|
|
|
+const OBJECT_TYPE_FALLBACK_LABEL: Record<string, string> = {
|
|
|
+ ORDER: '订单',
|
|
|
+ SALES_ORDER: '销售订单',
|
|
|
+ PURCHASE_ORDER: '供应商交付',
|
|
|
+ WORK_ORDER: '生产工单',
|
|
|
+ INVENTORY: '库存',
|
|
|
+ IQC: 'IQC 检验',
|
|
|
+ EQUIPMENT: '设备',
|
|
|
+ MATERIAL: '物料',
|
|
|
+ QUALITY_CHECK: '质量检验',
|
|
|
+};
|
|
|
+
|
|
|
// CONFIG-RULE-CENTER-SHELL-MVP-1:业务化筛选 + 前端本地分页 + 运行态列折叠。
|
|
|
const searchKeyword = ref('');
|
|
|
const filterMechanism = ref<'' | 'DATE' | 'VALUE_RANGE' | 'RATIO'>('');
|
|
|
@@ -193,21 +213,75 @@ function stopAutoRefresh() {
|
|
|
}
|
|
|
|
|
|
// CONFIG-RULE-CENTER-SHELL-MVP-1:业务化筛选 + 前端分页 + 业务字段解析。
|
|
|
+// S8-WATCH-RULE-CONFIG-CONSISTENCY-FIX-1:SeedData 60 条规则 paramsJson 不带 objectLabel/metricLabel/thresholdDisplay;
|
|
|
+// 这里增加派生 fallback,使列表"监控对象/监控指标/判定标准"不再全部显示"未配置"。
|
|
|
+function deriveObjectLabel(row: S8WatchRuleConfigRow, p: Record<string, unknown>): string {
|
|
|
+ if (typeof p.objectLabel === 'string' && p.objectLabel) return p.objectLabel;
|
|
|
+ const objType = (row.watchObjectType || row.sourceObjectType || '').toString();
|
|
|
+ if (!objType) return '未配置';
|
|
|
+ // 优先从已加载的 monitor 字典(objectType 匹配)取中文 label;同 objectType 多对象时取首条。
|
|
|
+ const hit = monitorObjects.value.find((o) => o.objectType === objType);
|
|
|
+ if (hit?.objectLabel) return hit.objectLabel;
|
|
|
+ return OBJECT_TYPE_FALLBACK_LABEL[objType] || objType;
|
|
|
+}
|
|
|
+function deriveMetricLabel(p: Record<string, unknown>): string {
|
|
|
+ if (typeof p.metricLabel === 'string' && p.metricLabel) return p.metricLabel;
|
|
|
+ const etc = typeof p.exceptionTypeCode === 'string' ? p.exceptionTypeCode : '';
|
|
|
+ if (etc) return EXCEPTION_TYPE_NAME_MAP[etc] || etc;
|
|
|
+ return '未配置';
|
|
|
+}
|
|
|
function parseRuleBizFields(row: S8WatchRuleConfigRow): { objectLabel: string; metricLabel: string; thresholdDisplay: string } {
|
|
|
const fallback = { objectLabel: '未配置', metricLabel: '未配置', thresholdDisplay: '未配置' };
|
|
|
- if (!row.paramsJson) return fallback;
|
|
|
+ if (!row.paramsJson) {
|
|
|
+ // 无 paramsJson 时仍按 watchObjectType 尝试展示对象,避免整行"未配置"。
|
|
|
+ return {
|
|
|
+ objectLabel: deriveObjectLabel(row, {}),
|
|
|
+ metricLabel: '未配置',
|
|
|
+ thresholdDisplay: '未配置',
|
|
|
+ };
|
|
|
+ }
|
|
|
try {
|
|
|
const p = JSON.parse(row.paramsJson) as Record<string, unknown>;
|
|
|
+ const explicitThr = typeof p.thresholdDisplay === 'string' && p.thresholdDisplay ? p.thresholdDisplay : '';
|
|
|
return {
|
|
|
- objectLabel: typeof p.objectLabel === 'string' && p.objectLabel ? p.objectLabel : '未配置',
|
|
|
- metricLabel: typeof p.metricLabel === 'string' && p.metricLabel ? p.metricLabel : '未配置',
|
|
|
- thresholdDisplay: typeof p.thresholdDisplay === 'string' && p.thresholdDisplay ? p.thresholdDisplay : '未配置',
|
|
|
+ objectLabel: deriveObjectLabel(row, p),
|
|
|
+ metricLabel: deriveMetricLabel(p),
|
|
|
+ thresholdDisplay: explicitThr || deriveThresholdDisplay(row, p) || '未配置',
|
|
|
};
|
|
|
} catch {
|
|
|
return fallback;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 从 row + paramsJson 派生"判定标准"中文展示;与 summarizeBizCondition 行为对齐,但作为纯函数供列表列调用。
|
|
|
+function deriveThresholdDisplay(row: S8WatchRuleConfigRow, p: Record<string, unknown>): string {
|
|
|
+ const unit = typeof p.unit === 'string' ? p.unit : '';
|
|
|
+ const mech = row.ruleMechanism;
|
|
|
+ if (mech === 'DATE') {
|
|
|
+ const grace = typeof p.graceMinutes === 'number' ? p.graceMinutes : 0;
|
|
|
+ return grace > 0 ? `超期 ${grace} 分钟仍未完成触发` : '超期即触发';
|
|
|
+ }
|
|
|
+ if (mech === 'RATIO') {
|
|
|
+ const tgt = typeof p.lowerBound === 'number' ? p.lowerBound : null;
|
|
|
+ return tgt != null ? `低于 ${tgt}${unit || '%'} 触发` : '';
|
|
|
+ }
|
|
|
+ if (mech === 'VALUE_RANGE') {
|
|
|
+ const lo = typeof p.lowerBound === 'number' ? p.lowerBound : null;
|
|
|
+ const up = typeof p.upperBound === 'number' ? p.upperBound : null;
|
|
|
+ const segs: string[] = [];
|
|
|
+ if (lo != null) segs.push(`低于 ${lo}${unit}`);
|
|
|
+ if (up != null) segs.push(`高于 ${up}${unit}`);
|
|
|
+ return segs.length > 0 ? segs.join(' 或 ') + ' 触发' : '';
|
|
|
+ }
|
|
|
+ return '';
|
|
|
+}
|
|
|
+
|
|
|
+// S8-WATCH-RULE-CONFIG-CONSISTENCY-FIX-1:判定规则是否为 SeedData / 演示预置(仅按 ruleCode 前缀,不动 DB)。
|
|
|
+function isSeedRule(row: S8WatchRuleConfigRow): boolean {
|
|
|
+ const code = row.ruleCode || '';
|
|
|
+ return code.startsWith('DEMO_') || /^RULE_S[1-7]_/.test(code);
|
|
|
+}
|
|
|
+
|
|
|
// CONFIG-RULE-EDIT-BIZ-VIEW-MVP-1:从 paramsJson 推导业务判定标准的中文展示(编辑抽屉摘要使用)。
|
|
|
function summarizeBizCondition(row: S8WatchRuleConfigRow | null): string {
|
|
|
if (!row) return '—';
|
|
|
@@ -1126,6 +1200,15 @@ onDeactivated(() => stopAutoRefresh());
|
|
|
|
|
|
<template>
|
|
|
<AidopDemoShell title="规则配置中心" subtitle="配置异常监控规则、报警机制、监控对象与判定标准。新建后默认停用,演示前由人工启用。">
|
|
|
+ <!-- S8-WATCH-RULE-CONFIG-CONSISTENCY-FIX-1:演示语义说明,避免用户把"已配规则"误解为"已在运行" -->
|
|
|
+ <el-alert
|
|
|
+ v-if="centerStats.disabled > 0"
|
|
|
+ type="info"
|
|
|
+ :closable="false"
|
|
|
+ show-icon
|
|
|
+ style="margin-bottom: 8px"
|
|
|
+ :title="`当前 ${centerStats.disabled} 条规则处于停用状态,调度器不会执行;大盘异常数据来自演示种子,不由本页规则实时产生。`"
|
|
|
+ />
|
|
|
<!-- CONFIG-RULE-CENTER-SHELL-MVP-1:主操作 + 统计 chip + 业务化筛选 + 前端分页 -->
|
|
|
<div class="rule-toolbar">
|
|
|
<el-button size="small" type="primary" @click="openWizard">新建监控配置</el-button>
|
|
|
@@ -1238,9 +1321,11 @@ onDeactivated(() => stopAutoRefresh());
|
|
|
<span :class="{ 'rule-biz-empty': parseRuleBizFields(row).thresholdDisplay === '未配置' }">{{ parseRuleBizFields(row).thresholdDisplay }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="状态" width="80">
|
|
|
+ <el-table-column label="状态" width="120">
|
|
|
<template #default="{ row }">
|
|
|
<el-tag :type="row.enabled ? 'success' : 'info'" size="small">{{ row.enabled ? '启用' : '停用' }}</el-tag>
|
|
|
+ <!-- S8-WATCH-RULE-CONFIG-CONSISTENCY-FIX-1:SeedData / DEMO 规则标记,避免被误读为生产运行规则 -->
|
|
|
+ <el-tag v-if="isSeedRule(row)" size="small" type="warning" effect="plain" style="margin-left: 4px">演示</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="严重度" width="80">
|