|
|
@@ -1,50 +1,111 @@
|
|
|
<script setup lang="ts" name="aidopS8AlertRulesConfig">
|
|
|
-import S8CrudConfigPage from '../components/config/S8CrudConfigPage.vue';
|
|
|
+/**
|
|
|
+ * S8-STEP6D-CFG-ALERT-CLOSURE-1:报警规则页收口为「历史兼容 · 只读」。
|
|
|
+ *
|
|
|
+ * 产品模型裁决 = LEGACY_SHELL。依据(运行时实证,非推断):
|
|
|
+ * 1. 三个 evaluator(TIMEOUT / SHORTAGE / OUT_OF_RANGE)的 EvaluateAsync 都接收
|
|
|
+ * IReadOnlyList<AdoS8AlertRule> alertRules 形参,但该标识符在每个文件中**只出现一次**
|
|
|
+ * (即形参声明本身),方法体内读取次数 = 0。
|
|
|
+ * 2. 生产调度 tick(S8WatchSchedulerJob → RunDispatchTickAsync → RunSingleRuleAsync)
|
|
|
+ * 在 S8WatchSchedulerService.cs:1294 为每条租约规则查一次 ado_s8_alert_rule,
|
|
|
+ * 转手传给 evaluator 后被丢弃 —— 即 NO-OP READ。
|
|
|
+ * 3. 唯一真正读取 alert_rule 字段的 LoadExecutionRulesAsync 只能经
|
|
|
+ * AdoS8WatchDebugController 抵达,而该 controller 在 WatchScheduler:DebugEndpointEnabled
|
|
|
+ * 为 false(生产默认)时全部返回 404。
|
|
|
+ * 4. 阈值/严重度/参数/表达式的真实来源已于 2026-04-27 迁入
|
|
|
+ * ado_s8_watch_rule 的 params_json / severity / expression / rule_type。
|
|
|
+ *
|
|
|
+ * 因此本页**不得**继续提供完整可编辑 CRUD —— 那会让用户保存一份永远不生效的配置。
|
|
|
+ * 保留正式 route 与页面(CFG_ALERT 属正式 20 页,不做删除),改为只读说明态:
|
|
|
+ * 如实告知运行时判定由监控规则接管,并只读展示历史遗留行。
|
|
|
+ *
|
|
|
+ * 未做(刻意):不接线回 evaluator(会改变真实异常生成行为,须先有产品拍板);
|
|
|
+ * 不修 CreateAsync 的自增回填(写路径已关闭,不为凑分修死路径);不 Seed;不动 alert_channel / alert_model。
|
|
|
+ */
|
|
|
+import { onMounted, ref } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import AidopDemoShell from '../../components/AidopDemoShell.vue';
|
|
|
import { s8ConfigApi } from '../api/s8ConfigApi';
|
|
|
|
|
|
-const columns = [
|
|
|
- { key: 'ruleCode', label: '规则编码', width: 160 },
|
|
|
- { key: 'sceneCode', label: '场景编码', width: 140 },
|
|
|
- { key: 'severity', label: '严重度', width: 120 },
|
|
|
- { key: 'triggerCondition', label: '触发条件' },
|
|
|
- { key: 'thresholdVal', label: '阈值', width: 140 },
|
|
|
-];
|
|
|
-
|
|
|
-const fields = [
|
|
|
- { key: 'ruleCode', label: '规则编码', type: 'input', required: true },
|
|
|
- { key: 'sceneCode', label: '场景编码', type: 'select', required: true, optionsKey: 'scenes' },
|
|
|
- { key: 'severity', label: '严重度', type: 'select', required: true, optionsKey: 'severities' },
|
|
|
- { key: 'triggerCondition', label: '触发条件', type: 'input', required: true },
|
|
|
- { key: 'thresholdVal', label: '阈值', type: 'input' },
|
|
|
- // S8-CONFIG-CLEANUP-DEMO-1:ado_s8_alert_rule.time_window 当前未被业务消费(不要误伤
|
|
|
- // ado_s8_dashboard_cell_config.time_window,那个在 S8DashboardCellDataService.TimeRange 大量消费)。
|
|
|
- // 仅渲染层隐藏,PUT 全量提交时旧值原样回写。
|
|
|
- { key: 'timeWindow', label: '时间窗口', type: 'input', hidden: true },
|
|
|
-] as const;
|
|
|
-
|
|
|
-const buildDefault = () => ({
|
|
|
- ruleCode: '',
|
|
|
- sceneCode: '',
|
|
|
- severity: 'FOLLOW',
|
|
|
- triggerCondition: '',
|
|
|
- thresholdVal: '',
|
|
|
- timeWindow: '',
|
|
|
-});
|
|
|
+const ENDPOINT = '/api/aidop/s8/config/alert-rules';
|
|
|
+
|
|
|
+const loading = ref(false);
|
|
|
+const rows = ref<Record<string, any>[]>([]);
|
|
|
|
|
|
-async function loadOptions() {
|
|
|
- const [scenes, severities] = await Promise.all([s8ConfigApi.scenes(), s8ConfigApi.severities()]);
|
|
|
- return { scenes: scenes.map((item: any) => ({ label: item.sceneName, value: item.sceneCode })), severities };
|
|
|
+const severityLabel = (val: string) => (val === 'SERIOUS' ? '严重' : val === 'FOLLOW' ? '关注' : val || '-');
|
|
|
+
|
|
|
+async function loadData() {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const data = (await s8ConfigApi.list(ENDPOINT)) as Record<string, any>[];
|
|
|
+ rows.value = Array.isArray(data) ? data : [];
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(e?.message || '加载报警规则失败');
|
|
|
+ rows.value = [];
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ void loadData();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <S8CrudConfigPage
|
|
|
- title="报警规则配置"
|
|
|
- subtitle="S8 / 配置 / 报警规则"
|
|
|
- endpoint="/api/aidop/s8/config/alert-rules"
|
|
|
- :columns="columns"
|
|
|
- :fields="fields"
|
|
|
- :build-default="buildDefault"
|
|
|
- :load-options="loadOptions"
|
|
|
- />
|
|
|
+ <AidopDemoShell title="报警规则配置" subtitle="S8 / 配置 / 报警规则">
|
|
|
+ <el-alert type="warning" :closable="false" show-icon class="legacy-notice">
|
|
|
+ <template #title>本页为历史兼容配置,不参与当前运行时判定</template>
|
|
|
+ <div class="legacy-notice__body">
|
|
|
+ 当前告警判定由<strong>「监控规则」</strong>(Watch Rule)管理,阈值、严重度与触发参数均在该页维护。
|
|
|
+ 本页的报警规则是早期版本的遗留配置,运行时不会读取,因此已收敛为只读展示,不提供新增、编辑与删除。
|
|
|
+ </div>
|
|
|
+ </el-alert>
|
|
|
+
|
|
|
+ <div class="toolbar">
|
|
|
+ <el-button :loading="loading" @click="loadData">刷新</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" :data="rows" border stripe>
|
|
|
+ <el-table-column prop="ruleCode" label="规则编码" width="180" />
|
|
|
+ <el-table-column prop="sceneCode" label="场景编码" width="160" />
|
|
|
+ <el-table-column label="严重度" width="110">
|
|
|
+ <template #default="{ row }">{{ severityLabel(row.severity) }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="triggerCondition" label="触发条件" />
|
|
|
+ <el-table-column prop="thresholdVal" label="阈值" width="140" />
|
|
|
+ <el-table-column label="状态" width="140">
|
|
|
+ <template #default>
|
|
|
+ <el-tag type="info" size="small">历史配置 · 未生效</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <template #empty>
|
|
|
+ <div class="legacy-empty">本工厂没有历史报警规则。告警判定请前往「监控规则」页维护。</div>
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </AidopDemoShell>
|
|
|
</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.legacy-notice {
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.legacy-notice__body {
|
|
|
+ margin-top: 6px;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 1.7;
|
|
|
+}
|
|
|
+
|
|
|
+.toolbar {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.legacy-empty {
|
|
|
+ padding: 12px 0;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+}
|
|
|
+</style>
|