Browse Source

配置调试

zhangjie 2 years ago
parent
commit
8b56cb53c7

+ 5 - 0
src/assets/styles/base.scss

@@ -418,6 +418,11 @@ body {
   .el-button + .el-button {
     margin-left: 10px;
   }
+
+  &.tab-nowrap {
+    white-space: nowrap;
+    overflow-y: auto;
+  }
 }
 
 .cont-link {

+ 1 - 1
src/components/EnvSelect.vue

@@ -28,7 +28,7 @@ export default {
     placeholder: { type: String, default: "请选择环境" },
     value: { type: [Number, String], default: "" },
     clearable: { type: Boolean, default: true },
-    appId: { type: String, default: "" }
+    appId: { type: [String, Number], default: "" }
   },
   data() {
     return {

+ 1 - 1
src/components/ModuleSelect.vue

@@ -28,7 +28,7 @@ export default {
     placeholder: { type: String, default: "请选择模块" },
     value: { type: [Number, String], default: "" },
     clearable: { type: Boolean, default: true },
-    appId: { type: String, default: "" }
+    appId: { type: [String, Number], default: "" }
   },
   data() {
     return {

+ 1 - 1
src/components/VersionSelect.vue

@@ -28,7 +28,7 @@ export default {
     placeholder: { type: String, default: "请选择版本" },
     value: { type: [Number, String], default: "" },
     clearable: { type: Boolean, default: true },
-    appId: { type: String, default: "" }
+    appId: { type: [String, Number], default: "" }
   },
   data() {
     return {

+ 3 - 3
src/modules/admin/api.js

@@ -1,4 +1,4 @@
-import { $postParam, qsRepeatParams } from "@/plugins/axios";
+import { $post, $postParam, qsRepeatParams } from "@/plugins/axios";
 
 // common-select
 
@@ -103,8 +103,8 @@ export const appConfigBaseline = datas => {
   return $postParam("/api/admin/config/baseline", datas);
 };
 export const appConfigBaselineUpdate = (datas, headerData) => {
-  return $postParam("/api/admin/config/baseline/update", datas, {
-    header: headerData
+  return $post("/api/admin/config/baseline/update", datas, {
+    headers: headerData
   });
 };
 export const appConfigBaselineItemUpdate = datas => {

+ 0 - 173
src/modules/admin/components/AppBaselineManage.vue

@@ -1,173 +0,0 @@
-<template>
-  <div class="app-baseline-manage">
-    <el-dialog
-      class="page-dialog"
-      :visible.sync="modalIsShow"
-      title="应用配置基线管理"
-      top="10px"
-      width="900px"
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      append-to-body
-      @opened="visibleChange"
-    >
-      <div class="part-box part-box-filter part-box-flex">
-        <el-form
-          ref="FilterForm"
-          label-position="left"
-          label-width="80px"
-          :model="filter"
-          :rules="rules"
-          inline
-        >
-          <el-form-item prop="versionId" label="版本">
-            <version-select
-              v-model="filter.versionId"
-              :app-id="filter.appId"
-              :clearable="false"
-            ></version-select>
-          </el-form-item>
-          <el-form-item prop="moduleId" label="模块">
-            <module-select
-              v-model="filter.moduleId"
-              :app-id="filter.appId"
-              :clearable="false"
-            ></module-select>
-          </el-form-item>
-          <el-form-item label-width="0px">
-            <el-button type="primary" icon="ios-search" @click="search"
-              >查询</el-button
-            >
-            <el-button type="success" icon="md-add" @click="toUpdate"
-              >修改</el-button
-            >
-          </el-form-item>
-        </el-form>
-      </div>
-
-      <div class="part-box part-box-pad">
-        <el-table ref="TableList" :data="dataList">
-          <el-table-column prop="key" label="配置项"> </el-table-column>
-          <el-table-column prop="value" label="配置值"> </el-table-column>
-          <el-table-column prop="mode" label="模式">
-            <span slot-scope="scope">{{ modeMap[scope.row.mode] }}</span>
-          </el-table-column>
-          <el-table-column prop="comment" label="注释"> </el-table-column>
-          <el-table-column label="操作" width="80" class-name="action-column">
-            <template slot-scope="scope">
-              <el-button
-                class="btn-primary"
-                type="text"
-                @click="toEdit(scope.row)"
-                >编辑</el-button
-              >
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-    </el-dialog>
-
-    <!-- UpdateAppBaseline -->
-    <update-app-baseline
-      ref="UpdateAppBaseline"
-      :data="filter"
-      @modified="search"
-    ></update-app-baseline>
-    <!-- ModifyAppBaselineItem -->
-    <modify-app-baseline-item
-      ref="ModifyAppBaselineItem"
-      :instance="curRow"
-      @modified="baselineItemModified"
-    ></modify-app-baseline-item>
-  </div>
-</template>
-
-<script>
-import { appConfigBaseline, appConfigModes } from "../api";
-import UpdateAppBaseline from "../components/UpdateAppBaseline.vue";
-import ModifyAppBaselineItem from "../components/ModifyAppBaselineItem.vue";
-
-export default {
-  name: "app-baseline-manage",
-  components: { UpdateAppBaseline, ModifyAppBaselineItem },
-  props: {
-    app: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      filter: {
-        appId: "",
-        moduleId: "",
-        versionId: ""
-      },
-      rules: {
-        moduleId: [
-          {
-            required: true,
-            message: "请选择模块",
-            triggr: "change"
-          }
-        ],
-        versionId: [
-          {
-            required: true,
-            message: "请选择版本",
-            triggr: "change"
-          }
-        ]
-      },
-      dataList: [],
-      curRow: {},
-      modeMap: {}
-    };
-  },
-  methods: {
-    async visibleChange() {
-      this.filter.appId = this.app.id;
-      // await this.getConfigModes();
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    async getConfigModes() {
-      if (Object.keys(this.modeMap).length) return;
-
-      const data = await appConfigModes();
-      let modeMap = {};
-      data.forEach(({ code, name }) => {
-        modeMap[code] = name;
-      });
-      this.modeMap = modeMap;
-    },
-    async search() {
-      const valid = await this.$refs.FilterForm.validate().catch(() => {});
-      if (!valid) return;
-
-      const data = await appConfigBaseline(this.filter);
-      this.dataList = data;
-    },
-    async toUpdate() {
-      const valid = await this.$refs.FilterForm.validate().catch(() => {});
-      if (!valid) return;
-
-      this.$refs.UpdateAppBaseline.open();
-    },
-    toEdit(row) {
-      this.curRow = { ...row, ...this.filter };
-      this.$refs.ModifyAppBaselineItem.open();
-    },
-    baselineItemModified(data) {
-      console.log(data);
-    }
-  }
-};
-</script>

+ 236 - 39
src/modules/admin/components/AppConfigManage.vue

@@ -4,11 +4,10 @@
       class="page-dialog"
       :visible.sync="modalIsShow"
       title="应用配置管理"
-      top="10px"
-      width="900px"
       :close-on-click-modal="false"
       :close-on-press-escape="false"
       append-to-body
+      fullscreen
       @opened="visibleChange"
     >
       <div class="part-box part-box-filter part-box-flex">
@@ -34,23 +33,36 @@
               :clearable="false"
             ></module-select>
           </el-form-item>
-          <el-form-item prop="envId" label="模块">
-            <env-select
-              v-model="filter.envId"
-              :app-id="filter.appId"
-              :clearable="false"
-            ></env-select>
-          </el-form-item>
           <el-form-item label-width="0px">
             <el-button type="primary" icon="ios-search" @click="search"
               >查询</el-button
             >
+            <el-button type="success" icon="md-add" @click="toUpdate"
+              >配置基线修改</el-button
+            >
           </el-form-item>
         </el-form>
       </div>
 
+      <div class="mb-4 tab-btns tab-nowrap">
+        <el-button
+          size="medium"
+          :type="filter.envId == null ? 'primary' : 'default'"
+          @click="selectEnv({ id: null })"
+          >基线
+        </el-button>
+        <el-button
+          v-for="env in envList"
+          :key="env.id"
+          size="medium"
+          :type="filter.envId == env.id ? 'primary' : 'default'"
+          @click="selectEnv(env)"
+          >{{ env.name }}
+        </el-button>
+      </div>
+
       <div class="part-box part-box-pad">
-        <el-table ref="TableList" :data="dataList">
+        <el-table ref="TableList" :data="configList">
           <el-table-column prop="key" label="配置项"> </el-table-column>
           <el-table-column prop="value" label="配置值"> </el-table-column>
           <el-table-column prop="mode" label="模式">
@@ -71,23 +83,41 @@
       </div>
     </el-dialog>
 
-    <modify-app-config
-      ref="ModifyAppConfig"
-      :instance="curRow"
-      @modified="search"
-    ></modify-app-config>
+    <!-- UpdateAppBaseline -->
+    <update-app-baseline
+      ref="UpdateAppBaseline"
+      :data="filter"
+      @modified="baselineModified"
+    ></update-app-baseline>
+    <!-- ModifyAppBaselineItem -->
+    <modify-app-baseline-item
+      ref="ModifyAppBaselineItem"
+      :instance="curBaselineItem"
+      @modified="baselineItemModified"
+    ></modify-app-baseline-item>
+    <!-- ModifyAppConfigItem -->
+    <modify-app-config-item
+      ref="ModifyAppConfigItem"
+      :instance="curConfigItem"
+    ></modify-app-config-item>
   </div>
 </template>
 
 <script>
-import { appConfigList, appConfigModes } from "../api";
-import ModifyAppConfig from "./ModifyAppConfig.vue";
+import {
+  appConfigBaseline,
+  appConfigModes,
+  appConfigGroups,
+  appEnvList,
+  appConfigList
+} from "../api";
+import UpdateAppBaseline from "../components/UpdateAppBaseline.vue";
+import ModifyAppBaselineItem from "../components/ModifyAppBaselineItem.vue";
+import ModifyAppConfigItem from "../components/ModifyAppConfigItem.vue";
 
 export default {
   name: "app-config-manage",
-  components: {
-    ModifyAppConfig
-  },
+  components: { UpdateAppBaseline, ModifyAppBaselineItem, ModifyAppConfigItem },
   props: {
     app: {
       type: Object,
@@ -101,14 +131,16 @@ export default {
       modalIsShow: false,
       filter: {
         appId: "",
-        moduleId: "",
-        versionId: "",
-        envId: ""
+        moduleId: null,
+        versionId: null,
+        envId: null
       },
+      searchFilter: {},
       rules: {
         moduleId: [
           {
             required: true,
+            type: "number",
             message: "请选择模块",
             triggr: "change"
           }
@@ -116,28 +148,48 @@ export default {
         versionId: [
           {
             required: true,
+            type: "number",
             message: "请选择版本",
             triggr: "change"
           }
-        ],
-        envId: [
-          {
-            required: true,
-            message: "请选择环境",
-            triggr: "change"
-          }
         ]
       },
-      dataList: [],
-      curRow: {},
-      modeMap: {}
+      configList: [],
+      curConfigItem: {},
+      baselineCaches: {},
+      baselineList: [],
+      curBaselineItem: {},
+      modeMap: {},
+      envList: [],
+      configGroups: [],
+      groupConfigList: []
     };
   },
   methods: {
     async visibleChange() {
+      await this.getConfigModes();
+      await this.appConfigGroups();
+      if (!this.filter.appId !== this.app.id) this.resetData();
       this.filter.appId = this.app.id;
 
-      // await this.getConfigModes();
+      await this.getEnvList();
+      // TODO:选择环境
+      this.selectEnv({ id: null });
+    },
+    resetData() {
+      this.filter = {
+        appId: "",
+        moduleId: null,
+        versionId: null,
+        envId: null
+      };
+      this.searchFilter = {};
+      this.configList = [];
+      this.curConfigItem = {};
+      this.baselineCaches = {};
+      this.baselineList = [];
+      this.curBaselineItem = {};
+      this.envList = [];
     },
     cancel() {
       this.modalIsShow = false;
@@ -145,6 +197,12 @@ export default {
     open() {
       this.modalIsShow = true;
     },
+    async getEnvList() {
+      const res = await appEnvList({
+        appId: this.app.id
+      });
+      this.envList = res || [];
+    },
     async getConfigModes() {
       if (Object.keys(this.modeMap).length) return;
 
@@ -155,16 +213,155 @@ export default {
       });
       this.modeMap = modeMap;
     },
+    async appConfigGroups() {
+      if (this.configGroups.length) return;
+
+      const data = await appConfigGroups();
+      this.configGroups = data || [];
+    },
+    selectEnv(env) {
+      this.filter.envId = env.id;
+      this.search();
+    },
     async search() {
       const valid = await this.$refs.FilterForm.validate().catch(() => {});
       if (!valid) return;
 
-      const data = await appConfigList(this.filter);
-      this.dataList = data;
+      this.searchFilter = { ...this.filter };
+
+      if (this.filter.envId) {
+        await this.getConfigList();
+        this.buildGroupConfigList(this.configList);
+      } else {
+        await this.getBaselineList();
+        this.buildGroupConfigList(this.baselineList);
+      }
+    },
+    getCacheBaselineList() {
+      const k = [
+        this.searchFilter.appId,
+        this.searchFilter.moduleId,
+        this.searchFilter.versionId
+      ].join("_");
+      return this.baselineCaches[k] || [];
+    },
+    setCacheBaselineList(baseline) {
+      const k = [
+        this.searchFilter.appId,
+        this.searchFilter.moduleId,
+        this.searchFilter.versionId
+      ].join("_");
+      this.baselineCaches[k] = baseline;
+    },
+    async getBaselineList() {
+      const cacheBaseline = this.getCacheBaselineList();
+      if (cacheBaseline.length) {
+        this.baselineList = cacheBaseline;
+        return;
+      }
+
+      const data = await appConfigBaseline(this.searchFilter);
+      this.setCacheBaselineList(data);
+    },
+    async getConfigList() {
+      await this.getBaselineList();
+      const data = await appConfigList(this.searchFilter);
+      // TODO:merge config data
+      this.configList = data;
+    },
+    buildGroupConfigList(dataList) {
+      console.log(dataList);
+
+      let groupConfigList = [];
+      dataList.forEach(configItem => {
+        const info = this.getConfigItemGroupPosInfo(configItem.key);
+        if (info) {
+          let group = groupConfigList.find(
+            gitem => gitem.name === info.group.name
+          );
+          if (!group) {
+            group.children = [];
+            groupConfigList.push(group);
+          }
+          group.children.push({
+            ...configItem,
+            available: info.available
+          });
+          return;
+        }
+
+        let group = groupConfigList.find(gitem => gitem.name === "other");
+        if (!group) {
+          group = [
+            {
+              name: "other",
+              prefix: "",
+              children: []
+            }
+          ];
+          groupConfigList.push(group);
+        }
+        group.children.push({
+          ...configItem,
+          available: info.available
+        });
+      });
+
+      this.groupConfigList = groupConfigList;
+    },
+    getConfigItemGroupPosInfo(configItemKey) {
+      const curGroup = this.configGroups.find(group =>
+        configItemKey.include(group.prefix)
+      );
+      if (!curGroup) return;
+      let groupData = {
+        name: curGroup.name,
+        prefix: curGroup.prefix
+      };
+
+      for (let i = 0; i < curGroup.available.length; i++) {
+        const avai = { ...curGroup.available[i] };
+        if (avai.key.include(".*.")) {
+          const regCont = avai.key
+            .split(".")
+            .join("\\.")
+            .replace("*", ".*");
+          const reg = new RegExp(`^${regCont}$`);
+          if (reg.test(configItemKey)) {
+            return {
+              group: groupData,
+              available: avai
+            };
+          }
+          continue;
+        }
+        if (avai.key === configItemKey) {
+          return {
+            group: groupData,
+            available: avai
+          };
+        }
+      }
+    },
+    async toUpdate() {
+      const valid = await this.$refs.FilterForm.validate().catch(() => {});
+      if (!valid) return;
+
+      this.$refs.UpdateAppBaseline.open();
+    },
+    toEditBaseline(row) {
+      this.curBaselineItem = { ...row, ...this.filter };
+      this.$refs.ModifyAppBaselineItem.open();
+    },
+    toEditConfigItem(row) {
+      this.curConfigItem = { ...row, ...this.filter };
+      this.$refs.ModifyAppConfigItem.open();
+    },
+    baselineItemModified(data) {
+      console.log(data);
     },
-    toEdit(row) {
-      this.curRow = { ...row, ...this.filter };
-      this.$refs.ModifyAppConfig.open();
+    baselineModified(data) {
+      this.setCacheBaselineList(data);
     }
   }
 };

+ 3 - 3
src/modules/admin/components/ModifyAppConfig.vue → src/modules/admin/components/ModifyAppConfigItem.vue

@@ -1,8 +1,8 @@
 <template>
   <el-dialog
-    class="modify-app-config"
+    class="modify-app-config-item"
     :visible.sync="modalIsShow"
-    title="应用配置基线配置项修改"
+    title="应用配置配置项修改"
     top="10vh"
     width="600px"
     :close-on-click-modal="false"
@@ -56,7 +56,7 @@ const initModalForm = {
 };
 
 export default {
-  name: "modify-app-config",
+  name: "modify-app-config-item",
   props: {
     instance: {
       type: Object,

+ 8 - 4
src/modules/admin/components/UpdateAppBaseline.vue

@@ -4,7 +4,7 @@
     :visible.sync="modalIsShow"
     title="应用配置基线修改"
     top="10vh"
-    width="500px"
+    width="600px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     append-to-body
@@ -108,6 +108,7 @@ export default {
     },
     fileChange(data) {
       this.uploadData = data;
+      console.log(data);
       this.$refs.modalFormComp.validateField("uploadData");
     },
     async confirm() {
@@ -119,10 +120,13 @@ export default {
 
       let formData = new FormData();
       Object.entries(this.modalForm).forEach(([k, v]) => {
-        formData.append(k, v);
+        if (v) formData.append(k, v);
       });
       formData.append("file", this.uploadData.file);
-      formData.append("extension", this.uploadData.file.ext);
+      formData.append(
+        "extension",
+        this.uploadData.filename.split(".").slice(-1)
+      );
 
       const data = await appConfigBaselineUpdate(formData, {
         md5: this.uploadData.md5
@@ -132,7 +136,7 @@ export default {
 
       this.$message.success("添加成功!");
       this.cancel();
-      this.$emit("modified");
+      this.$emit("modified", data);
     }
   }
 };

+ 62 - 0
src/modules/admin/components/baselineConfig.json

@@ -0,0 +1,62 @@
+[
+  {
+    "appId": 2,
+    "versionId": 2,
+    "moduleId": 1,
+    "envId": 0,
+    "key": "com.qmth.api.global-auth",
+    "value": "false",
+    "comment": null,
+    "mode": "MUTABLE",
+    "createTime": 1666941781910,
+    "updateTime": 1666941781910
+  },
+  {
+    "appId": 2,
+    "versionId": 2,
+    "moduleId": 1,
+    "envId": 0,
+    "key": "com.qmth.datasource.password",
+    "value": "scan",
+    "comment": null,
+    "mode": "MUTABLE",
+    "createTime": 1666941781910,
+    "updateTime": 1666941781910
+  },
+  {
+    "appId": 2,
+    "versionId": 2,
+    "moduleId": 1,
+    "envId": 0,
+    "key": "com.qmth.datasource.url",
+    "value": "jdbc:mysql://192.168.10.83:3306/ops_db?useUnicode=true&characterEncoding=UTF-8",
+    "comment": null,
+    "mode": "MUTABLE",
+    "createTime": 1666941781910,
+    "updateTime": 1666941781910
+  },
+  {
+    "appId": 2,
+    "versionId": 2,
+    "moduleId": 1,
+    "envId": 0,
+    "key": "com.qmth.datasource.username",
+    "value": "scan",
+    "comment": null,
+    "mode": "MUTABLE",
+    "createTime": 1666941781910,
+    "updateTime": 1666941781910
+  },
+  {
+    "appId": 2,
+    "versionId": 2,
+    "moduleId": 1,
+    "envId": 0,
+    "key": "server.port",
+    "value": "8080",
+    "comment": null,
+    "mode": "MUTABLE",
+    "createTime": 1666941781910,
+    "updateTime": 1666941781910
+  }
+]

+ 2 - 19
src/modules/admin/views/AppManage.vue

@@ -49,7 +49,7 @@
             >
           </template>
         </el-table-column>
-        <el-table-column label="管理" width="300" class-name="action-column">
+        <el-table-column label="管理" width="280" class-name="action-column">
           <template slot-scope="scope">
             <el-button
               class="btn-primary"
@@ -75,12 +75,6 @@
               @click="toEditEnv(scope.row)"
               >环境</el-button
             >
-            <el-button
-              class="btn-primary"
-              type="text"
-              @click="toEditBaseline(scope.row)"
-              >配置基线</el-button
-            >
             <el-button
               class="btn-primary"
               type="text"
@@ -120,11 +114,6 @@
     <app-env-manage ref="AppEnvManage" :app="curRow"></app-env-manage>
     <!-- AppConfigManage -->
     <app-config-manage ref="AppConfigManage" :app="curRow"></app-config-manage>
-    <!-- AppBaselineManage -->
-    <app-baseline-manage
-      ref="AppBaselineManage"
-      :app="curRow"
-    ></app-baseline-manage>
   </div>
 </template>
 
@@ -136,7 +125,6 @@ import AppModuleManage from "../components/AppModuleManage.vue";
 import AppVersionManage from "../components/AppVersionManage.vue";
 import AppEnvManage from "../components/AppEnvManage.vue";
 import AppConfigManage from "../components/AppConfigManage.vue";
-import AppBaselineManage from "../components/AppBaselineManage.vue";
 
 export default {
   name: "app-manage",
@@ -146,8 +134,7 @@ export default {
     AppModuleManage,
     AppVersionManage,
     AppEnvManage,
-    AppConfigManage,
-    AppBaselineManage
+    AppConfigManage
   },
   data() {
     return {
@@ -208,10 +195,6 @@ export default {
       this.curRow = row;
       this.$refs.AppEnvManage.open();
     },
-    toEditBaseline(row) {
-      this.curRow = row;
-      this.$refs.AppBaselineManage.open();
-    },
     toEditConfig(row) {
       this.curRow = row;
       this.$refs.AppConfigManage.open();