Browse Source

feat:优化API定义页面

microrain 5 months ago
parent
commit
e5732e3b15
4 changed files with 690 additions and 372 deletions
  1. 158 55
      package-lock.json
  2. 2 0
      package.json
  3. 307 99
      src/views/apihub/component/edit.vue
  4. 223 218
      yarn.lock

+ 158 - 55
package-lock.json

@@ -11,6 +11,7 @@
       "dependencies": {
         "@antv/g2plot": "2.4.20",
         "@element-plus/icons-vue": "2.0.9",
+        "@guolao/vue-monaco-editor": "^1.5.5",
         "axios": "0.26.0",
         "clipboard": "2.0.11",
         "codemirror": "5.65.16",
@@ -24,11 +25,13 @@
         "echarts-wordcloud": "2.0.0",
         "element-plus": "2.2.28",
         "event-source-polyfill": "1.0.31",
+        "html2canvas": "^1.4.1",
         "js-cookie": "3.0.5",
         "jsplumb": "2.15.6",
         "jsrsasign": "10.8.6",
         "loadsh": "0.0.4",
         "mitt": "3.0.0",
+        "monaco-editor": "^0.52.2",
         "nprogress": "0.2.0",
         "pako": "1.0.11",
         "print-js": "1.6.0",
@@ -44,6 +47,7 @@
         "vform3-builds": "3.0.8",
         "vue": "3.2.37",
         "vue-clipboard3": "1.0.1",
+        "vue-data-ui": "^2.4.17",
         "vue-grid-layout": "3.0.0-beta1",
         "vue-i18n": "9.1.10",
         "vue-router": "4.0.13",
@@ -63,7 +67,8 @@
         "@typescript-eslint/parser": "5.13.0",
         "@vitejs/plugin-vue": "3.1.0",
         "@vue/compiler-sfc": "3.2.45",
-        "dotenv": "16.0.0",
+        "cross-env": "^7.0.3",
+        "dotenv": "^16.4.5",
         "eslint": "8.10.0",
         "eslint-plugin-vue": "8.5.0",
         "prettier": "2.5.1",
@@ -454,6 +459,26 @@
       "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.7.tgz",
       "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA=="
     },
+    "node_modules/@guolao/vue-monaco-editor": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.5.5.tgz",
+      "integrity": "sha512-NFGImQ8dBYj6ehIxy1DngPRkctB9b6GbxvCm6aXZztNsgm/TtM4u+YM9ZwZHQPlXt7a4IODXoKCcTYEVycBSyA==",
+      "license": "MIT",
+      "dependencies": {
+        "@monaco-editor/loader": "^1.5.0",
+        "vue-demi": "latest"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.7.1",
+        "monaco-editor": ">=0.43.0",
+        "vue": "^2.6.14 || >=3.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@humanwhocodes/config-array": {
       "version": "0.9.5",
       "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
@@ -750,6 +775,15 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/@monaco-editor/loader": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
+      "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
+      "license": "MIT",
+      "dependencies": {
+        "state-local": "^1.0.6"
+      }
+    },
     "node_modules/@nodelib/fs.scandir": {
       "version": "2.1.5",
       "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1272,31 +1306,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/@vueuse/core/node_modules/vue-demi": {
-      "version": "0.14.10",
-      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
-      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/@vueuse/metadata": {
       "version": "9.13.0",
       "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
@@ -1316,31 +1325,6 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
-    "node_modules/@vueuse/shared/node_modules/vue-demi": {
-      "version": "0.14.10",
-      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
-      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
-      "hasInstallScript": true,
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/@wdns/vue-code-block": {
       "version": "2.3.3",
       "resolved": "https://registry.npmmirror.com/@wdns/vue-code-block/-/vue-code-block-2.3.3.tgz",
@@ -1673,6 +1657,15 @@
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
+    "node_modules/base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6.0"
+      }
+    },
     "node_modules/batch-processor": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz",
@@ -1967,6 +1960,25 @@
       "resolved": "https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.12.tgz",
       "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw=="
     },
+    "node_modules/cross-env": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
+      "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "cross-spawn": "^7.0.1"
+      },
+      "bin": {
+        "cross-env": "src/bin/cross-env.js",
+        "cross-env-shell": "src/bin/cross-env-shell.js"
+      },
+      "engines": {
+        "node": ">=10.14",
+        "npm": ">=6",
+        "yarn": ">=1"
+      }
+    },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1981,6 +1993,15 @@
         "node": ">= 8"
       }
     },
+    "node_modules/css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "license": "MIT",
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
     "node_modules/css-tree": {
       "version": "2.3.1",
       "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz",
@@ -2220,12 +2241,16 @@
       }
     },
     "node_modules/dotenv": {
-      "version": "16.0.0",
-      "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.0.0.tgz",
-      "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==",
+      "version": "16.5.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
+      "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
       "dev": true,
+      "license": "BSD-2-Clause",
       "engines": {
         "node": ">=12"
+      },
+      "funding": {
+        "url": "https://dotenvx.com"
       }
     },
     "node_modules/dotignore": {
@@ -3547,6 +3572,19 @@
         "node": ">=12.0.0"
       }
     },
+    "node_modules/html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "license": "MIT",
+      "dependencies": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
     "node_modules/ignore": {
       "version": "5.3.2",
       "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
@@ -4205,6 +4243,12 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/monaco-editor": {
+      "version": "0.52.2",
+      "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
+      "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
+      "license": "MIT"
+    },
     "node_modules/ms": {
       "version": "2.1.3",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
@@ -5013,6 +5057,12 @@
         "node": ">=0.8"
       }
     },
+    "node_modules/state-local": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+      "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
+      "license": "MIT"
+    },
     "node_modules/string.prototype.trim": {
       "version": "1.2.9",
       "resolved": "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
@@ -5135,6 +5185,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "license": "MIT",
+      "dependencies": {
+        "utrie": "^1.0.2"
+      }
+    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
@@ -5288,7 +5347,7 @@
       "version": "4.6.2",
       "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.6.2.tgz",
       "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
-      "devOptional": true,
+      "dev": true,
       "bin": {
         "tsc": "bin/tsc",
         "tsserver": "bin/tsserver"
@@ -5388,6 +5447,15 @@
         "punycode": "^2.1.0"
       }
     },
+    "node_modules/utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "license": "MIT",
+      "dependencies": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
     "node_modules/uuid": {
       "version": "9.0.0",
       "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz",
@@ -5505,6 +5573,41 @@
         "clipboard": "^2.0.6"
       }
     },
+    "node_modules/vue-data-ui": {
+      "version": "2.6.46",
+      "resolved": "https://registry.npmjs.org/vue-data-ui/-/vue-data-ui-2.6.46.tgz",
+      "integrity": "sha512-wg6wCNRxogYBRYSmVsaEni2DVBMjATmye3zHVAX4EGuntreLsSRmFBA5Iq1g0tnVqPhv/E/wN8Y9UD0YJ+oUPA==",
+      "license": "MIT",
+      "peerDependencies": {
+        "vue": ">=3.3.0"
+      }
+    },
+    "node_modules/vue-demi": {
+      "version": "0.14.10",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/vue-eslint-parser": {
       "version": "8.3.0",
       "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",

+ 2 - 0
package.json

@@ -25,6 +25,7 @@
   "dependencies": {
     "@antv/g2plot": "2.4.20",
     "@element-plus/icons-vue": "2.0.9",
+    "@guolao/vue-monaco-editor": "^1.5.5",
     "axios": "0.26.0",
     "clipboard": "2.0.11",
     "codemirror": "5.65.16",
@@ -44,6 +45,7 @@
     "jsrsasign": "10.8.6",
     "loadsh": "0.0.4",
     "mitt": "3.0.0",
+    "monaco-editor": "^0.52.2",
     "nprogress": "0.2.0",
     "pako": "1.0.11",
     "print-js": "1.6.0",

+ 307 - 99
src/views/apihub/component/edit.vue

@@ -1,103 +1,174 @@
 <template>
   <el-dialog class="api-edit" v-model="showDialog" :title="`${formData.id ? '编辑API' : '新增API'}`" width="800px" :close-on-click-modal="false" :close-on-press-escape="false">
-    <el-form ref="formRef" :model="formData" :rules="ruleForm" label-width="100px" @keyup.enter="onSubmit">
-      <el-form-item label="API名称" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入API名称" />
-      </el-form-item>
-      <el-form-item label="API路径" prop="path">
-        <el-input v-model="formData.path" placeholder="请输入API路径,如/api/v1/users" />
-      </el-form-item>
-      <el-form-item label="请求方法" prop="method">
-        <el-select v-model="formData.method" placeholder="请选择请求方法">
-          <el-option label="GET" value="GET"></el-option>
-          <el-option label="POST" value="POST"></el-option>
-          <el-option label="PUT" value="PUT"></el-option>
-          <el-option label="DELETE" value="DELETE"></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="数据源" prop="dataSourceKey">
-        <el-select v-model="formData.dataSourceKey" placeholder="请选择数据源" filterable>
-          <el-option v-for="item in dataSources" :key="item.id" :label="item.name" :value="item.dsKey"></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="SQL类型" prop="sqlType">
-        <el-radio-group v-model="formData.sqlType">
-          <el-radio label="query">查询</el-radio>
-          <el-radio label="procedure">存储过程</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="所属分组" prop="groupKey">
-        <el-cascader v-model="formData.groupKey" :options="groupOptions" :props="{ checkStrictly: true, emitPath: false, value: 'GroupKey', label: 'Name', children: 'Children' }" placeholder="请选择所属分组" clearable style="width: 100%" />
-      </el-form-item>
-      <el-form-item label="SQL内容" prop="sqlContent">
-        <el-input v-model="formData.sqlContent" type="textarea" :rows="4" placeholder="请输入SQL语句或存储过程名称" />
-      </el-form-item>
-
-      <el-form-item label="参数定义">
-        <el-button type="primary" size="small" @click="addParameter">
-          <el-icon><ele-Plus /></el-icon>添加参数
-        </el-button>
-        <el-table :data="formData.parameters" style="width: 100%; margin-top: 10px" border>
-          <el-table-column label="参数名" width="150">
-            <template #default="scope">
-              <el-input v-model="scope.row.name" placeholder="参数名"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="类型" width="120">
-            <template #default="scope">
-              <el-select v-model="scope.row.type" placeholder="类型">
-                <el-option label="string" value="string"></el-option>
-                <el-option label="int" value="int"></el-option>
-                <el-option label="float" value="float"></el-option>
-                <el-option label="bool" value="bool"></el-option>
+    <div class="dialog-body-with-tabs">
+      <div class="tab-navigation">
+        <ul>
+          <li @click="activeTab = 'basic'" :class="{ active: activeTab === 'basic' }">基本信息</li>
+          <li @click="activeTab = 'executor'" :class="{ active: activeTab === 'executor' }">执行器</li>
+          <li @click="activeTab = 'plugins'" :class="{ active: activeTab === 'plugins' }">全局插件</li>
+        </ul>
+      </div>
+      <div class="tab-content">
+        <el-form ref="formRef" :model="formData" :rules="ruleForm" label-width="100px" @keyup.enter="onSubmit">
+          <!-- 基本信息 Tab -->
+          <div v-show="activeTab === 'basic'" class="basic-info-tab">
+            <div class="form-section-title">基础配置</div>
+            <el-form-item label="API名称" prop="name">
+              <el-input v-model="formData.name" placeholder="请输入API名称" />
+            </el-form-item>
+            <el-form-item label="API路径" prop="path">
+              <el-input v-model="formData.path" placeholder="请输入API路径,如/api/v1/users" />
+            </el-form-item>
+            <el-form-item label="请求方法" prop="method">
+              <el-select v-model="formData.method" placeholder="请选择请求方法">
+                <el-option label="GET" value="GET"></el-option>
+                <el-option label="POST" value="POST"></el-option>
+                <el-option label="PUT" value="PUT"></el-option>
+                <el-option label="DELETE" value="DELETE"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="所属分组" prop="groupKey">
+              <el-cascader v-model="formData.groupKey" :options="groupOptions" :props="{ checkStrictly: true, emitPath: false, value: 'GroupKey', label: 'Name', children: 'Children' }" placeholder="请选择所属分组" clearable style="width: 100%" />
+            </el-form-item>
+            <el-form-item label="版本" prop="version">
+              <el-input v-model="formData.version" placeholder="请输入版本号,如1.0" />
+            </el-form-item>
+            <el-form-item label="状态" prop="status">
+              <el-select v-model="formData.status" placeholder="请选择状态">
+                <el-option label="草稿" value="Draft"></el-option>
+                <el-option label="已发布" value="Published"></el-option>
+                <el-option label="已废弃" value="Deprecated"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="描述" prop="description">
+              <el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入API描述" />
+            </el-form-item>
+
+            <div class="form-section-title">参数定义
+              <el-button type="primary" link @click="addParameter" style="margin-left: 10px;">
+                <el-icon><ele-Plus /></el-icon>添加参数
+              </el-button>
+            </div>
+            <el-form-item label-width="0">
+              <el-table :data="formData.parameters" style="width: 100%" border>
+                <el-table-column label="参数名" width="150">
+                  <template #default="scope">
+                    <el-input v-model="scope.row.name" placeholder="参数名"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="类型" width="120">
+                  <template #default="scope">
+                    <el-select v-model="scope.row.type" placeholder="类型">
+                      <el-option label="string" value="string"></el-option>
+                      <el-option label="int" value="int"></el-option>
+                      <el-option label="float" value="float"></el-option>
+                      <el-option label="bool" value="bool"></el-option>
+                    </el-select>
+                  </template>
+                </el-table-column>
+                <el-table-column label="必填" width="80">
+                  <template #default="scope">
+                    <el-checkbox v-model="scope.row.required"></el-checkbox>
+                  </template>
+                </el-table-column>
+                <el-table-column label="默认值" width="120">
+                  <template #default="scope">
+                    <el-input v-model="scope.row.defaultValue" placeholder="默认值"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="描述">
+                  <template #default="scope">
+                    <el-input v-model="scope.row.description" placeholder="参数描述"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" width="80">
+                  <template #default="scope">
+                    <el-button type="danger" link @click="removeParameter(scope.$index)">
+                      <el-icon><ele-Delete /></el-icon>
+                    </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+          </div>
+
+          <!-- 执行器 Tab -->
+          <div v-show="activeTab === 'executor'" class="executor-tab">
+            <div class="form-section-title">SQL配置</div>
+            <el-form-item label="数据源" prop="dataSourceKey">
+              <el-select v-model="formData.dataSourceKey" placeholder="请选择数据源" filterable>
+                <el-option v-for="item in dataSources" :key="item.id" :label="item.name" :value="item.dsKey"></el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item label="SQL类型" prop="sqlType">
+              <el-radio-group v-model="formData.sqlType">
+                <el-radio label="query">查询</el-radio>
+                <el-radio label="procedure">存储过程</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="SQL内容" prop="sqlContent">
+              <el-input v-model="formData.sqlContent" type="textarea" :rows="4" placeholder="请输入SQL语句或存储过程名称" />
+            </el-form-item>
+            <el-form-item label="返回格式" prop="returnFormat">
+              <el-select v-model="formData.returnFormat" placeholder="请选择返回格式">
+                <el-option label="JSON" value="JSON"></el-option>
+                <el-option label="XML" value="XML"></el-option>
               </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="必填" width="80">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.required"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="默认值" width="120">
-            <template #default="scope">
-              <el-input v-model="scope.row.defaultValue" placeholder="默认值"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="描述">
-            <template #default="scope">
-              <el-input v-model="scope.row.description" placeholder="参数描述"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="操作" width="80">
-            <template #default="scope">
-              <el-button type="danger" size="small" @click="removeParameter(scope.$index)" text>
-                <el-icon><ele-Delete /></el-icon>
+            </el-form-item>
+          </div>
+
+          <!-- 全局插件 Tab -->
+          <div v-show="activeTab === 'plugins'" class="plugins-tab">
+            <div class="form-section-title">插件列表
+              <el-button type="primary" link @click="addPlugin" style="margin-left: 10px;">
+                <el-icon><ele-Plus /></el-icon>添加插件
               </el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-form-item>
-
-      <el-form-item label="返回格式" prop="returnFormat">
-        <el-select v-model="formData.returnFormat" placeholder="请选择返回格式">
-          <el-option label="JSON" value="JSON"></el-option>
-          <el-option label="XML" value="XML"></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="版本" prop="version">
-        <el-input v-model="formData.version" placeholder="请输入版本号,如1.0" />
-      </el-form-item>
-      <el-form-item label="状态" prop="status">
-        <el-select v-model="formData.status" placeholder="请选择状态">
-          <el-option label="草稿" value="Draft"></el-option>
-          <el-option label="已发布" value="Published"></el-option>
-          <el-option label="已废弃" value="Deprecated"></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="描述" prop="description">
-        <el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入API描述" />
-      </el-form-item>
-    </el-form>
+            </div>
+            <div v-if="!formData.plugins || formData.plugins.length === 0" class="empty-plugins">
+              <el-empty description="暂无插件配置" :image-size="80"></el-empty>
+            </div>
+            <div v-else>
+              <div v-for="(plugin, index) in formData.plugins" :key="index" class="plugin-list-item">
+                <div class="plugin-item-details">
+                  <el-form-item
+                    :label="`名称`"
+                    :prop="`plugins[${index}].name`"
+                    :rules="[{ required: true, message: '插件名称不能为空', trigger: 'blur' }]"
+                    label-width="60px"
+                    class="plugin-field"
+                  >
+                    <el-input v-model="plugin.name" placeholder="插件Bean名称或类完整路径" size="small" />
+                  </el-form-item>
+                  <el-form-item
+                    :label="`参数`"
+                    :prop="`plugins[${index}].config`"
+                    label-width="60px"
+                    class="plugin-field"
+                  >
+                    <el-input
+                      v-model="plugin.config"
+                      type="textarea"
+                      :rows="2" 
+                      :placeholder="pluginParamsPlaceholder"
+                      size="small"
+                    />
+                  </el-form-item>
+                </div>
+                <div class="plugin-remove-action">
+                  <el-button 
+                    type="danger" 
+                    link 
+                    icon="ele-Delete" 
+                    @click="removePlugin(index)" 
+                    size="small"
+                  />
+                </div>
+              </div>
+            </div>
+          </div>
+        </el-form>
+      </div>
+    </div>
     <template #footer>
       <div class="dialog-footer">
         <el-button @click="cancel">取消</el-button>
@@ -109,15 +180,18 @@
 
 <script lang="ts" setup>
 import { ref, reactive, nextTick } from "vue";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import { ruleRequired } from "/@/utils/validator";
 import api from "/@/api/modules/apiHub";
+import { Plus as ElePlus, Delete as EleDelete } from '@element-plus/icons-vue';
 
 const emit = defineEmits(["getList"]);
 
 const showDialog = ref(false);
 const formRef = ref();
 const dataSources = ref<any[]>([]);
+const activeTab = ref('basic'); // 当前激活的Tab
+const pluginParamsPlaceholder = '插件参数 (JSON格式,例如:{"key": "value"})';
 
 api.dataSource.list().then((res: any) => {
   dataSources.value = res.list;
@@ -178,6 +252,22 @@ const removeParameter = (index: number) => {
   formData.parameters.splice(index, 1);
 };
 
+// 添加插件
+const addPlugin = () => {
+  if (!formData.plugins) {
+    formData.plugins = [];
+  }
+  formData.plugins.push({
+    name: "",
+    config: "",
+  });
+};
+
+// 移除插件
+const removePlugin = (index: number) => {
+  formData.plugins.splice(index, 1);
+};
+
 // 提交表单
 const onSubmit = async () => {
   // 表单验证
@@ -205,13 +295,28 @@ const onSubmit = async () => {
 // 重置表单
 const resetForm = () => {
   Object.assign(formData, JSON.parse(JSON.stringify(baseForm)));
+  activeTab.value = 'basic'; // 重置 Tab
   formRef.value && formRef.value.resetFields();
 };
 
 // 取消操作
 const cancel = () => {
-  resetForm();
-  showDialog.value = false;
+  ElMessageBox.confirm(
+    '确定要关闭吗?未保存的内容将会丢失',
+    '提示',
+    {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => {
+      showDialog.value = false;
+      resetForm();
+    })
+    .catch(() => {
+      // 用户取消关闭,不做任何操作
+    });
 };
 
 // 加载分组选项
@@ -254,8 +359,111 @@ defineExpose({ open });
 </script>
 
 <style scoped>
+.api-edit .dialog-body-with-tabs {
+  display: flex;
+  min-height: 450px; /* 调整最小高度以适应内容 */
+}
+
+.tab-navigation {
+  width: 150px; /* 稍微加宽一点导航宽度 */
+  border-right: 1px solid #e0e0e0; /* 颜色调整 */
+  padding-right: 0; /* 移除右边padding,让li撑满 */
+  margin-right: 0; /* 移除右边margin */
+}
+
+.tab-navigation ul {
+  list-style: none;
+  padding: 10px 0;
+  margin: 0;
+}
+
+.tab-navigation li {
+  padding: 12px 20px; /* 调整padding */
+  cursor: pointer;
+  /* border-radius: 4px; */ /* 移除圆角,使其更像设计图的tab */
+  margin-bottom: 2px; /* tab之间的间距 */
+  font-size: 14px;
+  color: #303133;
+}
+
+.tab-navigation li:hover {
+  background-color: #f0f2f5; /* hover颜色调整 */
+}
+
+.tab-navigation li.active {
+  background-color: #e6f7ff; /* active背景色调整 */
+  color: #1890ff; /* active文字颜色调整 */
+  border-right: 3px solid #1890ff; /* active时右侧有蓝色竖线 */
+  font-weight: 500; /* active时文字稍微加粗 */
+}
+
+.tab-content {
+  flex: 1;
+  overflow-y: auto;
+  max-height: 550px; /* Dialog内部内容区域的最大高度 */
+  padding: 10px 20px; /* tab内容的padding */
+}
+
+.form-section-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: #303133;
+  padding: 10px 0;
+  margin-bottom: 15px;
+  border-bottom: 1px solid #e0e0e0;
+  display: flex;
+  align-items: center;
+}
+
+.basic-info-tab .el-form-item,
+.executor-tab .el-form-item,
+.plugins-tab .el-form-item {
+  margin-bottom: 18px; /* 统一表单项间距 */
+}
+
+/* 全局插件样式 */
+.plugins-tab .form-section-title {
+  margin-bottom: 15px; /* Ensure space before the first plugin item or empty state */
+}
+
+.plugin-list-item {
+  display: flex;
+  align-items: flex-start; /* Aligns items to the top, good if details section can vary in height */
+  padding: 12px 0;
+  border-bottom: 1px solid #ebeef5;
+}
+.plugin-list-item:last-of-type {
+  border-bottom: none;
+  padding-bottom: 0; /* No padding if it's the last item and no border */
+}
+
+.plugin-item-details {
+  flex-grow: 1;
+}
+
+.plugin-item-details .plugin-field {
+  margin-bottom: 10px;
+}
+.plugin-item-details .plugin-field:last-of-type {
+  margin-bottom: 0; /* No margin for the last field in the details section */
+}
+
+.plugin-remove-action {
+  flex-shrink: 0;
+  margin-left: 15px;
+  padding-top: 5px; /* Small top padding to align better with first line of text or input */
+}
+
+.empty-plugins {
+  text-align: center;
+  padding: 20px 0;
+  color: #909399;
+}
+
 .dialog-footer {
   display: flex;
   justify-content: flex-end;
+  padding: 15px 20px;
+  border-top: 1px solid #e0e0e0;
 }
 </style>

+ 223 - 218
yarn.lock

@@ -203,7 +203,7 @@
   resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz"
   integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
 
-"@babel/parser@^7.16.4", "@babel/parser@^7.25.3":
+"@babel/parser@^7.12.0", "@babel/parser@^7.16.4", "@babel/parser@^7.25.3":
   version "7.25.6"
   resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz"
   integrity sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==
@@ -225,7 +225,7 @@
   dependencies:
     regenerator-runtime "^0.14.0"
 
-"@babel/types@^7.25.6":
+"@babel/types@^7.12.0", "@babel/types@^7.25.6":
   version "7.25.6"
   resolved "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz"
   integrity sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==
@@ -239,7 +239,7 @@
   resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
   integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
 
-"@element-plus/icons-vue@2.0.9", "@element-plus/icons-vue@^2.0.6":
+"@element-plus/icons-vue@^2.0.6", "@element-plus/icons-vue@2.0.9":
   version "2.0.9"
   resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.9.tgz"
   integrity sha512-okdrwiVeKBmW41Hkl0eMrXDjzJwhQMuKiBOu17rOszqM+LS/yBYpNQNV5Jvoh06Wc+89fMmb/uhzf8NZuDuUaQ==
@@ -249,16 +249,6 @@
   resolved "https://registry.npmmirror.com/@element-plus/icons/-/icons-0.0.11.tgz"
   integrity sha512-iKQXSxXu131Ai+I9Ymtcof9WId7kaXvB1+WRfAfpQCW7UiAMYgdNDqb/u0hgTo2Yq3MwC4MWJnNuTBEpG8r7+A==
 
-"@esbuild/android-arm@0.15.18":
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.15.18.tgz#266d40b8fdcf87962df8af05b76219bc786b4f80"
-  integrity sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==
-
-"@esbuild/linux-loong64@0.15.18":
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239"
-  integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==
-
 "@eslint/eslintrc@^1.2.0":
   version "1.4.1"
   resolved "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz"
@@ -294,6 +284,14 @@
   resolved "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.7.tgz"
   integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==
 
+"@guolao/vue-monaco-editor@^1.5.5":
+  version "1.5.5"
+  resolved "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.5.5.tgz"
+  integrity sha512-NFGImQ8dBYj6ehIxy1DngPRkctB9b6GbxvCm6aXZztNsgm/TtM4u+YM9ZwZHQPlXt7a4IODXoKCcTYEVycBSyA==
+  dependencies:
+    "@monaco-editor/loader" "^1.5.0"
+    vue-demi latest
+
 "@humanwhocodes/config-array@^0.9.2":
   version "0.9.5"
   resolved "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz"
@@ -308,7 +306,7 @@
   resolved "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz"
   integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
 
-"@interactjs/actions@1.10.27", "@interactjs/actions@^1.10.2":
+"@interactjs/actions@^1.10.2", "@interactjs/actions@1.10.27":
   version "1.10.27"
   resolved "https://registry.npmmirror.com/@interactjs/actions/-/actions-1.10.27.tgz"
   integrity sha512-FCRg5KwB+stkPcAMx/Cn0fgGP6p4LyMX9S/Upcn/W+hpYme31bPi54PCqmOebzz6myTthN6zFf9jMyLOqtI/gg==
@@ -322,7 +320,7 @@
   optionalDependencies:
     "@interactjs/interact" "1.10.27"
 
-"@interactjs/auto-start@1.10.27", "@interactjs/auto-start@^1.10.2":
+"@interactjs/auto-start@^1.10.2", "@interactjs/auto-start@1.10.27":
   version "1.10.27"
   resolved "https://registry.npmmirror.com/@interactjs/auto-start/-/auto-start-1.10.27.tgz"
   integrity sha512-ECLBO/nxmaF1knncJKIE5F7la3KKRgEkn0Cu2JTPOYj9xy/LpfYElo3wkRHsodgOqF651nR70GK2/IzPR2lO9A==
@@ -334,7 +332,7 @@
   resolved "https://registry.npmmirror.com/@interactjs/core/-/core-1.10.27.tgz"
   integrity sha512-SliUr/3ZbLAdED8LokzYzWHWMdCB5Cq+UnpXuRy+BIod1j97m4IUFf/D1iIKUBBjBcucgXbz28z96WnenVCB7Q==
 
-"@interactjs/dev-tools@1.10.27", "@interactjs/dev-tools@^1.10.2":
+"@interactjs/dev-tools@^1.10.2", "@interactjs/dev-tools@1.10.27":
   version "1.10.27"
   resolved "https://registry.npmmirror.com/@interactjs/dev-tools/-/dev-tools-1.10.27.tgz"
   integrity sha512-YolmBwRaKH1gWbvyLeV3m5QSwtD38lOZnCBA87PCAlcd9PQAC2gb03fEPeEyD336bE20oLB8f0WZt4Wre+afiw==
@@ -377,7 +375,7 @@
     "@interactjs/reflow" "1.10.27"
     "@interactjs/utils" "1.10.27"
 
-"@interactjs/modifiers@1.10.27", "@interactjs/modifiers@^1.10.2":
+"@interactjs/modifiers@^1.10.2", "@interactjs/modifiers@1.10.27":
   version "1.10.27"
   resolved "https://registry.npmmirror.com/@interactjs/modifiers/-/modifiers-1.10.27.tgz"
   integrity sha512-ei/qfoQ+9/8k6WzNzdNqHI6cWkIV576N4Ap16r5CoqOWwhA6Xzj3OMHf1g0t1O4eSq2HdJsVJn3eLNfw9HsbeQ==
@@ -494,6 +492,13 @@
   dependencies:
     call-bind "^1.0.7"
 
+"@monaco-editor/loader@^1.5.0":
+  version "1.5.0"
+  resolved "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz"
+  integrity sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==
+  dependencies:
+    state-local "^1.0.6"
+
 "@nodelib/fs.scandir@2.1.5":
   version "2.1.5"
   resolved "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@@ -502,7 +507,7 @@
     "@nodelib/fs.stat" "2.0.5"
     run-parallel "^1.1.9"
 
-"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
   version "2.0.5"
   resolved "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
   integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@@ -652,7 +657,7 @@
     "@typescript-eslint/types" "5.13.0"
     eslint-visitor-keys "^3.0.0"
 
-"@unocss/core@0.58.9", "@unocss/core@^0.58.9":
+"@unocss/core@^0.58.9", "@unocss/core@0.58.9":
   version "0.58.9"
   resolved "https://registry.npmmirror.com/@unocss/core/-/core-0.58.9.tgz"
   integrity sha512-wYpPIPPsOIbIoMIDuH8ihehJk5pAZmyFKXIYO/Kro98GEOFhz6lJoLsy6/PZuitlgp2/TSlubUuWGjHWvp5osw==
@@ -679,6 +684,17 @@
   resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-3.1.0.tgz"
   integrity sha512-fmxtHPjSOEIRg6vHYDaem+97iwCUg/uSIaTzp98lhELt2ISOQuDo2hbkBdXod0g15IhfPMQmAxh4heUks2zvDA==
 
+"@vue/compiler-core@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.1.5.tgz"
+  integrity sha512-TXBhFinoBaXKDykJzY26UEuQU1K07FOp/0Ie+OXySqqk0bS0ZO7Xvl7UmiTUPYcLrWbxWBR7Bs/y55AI0MNc2Q==
+  dependencies:
+    "@babel/parser" "^7.12.0"
+    "@babel/types" "^7.12.0"
+    "@vue/shared" "3.1.5"
+    estree-walker "^2.0.1"
+    source-map "^0.6.1"
+
 "@vue/compiler-core@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz"
@@ -710,6 +726,14 @@
     estree-walker "^2.0.2"
     source-map-js "^1.2.0"
 
+"@vue/compiler-dom@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.1.5.tgz"
+  integrity sha512-ZsL3jqJ52OjGU/YiT/9XiuZAmWClKInZM2aFJh9gnsAPqOrj2JIELMbkIFpVKR/CrVO/f2VxfPiiQdQTr65jcQ==
+  dependencies:
+    "@vue/compiler-core" "3.1.5"
+    "@vue/shared" "3.1.5"
+
 "@vue/compiler-dom@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz"
@@ -832,6 +856,13 @@
     estree-walker "^2.0.2"
     magic-string "^0.25.7"
 
+"@vue/reactivity@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.1.5.tgz"
+  integrity sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==
+  dependencies:
+    "@vue/shared" "3.1.5"
+
 "@vue/reactivity@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz"
@@ -846,6 +877,14 @@
   dependencies:
     "@vue/shared" "3.5.3"
 
+"@vue/runtime-core@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.1.5.tgz"
+  integrity sha512-YQbG5cBktN1RowQDKA22itmvQ+b40f0WgQ6CXK4VYoYICAiAfu6Cc14777ve8zp1rJRGtk5oIeS149TOculrTg==
+  dependencies:
+    "@vue/reactivity" "3.1.5"
+    "@vue/shared" "3.1.5"
+
 "@vue/runtime-core@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz"
@@ -862,6 +901,15 @@
     "@vue/reactivity" "3.5.3"
     "@vue/shared" "3.5.3"
 
+"@vue/runtime-dom@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.1.5.tgz"
+  integrity sha512-tNcf3JhVR0RfW0kw1p8xZgv30nvX8Y9rsz7eiQ0dHe273sfoCngAG0y4GvMaY4Xd8FsjUwFedd4suQ8Lu8meXg==
+  dependencies:
+    "@vue/runtime-core" "3.1.5"
+    "@vue/shared" "3.1.5"
+    csstype "^2.6.8"
+
 "@vue/runtime-dom@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz"
@@ -897,6 +945,11 @@
     "@vue/compiler-ssr" "3.5.3"
     "@vue/shared" "3.5.3"
 
+"@vue/shared@3.1.5":
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.1.5.tgz"
+  integrity sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==
+
 "@vue/shared@3.2.37":
   version "3.2.37"
   resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz"
@@ -944,11 +997,6 @@
     ua-parser-js "^1.0.38"
     vue "^3.4.31"
 
-JSV@^4.0.2:
-  version "4.0.2"
-  resolved "https://registry.npmmirror.com/JSV/-/JSV-4.0.2.tgz"
-  integrity sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==
-
 acorn-jsx@^5.3.2:
   version "5.3.2"
   resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
@@ -1096,7 +1144,7 @@ balanced-match@^1.0.0:
 
 base64-arraybuffer@^1.0.2:
   version "1.0.2"
-  resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
+  resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz"
   integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
 
 batch-processor@1.0.0:
@@ -1209,7 +1257,7 @@ claygl@^1.2.1:
   resolved "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz"
   integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==
 
-clipboard@2.0.11, clipboard@^2.0.10, clipboard@^2.0.6:
+clipboard@^2.0.10, clipboard@^2.0.6, clipboard@2.0.11:
   version "2.0.11"
   resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz"
   integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
@@ -1238,7 +1286,7 @@ codemirror-editor-vue3@2.5.8:
     diff-match-patch "^1.0.5"
     jsonlint-mod "^1.7.6"
 
-codemirror@5.65.16, codemirror@^5:
+codemirror@^5, codemirror@5.65.16:
   version "5.65.16"
   resolved "https://registry.npmmirror.com/codemirror/-/codemirror-5.65.16.tgz"
   integrity sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==
@@ -1265,16 +1313,16 @@ color-convert@^2.0.1:
   dependencies:
     color-name "~1.1.4"
 
-color-name@1.1.3:
-  version "1.1.3"
-  resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz"
-  integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
-
 color-name@~1.1.4:
   version "1.1.4"
   resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz"
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz"
+  integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
 commander@~2.14.1:
   version "2.14.1"
   resolved "https://registry.npmmirror.com/commander/-/commander-2.14.1.tgz"
@@ -1322,21 +1370,12 @@ cropperjs@1.5.12:
 
 cross-env@^7.0.3:
   version "7.0.3"
-  resolved "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
+  resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz"
   integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
   dependencies:
     cross-spawn "^7.0.1"
 
-cross-spawn@^7.0.1:
-  version "7.0.4"
-  resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.4.tgz#36d9cb36c32ae7a0df935f0191f79959962a2165"
-  integrity sha512-9KdyVPPtLHjPAD7tcuzSFs64UfHlLJt7U6qP4/bFVLyjLceyizj6s6jO6YBaV5d0G7g/9KnY/dOpLR4Rcg8YDg==
-  dependencies:
-    path-key "^3.1.0"
-    shebang-command "^2.0.0"
-    which "^2.0.1"
-
-cross-spawn@^7.0.2:
+cross-spawn@^7.0.1, cross-spawn@^7.0.2:
   version "7.0.3"
   resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz"
   integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -1347,7 +1386,7 @@ cross-spawn@^7.0.2:
 
 css-line-break@^2.1.0:
   version "2.1.0"
-  resolved "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
+  resolved "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz"
   integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
   dependencies:
     utrie "^1.0.2"
@@ -1429,7 +1468,7 @@ data-view-byte-offset@^1.0.0:
     es-errors "^1.3.0"
     is-data-view "^1.0.1"
 
-dayjs@1.11.8, dayjs@1.x, dayjs@^1.11.3:
+dayjs@^1.11.3, dayjs@1.11.8, dayjs@1.x:
   version "1.11.8"
   resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.8.tgz"
   integrity sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ==
@@ -1516,9 +1555,9 @@ doctrine@^3.0.0:
     esutils "^2.0.2"
 
 dotenv@^16.4.5:
-  version "16.4.5"
-  resolved "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
-  integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
+  version "16.5.0"
+  resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz"
+  integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==
 
 dotignore@~0.1.2:
   version "0.1.2"
@@ -1553,6 +1592,20 @@ echarts@5.5.0:
     tslib "2.3.0"
     zrender "5.5.0"
 
+element-plus@^1.0.2-beta.28:
+  version "1.0.2-beta.71"
+  resolved "https://registry.npmmirror.com/element-plus/-/element-plus-1.0.2-beta.71.tgz"
+  integrity sha512-tlfbRORIav8gJcIpjZI5F6aJIVHIaDuGO6/vKu43lgYq4JS2JPNRTjvrSE2p4f5xLfaFNfOWjCS3sybXLfMg8g==
+  dependencies:
+    "@element-plus/icons" "^0.0.11"
+    "@popperjs/core" "^2.4.4"
+    async-validator "^3.4.0"
+    dayjs "1.x"
+    lodash "^4.17.20"
+    mitt "^2.1.0"
+    normalize-wheel "^1.0.1"
+    resize-observer-polyfill "^1.5.1"
+
 element-plus@2.2.28:
   version "2.2.28"
   resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.28.tgz"
@@ -1574,20 +1627,6 @@ element-plus@2.2.28:
     memoize-one "^6.0.0"
     normalize-wheel-es "^1.2.0"
 
-element-plus@^1.0.2-beta.28:
-  version "1.0.2-beta.71"
-  resolved "https://registry.npmmirror.com/element-plus/-/element-plus-1.0.2-beta.71.tgz"
-  integrity sha512-tlfbRORIav8gJcIpjZI5F6aJIVHIaDuGO6/vKu43lgYq4JS2JPNRTjvrSE2p4f5xLfaFNfOWjCS3sybXLfMg8g==
-  dependencies:
-    "@element-plus/icons" "^0.0.11"
-    "@popperjs/core" "^2.4.4"
-    async-validator "^3.4.0"
-    dayjs "1.x"
-    lodash "^4.17.20"
-    mitt "^2.1.0"
-    normalize-wheel "^1.0.1"
-    resize-observer-polyfill "^1.5.1"
-
 element-resize-detector@^1.2.1:
   version "1.2.4"
   resolved "https://registry.npmmirror.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz"
@@ -1689,106 +1728,11 @@ es-to-primitive@^1.2.1:
     is-date-object "^1.0.1"
     is-symbol "^1.0.2"
 
-esbuild-android-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz#20a7ae1416c8eaade917fb2453c1259302c637a5"
-  integrity sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==
-
-esbuild-android-arm64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz#9cc0ec60581d6ad267568f29cf4895ffdd9f2f04"
-  integrity sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==
-
-esbuild-darwin-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz"
-  integrity sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==
-
 esbuild-darwin-arm64@0.15.18:
   version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz#b6dfc7799115a2917f35970bfbc93ae50256b337"
+  resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz"
   integrity sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==
 
-esbuild-freebsd-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz#4e190d9c2d1e67164619ae30a438be87d5eedaf2"
-  integrity sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==
-
-esbuild-freebsd-arm64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz#18a4c0344ee23bd5a6d06d18c76e2fd6d3f91635"
-  integrity sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==
-
-esbuild-linux-32@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz#9a329731ee079b12262b793fb84eea762e82e0ce"
-  integrity sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==
-
-esbuild-linux-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz#532738075397b994467b514e524aeb520c191b6c"
-  integrity sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==
-
-esbuild-linux-arm64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz#5372e7993ac2da8f06b2ba313710d722b7a86e5d"
-  integrity sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==
-
-esbuild-linux-arm@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz#e734aaf259a2e3d109d4886c9e81ec0f2fd9a9cc"
-  integrity sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==
-
-esbuild-linux-mips64le@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz#c0487c14a9371a84eb08fab0e1d7b045a77105eb"
-  integrity sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==
-
-esbuild-linux-ppc64le@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz#af048ad94eed0ce32f6d5a873f7abe9115012507"
-  integrity sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==
-
-esbuild-linux-riscv64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz#423ed4e5927bd77f842bd566972178f424d455e6"
-  integrity sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==
-
-esbuild-linux-s390x@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz#21d21eaa962a183bfb76312e5a01cc5ae48ce8eb"
-  integrity sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==
-
-esbuild-netbsd-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz#ae75682f60d08560b1fe9482bfe0173e5110b998"
-  integrity sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==
-
-esbuild-openbsd-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz#79591a90aa3b03e4863f93beec0d2bab2853d0a8"
-  integrity sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==
-
-esbuild-sunos-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz#fd528aa5da5374b7e1e93d36ef9b07c3dfed2971"
-  integrity sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==
-
-esbuild-windows-32@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz#0e92b66ecdf5435a76813c4bc5ccda0696f4efc3"
-  integrity sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==
-
-esbuild-windows-64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz#0fc761d785414284fc408e7914226d33f82420d0"
-  integrity sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==
-
-esbuild-windows-arm64@0.15.18:
-  version "0.15.18"
-  resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz#5b5bdc56d341d0922ee94965c89ee120a6a86eb7"
-  integrity sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==
-
 esbuild@^0.15.9:
   version "0.15.18"
   resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.15.18.tgz"
@@ -1822,7 +1766,12 @@ escape-html@^1.0.3:
   resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz"
   integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
 
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
+  integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
   integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
@@ -1850,7 +1799,15 @@ eslint-scope@^5.1.1:
     esrecurse "^4.3.0"
     estraverse "^4.1.1"
 
-eslint-scope@^7.0.0, eslint-scope@^7.1.1:
+eslint-scope@^7.0.0:
+  version "7.2.2"
+  resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz"
+  integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
+  dependencies:
+    esrecurse "^4.3.0"
+    estraverse "^5.2.0"
+
+eslint-scope@^7.1.1:
   version "7.2.2"
   resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz"
   integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
@@ -1944,12 +1901,17 @@ estraverse@^4.1.1:
   resolved "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz"
   integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
 
-estraverse@^5.1.0, estraverse@^5.2.0:
+estraverse@^5.1.0:
   version "5.3.0"
   resolved "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz"
   integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
 
-estree-walker@^2.0.2:
+estraverse@^5.2.0:
+  version "5.3.0"
+  resolved "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz"
+  integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+estree-walker@^2.0.1, estree-walker@^2.0.2:
   version "2.0.2"
   resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz"
   integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
@@ -2137,7 +2099,7 @@ gl-matrix@^3.0.0, gl-matrix@^3.3.0, gl-matrix@^3.4.3:
   resolved "https://registry.npmmirror.com/gl-matrix/-/gl-matrix-3.4.3.tgz"
   integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==
 
-glob-parent@^5.1.2, glob-parent@~5.1.2:
+glob-parent@^5.1.2:
   version "5.1.2"
   resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
   integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -2151,6 +2113,13 @@ glob-parent@^6.0.1:
   dependencies:
     is-glob "^4.0.3"
 
+glob-parent@~5.1.2:
+  version "5.1.2"
+  resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
+  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+  dependencies:
+    is-glob "^4.0.1"
+
 glob@^7.1.3, glob@~7.2.3:
   version "7.2.3"
   resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz"
@@ -2274,7 +2243,7 @@ highlight.js@^11.8.0:
 
 html2canvas@^1.4.1:
   version "1.4.1"
-  resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
+  resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz"
   integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
   dependencies:
     css-line-break "^2.1.0"
@@ -2311,7 +2280,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@~2.0.4:
+inherits@~2.0.4, inherits@2:
   version "2.0.4"
   resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -2524,8 +2493,8 @@ jsonlint-mod@^1.7.6:
   resolved "https://registry.npmmirror.com/jsonlint-mod/-/jsonlint-mod-1.7.6.tgz"
   integrity sha512-oGuk6E1ehmIpw0w9ttgb2KsDQQgGXBzZczREW8OfxEm9eCQYL9/LCexSnh++0z3AiYGcXpBgqDSx9AAgzl/Bvg==
   dependencies:
-    JSV "^4.0.2"
     chalk "^2.4.2"
+    JSV "^4.0.2"
     underscore "^1.9.1"
 
 jsplumb@2.15.6:
@@ -2538,6 +2507,11 @@ jsrsasign@10.8.6:
   resolved "https://registry.npmmirror.com/jsrsasign/-/jsrsasign-10.8.6.tgz"
   integrity sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==
 
+JSV@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.npmmirror.com/JSV/-/JSV-4.0.2.tgz"
+  integrity sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==
+
 keyv@^4.5.3:
   version "4.5.4"
   resolved "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz"
@@ -2602,7 +2576,14 @@ magic-string@^0.25.7:
   dependencies:
     sourcemap-codec "^1.4.8"
 
-magic-string@^0.30.11, magic-string@^0.30.8:
+magic-string@^0.30.11:
+  version "0.30.11"
+  resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz"
+  integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==
+  dependencies:
+    "@jridgewell/sourcemap-codec" "^1.5.0"
+
+magic-string@^0.30.8:
   version "0.30.11"
   resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz"
   integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==
@@ -2644,16 +2625,16 @@ minimist@^1.2.0, minimist@~1.2.8:
   resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz"
   integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
 
-mitt@3.0.0:
-  version "3.0.0"
-  resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.0.tgz"
-  integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==
-
 mitt@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/mitt/-/mitt-2.1.0.tgz"
   integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
 
+mitt@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.0.tgz"
+  integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==
+
 mock-property@~1.0.0:
   version "1.0.3"
   resolved "https://registry.npmmirror.com/mock-property/-/mock-property-1.0.3.tgz"
@@ -2666,6 +2647,11 @@ mock-property@~1.0.0:
     hasown "^2.0.0"
     isarray "^2.0.5"
 
+monaco-editor@^0.52.2:
+  version "0.52.2"
+  resolved "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz"
+  integrity sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==
+
 ms@^2.1.3:
   version "2.1.3"
   resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz"
@@ -3009,7 +2995,7 @@ select@^1.1.2:
   resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz"
   integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
 
-semver@7.6.2, semver@^7.3.5:
+semver@^7.3.5, semver@7.6.2:
   version "7.6.2"
   resolved "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz"
   integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
@@ -3073,7 +3059,7 @@ sortablejs@1.14.0:
   resolved "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz"
   integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==
 
-"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0:
+source-map-js@^1.0.1, source-map-js@^1.2.0, "source-map-js@>=0.6.2 <2.0.0":
   version "1.2.0"
   resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz"
   integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
@@ -3085,14 +3071,7 @@ source-map-support@^0.3.2:
   dependencies:
     source-map "0.1.32"
 
-source-map@0.1.32:
-  version "0.1.32"
-  resolved "https://registry.npmmirror.com/source-map/-/source-map-0.1.32.tgz"
-  integrity sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==
-  dependencies:
-    amdefine ">=0.0.4"
-
-source-map@0.6.1, source-map@^0.6.1:
+source-map@^0.6.1, source-map@0.6.1:
   version "0.6.1"
   resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -3102,6 +3081,13 @@ source-map@~0.5.1:
   resolved "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz"
   integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
 
+source-map@0.1.32:
+  version "0.1.32"
+  resolved "https://registry.npmmirror.com/source-map/-/source-map-0.1.32.tgz"
+  integrity sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==
+  dependencies:
+    amdefine ">=0.0.4"
+
 sourcemap-codec@^1.4.8:
   version "1.4.8"
   resolved "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz"
@@ -3119,6 +3105,11 @@ ssf@~0.11.2:
   dependencies:
     frac "~1.1.2"
 
+state-local@^1.0.6:
+  version "1.0.7"
+  resolved "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz"
+  integrity sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==
+
 string.prototype.trim@^1.2.9, string.prototype.trim@~1.2.8:
   version "1.2.9"
   resolved "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz"
@@ -3214,7 +3205,7 @@ tape@^4.5.1:
 
 text-segmentation@^1.0.3:
   version "1.0.3"
-  resolved "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
+  resolved "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz"
   integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
   dependencies:
     utrie "^1.0.2"
@@ -3241,12 +3232,12 @@ to-regex-range@^5.0.1:
   dependencies:
     is-number "^7.0.0"
 
-tslib@2.3.0:
-  version "2.3.0"
-  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz"
-  integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+tslib@^1.10.0:
+  version "1.14.1"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz"
+  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 
-tslib@^1.10.0, tslib@^1.8.1:
+tslib@^1.8.1:
   version "1.14.1"
   resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz"
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -3256,6 +3247,11 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1:
   resolved "https://registry.npmmirror.com/tslib/-/tslib-2.7.0.tgz"
   integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
 
+tslib@2.3.0:
+  version "2.3.0"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz"
+  integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+
 tsutils@^3.21.0:
   version "3.21.0"
   resolved "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz"
@@ -3373,7 +3369,7 @@ uri-js@^4.2.2:
 
 utrie@^1.0.2:
   version "1.0.2"
-  resolved "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
+  resolved "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz"
   integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
   dependencies:
     base64-arraybuffer "^1.0.2"
@@ -3422,16 +3418,16 @@ vue-clipboard3@1.0.1:
     clipboard "^2.0.6"
 
 vue-data-ui@^2.4.17:
-  version "2.6.2"
-  resolved "https://registry.npmjs.org/vue-data-ui/-/vue-data-ui-2.6.2.tgz#960569237e0ccf65e797e7517756bc735ec4a075"
-  integrity sha512-YQxX04a8raB/BVk95HeQegtvTXrvmDMbaIDE52s5lEPNUArGHVIF6G5EUPuNuPRgZDtJJW6csZ/0zOYAaCafAA==
+  version "2.6.46"
+  resolved "https://registry.npmjs.org/vue-data-ui/-/vue-data-ui-2.6.46.tgz"
+  integrity sha512-wg6wCNRxogYBRYSmVsaEni2DVBMjATmye3zHVAX4EGuntreLsSRmFBA5Iq1g0tnVqPhv/E/wN8Y9UD0YJ+oUPA==
 
-vue-demi@*:
+vue-demi@*, vue-demi@latest:
   version "0.14.10"
-  resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz"
+  resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz"
   integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
 
-vue-eslint-parser@8.3.0, vue-eslint-parser@^8.0.1:
+vue-eslint-parser@^8.0.1, vue-eslint-parser@8.3.0:
   version "8.3.0"
   resolved "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz"
   integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
@@ -3474,6 +3470,37 @@ vue-router@4.0.13:
   dependencies:
     "@vue/devtools-api" "^6.0.0"
 
+vue@^3.0.0:
+  version "3.1.5"
+  resolved "https://registry.npmmirror.com/vue/-/vue-3.1.5.tgz"
+  integrity sha512-Ho7HNb1nfDoO+HVb6qYZgeaobt1XbY6KXFe4HGs1b9X6RhkWG/113n4/SrtM1LUclM6OrP/Se5aPHHvAPG1iVQ==
+  dependencies:
+    "@vue/compiler-dom" "3.1.5"
+    "@vue/runtime-dom" "3.1.5"
+    "@vue/shared" "3.1.5"
+
+vue@^3.4.31:
+  version "3.5.3"
+  resolved "https://registry.npmmirror.com/vue/-/vue-3.5.3.tgz"
+  integrity sha512-xvRbd0HpuLovYbOHXRHlSBsSvmUJbo0pzbkKTApWnQGf3/cu5Z39mQeA5cZdLRVIoNf3zI6MSoOgHUT5i2jO+Q==
+  dependencies:
+    "@vue/compiler-dom" "3.5.3"
+    "@vue/compiler-sfc" "3.5.3"
+    "@vue/runtime-dom" "3.5.3"
+    "@vue/server-renderer" "3.5.3"
+    "@vue/shared" "3.5.3"
+
+vue@3, vue@3.2.37:
+  version "3.2.37"
+  resolved "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz"
+  integrity sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==
+  dependencies:
+    "@vue/compiler-dom" "3.2.37"
+    "@vue/compiler-sfc" "3.2.37"
+    "@vue/runtime-dom" "3.2.37"
+    "@vue/server-renderer" "3.2.37"
+    "@vue/shared" "3.2.37"
+
 vue3-clipboard@1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/vue3-clipboard/-/vue3-clipboard-1.0.0.tgz"
@@ -3497,28 +3524,6 @@ vue3-json-viewer@2.2.2:
   dependencies:
     clipboard "^2.0.10"
 
-vue@3, vue@3.2.37, vue@^3.0.0:
-  version "3.2.37"
-  resolved "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz"
-  integrity sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==
-  dependencies:
-    "@vue/compiler-dom" "3.2.37"
-    "@vue/compiler-sfc" "3.2.37"
-    "@vue/runtime-dom" "3.2.37"
-    "@vue/server-renderer" "3.2.37"
-    "@vue/shared" "3.2.37"
-
-vue@^3.4.31:
-  version "3.5.3"
-  resolved "https://registry.npmmirror.com/vue/-/vue-3.5.3.tgz"
-  integrity sha512-xvRbd0HpuLovYbOHXRHlSBsSvmUJbo0pzbkKTApWnQGf3/cu5Z39mQeA5cZdLRVIoNf3zI6MSoOgHUT5i2jO+Q==
-  dependencies:
-    "@vue/compiler-dom" "3.5.3"
-    "@vue/compiler-sfc" "3.5.3"
-    "@vue/runtime-dom" "3.5.3"
-    "@vue/server-renderer" "3.5.3"
-    "@vue/shared" "3.5.3"
-
 vuex@4.0.2:
   version "4.0.2"
   resolved "https://registry.npmmirror.com/vuex/-/vuex-4.0.2.tgz"
@@ -3620,7 +3625,7 @@ yargs@~3.10.0:
     decamelize "^1.0.0"
     window-size "0.1.0"
 
-zrender@5.5.0, zrender@^5.1.1:
+zrender@^5.1.1, zrender@5.5.0:
   version "5.5.0"
   resolved "https://registry.npmmirror.com/zrender/-/zrender-5.5.0.tgz"
   integrity sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==