Browse Source

应用部署关联机构和设备

zhangjie 2 years ago
parent
commit
e2bee7fe38

+ 1 - 0
package.json

@@ -16,6 +16,7 @@
     "js-md5": "^0.7.3",
     "qs": "^6.11.0",
     "vue": "^2.6.11",
+    "vue-json-viewer": "^2.2.22",
     "vue-ls": "^3.2.1",
     "vue-router": "^3.1.6",
     "vuex": "^3.1.3"

+ 2 - 0
src/main.js

@@ -13,6 +13,8 @@ import VueLocalStorage from "vue-ls";
 import ElementUI from "element-ui";
 import "element-ui/lib/theme-chalk/index.css";
 import "./assets/styles/index.scss";
+import JsonViewr from "vue-json-viewer";
+Vue.use(JsonViewr);
 
 Vue.use(ElementUI, { size: "small" });
 Vue.use(VueLocalStorage, { namespace: "vs_", storage: "session" });

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

@@ -141,10 +141,41 @@ export const appDeployInsertOrUpdate = datas => {
     return $post("/api/admin/deploy/insert", datas);
   }
 };
-
+export const appDeployLicenseDownload = datas => {
+  return $postParam("/api/admin/deploy/license/download", datas, {
+    responseType: "blob"
+  });
+};
+// app-deploy-org
+export const appDeployOrgList = deployId => {
+  return $postParam("/api/admin/deploy/org/list", { id: deployId });
+};
+export const appDeployOrgUpdate = datas => {
+  return $postParam("/api/admin/deploy/org/update", datas);
+};
+// app-deploy-devive
+export const appDeployDeviceList = deployId => {
+  return $postParam("/api/admin/deploy/device/list", { id: deployId });
+};
+export const appDeployDeviceInfo = deviceId => {
+  return $postParam("/api/admin/deploy/device/info", { deviceId });
+};
+export const appDeployDeviceSave = datas => {
+  let formData = new FormData();
+  Object.keys(datas).forEach(key => {
+    formData.append(key, datas[key]);
+  });
+  return $post("/api/admin/deploy/device/save", formData);
+};
+export const appDeployDeviceDelete = ({ deployId, deviceId }) => {
+  return $postParam("/api/admin/deploy/device/delete", {
+    id: deployId,
+    deviceId
+  });
+};
 // org-manage
-export const orgTypesList = datas => {
-  return $postParam("/api/admin/org/types", datas);
+export const orgTypesList = () => {
+  return $postParam("/api/admin/org/types", {});
 };
 export const orgQuery = datas => {
   return $postParam("/api/admin/org/query", datas);

+ 164 - 0
src/modules/admin/components/AppDeployBindDevice.vue

@@ -0,0 +1,164 @@
+<template>
+  <div class="app-deploy-bind-device">
+    <el-dialog
+      class="page-dialog"
+      :visible.sync="modalIsShow"
+      title="应用关联设备"
+      top="10px"
+      width="1000px"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      append-to-body
+      @opened="visibleChange"
+    >
+      <div class="flex-between md-2">
+        <el-button type="success" @click="toExport">导出通用许可证</el-button>
+        <el-button type="primary" @click="toUpload">上传设备信息</el-button>
+      </div>
+      <div class="part-box part-box-pad">
+        <el-table ref="TableList" :data="dataList">
+          <el-table-column prop="deviceId" label="设备"></el-table-column>
+          <el-table-column prop="remark" label="备注"></el-table-column>
+          <el-table-column prop="createTime" label="创建时间" width="160">
+            <span slot-scope="scope">{{
+              scope.row.createTime | timestampFilter
+            }}</span>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="280">
+            <template slot-scope="scope">
+              <el-button size="mini" type="primary" @click="toDetail(scope.row)"
+                >设备信息</el-button
+              >
+              <el-button size="mini" type="success" @click="toExport(scope.row)"
+                >导出许可证</el-button
+              >
+              <el-button size="mini" type="danger" @click="toDelete(scope.row)"
+                >删除</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div slot="footer"></div>
+    </el-dialog>
+
+    <AppDeployDeviceInfoView
+      ref="AppDeployDeviceInfoView"
+      :device-id="curDeviceId"
+    />
+    <!-- AppDeployDeviceUpload -->
+    <AppDeployDeviceUpload
+      ref="AppDeployDeviceUpload"
+      :deploy-id="instance.id"
+      @modified="getList"
+    ></AppDeployDeviceUpload>
+  </div>
+</template>
+
+<script>
+import { downloadBlob } from "../../../plugins/utils";
+import {
+  appDeployDeviceList,
+  appDeployDeviceDelete,
+  appDeployLicenseDownload
+} from "../api";
+import AppDeployDeviceInfoView from "./AppDeployDeviceInfoView.vue";
+import AppDeployDeviceUpload from "./AppDeployDeviceUpload.vue";
+
+export default {
+  name: "app-device-manage",
+  components: { AppDeployDeviceInfoView, AppDeployDeviceUpload },
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      dataList: [],
+      curDeviceId: null,
+      uploading: false
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.getList();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getList() {
+      const data = await appDeployDeviceList(this.instance.id);
+      this.dataList = data || [];
+    },
+    toDetail(row) {
+      this.curDeviceId = row.deviceId;
+      this.$refs.AppDeployDeviceInfoView.open();
+    },
+    toUpload() {
+      this.$refs.AppDeployDeviceUpload.open();
+    },
+    async toExport(row = {}) {
+      if (this.loading) return;
+
+      this.$prompt("", "导出设置", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        // inputPattern: /^\d{1,}\.\d{1,}\.\d{1,}$/,
+        // inputErrorMessage: "版本号格式不对",
+        inputPlaceholder: "版本号,非必填",
+        inputValidator(val) {
+          if (!val) return true;
+          if (!/^\d{1,}\.\d{1,}\.\d{1,}$/.test(val)) {
+            return "版本号格式不对";
+          }
+          return true;
+        }
+      })
+        .then(({ value }) => {
+          this.exportLicense({ ...row, version: value });
+        })
+        .catch(() => {});
+    },
+    async exportLicense(row) {
+      this.loading = true;
+      const res = await downloadBlob(() => {
+        const params = {
+          id: this.instance.id
+        };
+        if (row) params.deviceId = row.deviceId;
+        if (row.version) params.version = row.version;
+
+        return appDeployLicenseDownload(params);
+      }).catch(() => {});
+
+      this.loading = false;
+
+      if (res) {
+        this.$message.success("文件下载成功!");
+      } else {
+        this.$message.error("文件下载失败,请重新尝试!");
+      }
+    },
+    async toDelete(row) {
+      const result = await this.$confirm("确定要删除当前设备吗?", "操作警告", {
+        type: "warning"
+      }).catch(() => {});
+      if (result !== "confirm") return;
+      await appDeployDeviceDelete({
+        deployId: this.instance.id,
+        deviceId: row.deviceId
+      });
+      this.$message.success("删除成功!");
+      this.getList();
+    }
+  }
+};
+</script>

+ 345 - 0
src/modules/admin/components/AppDeployBindOrg.vue

@@ -0,0 +1,345 @@
+<template>
+  <el-dialog
+    class="page-dialog config-manage-dialog"
+    :visible.sync="modalIsShow"
+    top="10px"
+    width="1000px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <div class="part-box flex-between" slot="title">
+      <h3>应用关联机构</h3>
+      <div>
+        <el-button size="mini" type="danger" plain @click="cancel"
+          >取消</el-button
+        >
+        <el-button
+          size="mini"
+          type="primary"
+          :disabled="isSubmit"
+          @click="submit"
+          >确定</el-button
+        >
+      </div>
+    </div>
+
+    <el-tabs v-model="tabType" type="card" @tab-click="tabChange">
+      <el-tab-pane name="selected">
+        <span slot="label">
+          <span>已选机构</span>
+          <span class="color-primary">({{ curSelectedOrgs.length }})</span>
+        </span>
+
+        <el-table :data="curSelectedOrgs" border>
+          <!-- <el-table-column width="60" type="index" label="序号" align="center">
+          </el-table-column> -->
+          <el-table-column prop="id" label="ID" width="80"></el-table-column>
+          <el-table-column prop="name" label="名称"> </el-table-column>
+          <el-table-column prop="code" label="编码"> </el-table-column>
+          <el-table-column prop="typeName" label="一级分类" width="100">
+          </el-table-column>
+          <el-table-column prop="subTypesName" label="二级分类">
+          </el-table-column>
+          <el-table-column label="状态" width="100">
+            <span
+              slot-scope="scope"
+              :class="{ 'color-primary': scope.row.selected }"
+            >
+              {{ scope.row.selected ? "已选择" : "未选择" }}
+            </span>
+          </el-table-column>
+          <el-table-column label="操作" width="120">
+            <div slot-scope="scope">
+              <el-button
+                size="mini"
+                type="danger"
+                @click="toDeleteSelected(scope.row)"
+              >
+                删除
+              </el-button>
+            </div>
+          </el-table-column>
+        </el-table>
+      </el-tab-pane>
+      <el-tab-pane name="resource">
+        <span slot="label">机构筛选</span>
+
+        <div class="part-filter">
+          <div class="part-filter-form" style="padding-left: 0">
+            <el-form :model="filter" inline>
+              <el-form-item label="一级分类">
+                <el-select
+                  v-model="filter.type"
+                  placeholder="选择一级分类"
+                  clearable
+                  @change="typeChange"
+                >
+                  <el-option
+                    v-for="item in orgTypes"
+                    :key="item.code"
+                    :value="item.code"
+                    :label="item.name"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label="二级分类">
+                <el-select
+                  v-model="filter.subType"
+                  placeholder="选择二级分类"
+                  clearable
+                >
+                  <el-option
+                    v-for="item in curSubTypes"
+                    :key="item.code"
+                    :value="item.code"
+                    :label="item.name"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label="编码" label-width="50">
+                <el-input
+                  v-model="filter.code"
+                  placeholder="编码"
+                  clearable
+                ></el-input>
+              </el-form-item>
+              <el-form-item label="模糊查询">
+                <el-input
+                  v-model.trim="filter.nameStartWith"
+                  placeholder="名称前缀"
+                  clearable
+                ></el-input>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" @click="toPage(1)">查询</el-button>
+              </el-form-item>
+            </el-form>
+          </div>
+        </div>
+
+        <el-table :data="orgs" border>
+          <!-- <el-table-column
+            width="60"
+            type="index"
+            label="序号"
+            align="center"
+            :index="indexMethod"
+          >
+          </el-table-column> -->
+          <el-table-column prop="id" label="ID" width="80"></el-table-column>
+          <el-table-column prop="name" label="名称"> </el-table-column>
+          <el-table-column prop="code" label="编码"> </el-table-column>
+          <el-table-column prop="typeName" label="一级分类" width="100">
+          </el-table-column>
+          <el-table-column prop="subTypesName" label="二级分类">
+          </el-table-column>
+          <el-table-column label="状态" width="100">
+            <span
+              slot-scope="scope"
+              :class="{ 'color-primary': scope.row.selected }"
+            >
+              {{ scope.row.selected ? "已选择" : "未选择" }}
+            </span>
+          </el-table-column>
+          <el-table-column label="操作" width="120">
+            <div slot-scope="scope">
+              <el-button
+                v-if="scope.row.selected"
+                size="mini"
+                type="danger"
+                @click="toDelete(scope.row)"
+              >
+                删除
+              </el-button>
+              <el-button
+                v-else
+                size="mini"
+                type="primary"
+                @click="toSelect(scope.row)"
+              >
+                添加
+              </el-button>
+            </div>
+          </el-table-column>
+        </el-table>
+
+        <div class="part-page">
+          <el-pagination
+            background
+            layout="total,prev, pager, next"
+            :current-page="current"
+            :total="total"
+            :page-size="size"
+            @current-change="toPage"
+          />
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { orgQuery, appDeployOrgList, appDeployOrgUpdate } from "../api";
+
+export default {
+  name: "app-deploy-bind-org",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      filter: {
+        type: "",
+        subType: "",
+        code: "",
+        nameStartWith: ""
+      },
+      isSubmit: false,
+      tabType: "selected",
+      current: 1,
+      size: 10,
+      total: 10,
+      orgTypes: this.$ls.get("orgTypes", []),
+      orgTypeMap: this.$ls.get("orgTypeMap", {}),
+      curSubTypes: [],
+      orgs: [],
+      curSelectedOrgs: [],
+      curSelectedOrgIds: []
+    };
+  },
+  methods: {
+    async initData() {
+      await this.getSelectedOrgs();
+      if (this.curSelectedOrgs && this.curSelectedOrgs.length) {
+        this.tabType = "selected";
+      } else {
+        this.tabType = "resource";
+        this.toPage(this.current);
+      }
+    },
+    visibleChange() {
+      this.initData();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    typeChange() {
+      const curType = this.orgTypes.find(
+        item => item.code === this.filter.type
+      );
+      this.curSubTypes = curType ? curType.subTypes : [];
+      this.filter.subType = null;
+    },
+    async getSelectedOrgs() {
+      const res = await appDeployOrgList(this.instance.id);
+      const resData = res || [];
+      this.curSelectedOrgs = resData.map(item => {
+        item.typeName = this.orgTypeMap[item.type].name;
+        item.selected = true;
+        if (item.subTypes && item.subTypes.length) {
+          item.subTypesName = item.subTypes
+            .map(type => this.orgTypeMap[item.type].subType[type])
+            .join(",");
+        }
+        return item;
+      });
+      this.updateSelectedOrgIds();
+    },
+    indexMethod(index) {
+      return index + (this.current - 1) * this.size + 1;
+    },
+    async getList() {
+      const res = await orgQuery({
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      });
+      this.orgs = res.records.map(item => {
+        item.typeName = this.orgTypeMap[item.type].name;
+        item.selected = this.curSelectedOrgIds.includes(item.id);
+        if (item.subTypes && item.subTypes.length) {
+          item.subTypesName = item.subTypes
+            .map(type => this.orgTypeMap[item.type].subType[type])
+            .join(",");
+        }
+        return item;
+      });
+      this.total = res.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    tabChange(val) {
+      if (val.name === "resource") {
+        if (this.orgs.length) {
+          this.orgs.forEach(item => {
+            item.selected = this.curSelectedOrgIds.includes(item.id);
+          });
+        } else {
+          this.toPage(this.current);
+        }
+      }
+    },
+    toSelect(row) {
+      row.selected = true;
+      this.curSelectedOrgs.push({ ...row });
+      this.updateSelectedOrgIds();
+    },
+    toDelete(row) {
+      row.selected = false;
+      this.toDeleteSelected(row);
+    },
+    toDeleteSelected(row) {
+      const pos = this.curSelectedOrgs.findIndex(item => item.id === row.id);
+      this.curSelectedOrgs.splice(pos, 1);
+
+      this.updateSelectedOrgIds();
+    },
+    updateSelectedOrgIds() {
+      this.curSelectedOrgIds = this.curSelectedOrgs.map(item => item.id);
+    },
+    async submit() {
+      if (!this.curSelectedOrgIds.length) {
+        const result = await this.$confirm("确定不关联任何机构吗?", "警告", {
+          type: "warning"
+        }).catch(() => {});
+        if (result !== "confirm") return;
+      }
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const datas = {
+        appId: this.curApp.id,
+        orgId: this.curSelectedOrgIds.length ? this.curSelectedOrgIds : ""
+      };
+      const data = await appDeployOrgUpdate(datas).catch(() => {
+        this.isSubmit = false;
+      });
+
+      if (!data) return;
+
+      this.isSubmit = false;
+      this.$message.success("关联成功!");
+      this.$emit("modified");
+      this.cancel();
+    }
+  }
+};
+</script>

+ 2 - 2
src/modules/admin/components/AppControlKey.vue → src/modules/admin/components/AppDeployControlKey.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="app-control-key">
+  <div class="app-deploy-control-key">
     <el-input-number
       v-if="keyType === 'number'"
       v-model="data"
@@ -23,7 +23,7 @@
 
 <script>
 export default {
-  name: "app-control-key",
+  name: "app-deploy-control-key",
   props: {
     value: { type: [Number, String] },
     keyType: {

+ 85 - 0
src/modules/admin/components/AppDeployDeviceInfoView.vue

@@ -0,0 +1,85 @@
+<template>
+  <el-dialog
+    class="app-deploy-device-info-view"
+    :visible.sync="modalIsShow"
+    title="设备信息"
+    top="10px"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @opened="visibleChange"
+  >
+    <div class="flex-between">
+      <h4 class="info-title">{{ deviceId }}</h4>
+      <el-button type="primary" @click="copy">复制信息</el-button>
+    </div>
+    <div class="info-body">
+      <json-viewer v-if="info" :value="info" :expand-depth="9"></json-viewer>
+    </div>
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { appDeployDeviceInfo } from "../api";
+
+export default {
+  name: "app-deploy-device-info-view",
+  props: {
+    deviceId: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      info: null
+    };
+  },
+  methods: {
+    async visibleChange() {
+      this.info = null;
+      const data = await appDeployDeviceInfo(this.deviceId);
+      this.info = data || {};
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    copy() {
+      const inputDom = document.createElement("textarea");
+      inputDom.value = JSON.stringify(this.info);
+      document.body.appendChild(inputDom);
+      inputDom.select();
+      document.execCommand("copy");
+      inputDom.parentNode.removeChild(inputDom);
+      this.$message.success("复制成功!");
+    }
+  }
+};
+</script>
+
+<style scoped>
+.info-title {
+  font-size: 18px;
+}
+.info-body {
+  margin-top: 10px;
+  min-height: 200px;
+  background-color: #f0f4f9;
+}
+.info-body >>> .jv-container.jv-light {
+  background-color: transparent;
+  border-radius: 10px;
+}
+.info-body >>> .jv-code {
+  padding: 15px;
+  line-height: 20px;
+}
+.info-body >>> .jv-toggle {
+  margin-right: 5px;
+}
+</style>

+ 122 - 0
src/modules/admin/components/AppDeployDeviceUpload.vue

@@ -0,0 +1,122 @@
+<template>
+  <el-dialog
+    class="modify-device"
+    :visible.sync="modalIsShow"
+    title="上传设备信息"
+    top="10vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @opened="visibleChange"
+  >
+    <el-form
+      ref="modalFormComp"
+      :model="modalForm"
+      :rules="rules"
+      label-width="70px"
+    >
+      <el-form-item prop="deviceInfo" label="文件">
+        <UploadFetchFile
+          ref="UploadFetchFile"
+          :format="[]"
+          :disabled="isSubmit"
+          @file-change="deviceFileChange"
+          @valid-change="validChange"
+        />
+      </el-form-item>
+      <el-form-item label="备注">
+        <el-input
+          v-model.trim="modalForm.remark"
+          type="textarea"
+          placeholder="请输入备注"
+          clearable
+        ></el-input>
+      </el-form-item>
+    </el-form>
+    <div slot="footer">
+      <el-button type="danger" @click="cancel" plain>取消</el-button>
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { appDeployDeviceSave } from "../api";
+import UploadFetchFile from "../../../components/UploadFetchFile.vue";
+
+const initModalForm = {
+  id: "",
+  remark: "",
+  deviceInfo: null,
+  md5: ""
+};
+
+export default {
+  name: "modify-device",
+  components: { UploadFetchFile },
+  props: {
+    deployId: {
+      type: [String, Number]
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      modalForm: {
+        ...initModalForm
+      },
+      rules: {
+        deviceInfo: [
+          {
+            required: true,
+            message: "请选择要上传的文件",
+            trigger: "change"
+          }
+        ]
+      }
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.modalForm = { ...initModalForm };
+      this.modalForm.id = this.deployId;
+      this.$nextTick(() => {
+        this.$refs.UploadFetchFile.setAttachmentName("");
+      });
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    deviceFileChange({ file, md5 }) {
+      this.modalForm.md5 = md5;
+      this.modalForm.deviceInfo = file;
+
+      this.$refs.modalFormComp.validateField("deviceInfo", () => {});
+    },
+    validChange(res) {
+      if (!res.success)
+        this.$notify.error({ title: "错误提示", message: res.message });
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate();
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const result = await appDeployDeviceSave(this.modalForm).catch(() => {});
+      this.isSubmit = false;
+      if (!result) return;
+      this.$message.success("上传成功!");
+      this.$emit("modified");
+      this.cancel();
+    }
+  }
+};
+</script>

+ 10 - 3
src/modules/admin/components/AppDeployManage.vue

@@ -94,16 +94,22 @@
       :deploy-modes="deployModes"
       @modified="getList"
     ></modify-app-deploy>
+    <!-- AppDeployBindOrg -->
+    <app-deploy-bind-org
+      ref="AppDeployBindOrg"
+      :instance="curRow"
+    ></app-deploy-bind-org>
   </div>
 </template>
 
 <script>
 import { appDeployList, appDeployModes } from "../api";
 import ModifyAppDeploy from "./ModifyAppDeploy.vue";
+import AppDeployBindOrg from "./AppDeployBindOrg.vue";
 
 export default {
   name: "app-deploy-manage",
-  components: { ModifyAppDeploy },
+  components: { ModifyAppDeploy, AppDeployBindOrg },
   props: {
     app: {
       type: Object,
@@ -176,10 +182,11 @@ export default {
       this.$refs.ModifyAppDeploy.open();
     },
     toBindOrg(row) {
-      this.curRow = { ...row, app: this.app };
+      this.curRow = { ...row, appId: this.app.id };
+      this.$refs.AppDeployBindOrg.open();
     },
     toBindDevice(row) {
-      this.curRow = { ...row, app: this.app };
+      this.curRow = { ...row, appId: this.app.id };
     }
   }
 };

+ 12 - 15
src/modules/admin/components/ModifyAppDeploy.vue

@@ -15,16 +15,16 @@
       :model="modalForm"
       :rules="rules"
       :key="modalForm.id"
-      label-width="110px"
+      label-width="130px"
     >
-      <el-form-item prop="name" label="名称">
+      <el-form-item prop="name" label="名称">
         <el-input
           v-model.trim="modalForm.name"
           placeholder="请输入名称"
           clearable
         ></el-input>
       </el-form-item>
-      <el-form-item prop="mode" label="分类">
+      <el-form-item prop="mode" label="分类">
         <el-select v-model="modalForm.mode" placeholder="选择分类" clearable>
           <el-option
             v-for="item in deployModes"
@@ -35,7 +35,7 @@
           </el-option>
         </el-select>
       </el-form-item>
-      <el-form-item label="IP白名单">
+      <el-form-item label="IP白名单">
         <el-input
           v-model.trim="modalForm.ipAllow"
           type="textarea"
@@ -44,11 +44,11 @@
       </el-form-item>
 
       <template v-for="cont in DEPLOY_CONTROL_KEYS">
-        <el-form-item :key="cont.code" :label="cont.name">
-          <app-control-key
+        <el-form-item :key="cont.code" :label="`${cont.name}:`">
+          <app-deploy-control-key
             v-model="modalForm.control[cont.code]"
             :key-type="cont.type"
-          ></app-control-key>
+          ></app-deploy-control-key>
         </el-form-item>
       </template>
     </el-form>
@@ -65,7 +65,7 @@
 import { DEPLOY_CONTROL_KEYS } from "../../../constants/enumerate";
 import { clearData } from "../../../plugins/utils";
 import { appDeployInsertOrUpdate } from "../api";
-import AppControlKey from "./AppControlKey";
+import AppDeployControlKey from "./AppDeployControlKey.vue";
 
 const initModalForm = {
   id: null,
@@ -78,7 +78,7 @@ const initModalForm = {
 
 export default {
   name: "modify-app",
-  components: { AppControlKey },
+  components: { AppDeployControlKey },
   props: {
     instance: {
       type: Object,
@@ -127,14 +127,11 @@ export default {
   },
   methods: {
     initData(val) {
-      if (val.id) {
-        this.modalForm = this.$objAssign(initModalForm, val);
-      } else {
-        this.modalForm = { ...initModalForm };
-      }
+      this.modalForm = this.$objAssign(initModalForm, val);
+
       const controlVals = val.control || {};
       let control = {};
-      this.datas.controlKeys.forEach(cont => {
+      this.DEPLOY_CONTROL_KEYS.forEach(cont => {
         const defaultVal = cont.type === "number" ? undefined : null;
         control[cont.code] =
           controlVals[cont.code] || controlVals[cont.code] === 0

+ 16 - 1
src/modules/login/views/Login.vue

@@ -34,7 +34,7 @@
           </el-form-item>
           <el-form-item>
             <el-button
-              style="width:100%;"
+              style="width: 100%"
               type="primary"
               :disabled="isSubmit"
               @click="submit('loginForm')"
@@ -49,6 +49,7 @@
 
 <script>
 import { login } from "../api";
+import { orgTypesList } from "../../../modules/admin/api";
 import { APP_TITLE } from "../../../constants/app";
 
 export default {
@@ -83,6 +84,19 @@ export default {
     this.$ls.clear();
   },
   methods: {
+    async getOrgTypes() {
+      const types = await orgTypesList();
+      let orgTypeMap = {};
+      types.forEach(item => {
+        let kv = { name: item.name, subType: {} };
+        item.subTypes.forEach(elem => {
+          kv.subType[elem.code] = elem.name;
+        });
+        orgTypeMap[item.code] = kv;
+      });
+      this.$ls.set("orgTypes", types || []);
+      this.$ls.set("orgTypeMap", orgTypeMap);
+    },
     async submit(name) {
       const valid = await this.$refs[name].validate().catch(() => {});
       if (!valid) return;
@@ -101,6 +115,7 @@ export default {
       }
       this.$ls.set("token", data.token);
       this.$ls.set("user", data);
+      await this.getOrgTypes();
       this.$router.push({
         name: "Home"
       });

+ 38 - 0
yarn.lock

@@ -2569,6 +2569,15 @@ cli-width@^3.0.0:
   resolved "https://registry.npmmirror.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
   integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
 
+clipboard@^2.0.4:
+  version "2.0.11"
+  resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5"
+  integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
+  dependencies:
+    good-listener "^1.2.2"
+    select "^1.1.2"
+    tiny-emitter "^2.0.0"
+
 clipboardy@^2.3.0:
   version "2.3.0"
   resolved "https://registry.npmmirror.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
@@ -3296,6 +3305,11 @@ delayed-stream@~1.0.0:
   resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
   integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
 
+delegate@^3.1.2:
+  version "3.2.0"
+  resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
+  integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
+
 depd@2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
@@ -4493,6 +4507,13 @@ globby@^9.2.0:
     pify "^4.0.1"
     slash "^2.0.0"
 
+good-listener@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
+  integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
+  dependencies:
+    delegate "^3.1.2"
+
 graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.2:
   version "4.2.10"
   resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
@@ -7707,6 +7728,11 @@ select-hose@^2.0.0:
   resolved "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
   integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
 
+select@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
+  integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
+
 selfsigned@^1.10.8:
   version "1.10.14"
   resolved "https://registry.npmmirror.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574"
@@ -8474,6 +8500,11 @@ timsort@^0.3.0:
   resolved "https://registry.npmmirror.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
   integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==
 
+tiny-emitter@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
+  integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
+
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -8878,6 +8909,13 @@ vue-hot-reload-api@^2.3.0:
   resolved "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
   integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==
 
+vue-json-viewer@^2.2.22:
+  version "2.2.22"
+  resolved "https://registry.npmmirror.com/vue-json-viewer/-/vue-json-viewer-2.2.22.tgz#7ea7454b8aac3701245b88acf39de876cc54221e"
+  integrity sha512-3oPH5BxoUWva/qp7wNJj+15FBXyi9Yu5VDW4mCWivjHR1pUpMv34fjqqxML7jh2uOqm1S/3Xks5nQ5JjC5+OWw==
+  dependencies:
+    clipboard "^2.0.4"
+
 vue-loader@^15.9.1:
   version "15.10.1"
   resolved "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.10.1.tgz#c451c4cd05a911aae7b5dbbbc09fb913fb3cca18"