Parcourir la source

修改算法和分析结果

wukai il y a 1 mois
Parent
commit
25244e49ff
2 fichiers modifiés avec 255 ajouts et 88 suppressions
  1. 185 78
      src/views/ripa/algo/index.vue
  2. 70 10
      src/views/ripa/analy/index.vue

+ 185 - 78
src/views/ripa/algo/index.vue

@@ -114,86 +114,116 @@
     />
 
     <!-- 添加或修改算法管理对话框 -->
-    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
+    <el-dialog :title="title" v-model="open" width="1200px" append-to-body>
       <el-form ref="algoRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="算法名称" prop="algoName" label-width="100px">
-          <el-input v-model="form.algoName" placeholder="请输入算法名称"/>
-        </el-form-item>
-        <el-form-item label="算法描述" prop="algoDesc" label-width="100px">
-          <el-input v-model="form.algoDesc" placeholder="请输入算法描述"/>
-        </el-form-item>
-        <el-form-item label="算法参数" prop="algoPara" label-width="100px">
-          <el-radio-group v-model="form.algoPara">
-            <el-radio
-                v-for="dict in algo_para"
-                :key="dict.value"
-                :label="dict.value"
-            >{{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="算法脚本" prop="algoScript" label-width="100px">
-          <el-tabs style="width: 100%;" v-model="activeTabsName" @tab-click="handleTabClick">
-            <el-tab-pane label="脚本" name="100">
-              <div :ref="(el)=>setItemRef(el)" class="code-editor"></div>
-            </el-tab-pane>
-            <el-tab-pane label="验证" name="200">
-              <el-tabs style="width:100%;height: 100%;" v-model="activeTabsParaName">
-                <el-tab-pane label="数据样例:一周" name="lastweek" style="width:100%;height: 100%;">
-                  <el-input
-                      v-model="lastweek_value"
-                      type="textarea"
-                      :rows="9"
-                      placeholder="请输入内容"
-                  />
+        <el-row :gutter="20">
+          <!-- 左侧栏 -->
+          <el-col :span="12">
+            <el-form-item label="算法名称" prop="algoName" label-width="100px">
+              <el-input v-model="form.algoName" placeholder="请输入算法名称"/>
+            </el-form-item>
+            <el-form-item label="算法描述" prop="algoDesc" label-width="100px">
+              <el-input v-model="form.algoDesc" type="textarea" placeholder="请输入算法描述"/>
+            </el-form-item>
+            <el-form-item label="算法参数" prop="algoPara" label-width="100px">
+              <el-radio-group v-model="form.algoPara">
+                <el-radio
+                    v-for="dict in algo_para"
+                    :key="dict.value"
+                    :label="dict.value"
+                >{{ dict.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="算法是否正确" prop="algoOk" label-width="100px">
+              <el-radio-group v-model="form.algoOk">
+                <el-radio
+                    v-for="dict in sys_common_status"
+                    :key="dict.value"
+                    :label="dict.value"
+                    disabled
+                >{{ dict.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="算法类别" prop="algoType" label-width="100px">
+              <el-radio-group v-model="form.algoType">
+                <el-radio
+                    v-for="dict in algo_type"
+                    :key="dict.value"
+                    :label="dict.value"
+                    :disabled="form.algoOk!='0'"
+                >{{ dict.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="返回结果" prop="results" label-width="100px">
+              <el-table :data="form.results" style="width: 100%" border>
+                <el-table-column label="返回描述" align="center">
+                  <template #default="{ row }">
+                    <el-input
+                        v-model="row.name"
+                        placeholder="请输入返回描述"
+                        :rules="[
+                  { required: true, message: '返回描述不能为空', trigger: 'blur' }
+                ]"
+                    />
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" width="100">
+                  <template #default="{ $index }">
+                    <el-button link type="danger" @click="removeResultRow($index)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <el-button type="primary" link @click="addResultRow">+ 添加结果项</el-button>
+            </el-form-item>
+          </el-col>
+
+          <!-- 右侧栏 -->
+          <el-col :span="12">
+            <el-form-item label="算法脚本" prop="algoScript" label-width="100px">
+              <el-tabs style="width: 100%;" v-model="activeTabsName" @tab-click="handleTabClick">
+                <el-tab-pane label="脚本" name="100">
+                  <div :ref="(el)=>setItemRef(el)" class="code-editor"></div>
                 </el-tab-pane>
-                <el-tab-pane label="数据样例:两周" name="currweek" style="width:100%;height: 100%;"
-                             v-if="form.algoPara=='2'">
-                  <el-input
-                      v-model="currweek_value"
-                      type="textarea"
-                      :rows="9"
-                      placeholder="请输入内容"
-                  />
+                <el-tab-pane label="验证" name="200">
+                  <el-tabs style="width:100%;height: 100%;" v-model="activeTabsParaName">
+                    <el-tab-pane label="数据样例:一周" name="lastweek" style="width:100%;height: 100%;">
+                      <el-input
+                          v-model="lastweek_value"
+                          type="textarea"
+                          :rows="9"
+                          placeholder="请输入内容"
+                      />
+                    </el-tab-pane>
+                    <el-tab-pane label="数据样例:两周" name="currweek" style="width:100%;height: 100%;"
+                                 v-if="form.algoPara=='2'">
+                      <el-input
+                          v-model="currweek_value"
+                          type="textarea"
+                          :rows="9"
+                          placeholder="请输入内容"
+                      />
+                    </el-tab-pane>
+                  </el-tabs>
                 </el-tab-pane>
               </el-tabs>
-            </el-tab-pane>
-          </el-tabs>
-          <div class="data_exp_list" v-if="showExpList">
-            <div v-for="item in explist">
-              <el-checkbox :key="item.dataId" :label="item.dataName" @change="selecedData(item)"></el-checkbox>
-            </div>
-          </div>
-          <div v-if="activeTabsName=='200'">
-            <el-button @click="selectDataExp">生成数据样例</el-button>
-            <el-button type="primary" @click="checkJS">验 证</el-button>
-          </div>
-        </el-form-item>
-        <el-form-item label="算法验证结果" label-width="100px">
-          <div class="width:100%;height:50px">{{ jsCheckResult }}</div>
-        </el-form-item>
-        <el-form-item label="算法是否正确" prop="algoOk" label-width="100px">
-          <el-radio-group v-model="form.algoOk">
-            <el-radio
-                v-for="dict in sys_common_status"
-                :key="dict.value"
-                :label="dict.value"
-                disabled
-            >{{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="算法类别" prop="algoType" label-width="100px">
-          <el-radio-group v-model="form.algoType">
-            <el-radio
-                v-for="dict in algo_type"
-                :key="dict.value"
-                :label="dict.value"
-                :disabled="form.algoOk!='0'"
-            >{{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
+              <div class="data_exp_list" v-if="showExpList">
+                <div v-for="item in explist">
+                  <el-checkbox :key="item.dataId" :label="item.dataName" @change="selecedData(item)"></el-checkbox>
+                </div>
+              </div>
+              <div v-if="activeTabsName=='200'">
+                <el-button @click="selectDataExp">生成数据样例</el-button>
+                <el-button type="primary" @click="checkJS">验 证</el-button>
+              </div>
+            </el-form-item>
+            <el-form-item label="算法验证结果" label-width="100px">
+              <div class="width:100%;height:50px">{{ jsCheckResult }}</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -202,6 +232,7 @@
         </div>
       </template>
     </el-dialog>
+
   </div>
 </template>
 
@@ -257,6 +288,23 @@ const data = reactive({
     ],
     algoScript: [
       {required: true, message: "算法脚本不能为空", trigger: "blur"}
+    ],
+    results: [
+      {
+        validator: (rule, value, callback) => {
+          if (!value || value.length === 0) {
+            callback(new Error('至少需要添加一条返回结果'));
+          } else {
+            const valid = value.every(item => item.name && item.name.trim() !== '');
+            if (valid) {
+              callback();
+            } else {
+              callback(new Error('所有返回描述都为必填项'));
+            }
+          }
+        },
+        trigger: 'change'
+      }
     ]
   }
 });
@@ -270,6 +318,32 @@ const setItemRef = (el) => {
   }
 }
 
+// 在<script setup>部分适当位置添加以下函数
+
+/**
+ * 添加结果行
+ */
+function addResultRow() {
+  if (!form.value.results) {
+    form.value.results = [];
+  }
+  form.value.results.push({
+    name: '',
+    value: ''
+  });
+}
+
+/**
+ * 删除结果行
+ * @param index 索引
+ */
+function removeResultRow(index) {
+  if (form.value.results && form.value.results.length > index) {
+    form.value.results.splice(index, 1);
+  }
+}
+
+
 const handleTabClick = () => {
 
 }
@@ -316,15 +390,24 @@ const checkJS = () => {
   try {
     scriptStr = "const nonefun = " + scriptStr + "; nonefun(" + paramsStr + ")";
     var result = eval(scriptStr);
+
+    // 验证返回结果长度不超过255字符
+    if (typeof result === 'string' && result.length > 400) {
+      jsCheckResult.value = "验证失败:返回结果字符串长度超过400个字符;";
+      jsCheckResult.value += "返回结果:" + result;
+      return;
+    }
+
     jsCheckResult.value = result
     form.value.algoOk = "0";
   } catch (e) {
     console.log(e)
     form.value.algoOk = "1";
-    jsCheckResult.value = "验证失败:脚本错误!";
+    jsCheckResult.value = "验证失败:脚本错误!"+e.message;
   }
 };
 
+
 // 创建编辑器配置
 const createEditorState = (content) => {
   const extensions = [
@@ -404,8 +487,14 @@ function reset() {
     createTime: null,
     updateBy: null,
     updateTime: null,
-    remark: null
+    remark: null,
+    results: [] // 添加这一行
   };
+  jsCheckResult.value = "";
+  activeTabsName.value = "100";
+  activeTabsParaName.value = "lastweek";
+  lastweek_value.value = "";
+  currweek_value.value = "";
   proxy.resetForm("algoRef");
 }
 
@@ -447,6 +536,15 @@ function handleUpdate(row) {
   getAlgo(_algoId).then(response => {
     form.value = response.data;
     open.value = true;
+    // 在指定位置添加以下代码
+    if (form.value.remark) {
+      form.value.results = form.value.remark.split('||').map(name => ({
+        name: name,
+        value: ''
+      }));
+    } else {
+      form.value.results = [];
+    }
     title.value = "修改算法管理";
     modelValue.value = form.value.algoScript;
     setTimeout(() => {
@@ -457,6 +555,15 @@ function handleUpdate(row) {
 
 /** 提交按钮 */
 function submitForm() {
+  // 将results组装成以||分隔的字符串,放入remark
+  if (form.value.results && form.value.results.length > 0) {
+    form.value.remark = form.value.results
+        .map(item => item.name)
+        .filter(name => name && name.trim() !== '')
+        .join('||');
+  } else {
+    form.value.remark = ''; // 如果没有结果项,则设为空字符串
+  }
   //console.log("====:",editorView.state.doc.toString())
   if (form.value.algoOk != "0") {
     proxy.$modal.msgError("算法验证失败,不允许保存!");

+ 70 - 10
src/views/ripa/analy/index.vue

@@ -103,7 +103,7 @@
           <span>{{ parseTime(scope.row.lastTime, '{y}-{m}-{d} {h}:{mi}:{s}') }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="告警关键字" align="center" prop="alarmKey"/>
+      <el-table-column label="指标恶化包含关键字" align="center" prop="alarmKey"/>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
           <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">配置算法</el-button>
@@ -148,6 +148,15 @@
             <el-form-item label="对象名称">
               {{ form.objName }}
             </el-form-item>
+            <el-form-item label="告警说明">
+              <el-alert
+                  title="启用告警后,系统将在满足算法返回结果包含选择的关键字时,在运行风险监测系统中产生告警记录。"
+                  type="warning"
+                  show-icon
+                  :closable="false"
+                  style="margin-top: 10px;"
+              />
+            </el-form-item>
           </el-col>
           <el-col :span="14" :xs="24">
             <!--          <el-table-column label="算法名称" align="center" prop="algoName"/>-->
@@ -160,8 +169,8 @@
               <el-text v-model="form.autoId" placeholder="请输入指标自动ID"/>
             </el-form-item>
             <el-form-item label="算法名称" prop="algoId">
-              <el-select v-model="form.algoId" placeholder="请选择算法" style="width: 260px" clearable
-                         filterable remote reserve-keyword>
+              <el-select v-model="form.algoId" placeholder="请选择算法" style="width: 260px" clearable filterable remote
+                         reserve-keyword @change="handleAlgoChange">
                 <el-option
                     v-for="dict in algoList"
                     :key="dict.algoId"
@@ -201,15 +210,26 @@
                 ></el-option>
               </el-select>
             </el-form-item>
-            <el-form-item label="告警关键字" prop="alarmKey" v-if="form.alarmWitch === 'Y'">
-              <el-input v-model="form.alarmKey" placeholder="请输入告警包含关键字"/>
+            <el-form-item label="指标恶化包含关键字" prop="alarmKey" v-if="form.alarmWitch === 'Y'" label-width="150px">
+              <el-select
+                  v-model="form.alarmKey"
+                  placeholder="指标恶化包含关键字"
+                  clearable
+              >
+                <el-option
+                    v-for="item in algoResultList"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                ></el-option>
+              </el-select>
             </el-form-item>
 
             <!--                    <el-form-item label="告警内容">-->
             <!--                      <editor v-model="form.alarmContent" :min-height="192"/>-->
             <!--                    </el-form-item>-->
-            <el-form-item label="备注" prop="remark">
-              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"/>
+            <el-form-item label="告警内容" prop="alarmContent" v-if="form.alarmWitch === 'Y'" >
+              <el-input v-model="form.alarmContent" type="textarea" placeholder="请输入告警内容"/>
             </el-form-item>
           </el-col>
         </el-row>
@@ -234,7 +254,7 @@
     </el-dialog>
 
     <el-dialog :title="titleH" v-model="openH" width="1300" append-to-body>
-      <history ref="historyRef" :analy-id="_analyId" style="height: 600px; overflow-y: auto;"/>
+      <history v-if="openH" ref="historyRef" :analy-id="_analyId" style="height: 600px; overflow-y: auto;"/>
       <template #footer>
         <div class="dialog-footer">
           <el-button type="primary" @click="selectOK">确 定</el-button>
@@ -258,6 +278,7 @@ const _unused = selectMetrics; // 防止IDE认为组件未被使用
 const _unused1 = history; // 防止IDE认为组件未被使用
 const analyList = ref([]);
 const algoList = ref([]);
+const algoResultList = ref([]);
 const open = ref(false);
 const openS = ref(false);
 const openH = ref(false);
@@ -300,12 +321,27 @@ const data = reactive({
     alarmKey: [
       {
         required: true,
-        message: "告警关键字不能为空",
+        message: "告警包含关键字不能为空",
         trigger: "blur",
         validator: (rule, value, callback) => {
           // 只有当 alarmWitch 为 'Y' 时才验证
           if (form.value.alarmWitch === 'Y' && (!value || value.trim() === '')) {
-            callback(new Error('告警关键字不能为空'));
+            callback(new Error('告警包含关键字不能为空'));
+          } else {
+            callback();
+          }
+        }
+      }
+    ],
+    alarmContent: [
+      {
+        required: true,
+        message: "告警内容不能为空",
+        trigger: "blur",
+        validator: (rule, value, callback) => {
+          // 只有当 alarmWitch 为 'Y' 时才验证
+          if (form.value.alarmWitch === 'Y' && (!value || value.trim() === '')) {
+            callback(new Error('告警内容不能为空'));
           } else {
             callback();
           }
@@ -317,6 +353,30 @@ const data = reactive({
 
 const {queryParams, form, rules} = toRefs(data);
 
+// 监听算法选择变化
+function handleAlgoChange(newVal) {
+  if (newVal) {
+    // 找到选中的算法
+    const selectedAlgo = algoList.value.find(algo => algo.algoId === newVal);
+    const defaultTemplate = `使用算法"${selectedAlgo.algoName}"检测,发现指标恶化,请注意!`;
+    form.value.alarmContent = defaultTemplate;
+    form.value.algoName = selectedAlgo.algoName;
+    if (selectedAlgo && selectedAlgo.remark) {
+      // 将remark按||拆分并转换为选项列表
+      algoResultList.value = selectedAlgo.remark.split('||').map(item => ({
+        value: item,
+        label: item
+      }));
+      // 只有当 alarmContent 为空时才设置默认值
+      // 检查是否使用默认模板或为空,如果是则更新
+    } else {
+      algoResultList.value = [];
+    }
+  } else {
+    algoResultList.value = [];
+  }
+}
+
 /** 选择指标确定按钮 */
 function selectOK() {
   try {