Browse Source

完善算法模块

liling 1 week ago
parent
commit
b8d959ee9f
1 changed files with 192 additions and 25 deletions
  1. 192 25
      src/views/biz/algo/index.vue

+ 192 - 25
src/views/biz/algo/index.vue

@@ -78,7 +78,7 @@
       <el-table-column label="算法ID" align="center" prop="algoId" />
       <el-table-column label="算法名称" align="center" prop="algoName" />
       <el-table-column label="算法描述" align="center" prop="algoDesc" />
-      <el-table-column label="算法脚本" align="center" prop="algoScript" />
+      <el-table-column label="算法脚本" align="center" prop="algoScript" show-overflow-tooltip/>
       <el-table-column label="算法是否正确" align="center" prop="algoOk">
         <template #default="scope">
           <dict-tag :options="sys_common_status" :value="scope.row.algoOk"/>
@@ -111,41 +111,71 @@
     />
 
     <!-- 添加或修改算法管理对话框 -->
-    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
       <el-form ref="algoRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="算法名称" prop="algoName">
+        <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">
+        <el-form-item label="算法描述" prop="algoDesc" label-width="100px">
           <el-input v-model="form.algoDesc" placeholder="请输入算法描述" />
         </el-form-item>
-        <el-form-item label="算法脚本" prop="algoScript">
-          <el-input v-model="form.algoScript" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-        <el-form-item label="算法是否正确" prop="algoOk">
-          <el-radio-group v-model="form.algoOk">
+        <el-form-item label="算法参数" prop="algoPara" label-width="100px">
+          <el-radio-group v-model="form.algoPara">
             <el-radio
-              v-for="dict in sys_common_status"
+              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="algoType">
-          <el-radio-group v-model="form.algoType">
+        <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-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>   
+            <div v-if="activeTabsName=='200'"><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 algo_type"
+              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="algoPara">
-          <el-radio-group v-model="form.algoPara">
+        <el-form-item label="算法类别" prop="algoType" label-width="100px">
+          <el-radio-group v-model="form.algoType">
             <el-radio
-              v-for="dict in algo_para"
+              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>
@@ -161,9 +191,15 @@
 </template>
 
 <script setup name="Algo">
-    import { listAlgo, getAlgo, delAlgo, addAlgo, updateAlgo } from "@/api/biz/algo";
-
-    const { proxy } = getCurrentInstance();
+import { listAlgo, getAlgo, delAlgo, addAlgo, updateAlgo } from "@/api/biz/algo";
+import { listData, getData } from "@/api/biz/data";
+import { EditorView, keymap } from '@codemirror/view'
+import { EditorState } from '@codemirror/state'
+import { defaultKeymap } from '@codemirror/commands'
+import { highlightSelectionMatches } from '@codemirror/search'
+import { javascript } from '@codemirror/lang-javascript'
+import { oneDark } from '@codemirror/theme-one-dark'
+const { proxy } = getCurrentInstance();
 const { sys_common_status, algo_type, algo_para } = proxy.useDict('sys_common_status', 'algo_type', 'algo_para');
 
 const algoList = ref([]);
@@ -175,22 +211,110 @@ const single = ref(true);
 const multiple = ref(true);
 const total = ref(0);
 const title = ref("");
+const activeTabsName = ref("100");
+const activeTabsParaName = ref("lastweek");
+const lastweek_value = ref("");
+const currweek_value = ref("");
 
+const editorContainer  =  ref(null);
+let editorView = null;
+const modelValue = ref('这是一段js脚本 !');
 const data = reactive({
-  form: {},
+  form: {algoPara: "1"},
   queryParams: {
     pageNum: 1,
     pageSize: 10,
     algoName: null,
     algoDesc: null,
     algoType: null,
-    algoPara: null,
+    algoPara: "1",
   },
   rules: {
   }
 });
 
+const jsCheckResult = ref("未验证"); //脚本验证结果
+
 const { queryParams, form, rules } = toRefs(data);
+const setItemRef = (el) => {
+  if (el) {
+    editorContainer.value = el
+  }
+}
+
+const handleTabClick=()=>{
+
+}
+
+const checkJS=()=>{
+  let scriptStr=editorView.state.doc.toString();
+  if(scriptStr==''){
+    proxy.$modal.msgError("算法脚本不能为空!");
+    return;
+  }
+  //lastweek_value
+  let paramsStr = "";
+  if(lastweek_value.value==''){
+    proxy.$modal.msgError("数据样例(一周)不能为空!");
+    return;
+  }
+  paramsStr = lastweek_value.value.substring(0,1)!='[' ? "'"+lastweek_value.value+"'" : lastweek_value.value;
+  if(form.value.algoPara=="2" && currweek_value.value==''){
+    proxy.$modal.msgError("数据样例(两周)不能为空!");
+    return;
+  }
+  if(form.value.algoPara=="2"){
+    if(currweek_value.value.substring(0,1)!='[')
+      paramsStr += ",'"+currweek_value.value+"'";
+    else
+    paramsStr += ","+currweek_value.value;
+  }
+  try{
+    scriptStr = "const nonefun = "+scriptStr+"; nonefun("+paramsStr+")";
+    console.log(scriptStr)
+    var result = eval(scriptStr);
+    jsCheckResult.value=result
+    form.value.algoOk="0";
+  }catch(e){
+    console.log(e)
+    form.value.algoOk="1";
+    jsCheckResult.value="验证失败:脚本错误!";
+  }
+};
+
+// 创建编辑器配置
+const createEditorState = (content) => {
+  const extensions = [
+    keymap.of(defaultKeymap),
+    highlightSelectionMatches(),
+    EditorView.updateListener.of((update) => {
+      if (update.docChanged) {
+        //const content = update.state.doc.toString()
+        //emit('update:modelValue', content)
+      }
+    }),
+    EditorView.editable.of(true)
+  ]
+
+  // 添加语言支持
+  extensions.push(javascript());
+  extensions.push(oneDark)
+
+  return EditorState.create({
+    doc: content,
+    extensions
+  })
+}
+
+// 初始化编辑器
+ const initEditor = () => {
+  if (editorContainer.value) {
+    editorView = new EditorView({
+      state: createEditorState(modelValue.value),
+      parent: editorContainer.value
+    })
+  }
+}
 
 /** 查询算法管理列表 */
 function getList() {
@@ -202,6 +326,13 @@ function getList() {
   });
 }
 
+function getDataExp(){
+  listData({}).then(res=>{
+    lastweek_value.value = res.rows[0]["currData"];
+    currweek_value.value = res.rows[0]["lastData"];
+  })
+}
+
 // 取消按钮
 function cancel() {
   open.value = false;
@@ -214,10 +345,10 @@ function reset() {
     algoId: null,
     algoName: null,
     algoDesc: null,
-    algoScript: null,
-    algoOk: null,
+    algoScript: "",
+    algoOk: "1",
     algoType: null,
-    algoPara: null,
+    algoPara: "1",
     createBy: null,
     createTime: null,
     updateBy: null,
@@ -251,6 +382,9 @@ function handleAdd() {
   reset();
   open.value = true;
   title.value = "添加算法管理";
+  setTimeout(() => {
+    initEditor();
+  }, 100);  
 }
 
 /** 修改按钮操作 */
@@ -261,11 +395,21 @@ function handleUpdate(row) {
     form.value = response.data;
     open.value = true;
     title.value = "修改算法管理";
+    modelValue.value = form.value.algoScript;
+    setTimeout(() => {
+      initEditor();
+    }, 100);
   });
 }
 
 /** 提交按钮 */
 function submitForm() {
+  //console.log("====:",editorView.state.doc.toString())
+  if(form.value.algoOk!="0"){
+    proxy.$modal.msgError("算法验证失败,不允许保存!");
+    return;
+  }
+  form.value.algoScript = editorView.state.doc.toString()
   proxy.$refs["algoRef"].validate(valid => {
     if (valid) {
       if (form.value.algoId != null) {
@@ -302,6 +446,29 @@ function handleExport() {
     ...queryParams.value
   }, `algo_${new Date().getTime()}.xlsx`)
 }
-
 getList();
+getDataExp();
 </script>
+<style scoped>
+.code-editor {
+  border: 1px solid #ccc;
+  border-radius: 4px;
+  overflow: hidden;
+  height: 300px;
+  width: 100%;
+}
+
+:deep(.cm-editor) {
+  height: 100%;
+}
+
+:deep(.cm-content) {
+  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
+  font-size: 14px;
+  line-height: 1.5;
+}
+
+:deep(.cm-selectionMatch) {
+  background-color: #ffff0055;
+}
+</style>