Browse Source

服务编辑页面修改

zhongxiaoyu 2 năm trước cách đây
mục cha
commit
b35f1d5a20

+ 1 - 1
.eslintrc.js

@@ -191,7 +191,7 @@ module.exports = {
     'prefer-const': 2,
     'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
     'object-curly-spacing': [2, 'always', {
-      objectsInObjects: false
+      objectsInObjects: true
     }],
     'array-bracket-spacing': [2, 'never']
   }

+ 11 - 1
src/utils/validate.js

@@ -269,7 +269,7 @@ export function lengthValidator(rule, value, callback) {
  * @param value
  * @param callback
  */
- export function validateIP(rule, value, callback) {
+export function validateIP(rule, value, callback) {
   if (value === '' || typeof value === 'undefined' || value == null) {
     callback(new Error('请输入正确的IP地址'))
   } else {
@@ -281,3 +281,13 @@ export function lengthValidator(rule, value, callback) {
     }
   }
 }
+
+// 表单验证输入内容验证
+export const regular = {
+  integer: /^[0-9]*$/,
+  positiveInteger: /^[1-9][0-9]*$/,
+  name: /^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$/,
+  nameMessage: '只能包含中文、英文、数字和下划线且不能以下划线开头',
+  url: /([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/|[wW]{3}.|[wW][aA][pP].|[fF][tT][pP].|[fF][iI][lL][eE].)[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/,
+  urlMessage: '请输入正确地址'
+}

+ 101 - 0
src/views/systemSettings/views/serviceManagement/mixins/operate.js

@@ -0,0 +1,101 @@
+/*
+ * @Author: Badguy
+ * @Date: 2022-04-29 09:17:55
+ * @LastEditTime: 2022-04-29 14:21:27
+ * @LastEditors: your name
+ * @Description: 服务相关操作
+ * have a nice day!
+ */
+
+import { GeneralDataReception } from '@/api/dataIntegration'
+
+const operateMap = {
+  create: 1,
+  update: 2,
+  delete: 3
+}
+
+export default {
+  methods: {
+    async updateService() {
+      const params = {
+        ...this.serviceForm,
+        ...this.inputForm,
+        operate: 2
+      }
+      try {
+        const result = await GeneralDataReception({
+          serviceId: 3,
+          dataContent: JSON.stringify(params)
+        })
+        if (Number(result.code === 0)) {
+          this.$message.success(result.message ?? '成功')
+        } else {
+          this.$message.error(result.message ?? '失败')
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
+    },
+    async updateServiceNode(operate, deployNodeID) {
+      const params = {
+        operate: operateMap[operate],
+        serviceID: this.serviceID,
+        deployNodeID
+      }
+      try {
+        const result = await GeneralDataReception({
+          serviceId: 3,
+          dataContent: JSON.stringify(params)
+        })
+        if (Number(result.code) === 0) {
+          return result.returnData
+        } else {
+          return Promise.reject(result.message)
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
+    },
+    async updateServiceSource(operate, sourceDataID) {
+      const params = {
+        operate: operateMap[operate],
+        serviceID: this.serviceID,
+        sourceDataID
+      }
+      try {
+        const result = await GeneralDataReception({
+          serviceId: 6,
+          dataContent: JSON.stringify(params)
+        })
+        if (Number(result.code) === 0) {
+          return result.returnData
+        } else {
+          return Promise.reject(result.message)
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
+    },
+    async updateServiceOutput(operate, outputTarget) {
+      const params = {
+        operate: operateMap[operate],
+        serviceID: this.serviceID,
+        ...outputTarget
+      }
+      try {
+        const result = await GeneralDataReception({
+          serviceId: 9,
+          dataContent: JSON.stringify(params)
+        })
+        if (Number(result.code) === 0) {
+          this.$message.success(result.message ?? '成功')
+        } else {
+          this.$message.error(result.message ?? '失败')
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
+    }
+  }
+}

+ 135 - 52
src/views/systemSettings/views/serviceManagement/mixins/query.js

@@ -1,7 +1,7 @@
 /*
  * @Author: Badguy
  * @Date: 2022-04-27 15:54:38
- * @LastEditTime: 2022-04-28 09:51:22
+ * @LastEditTime: 2022-04-29 13:56:03
  * @LastEditors: your name
  * @Description: 服务相关数据查询
  * have a nice day!
@@ -11,25 +11,25 @@ import { Query } from '@/api/dataIntegration'
 
 const queryMap = {
   protocol: 1,
-  machine: 2,
+  node: 2,
   service: 3,
   source: 4,
-  sourceInfo: 5,
-  sourceAndService: 6,
-  outputTarget: 7,
-  outputTargetDetail: 8,
-  outputTargetAndService: 9,
-  machineAndService: 10,
-  serviceDetail: 11,
-  machineByServiceID: 12,
+  sourceItem: 5,
+  serviceAndSource: 6,
+  target: 7,
+  targetItem: 8,
+  serviceAndOutput: 9,
+  serviceAndNode: 10,
+  serviceByID: 11,
+  nodeByServiceID: 12,
   sourceByServiceID: 13,
   targetByServiceID: 14,
-  targetDetailByID: 15,
-  sourceDetailByID: 16,
+  targetItemByTargetID: 15,
+  sourceItemBySourceID: 16,
   targetByID: 17,
   sourceByID: 18,
-  processByServiceID: 19,
-  outputTargetByServiceID: 20
+  serviceAlgorithmByServiceID: 19,
+  outputListByServiceID: 20
 }
 
 export default {
@@ -40,54 +40,137 @@ export default {
     this.serviceID && this.queryAll(this.serviceID)
   },
   methods: {
-    myQuery(queryID, serviceID) {
+    async myQuery(type, queryID) {
       const params = {
-        id: queryID,
+        id: type,
         dataContent: []
       }
-      serviceID ?? params.dataContent.push(serviceID)
-      return new Promise((resolve, reject) => {
-        Query(params)
-          .then(result => {
-            if (Number(result.code) === 0) {
-              resolve(result.returnData)
-            } else {
-              reject(result.message)
-            }
-          })
-          .catch(error => {
-            console.log('错误', error)
-          })
-      })
-    },
-    queryService(serviceID) {
-      return this.myQuery(queryMap.serviceDetail, serviceID)
-    },
-    queryMachineListByServiceId(serviceID) {
-      return this.myQuery(queryMap.machineByServiceID, serviceID)
+      queryID && params.dataContent.push(queryID)
+      try {
+        const result = await Query(params)
+        if (Number(result.code) === 0) {
+          return result.returnData
+        } else {
+          return Promise.reject(result.message)
+        }
+      } catch (error) {
+        return Promise.reject(error)
+      }
     },
+    // 协议 id: 1
     queryProtocolList() {
       return this.myQuery(queryMap.protocol)
     },
+    // 机器/节点 id: 2
+    queryNodeList() {
+      return this.myQuery(queryMap.node)
+    },
+    // 服务 id: 3
+    queryServiceList() {
+      return this.myQuery(queryMap.service)
+    },
+    // 源数据 id: 4
+    querySourceList() {
+      return this.myQuery(queryMap.source)
+    },
+    // 源数据项 id: 5
+    querySourceItemList() {
+      return this.myQuery(queryMap.sourceItem)
+    },
+    // 源数据服务关联 id: 6
+    queryServiceAndSourceList() {
+      return this.myQuery(queryMap.serviceAndSource)
+    },
+    // 目标数据 id: 7
+    queryTargetList() {
+      return this.myQuery(queryMap.target)
+    },
+    // 目标数据项 id: 8
+    queryTargetItemList() {
+      return this.myQuery(queryMap.targetItem)
+    },
+    // 服务输出项关联 id: 9
+    queryServiceAndOutputList() {
+      return this.myQuery(queryMap.serviceAndOutput)
+    },
+    // 服务节点关联 id: 10
+    queryServiceAndNodeList() {
+      return this.myQuery(queryMap.targetItem)
+    },
+    // 按照ID查询服务 id: 11
+    queryServiceByID(serviceID) {
+      return this.myQuery(queryMap.serviceByID, serviceID)
+    },
+    // 按照服务ID查询节点列表 id: 12
+    queryNodeListByServiceId(serviceID) {
+      return this.myQuery(queryMap.nodeByServiceID, serviceID)
+    },
+    // 按照服务ID查询源数据列表 id: 13
     querySourceListByServiceId(serviceID) {
       return this.myQuery(queryMap.sourceByServiceID, serviceID)
     },
-    queryOutputTargetListByServiceId(serviceID) {
-      return this.myQuery(queryMap.outputTargetByServiceID, serviceID)
-    },
-    queryAll(serviceID) {
-      Promise.all([
-        this.queryService(serviceID),
-        this.queryMachineListByServiceId(serviceID),
-        this.queryProtocolList(),
-        this.querySourceListByServiceId(serviceID),
-        this.queryOutputTargetListByServiceId(serviceID)
-      ]).then(results => {
-        // const [serviceInfo, machineList, sourceList, targetList] = results
-        console.log(results)
-      }).catch(error => {
-        this.$message.error(error ?? '失败')
-      })
+    // 按照服务ID查询目标数据列表 id: 14
+    queryTargetListByServiceId(serviceID) {
+      return this.myQuery(queryMap.targetByServiceID, serviceID)
+    },
+    // 按照目标数据ID查询目标数据项列表 id: 15
+    queryTargetItemListByTargetID(targetID) {
+      return this.myQuery(queryMap.targetItemByTargetID, targetID)
+    },
+    // 按照源数据ID查询源数据项列表 id: 16
+    querySourceItemListBySourceID(sourceID) {
+      return this.myQuery(queryMap.sourceItemBySourceID, sourceID)
+    },
+    // 按照目标数据ID查询目标数据 id: 17
+    queryTargetByID(targetID) {
+      return this.myQuery(queryMap.targetByID, targetID)
+    },
+    // 按照源数据ID查询源数据 id: 18
+    querySourceBySourceID(sourceID) {
+      return this.myQuery(queryMap.sourceByID, sourceID)
+    },
+    // 按照服务ID查询算法计算方式 id: 19
+    queryAlgorithmByServiceID(serviceID) {
+      return this.myQuery(queryMap.sourceItemBySourceID, serviceID)
+    },
+    // 按照服务ID查询服务输出列表 id: 20
+    queryOutputListByServiceId(serviceID) {
+      return this.myQuery(queryMap.outputListByServiceID, serviceID)
+    },
+    async queryAll(serviceID) {
+      try {
+        const [
+          [serviceInfo],
+          nodeList,
+          checkedNodeList,
+          protocolList,
+          sourceList,
+          checkedSourceList,
+          outputList,
+          targetList
+        ] = await Promise.all([
+          this.queryServiceByID(serviceID),
+          this.queryNodeList(),
+          this.queryNodeListByServiceId(serviceID),
+          this.queryProtocolList(),
+          this.querySourceList(),
+          this.querySourceListByServiceId(serviceID),
+          this.queryOutputListByServiceId(serviceID),
+          this.queryTargetList()
+        ])
+        Object.keys(this.serviceForm).forEach(key => {
+          this.serviceForm[key] = serviceInfo[key]
+        })
+        this.nodeList = nodeList
+        this.checkedNodeKeys = checkedNodeList.map(node => node.deployNodeID)
+        this.protocolList = protocolList
+        this.sourceList = sourceList
+        this.checkedSourceKeys = checkedSourceList.map(source => source.sourceDataID)
+        this.outputList = outputList
+        this.targetList = targetList
+      } catch (error) {
+        console.log('错误', error)
+      }
     }
   }
 }

+ 260 - 260
src/views/systemSettings/views/serviceManagement/serviceEdit.vue

@@ -1,6 +1,6 @@
 <!--
  * @Date: 2022-03-24 09:55:13
- * @LastEditTime: 2022-04-28 10:33:02
+ * @LastEditTime: 2022-04-29 14:21:16
  * @LastEditors: your name
  * @Description: 服务管理-编辑服务
  * have a nice day!
@@ -18,6 +18,7 @@
                 size="small"
                 type="primary"
                 class="btn-save"
+                @click="btnSaveClickHandler"
               >保存</el-button>
             </header>
             <main class="content">
@@ -31,27 +32,27 @@
               >
                 <el-form-item
                   label="服务名称"
-                  prop="name"
+                  prop="serviceName"
                 >
                   <el-input
-                    v-model="serviceForm.name"
+                    v-model="serviceForm.serviceName"
                     width="240px"
                     placeholder="请输入服务名称"
                     clearable
                   />
                 </el-form-item>
                 <el-form-item label="是否同步">
-                  <el-radio-group v-model="serviceForm.sync">
-                    <el-radio :label="1">是</el-radio>
-                    <el-radio :label="0">否</el-radio>
+                  <el-radio-group v-model="serviceForm.isAsynchronous">
+                    <el-radio :label="0">是</el-radio>
+                    <el-radio :label="1">否</el-radio>
                   </el-radio-group>
                 </el-form-item>
                 <el-form-item
                   label="服务描述"
-                  prop="desc"
+                  prop="serviceDescribe"
                 >
                   <el-input
-                    v-model="serviceForm.desc"
+                    v-model="serviceForm.serviceDescribe"
                     placeholder="请输入描述"
                     type="textarea"
                     :autosize="{ minRows: 5, maxRows: 5 }"
@@ -75,26 +76,26 @@
                     <div class="service-edit-card">
                       <div
                         class="card-btn-add"
-                        @click="showDialog('machine')"
+                        @click="showOperateDialog('node')"
                       >
                         <i class="el-icon-plus" />
                       </div>
                     </div>
                   </el-col>
                   <el-col
-                    v-for="(machine, index) in checkedMachineList"
-                    :key="machine.id"
+                    v-for="node in checkedNodeList"
+                    :key="node.deployNodeID"
                     :span="8"
                   >
                     <div class="service-edit-card">
                       <div
                         class="card-btn-close"
-                        @click="removeItem(index, 'machine')"
+                        @click="showDeleteDialog(node, 'node')"
                       >
                         <i class="el-icon-close" />
                       </div>
                       <div class="card-header">
-                        <span>{{ machine.machineName }}</span>
+                        <span>{{ node.deployNodeName }}</span>
                       </div>
                     </div>
                   </el-col>
@@ -119,24 +120,24 @@
               >
                 <el-form-item
                   label="来源"
-                  prop="source"
+                  prop="protocolID"
                 >
-                  <el-select v-model="inputForm.source">
+                  <el-select v-model="inputForm.protocolID">
                     <el-option
-                      v-for="item in sourceOptions"
-                      :key="item.id"
-                      :value="item.value"
-                      :label="item.label"
+                      v-for="protocol in protocolList"
+                      :key="protocol.protocolID"
+                      :value="protocol.protocolID"
+                      :label="protocol.protocolName"
                     />
                   </el-select>
                 </el-form-item>
                 <el-form-item
                   label="并发线程数"
-                  prop="concurrent"
+                  prop="threads"
                   label-width="86px"
                 >
                   <el-input
-                    v-model="inputForm.concurrent"
+                    v-model="inputForm.threads"
                     width="166px"
                     placeholder="请输入并发线程数"
                     clearable
@@ -144,10 +145,10 @@
                 </el-form-item>
                 <el-form-item
                   label="来源配置"
-                  prop="config"
+                  prop="connectConfig"
                 >
                   <el-input
-                    v-model="inputForm.config"
+                    v-model="inputForm.connectConfig"
                     placeholder="请输入来源配置"
                     type="textarea"
                     :autosize="{ minRows: 4, maxRows: 4 }"
@@ -167,26 +168,26 @@
                     <div class="service-edit-card">
                       <div
                         class="card-btn-add"
-                        @click="showDialog('source')"
+                        @click="showOperateDialog('source')"
                       >
                         <i class="el-icon-plus" />
                       </div>
                     </div>
                   </el-col>
                   <el-col
-                    v-for="item in checkedSourceList"
-                    :key="item.id"
+                    v-for="source in checkedSourceList"
+                    :key="source.sourceDataID"
                     :span="8"
                   >
                     <div class="service-edit-card">
                       <div
                         class="card-btn-close"
-                        @click="removeItem(index, 'source')"
+                        @click="showDeleteDialog(source, 'source')"
                       >
                         <i class="el-icon-close" />
                       </div>
                       <div class="card-header">
-                        <span>{{ item.sourceName }}</span>
+                        <span>{{ source.dataName }}</span>
                       </div>
                     </div>
                   </el-col>
@@ -202,35 +203,40 @@
             </header>
             <main class="content">
               <div class="scrollbar">
-                <el-row :gutter="16">
-                  <el-col :span="8">
-                    <div class="service-edit-card">
-                      <div
-                        class="card-btn-add"
-                        @click="showDialog('process')"
-                      >
-                        <i class="el-icon-plus" />
-                      </div>
-                    </div>
-                  </el-col>
-                  <el-col
-                    v-for="item in checkedProcessList"
-                    :key="item.id"
-                    :span="8"
-                  >
-                    <div class="service-edit-card">
-                      <div
-                        class="card-btn-close"
-                        @click="removeItem(index, 'process')"
-                      >
-                        <i class="el-icon-close" />
+                <template v-if="processList.length">
+                  <el-row :gutter="16">
+                    <el-col :span="8">
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-add"
+                          @click="showOperateDialog('process')"
+                        >
+                          <i class="el-icon-plus" />
+                        </div>
                       </div>
-                      <div class="card-header">
-                        <span>{{ item.processName }}</span>
+                    </el-col>
+                    <el-col
+                      v-for="process in checkedProcessList"
+                      :key="process.id"
+                      :span="8"
+                    >
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-close"
+                          @click="showDeleteDialog(process, 'process')"
+                        >
+                          <i class="el-icon-close" />
+                        </div>
+                        <div class="card-header">
+                          <span>{{ process.processName }}</span>
+                        </div>
                       </div>
-                    </div>
-                  </el-col>
-                </el-row>
+                    </el-col>
+                  </el-row>
+                </template>
+                <template v-else>
+                  <NoData />
+                </template>
               </div>
             </main>
           </div>
@@ -243,37 +249,43 @@
                 size="small"
                 type="primary"
                 class="btn-white"
-                @click="showDialog('output')"
+                @click="showOperateDialog('output')"
               >新增</el-button>
             </header>
             <main class="content">
               <div class="scrollbar">
                 <el-row :gutter="16">
                   <el-col
-                    v-for="(item, index) in targetList"
-                    :key="item.id"
+                    v-for="outputTarget in outputList"
+                    :key="outputTarget.serviceOutputID"
                     :span="24"
                   >
                     <div
                       class="service-edit-card"
                       style="height: 160px"
                     >
-                      <div class="card-btn-close" @click="removeOutputTarget(index)">
+                      <div
+                        class="card-btn-close"
+                        @click="showDeleteDialog(outputTarget, 'output')"
+                      >
                         <i class="el-icon-close" />
                       </div>
                       <div class="card-header">
-                        <span>{{ item.protocolType }}</span>
-                        <i class="icon-edit" @click="btnEditClickHandler(index, 'output')" />
+                        <span>{{ outputTargetProtocolName(outputTarget.protocolID) }}</span>
+                        <i
+                          class="icon-edit"
+                          @click="btnEditClickHandler(outputTarget, 'output')"
+                        />
                       </div>
                       <div class="card-main">
                         <div class="flex">
                           <div class="left">目标配置:</div>
                           <div
                             class="multiple-ellipsis"
-                            :title="item.protocolConfig"
-                          >{{ item.protocolConfig }}</div>
+                            :title="outputTarget.dataOutputConfig"
+                          >{{ outputTarget.dataOutputConfig }}</div>
                         </div>
-                        <span>{{ item.targetData }}</span>
+                        <span>{{ outputTargetDataName(outputTarget.targetdataID) }}</span>
                       </div>
                     </div>
                   </el-col>
@@ -285,19 +297,19 @@
       </el-row>
     </div>
     <Dialog
-      :flag="dialogVisible"
+      :flag="operateDialogVisible"
       width="500px"
     >
-      <template v-if="['machine', 'source', 'process'].includes(dialogContentType)">
+      <template v-if="['node', 'source', 'process'].includes(operateDialogType)">
         <div class="dialog-checkbox">
-          <div class="title">{{ getDataInMap(dialogContentType, 'title') }}</div>
+          <div class="title">{{ dataInMap(operateDialogType, 'title') }}</div>
           <main class="content">
             <el-checkbox-group v-model="tempCheckedKeys">
               <el-checkbox
-                v-for="item in getDataInMap(dialogContentType, 'list')"
-                :key="item.id"
-                :label="item[getDataInMap(dialogContentType, 'label')]"
-              />
+                v-for="item in dataInMap(operateDialogType, 'list')"
+                :key="item[dataInMap(operateDialogType, 'key')]"
+                :label="item[dataInMap(operateDialogType, 'key')]"
+              >{{ item[dataInMap(operateDialogType, 'label')] }}</el-checkbox>
             </el-checkbox-group>
           </main>
           <div class="foot">
@@ -305,17 +317,17 @@
               size="medium"
               type="primary"
               class="r25 r26"
-              @click="checkedSubmitHandler(dialogContentType)"
+              @click="checkedSubmitHandler"
             >提交</el-button>
             <el-button
               size="medium"
               class="r26"
-              @click="closeDialog"
+              @click="hideOperateDialog"
             >取消</el-button>
           </div>
         </div>
       </template>
-      <template v-if="dialogContentType === 'output'">
+      <template v-if="operateDialogType === 'output'">
         <div id="dialog-form">
           <div class="title">数据输出编辑</div>
           <main class="content">
@@ -329,23 +341,23 @@
             >
               <el-form-item
                 label="协议类型"
-                prop="protocolType"
+                prop="protocolID"
               >
-                <el-select v-model="outputForm.protocolType">
+                <el-select v-model="outputForm.protocolID">
                   <el-option
-                    v-for="item in protocolTypeOptions"
-                    :key="item.id"
-                    :value="item.value"
-                    :label="item.label"
+                    v-for="item in protocolList"
+                    :key="item.protocolID"
+                    :value="item.protocolID"
+                    :label="item.protocolName"
                   />
                 </el-select>
               </el-form-item>
               <el-form-item
                 label="协议配置"
-                prop="protocolConfig"
+                prop="dataOutputConfig"
               >
                 <el-input
-                  v-model="outputForm.protocolConfig"
+                  v-model="outputForm.dataOutputConfig"
                   type="textarea"
                   placeholder="请输入协议配置"
                   :autosize="{ minRows: 4, maxRows: 4 }"
@@ -355,14 +367,14 @@
               </el-form-item>
               <el-form-item
                 label="目标数据"
-                prop="targetData"
+                prop="targetdataID"
               >
-                <el-select v-model="outputForm.targetData">
+                <el-select v-model="outputForm.targetdataID">
                   <el-option
-                    v-for="item in targetDataOptions"
-                    :key="item.id"
-                    :value="item.value"
-                    :label="item.label"
+                    v-for="item in targetList"
+                    :key="item.targetdataID"
+                    :value="item.targetdataID"
+                    :label="item.tdataName"
                   />
                 </el-select>
               </el-form-item>
@@ -391,238 +403,223 @@
             <el-button
               size="medium"
               class="r26"
-              @click="closeDialog"
+              @click="hideOperateDialog"
             >取消</el-button>
           </div>
         </div>
       </template>
     </Dialog>
+    <!--删除弹框-->
+    <Dialog :flag="deleteDialogVisible">
+      <div class="dialog-delete">
+        <div class="del-title">删除{{ dataInMap(deleteDialogType, 'deleteTitle') }}</div>
+        <div class="content er">
+          <div class="log">
+            你是否确认删除{{ delObj[dataInMap(deleteDialogType, 'label')] || '这一项' }}?
+          </div>
+        </div>
+        <div class="del-foot right t30">
+          <el-button
+            size="medium"
+            class="r25 r26"
+            type="danger"
+            @click="deleteSubmitHandler"
+          >删除</el-button>
+          <el-button
+            size="medium"
+            class="r26"
+            @click="hideDeleteDialog"
+          >取消</el-button>
+        </div>
+      </div>
+    </Dialog>
   </div>
 </template>
 
 <script>
+import NoData from '@/components/nodata'
 import Dialog from '@/layout/components/Dialog'
 import query from './mixins/query'
+import operate from './mixins/operate'
 
 const keyMap = {
-  machine: {
+  node: {
     title: '部署机器选择',
-    list: 'machineList',
-    checked: 'checkedMachineKeys',
-    label: 'machineName'
+    deleteTitle: '机器',
+    key: 'deployNodeID',
+    label: 'deployNodeName',
+    list: 'nodeList',
+    checked: 'checkedNodeKeys',
+    operate: 'updateServiceNode'
   },
   source: {
     title: '源数据',
+    deleteTitle: '源数据',
+    key: 'sourceDataID',
+    label: 'dataName',
     list: 'sourceList',
     checked: 'checkedSourceKeys',
-    label: 'sourceName'
+    operate: 'updateServiceSource'
   },
   process: {
     title: '数据处理',
+    deleteTitle: '数据处理流程',
+    key: 'processID',
+    label: 'processName',
     list: 'processList',
     checked: 'checkedProcessKeys',
-    label: 'processName'
+    operate: 'updateServiceProcess'
+  },
+  output: {
+    deleteTitle: '输出目标',
+    key: 'serviceOutputID',
+    list: 'outputList',
+    operate: 'updateServiceOutput'
   }
 }
 
 export default {
-  components: { Dialog },
-  mixins: [query],
+  components: { NoData, Dialog },
+  mixins: [query, operate],
   data() {
     return {
       serviceID: this.$route.query.serviceID,
-      dialogContentType: null,
+      operateDialogType: null,
+      delObj: {},
+      deleteDialogType: null,
       tempCheckedKeys: [],
       serviceForm: {
-        name: '',
-        sync: 1,
-        desc: ''
+        serviceName: '',
+        isAsynchronous: null,
+        serviceDescribe: ''
       },
       inputForm: {
-        source: '',
-        concurrent: null,
-        config: ''
+        protocolID: null,
+        threads: null,
+        connectConfig: ''
       },
       outputForm: {
-        protocolType: null,
-        protocolConfig: '',
-        targetData: null,
+        protocolID: null,
+        dataOutputConfig: '',
+        targetdataID: null,
         outputCondition: ''
       },
-      protocolTypeOptions: [
-        {
-          id: 0,
-          value: 'Kafka',
-          label: 'Kafka'
-        },
-        {
-          id: 1,
-          value: 'Mysql',
-          label: 'Mysql'
-        }
-      ],
-      targetDataOptions: [
-        {
-          id: 0,
-          value: 'BSM报文',
-          label: 'BSM报文'
-        },
-        {
-          id: 1,
-          value: 'BSM解析结果',
-          label: 'BSM解析结果'
-        },
-        {
-          id: 2,
-          value: '行李基础数据',
-          label: '行李基础数据'
-        }
-      ],
-      sourceOptions: [
-        {
-          id: 0,
-          value: 0,
-          label: '来源1'
-        },
-        {
-          id: 1,
-          value: 1,
-          label: '来源2'
-        }
-      ],
-      machineList: [
-        {
-          id: 0,
-          machineName: '主动采集服务器'
-        },
-        {
-          id: 1,
-          machineName: '备用采集服务器'
-        },
-        {
-          id: 2,
-          machineName: '解析服务器'
-        },
-        {
-          id: 3,
-          machineName: '存储服务器'
-        }
-      ],
-      checkedMachineKeys: [],
-      sourceList: [
-        {
-          id: 0,
-          sourceName: 'BSM',
-          desc: '行李源报文'
-        },
-        {
-          id: 1,
-          sourceName: 'BPM',
-          desc: '行李处理报文'
-        }
-      ],
+      targetList: [],
+      protocolList: [],
+      nodeList: [],
+      checkedNodeKeys: [],
+      sourceList: [],
       checkedSourceKeys: [],
-      processList: [
-        {
-          id: 0,
-          processName: '数据包合法性检测'
-        },
-        {
-          id: 1,
-          processName: '数据解析'
-        }
-      ],
+      processList: [],
       checkedProcessKeys: [],
-      targetList: [
-        {
-          id: 0,
-          protocolType: 'Kafka',
-          protocolConfig:
-            '"bootstrap.servers": "192.168.3.74:9092","key.serializer": "org.apache.kafka.common.serialization.StringSerializer","value.serializerXXXXXXXXXXXXXXXXXXXXXXX',
-          targetData: 'BSM报文',
-          outputCondition: ''
-        },
-        {
-          id: 1,
-          protocolType: 'Kafka',
-          protocolConfig:
-            '"bootstrap.servers": "192.168.3.74:9092","key.serializer": "org.apache.kafka.common.serialization.StringSerializer","value.serializerXXXXXXXXXXXXXXXXXXXXXXX',
-          targetData: 'BSM解析结果',
-          outputCondition: ''
-        },
-        {
-          id: 2,
-          protocolType: 'Mysql',
-          protocolConfig:
-            '"bootstrap.servers": "192.168.3.74:9092","key.serializer": "org.apache.kafka.common.serialization.StringSerializer","value.serializerXXXXXXXXXXXXXXXXXXXXXXX',
-          targetData: '行李基础数据',
-          outputCondition: ''
-        }
-      ]
+      outputList: []
     }
   },
   computed: {
-    dialogVisible() {
-      return Boolean(this.dialogContentType)
+    dataInMap() {
+      return function (type, keyType) {
+        if (type === null) {
+          return null
+        }
+        if (['title', 'deleteTitle', 'key', 'label'].includes(keyType)) {
+          return keyMap[type][keyType]
+        } else {
+          return this[keyMap[type][keyType]]
+        }
+      }
+    },
+    operateDialogVisible() {
+      return Boolean(this.operateDialogType)
     },
-    checkedMachineList() {
-      return this.machineList.filter(item => this.checkedMachineKeys.includes(item.machineName))
+    deleteDialogVisible() {
+      return Boolean(this.deleteDialogType)
+    },
+    checkedNodeList() {
+      return this.nodeList.filter(item => this.checkedNodeKeys.includes(item.deployNodeID))
     },
     checkedSourceList() {
-      return this.sourceList.filter(item => this.checkedSourceKeys.includes(item.sourceName))
+      return this.sourceList.filter(item => this.checkedSourceKeys.includes(item.sourceDataID))
     },
     checkedProcessList() {
       return this.processList.filter(item => this.checkedProcessKeys.includes(item.processName))
+    },
+    outputTargetProtocolName() {
+      return function (protocolID) {
+        return this.protocolList.find(protocol => protocol.protocolID === protocolID).protocolName
+      }
+    },
+    outputTargetDataName() {
+      return function (targetdataID) {
+        return this.targetList.find(target => target.targetdataID === targetdataID).tdataName
+      }
     }
   },
   methods: {
-    getDataInMap(type, keyType) {
-      if (['title', 'label'].includes(keyType)) {
-        return keyMap[type][keyType]
-      } else {
-        return this[keyMap[type][keyType]]
-      }
+    async btnSaveClickHandler() {
+      this.$refs['serviceForm'].validate(valid => {
+        if (!valid) return
+      })
+      this.$refs['inputForm'].validate(valid => {
+        if (!valid) return
+      })
+      await this.updateService()
+      this.queryAll()
     },
-    showDialog(type) {
-      if (Object.keys(keyMap).includes(type)) {
-        this.tempCheckedKeys = [...this[keyMap[type]['checked']]]
+    showOperateDialog(type) {
+      if (['node', 'source', 'process'].includes(type)) {
+        this.tempCheckedKeys = [...this.dataInMap(type, 'checked')]
       }
-      this.dialogContentType = type
+      this.operateDialogType = type
     },
-    btnEditClickHandler(index, type) {
-      if (type === 'output') {
-        Object.entries(this.targetList[index]).forEach(arr => {
-          const [key, value] = arr
-          this.outputForm[key] = value
-        })
-      }
-      this.showDialog(type)
+    btnEditClickHandler(obj, type) {
+      Object.entries(obj).forEach(arr => {
+        const [key, value] = arr
+        this.outputForm[key] = value
+      })
+      this.showOperateDialog(type)
     },
-    checkedSubmitHandler() {
-      this[keyMap[this.dialogContentType]['checked']] = [...this.tempCheckedKeys]
-      this.closeDialog()
+    async checkedSubmitHandler() {
+      const addKeys = this.tempCheckedKeys.filter(
+        key => !this.dataInMap(this.operateDialogType, 'checked').includes(key)
+      )
+      const removeKeys = this.dataInMap(this.operateDialogType, 'checked').filter(
+        key => !this.tempCheckedKeys.includes(key)
+      )
+      const createArr = addKeys.map(key => this.dataInMap(this.operateDialogType, 'operate')('create', key))
+      const deleteArr = removeKeys.map(key => this.dataInMap(this.operateDialogType, 'operate')('delete', key))
+      try {
+        await Promise.all([...createArr, ...deleteArr])
+        this.$message.success('成功')
+        this.queryAll()
+        this.hideOperateDialog()
+      } catch (error) {
+        this.$message.error(error)
+      }
     },
-    outputSubmitHandler() {
-      const target = {
+    async outputSubmitHandler() {
+      const outputTarget = {
         ...this.outputForm
       }
-      if (typeof target.id === 'undefined') {
-        target.id = this.targetList.at(-1).id + 1
-        this.targetList.push(target)
+      if (outputTarget.serviceOutputID) {
+        await this.updateServiceOutput('update', outputTarget)
       } else {
-        const index = this.targetList.findIndex(element => element.id === target.id)
-        this.targetList[index] = target
+        await this.updateServiceOutput('create', outputTarget)
       }
-      this.closeDialog()
+      this.queryAll()
+      this.hideOperateDialog()
     },
-    closeDialog() {
-      this.dialogContentType = null
+    hideOperateDialog() {
+      this.operateDialogType = null
     },
-    removeItem(index, type) {
-      this[keyMap[type]['checked']].splice(index, 1)
+    showDeleteDialog(obj, type) {
+      this.delObj = obj
+      this.deleteDialogType = type
     },
-    removeOutputTarget(index) {
-      this.targetList.splice(index, 1)
+    deleteSubmitHandler() {
+      this.dataInMap(this.deleteDialogType, 'operate')('delete', this.delObj)
+    },
+    hideDeleteDialog() {
+      this.deleteDialogType = null
     }
   }
 }
@@ -706,7 +703,7 @@ export default {
           height: calc(100% - 32px - 24px);
         }
         &.second-content {
-          height: calc(100% - 297px)
+          height: calc(100% - 297px);
         }
         > .scrollbar {
           margin: -12px -24px 0 0;
@@ -846,10 +843,13 @@ export default {
   .dialog-checkbox {
     .content {
       margin-left: 16px;
-      .el-checkbox {
-        margin-bottom: 24px;
-        font-family: Helvetica, Microsoft YaHei;
-        color: #303133;
+      .el-checkbox-group {
+        margin-right: 24px;
+        .el-checkbox {
+          margin-bottom: 24px;
+          font-family: Helvetica, Microsoft YaHei;
+          color: #303133;
+        }
       }
     }
   }

+ 148 - 78
src/views/systemSettings/views/serviceManagement/serviceHome.vue

@@ -1,6 +1,6 @@
 <!--
  * @Date: 2022-04-12 17:49:47
- * @LastEditTime: 2022-04-28 11:17:01
+ * @LastEditTime: 2022-04-28 15:14:53
  * @LastEditors: your name
  * @Description: 服务管理-首页
  * have a nice day!
@@ -11,18 +11,18 @@
     <div class="wrap">
       <div class="service-header flex">
         <div class="manageTitle">服务管理</div>
-        <div class="addBtn">
+        <div class="btn-create">
           <el-button
-            class="button-white"
+            class="btn-white"
             size="small"
-            @click="btnAddClickHandler"
+            @click="showCreateDialog"
           >新增</el-button>
         </div>
       </div>
       <div class="service-content">
         <el-row :gutter="24">
           <el-col
-            v-for="item in dataList"
+            v-for="item in serviceList"
             :key="item.serviceID"
             :span="4"
           >
@@ -45,7 +45,7 @@
                 </div>
                 <i
                   class="el-icon-close icon"
-                  @click="showRemoveDialog(item)"
+                  @click="showDeleteDialog(item)"
                 />
               </div>
             </div>
@@ -53,12 +53,12 @@
         </el-row>
       </div>
       <!--删除弹框-->
-      <Dialog :flag="removeDialogVisible">
+      <Dialog :flag="deleteDialogVisible">
         <div class="dialog-delete">
           <div class="del-title">删除服务</div>
           <div class="content er">
             <div class="log">
-              你是否确认删除{{ rmObj.serviceName }}?
+              你是否确认删除{{ delObj.serviceName }}?
             </div>
           </div>
           <div class="del-foot right t30">
@@ -66,29 +66,30 @@
               size="medium"
               class="r25 r26"
               type="danger"
-              @click="removeSubmit()"
+              @click="deleteSubmitHandler"
             >删除</el-button>
             <el-button
               size="medium"
               class="r26"
-              @click="removeDialogVisible = false"
+              @click="hideDeleteDialog"
             >取消</el-button>
           </div>
         </div>
       </Dialog>
       <Dialog
-        :flag="addDialogVisible"
+        :flag="createDialogVisible"
         width="600px"
       >
-        <div class="dialog-add">
+        <div class="dialog-create">
           <div class="title">新增服务</div>
           <main class="content">
             <el-form
-              ref="addForm"
-              class="add-form"
-              :model="addForm"
+              ref="createForm"
+              class="create-form"
+              :model="createForm"
+              :rules="createFormRules"
               label-position="right"
-              label-width="72px"
+              label-width="82px"
               size="mini"
             >
               <el-form-item
@@ -96,17 +97,17 @@
                 prop="serviceName"
               >
                 <el-input
-                  v-model="addForm.serviceName"
+                  v-model="createForm.serviceName"
                   placeholder="请输入服务名称"
                   clearable
                 />
               </el-form-item>
               <el-form-item
                 label="描述"
-                prop="desc"
+                prop="serviceDescribe"
               >
                 <el-input
-                  v-model="addForm.desc"
+                  v-model="createForm.serviceDescribe"
                   placeholder="请输入描述"
                   type="textarea"
                   :autosize="{ minRows: 4, maxRows: 4 }"
@@ -115,42 +116,44 @@
                 />
               </el-form-item>
               <el-form-item label="是否同步">
-                <el-radio-group v-model="addForm.sync">
-                  <el-radio :label="1">是</el-radio>
-                  <el-radio :label="0">否</el-radio>
+                <el-radio-group v-model="createForm.isAsynchronous">
+                  <el-radio :label="0">是</el-radio>
+                  <el-radio :label="1">否</el-radio>
                 </el-radio-group>
               </el-form-item>
               <el-form-item
                 label="来源"
-                prop="source"
+                prop="protocolID"
               >
-                <el-select v-model="addForm.source">
+                <el-select
+                  v-model="createForm.protocolID"
+                  placeholder="请选择来源"
+                >
                   <el-option
-                    v-for="item in sourceOptions"
-                    :key="item.id"
-                    :value="item.value"
-                    :label="item.label"
+                    v-for="item in protocolList"
+                    :key="item.protocolID"
+                    :value="item.protocolID"
+                    :label="item.protocolName"
                   />
                 </el-select>
               </el-form-item>
               <el-form-item
                 label="并发线程数"
                 prop="threads"
-                label-width="86px"
+                label-width="96px"
               >
                 <el-input
-                  v-model="addForm.threads"
-                  width="180px"
+                  v-model="createForm.threads"
                   placeholder="请输入并发线程数"
                   clearable
                 />
               </el-form-item>
               <el-form-item
                 label="来源配置"
-                prop="config"
+                prop="connectConfig"
               >
                 <el-input
-                  v-model="addForm.sourceConfig"
+                  v-model="createForm.connectConfig"
                   placeholder="请输入来源配置"
                   type="textarea"
                   :autosize="{ minRows: 4, maxRows: 4 }"
@@ -165,12 +168,12 @@
               size="medium"
               type="primary"
               class="r25 r26"
-              @click="addSubmitHandler"
+              @click="createSubmitHandler"
             >提交</el-button>
             <el-button
               size="medium"
               class="r26"
-              @click="addDialogClose"
+              @click="hideCreateDialog"
             >取消</el-button>
           </div>
         </div>
@@ -181,40 +184,84 @@
 
 <script>
 import Dialog from '@/layout/components/Dialog/index.vue'
-import { Query } from '@/api/dataIntegration'
+import { GeneralDataReception, Query } from '@/api/dataIntegration'
+import { regular } from '@/utils/validate'
 
 export default {
   name: 'ProtocolHome',
   components: { Dialog },
   data() {
     return {
-      dataList: [],
-      addDialogVisible: false,
-      addForm: {
+      serviceList: [],
+      createDialogVisible: false,
+      createForm: {
         serviceName: '',
-        desc: '',
-        sync: 1,
-        source: '',
+        serviceDescribe: '',
+        isAsynchronous: 0,
+        protocolID: '',
         threads: '',
-        sourceConfig: ''
+        connectConfig: ''
       },
-      sourceOptions: [],
-      removeDialogVisible: false,
-      rmObj: {}
+      createFormRules: {
+        serviceName: [{ required: true, message: '请输入服务名称', trigger: 'blur' }],
+        protocolID: [{ required: true, message: '请选择来源', trigger: 'blur' }],
+        threads: [
+          { required: true, message: '请输入并发线程数', trigger: 'blur' },
+          { pattern: regular.positiveInteger, message: '请输入正整数', trigger: ['blur', 'change'] }
+        ]
+      },
+      protocolList: [],
+      deleteDialogVisible: false,
+      delObj: {}
     }
   },
   mounted() {
-    this.getList()
+    this.getServiceList()
   },
   methods: {
-    async getList() {
+    // 新增-弹框
+    showCreateDialog() {
+      this.getProtocolList()
+      this.createDialogVisible = true
+    },
+    // 新增-提交
+    createSubmitHandler() {
+      this.$refs['createForm'].validate(valid => {
+        if (valid) {
+          this.createService()
+        }
+      })
+    },
+    // 新增-关闭
+    hideCreateDialog() {
+      this.$refs['createForm'].resetFields()
+      this.createDialogVisible = false
+    },
+    // 编辑-跳转
+    btnEditClickHandler(item) {
+      this.$router.push({ path: '/systemSettings/serviceEdit', query: { serviceID: item.serviceID } })
+    },
+    // 删除-弹框
+    showDeleteDialog(item) {
+      this.delObj = item
+      this.deleteDialogVisible = true
+    },
+    // 删除-提交
+    deleteSubmitHandler() {
+      this.deleteService()
+    },
+    // 删除-关闭
+    hideDeleteDialog() {
+      this.deleteDialogVisible = false
+    },
+    async getServiceList() {
       try {
         const res = await Query({
           id: 3,
           dataContent: []
         })
-        if (res.code === '0') {
-          this.dataList = res.returnData
+        if (Number(res.code) === 0) {
+          this.serviceList = res.returnData
         } else {
           this.$message.error(res.message ?? '失败')
         }
@@ -222,33 +269,56 @@ export default {
         console.log('错误', error)
       }
     },
-    // 新增-弹框
-    btnAddClickHandler() {
-      this.addDialogVisible = true
-    },
-    // 新增-提交
-    addSubmitHandler() {
-      this.addDialogClose()
-    },
-    // 新增-关闭
-    addDialogClose() {
-      this.$refs['addForm'].resetFields()
-      this.addDialogVisible = false
-    },
-    // 编辑-跳转
-    btnEditClickHandler(item) {
-      const { serviceID } = item
-      this.$router.push({ path: '/systemSettings/serviceEdit', query: { serviceID } })
+    async getProtocolList() {
+      try {
+        const res = await Query({
+          id: 1,
+          dataContent: []
+        })
+        if (Number(res.code) === 0) {
+          this.protocolList = res.returnData
+        } else {
+          this.$message.error(res.message ?? '失败')
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
     },
-    // 删除-弹框
-    showRemoveDialog(item) {
-      this.rmObj = item
-      this.removeDialogVisible = true
+    async createService() {
+      try {
+        this.createForm['operate'] = 1
+        const res = await GeneralDataReception({
+          serviceId: 3,
+          dataContent: JSON.stringify(this.createForm)
+        })
+        if (Number(res.code) === 0) {
+          this.$message.success(res.message ?? '成功')
+          this.hideCreateDialog()
+          this.getServiceList()
+        } else {
+          this.$message.error(res.message ?? '失败')
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
     },
-    // 确认删除
-    removeSubmit() {
-      this.removeDialogVisible = false
-      this.$message.success('删除成功')
+    async deleteService() {
+      try {
+        this.delObj['operate'] = 3
+        const res = await GeneralDataReception({
+          serviceId: 3,
+          dataContent: JSON.stringify(this.delObj)
+        })
+        if (Number(res.code) === 0) {
+          this.$message.success(res.message ?? '成功')
+          this.hideDeleteDialog()
+          this.getServiceList()
+        } else {
+          this.$message.error(res.message ?? '失败')
+        }
+      } catch (error) {
+        console.log('错误', error)
+      }
     }
   }
 }
@@ -261,7 +331,7 @@ export default {
     .service-header {
       line-height: 32px;
       font-size: 14px;
-      .button-white {
+      .btn-white {
         border: 1px solid #9ebbf7;
         background: #f5f7fa;
         -webkit-box-shadow: 0px 6px 7px 0px rgb(0 0 0 / 6%);
@@ -318,8 +388,8 @@ export default {
         }
       }
     }
-    .dialog-add {
-      ::v-deep .add-form {
+    .dialog-create {
+      ::v-deep .create-form {
         display: flex;
         flex-wrap: wrap;
         > .el-form-item {