zhongxiaoyu 2 жил өмнө
parent
commit
3f98dfe8d0

+ 15 - 4
src/components/Table/index.vue

@@ -1,11 +1,11 @@
 <template>
-  <div class="data-table">
+  <div class="data-table" :style="{ marginTop: marginTop }">
     <div :style="{ 'min-height': minHeight + 'vh' }" v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" class="data-table-content">
       <div v-if="isBtn" class="data-table-btn flex-end">
         <el-button size="small" @click="handleAdd" plain type="primary">新增</el-button>
       </div>
       <template v-if="tableData.length">
-        <el-table :data="filteredTableData" :summary-method="getSummaries" :span-method="tableSpanMethod" stripe show-summary border ref="table" :height="minHeight - 8 + 'vh'" class="table" style="width: 100%; overflow: auto">
+        <el-table :data="filteredTableData" :summary-method="getSummaries" :span-method="tableSpanMethod" stripe :show-summary="showSummary" border ref="table" :height="minHeight - 8 + 'vh'" class="table" style="width: 100%; overflow: auto">
           <el-table-column v-for="(item, index) in tableColsCopy" :sortable="item.needSort ? true : false" :key="index" :prop="item.columnName" :label="item.columnLabel">
             <template #header>
               <span class="colTips">
@@ -138,6 +138,15 @@ export default {
       type: Boolean,
       default: true,
     },
+    // 是否显示合计行
+    showSummary: {
+      type: Boolean,
+      default: false
+    },
+    marginTop: {
+      type: String,
+      default: '20px'
+    }
   },
   components: { Dialog, NoData },
   data () {
@@ -212,6 +221,9 @@ export default {
   created () {
     this.getQuery();
   },
+  updated() {
+    this.$refs['table'].doLayout()
+  },
   methods: {
     changeSelect(data){
       this.tableForm[this.tableOptions[data][0].setvalue] = this.tableForm[data];
@@ -451,7 +463,7 @@ export default {
     //表格-删除
     handleRemove (row) {
       this.rmFlag = true;
-      this.rmTitle = row.className || row.username;
+      this.rmTitle = row.className || row.username || row.serviceName;
       this.tableObj = row;
     },
     //表格-删除-确认
@@ -468,7 +480,6 @@ export default {
   width: 100%;
   background-color: #fff;
   padding: 20px;
-  margin-top: 20px;
   ::v-deep .table {
     width: 100%;
     .cell {

+ 899 - 0
src/views/systemSettings/views/serviceManagement/serviceEdit copy.vue

@@ -0,0 +1,899 @@
+<!--
+ * @Date: 2022-03-24 09:55:13
+ * @LastEditTime: 2022-05-16 09:55:51
+ * @LastEditors: your name
+ * @Description: 服务管理-编辑服务
+ * have a nice day!
+-->
+
+<template>
+  <div class="service-edit">
+    <div class="scrollbar">
+      <el-row :gutter="24">
+        <el-col :span="16">
+          <div class="part part-top">
+            <header class="title">
+              <p class="manageTitle">服务</p>
+              <el-button
+                size="small"
+                type="primary"
+                class="btn-save"
+                @click="btnSaveClickHandler"
+              >保存</el-button>
+            </header>
+            <main class="content">
+              <el-form
+                ref="serviceForm"
+                class="service-form"
+                :model="serviceForm"
+                label-position="right"
+                label-width="72px"
+                size="mini"
+              >
+                <el-form-item
+                  label="服务名称"
+                  prop="serviceName"
+                >
+                  <el-input
+                    v-model="serviceForm.serviceName"
+                    width="240px"
+                    placeholder="请输入服务名称"
+                    clearable
+                  />
+                </el-form-item>
+                <el-form-item label="是否同步">
+                  <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="serviceDescribe"
+                >
+                  <el-input
+                    v-model="serviceForm.serviceDescribe"
+                    placeholder="请输入描述"
+                    type="textarea"
+                    :autosize="{ minRows: 5, maxRows: 5 }"
+                    resize="none"
+                    clearable
+                  />
+                </el-form-item>
+              </el-form>
+            </main>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="part part-top">
+            <header class="title">
+              <p class="manageTitle">部署机器</p>
+            </header>
+            <main class="content">
+              <div class="scrollbar">
+                <template v-if="nodeList.length">
+                  <el-row :gutter="16">
+                    <el-col :span="8">
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-add"
+                          @click="showOperateDialog('node')"
+                        >
+                          <i class="el-icon-plus" />
+                        </div>
+                      </div>
+                    </el-col>
+                    <el-col
+                      v-for="node in checkedNodeList"
+                      :key="node.deployNodeID"
+                      :span="8"
+                    >
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-close"
+                          @click="showDeleteDialog(node, 'node')"
+                        >
+                          <i class="el-icon-close" />
+                        </div>
+                        <div class="card-header">
+                          <span>{{ node.deployNodeName }}</span>
+                        </div>
+                      </div>
+                    </el-col>
+                  </el-row>
+                </template>
+                <template v-else>
+                  <NoData />
+                </template>
+              </div>
+            </main>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="part">
+            <header class="title">
+              <p class="manageTitle">输入</p>
+            </header>
+            <main class="content first-content">
+              <el-form
+                ref="inputForm"
+                class="input-form"
+                :model="inputForm"
+                label-position="right"
+                label-width="72px"
+                size="mini"
+              >
+                <el-form-item
+                  label="来源"
+                  prop="protocolID"
+                >
+                  <el-select v-model="inputForm.protocolID">
+                    <el-option
+                      v-for="protocol in protocolList"
+                      :key="protocol.protocolID"
+                      :value="protocol.protocolID"
+                      :label="protocol.protocolName"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item
+                  label="并发线程数"
+                  prop="threads"
+                  label-width="86px"
+                >
+                  <el-input
+                    v-model="inputForm.threads"
+                    width="166px"
+                    placeholder="请输入并发线程数"
+                    clearable
+                  />
+                </el-form-item>
+                <el-form-item
+                  label="来源配置"
+                  prop="connectConfig"
+                >
+                  <el-input
+                    v-model="inputForm.connectConfig"
+                    placeholder="请输入来源配置"
+                    type="textarea"
+                    :autosize="{ minRows: 4, maxRows: 4 }"
+                    resize="none"
+                    clearable
+                  />
+                </el-form-item>
+              </el-form>
+            </main>
+            <header class="title">
+              <p class="manageTitle">源数据</p>
+            </header>
+            <main class="content second-content">
+              <div class="scrollbar">
+                <template v-if="sourceList.length">
+                  <el-row :gutter="16">
+                    <el-col :span="8">
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-add"
+                          @click="showOperateDialog('source')"
+                        >
+                          <i class="el-icon-plus" />
+                        </div>
+                      </div>
+                    </el-col>
+                    <el-col
+                      v-for="source in checkedSourceList"
+                      :key="source.sourceDataID"
+                      :span="8"
+                    >
+                      <div class="service-edit-card">
+                        <div
+                          class="card-btn-close"
+                          @click="showDeleteDialog(source, 'source')"
+                        >
+                          <i class="el-icon-close" />
+                        </div>
+                        <div class="card-header">
+                          <span>{{ source.dataName }}</span>
+                        </div>
+                      </div>
+                    </el-col>
+                  </el-row>
+                </template>
+                <template v-else>
+                  <NoData />
+                </template>
+              </div>
+            </main>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="part">
+            <header class="title">
+              <p class="manageTitle">数据处理</p>
+            </header>
+            <main class="content">
+              <div class="scrollbar">
+                <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>
+                    </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>
+                    </el-col>
+                  </el-row>
+                </template>
+                <template v-else>
+                  <NoData />
+                </template>
+              </div>
+            </main>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="part">
+            <header class="title">
+              <p class="manageTitle">数据输出</p>
+              <el-button
+                size="small"
+                type="primary"
+                class="btn-white"
+                @click="showOperateDialog('output')"
+              >新增</el-button>
+            </header>
+            <main class="content">
+              <div class="scrollbar">
+                <el-row :gutter="16">
+                  <el-col
+                    v-for="outputTarget in outputList"
+                    :key="outputTarget.serviceOutputID"
+                    :span="24"
+                  >
+                    <div
+                      class="service-edit-card"
+                      style="height: 160px"
+                    >
+                      <div
+                        class="card-btn-close"
+                        @click="showDeleteDialog(outputTarget, 'output')"
+                      >
+                        <i class="el-icon-close" />
+                      </div>
+                      <div class="card-header">
+                        <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="outputTarget.dataOutputConfig"
+                          >{{ outputTarget.dataOutputConfig }}</div>
+                        </div>
+                        <span>{{ outputTargetDataName(outputTarget.targetdataID) }}</span>
+                      </div>
+                    </div>
+                  </el-col>
+                </el-row>
+              </div>
+            </main>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+    <Dialog
+      :flag="operateDialogVisible"
+      width="500px"
+    >
+      <template v-if="['node', 'source', 'process'].includes(operateDialogType)">
+        <div class="dialog-checkbox">
+          <div class="title">{{ dataInMap(operateDialogType, 'title') }}</div>
+          <main class="content">
+            <el-checkbox-group v-model="tempCheckedKeys">
+              <el-checkbox
+                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">
+            <el-button
+              size="medium"
+              type="primary"
+              class="r25 r26"
+              @click="checkedSubmitHandler"
+            >提交</el-button>
+            <el-button
+              size="medium"
+              class="r26"
+              @click="hideOperateDialog"
+            >取消</el-button>
+          </div>
+        </div>
+      </template>
+      <template v-if="operateDialogType === 'output'">
+        <div id="dialog-form">
+          <div class="title">数据输出编辑</div>
+          <main class="content">
+            <el-form
+              ref="outputForm"
+              class="output-form"
+              :model="outputForm"
+              label-position="right"
+              label-width="72px"
+              size="mini"
+            >
+              <el-form-item
+                label="协议类型"
+                prop="protocolID"
+              >
+                <el-select v-model="outputForm.protocolID">
+                  <el-option
+                    v-for="item in protocolList"
+                    :key="item.protocolID"
+                    :value="item.protocolID"
+                    :label="item.protocolName"
+                  />
+                </el-select>
+              </el-form-item>
+              <el-form-item
+                label="协议配置"
+                prop="dataOutputConfig"
+              >
+                <el-input
+                  v-model="outputForm.dataOutputConfig"
+                  type="textarea"
+                  placeholder="请输入协议配置"
+                  :autosize="{ minRows: 4, maxRows: 4 }"
+                  resize="none"
+                  clearable
+                />
+              </el-form-item>
+              <el-form-item
+                label="目标数据"
+                prop="targetdataID"
+              >
+                <el-select v-model="outputForm.targetdataID">
+                  <el-option
+                    v-for="item in targetList"
+                    :key="item.targetdataID"
+                    :value="item.targetdataID"
+                    :label="item.tdataName"
+                  />
+                </el-select>
+              </el-form-item>
+              <el-form-item
+                label="输出条件"
+                prop="outputCondition"
+              >
+                <el-input
+                  v-model="outputForm.outputCondition"
+                  type="textarea"
+                  placeholder="请输入输出条件"
+                  :autosize="{ minRows: 4, maxRows: 4 }"
+                  resize="none"
+                  clearable
+                />
+              </el-form-item>
+            </el-form>
+          </main>
+          <div class="foot">
+            <el-button
+              size="medium"
+              type="primary"
+              class="r25 r26"
+              @click="outputSubmitHandler"
+            >提交</el-button>
+            <el-button
+              size="medium"
+              class="r26"
+              @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 = {
+  node: {
+    title: '部署机器选择',
+    deleteTitle: '机器',
+    key: 'deployNodeID',
+    label: 'deployNodeName',
+    list: 'nodeList',
+    checked: 'checkedNodeKeys',
+    operate: 'updateServiceNode'
+  },
+  source: {
+    title: '源数据',
+    deleteTitle: '源数据',
+    key: 'sourceDataID',
+    label: 'dataName',
+    list: 'sourceList',
+    checked: 'checkedSourceKeys',
+    operate: 'updateServiceSource'
+  },
+  process: {},
+  output: {
+    deleteTitle: '输出目标',
+    key: 'serviceOutputID',
+    list: 'outputList',
+    operate: 'updateServiceOutput'
+  }
+}
+
+export default {
+  components: { NoData, Dialog },
+  mixins: [query, operate],
+  data() {
+    return {
+      serviceID: Number(this.$route.query.serviceID),
+      operateDialogType: null,
+      delObj: {},
+      deleteDialogType: null,
+      tempCheckedKeys: [],
+      serviceForm: {
+        serviceName: '',
+        isAsynchronous: null,
+        serviceDescribe: ''
+      },
+      inputForm: {
+        protocolID: null,
+        threads: null,
+        connectConfig: ''
+      },
+      outputForm: {
+        protocolID: null,
+        dataOutputConfig: '',
+        targetdataID: null,
+        outputCondition: '',
+        serviceOutputID: null
+      },
+      targetList: [],
+      protocolList: [],
+      nodeList: [],
+      checkedNodeKeys: [],
+      serviceAndNodeList: [],
+      sourceList: [],
+      checkedSourceKeys: [],
+      serviceAndSourceList: [],
+      processList: [],
+      checkedProcessKeys: [],
+      outputList: []
+    }
+  },
+  computed: {
+    // 获取各关联项的标题、键名、操作方法等
+    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)
+    },
+    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.sourceDataID))
+    },
+    checkedProcessList() {
+      return this.processList.filter(item => this.checkedProcessKeys.includes(item.processName))
+    },
+    // 从协议列表中根据协议ID获取协议名称
+    outputTargetProtocolName() {
+      return function (protocolID) {
+        return this.protocolList.find(protocol => protocol.protocolID === protocolID).protocolName
+      }
+    },
+    // 从目标数据列表中根据目标数据ID获取目标数据名称
+    outputTargetDataName() {
+      return function (targetdataID) {
+        return this.targetList.find(target => target.targetdataID === targetdataID).tdataName
+      }
+    }
+  },
+  methods: {
+    // 服务信息保存
+    async btnSaveClickHandler() {
+      this.$refs['serviceForm'].validate(valid => {
+        if (!valid) return
+      })
+      this.$refs['inputForm'].validate(valid => {
+        if (!valid) return
+      })
+      await this.updateService()
+      this.queryAll()
+    },
+    // 关联编辑-显示弹框
+    showOperateDialog(type) {
+      if (['node', 'source', 'process'].includes(type)) {
+        this.tempCheckedKeys = [...this.dataInMap(type, 'checked')]
+      }
+      this.operateDialogType = type
+    },
+    btnEditClickHandler(obj, type) {
+      // Object.keys(this.outputForm).forEach(key => {
+      //   this.outputForm[key] = obj[key]
+      // })
+      this.outputForm = obj
+      this.showOperateDialog(type)
+    },
+    // 关联编辑-提交
+    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('成功')
+        await this.queryAll()
+        this.hideOperateDialog()
+      } catch (error) {
+        this.$message.error(error)
+      }
+    },
+    // 服务输出项新增/编辑
+    async outputSubmitHandler() {
+      const outputTarget = {
+        ...this.outputForm
+      }
+      try {
+        let message
+        if (outputTarget.serviceOutputID !== null) {
+          message = await this.updateServiceOutput('update', outputTarget)
+        } else {
+          message = await this.updateServiceOutput('create', outputTarget)
+        }
+        this.$message.success(message ?? '成功')
+        await this.queryAll()
+        this.hideOperateDialog()
+      } catch (error) {
+        this.$message.error(error)
+      }
+    },
+    // 关联编辑-隐藏弹框
+    hideOperateDialog() {
+      if (this.operateDialogType === 'output') {
+        this.$refs['outputForm'].resetFields()
+      }
+      this.operateDialogType = null
+    },
+    // 关联删除-显示弹框
+    showDeleteDialog(obj, type) {
+      this.delObj = obj
+      this.deleteDialogType = type
+    },
+    // 关联删除-提交
+    async deleteSubmitHandler() {
+      const operate = this.dataInMap(this.deleteDialogType, 'operate')
+      let message
+      try {
+        if (this.deleteDialogType === 'output') {
+          message = await operate('delete', this.delObj)
+        } else {
+          message = await operate('delete', this.delObj[this.dataInMap(this.deleteDialogType, 'key')])
+        }
+        this.$message.success(message ?? '成功')
+        await this.queryAll()
+        this.hideDeleteDialog()
+      } catch (error) {
+        this.$message.error(error)
+      }
+    },
+    // 关联删除-隐藏弹框
+    hideDeleteDialog() {
+      this.deleteDialogType = null
+      this.delObj = {}
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.service-edit {
+  margin: 0 -24px;
+  padding-bottom: 16px;
+  overflow: hidden;
+  .scrollbar {
+    height: calc(100vh - 120px);
+    padding: 0 24px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    ::v-deep .part {
+      height: 640px;
+      padding: 26px 24px 0 24px;
+      background: #ffffff;
+      box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 4px;
+      &.part-top {
+        height: 296px;
+        margin-bottom: 24px;
+        overflow: hidden;
+      }
+      .title {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 24px;
+        &:nth-of-type(2) {
+          margin-top: 10px;
+        }
+        .manageTitle {
+          height: 32px;
+          line-height: 30px;
+        }
+        .el-button {
+          width: 64px;
+          height: 32px;
+          border: none;
+          &.btn-white {
+            background-color: #ffffff;
+            border: 1px solid #92ace2;
+            color: #2d67e3;
+          }
+          &:hover {
+            background-color: #487be8;
+            color: #ffffff;
+          }
+        }
+      }
+      label,
+      span,
+      button,
+      input,
+      optgroup,
+      select,
+      textarea {
+        font-family: Helvetica, Microsoft YaHei;
+        font-size: 14px;
+        font-weight: 400;
+      }
+      label {
+        color: #303133;
+      }
+      input {
+        color: #101116;
+      }
+      .el-input__inner,
+      .el-textarea__inner {
+        padding-left: 8px;
+        padding-right: 8px;
+      }
+      .el-radio {
+        font-weight: 400;
+      }
+      .content {
+        margin: 0;
+        &:not(.first-content) {
+          height: calc(100% - 32px - 24px);
+        }
+        &.second-content {
+          height: calc(100% - 297px);
+        }
+        > .scrollbar {
+          margin: -12px -24px 0 0;
+          padding: 12px 24px 28px 0;
+          height: calc(100% + 12px);
+          > .el-row > .el-col {
+            margin-bottom: 16px;
+            .service-edit-card {
+              height: 80px;
+              padding: 16px 14px 0 16px;
+              background: #f5f7fa;
+              box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.1);
+              border-radius: 4px;
+              position: relative;
+              font-family: Helvetica, 'Microsoft YaHei';
+              .card-btn-add {
+                margin: -16px -14px 0 -16px;
+                height: calc(100% + 16px);
+                border: 1px dashed #9ebbf7;
+                cursor: pointer;
+                position: relative;
+                .el-icon-plus {
+                  font-size: 32px;
+                  color: #9ebbf7;
+                  position: absolute;
+                  top: 50%;
+                  left: 50%;
+                  margin: -16px -16px;
+                }
+              }
+              .card-btn-close {
+                position: absolute;
+                top: -12px;
+                right: -12px;
+                z-index: 10;
+                width: 24px;
+                height: 24px;
+                line-height: 24px;
+                text-align: center;
+                background: #000000;
+                opacity: 0.8;
+                border-radius: 50%;
+                color: #ffffff;
+                cursor: pointer;
+              }
+              .card-header {
+                display: flex;
+                justify-content: flex-start;
+                color: #101116;
+                font-size: 14px;
+                margin-bottom: 30px;
+                .icon-edit {
+                  width: 14px;
+                  height: 14px;
+                  display: inline-block;
+                  background-repeat: no-repeat;
+                  background-size: cover;
+                  transition: all 0.3s;
+                  margin-left: 16px;
+                  cursor: pointer;
+                  background-image: url('../../../../assets/status/ic_edit_default.png');
+                  &:hover {
+                    background-image: url('../../../../assets/status/ic_edit_hovar.png');
+                  }
+                }
+              }
+              .card-main {
+                font-size: 14px;
+                font-family: Helvetica, Microsoft YaHei;
+                color: #101116;
+                .flex {
+                  height: 32px;
+                  margin-bottom: 23px;
+                  .left {
+                    padding-right: 9px;
+                  }
+                  .multiple-ellipsis {
+                    flex: 1;
+                    display: -webkit-box;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    word-break: break-all;
+                    -webkit-box-orient: vertical;
+                    -webkit-line-clamp: 2;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      &:nth-last-child(1) .content > .scrollbar > .el-row > .el-col {
+        margin-bottom: 24px;
+        &:nth-last-child(1) {
+          margin-bottom: 0;
+        }
+      }
+    }
+  }
+  ::v-deep .service-form {
+    display: flex;
+    flex-wrap: wrap;
+    .el-form-item {
+      margin-bottom: 25px;
+      .el-form-item__label {
+        padding-right: 16px;
+      }
+      &:nth-child(2) {
+        margin-left: 80px;
+        flex: 1;
+        .el-form-item__label {
+          margin-right: 9px;
+        }
+      }
+      &:nth-child(3) {
+        width: 100%;
+      }
+    }
+  }
+  ::v-deep .input-form {
+    display: flex;
+    flex-wrap: wrap;
+    .el-form-item {
+      margin-bottom: 25px;
+      .el-form-item__label {
+        padding-right: 16px;
+      }
+      &:nth-child(2) {
+        margin-left: 54px;
+        flex: 1;
+      }
+      &:nth-child(3) {
+        width: 100%;
+      }
+    }
+  }
+  .dialog-checkbox {
+    .content {
+      margin-left: 16px;
+      .el-checkbox-group {
+        margin-right: 24px;
+        .el-checkbox {
+          margin-bottom: 24px;
+          font-family: Helvetica, Microsoft YaHei;
+          color: #303133;
+        }
+      }
+    }
+  }
+  ::v-deep #dialog-form .el-select .el-input__inner {
+    width: 100%;
+  }
+}
+</style>

+ 334 - 737
src/views/systemSettings/views/serviceManagement/serviceEdit.vue

@@ -1,6 +1,6 @@
 <!--
  * @Date: 2022-03-24 09:55:13
- * @LastEditTime: 2022-05-16 09:55:51
+ * @LastEditTime: 2022-06-10 18:01:59
  * @LastEditors: your name
  * @Description: 服务管理-编辑服务
  * have a nice day!
@@ -9,44 +9,101 @@
 <template>
   <div class="service-edit">
     <div class="scrollbar">
-      <el-row :gutter="24">
-        <el-col :span="16">
-          <div class="part part-top">
-            <header class="title">
-              <p class="manageTitle">服务</p>
-              <el-button
-                size="small"
-                type="primary"
-                class="btn-save"
-                @click="btnSaveClickHandler"
-              >保存</el-button>
-            </header>
-            <main class="content">
-              <el-form
-                ref="serviceForm"
-                class="service-form"
-                :model="serviceForm"
-                label-position="right"
-                label-width="72px"
-                size="mini"
-              >
+      <div class="service-form-wrapper service-edit-wrapper">
+        <header class="title">
+          <p class="manageTitle">服务</p>
+          <el-button
+            size="small"
+            type="primary"
+            class="btn-save"
+          >保存</el-button>
+        </header>
+        <main class="content">
+          <el-form
+            ref="serviceForm"
+            class="service-form"
+            :model="serviceForm"
+            label-position="right"
+            label-width="72px"
+            size="mini"
+          >
+            <el-row
+              :gutter="60"
+              type="flex"
+            >
+              <el-col :span="8">
                 <el-form-item
                   label="服务名称"
                   prop="serviceName"
                 >
                   <el-input
                     v-model="serviceForm.serviceName"
-                    width="240px"
                     placeholder="请输入服务名称"
                     clearable
                   />
                 </el-form-item>
-                <el-form-item label="是否同步">
-                  <el-radio-group v-model="serviceForm.isAsynchronous">
-                    <el-radio :label="0">是</el-radio>
-                    <el-radio :label="1">否</el-radio>
-                  </el-radio-group>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="类型"
+                  prop="serviceType"
+                  label-width="44px"
+                >
+                  <el-select
+                    v-model="serviceForm.serviceType"
+                    clearable
+                  >
+                    <el-option
+                      :value="1"
+                      label="管理前端"
+                    />
+                    <el-option
+                      :value="2"
+                      label="管理后端"
+                    />
+                    <el-option
+                      :value="3"
+                      label="业务前端"
+                    />
+                    <el-option
+                      :value="4"
+                      label="业务后端"
+                    />
+                  </el-select>
                 </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item
+                  label="数据来源"
+                  prop="dataSourceID"
+                >
+                  <el-select
+                    v-model="serviceForm.dataSourceID"
+                    clearable
+                  >
+                    <el-option
+                      v-for="dataSource in dataSourceList"
+                      :key="dataSource.dataSourceID"
+                      :value="dataSource.dataSourceID"
+                      :label="dataSource.dataSourceName"
+                    />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item
+                  label="生命周期ID键名"
+                  prop="lifeCycleCol"
+                  label-width="114px"
+                >
+                  <el-input
+                    v-model="serviceForm.lifeCycleCol"
+                    placeholder="请输入服务名称"
+                    clearable
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
                 <el-form-item
                   label="服务描述"
                   prop="serviceDescribe"
@@ -55,434 +112,211 @@
                     v-model="serviceForm.serviceDescribe"
                     placeholder="请输入描述"
                     type="textarea"
-                    :autosize="{ minRows: 5, maxRows: 5 }"
+                    :autosize="{ minRows: 4, maxRows: 4 }"
                     resize="none"
                     clearable
                   />
                 </el-form-item>
-              </el-form>
-            </main>
-          </div>
-        </el-col>
-        <el-col :span="8">
-          <div class="part part-top">
-            <header class="title">
-              <p class="manageTitle">部署机器</p>
-            </header>
-            <main class="content">
-              <div class="scrollbar">
-                <template v-if="nodeList.length">
-                  <el-row :gutter="16">
-                    <el-col :span="8">
-                      <div class="service-edit-card">
-                        <div
-                          class="card-btn-add"
-                          @click="showOperateDialog('node')"
-                        >
-                          <i class="el-icon-plus" />
-                        </div>
-                      </div>
-                    </el-col>
-                    <el-col
-                      v-for="node in checkedNodeList"
-                      :key="node.deployNodeID"
-                      :span="8"
-                    >
-                      <div class="service-edit-card">
-                        <div
-                          class="card-btn-close"
-                          @click="showDeleteDialog(node, 'node')"
-                        >
-                          <i class="el-icon-close" />
-                        </div>
-                        <div class="card-header">
-                          <span>{{ node.deployNodeName }}</span>
-                        </div>
-                      </div>
-                    </el-col>
-                  </el-row>
-                </template>
-                <template v-else>
-                  <NoData />
-                </template>
-              </div>
-            </main>
-          </div>
-        </el-col>
-        <el-col :span="8">
-          <div class="part">
-            <header class="title">
-              <p class="manageTitle">输入</p>
-            </header>
-            <main class="content first-content">
-              <el-form
-                ref="inputForm"
-                class="input-form"
-                :model="inputForm"
-                label-position="right"
-                label-width="72px"
-                size="mini"
-              >
-                <el-form-item
-                  label="来源"
-                  prop="protocolID"
-                >
-                  <el-select v-model="inputForm.protocolID">
-                    <el-option
-                      v-for="protocol in protocolList"
-                      :key="protocol.protocolID"
-                      :value="protocol.protocolID"
-                      :label="protocol.protocolName"
-                    />
-                  </el-select>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="是否同步">
+                  <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-col>
+              <el-col :span="12">
                 <el-form-item
-                  label="并发线程数"
-                  prop="threads"
-                  label-width="86px"
+                  label="取值规则"
+                  prop="computingMethod"
                 >
                   <el-input
-                    v-model="inputForm.threads"
-                    width="166px"
-                    placeholder="请输入并发线程数"
+                    v-model="serviceForm.computingMethod"
+                    placeholder="请输入取值规则"
+                    type="textarea"
+                    :autosize="{ minRows: 4, maxRows: 4 }"
+                    resize="none"
                     clearable
                   />
                 </el-form-item>
+              </el-col>
+              <el-col :span="12">
                 <el-form-item
-                  label="来源配置"
-                  prop="connectConfig"
+                  label="检测规则"
+                  prop="validationExpression"
                 >
                   <el-input
-                    v-model="inputForm.connectConfig"
-                    placeholder="请输入来源配置"
+                    v-model="serviceForm.validationExpression"
+                    placeholder="请输入检测规则"
                     type="textarea"
                     :autosize="{ minRows: 4, maxRows: 4 }"
                     resize="none"
                     clearable
                   />
                 </el-form-item>
-              </el-form>
-            </main>
-            <header class="title">
-              <p class="manageTitle">源数据</p>
-            </header>
-            <main class="content second-content">
-              <div class="scrollbar">
-                <template v-if="sourceList.length">
-                  <el-row :gutter="16">
-                    <el-col :span="8">
-                      <div class="service-edit-card">
-                        <div
-                          class="card-btn-add"
-                          @click="showOperateDialog('source')"
-                        >
-                          <i class="el-icon-plus" />
-                        </div>
-                      </div>
-                    </el-col>
-                    <el-col
-                      v-for="source in checkedSourceList"
-                      :key="source.sourceDataID"
-                      :span="8"
-                    >
-                      <div class="service-edit-card">
-                        <div
-                          class="card-btn-close"
-                          @click="showDeleteDialog(source, 'source')"
-                        >
-                          <i class="el-icon-close" />
-                        </div>
-                        <div class="card-header">
-                          <span>{{ source.dataName }}</span>
-                        </div>
-                      </div>
-                    </el-col>
-                  </el-row>
-                </template>
-                <template v-else>
-                  <NoData />
-                </template>
-              </div>
-            </main>
-          </div>
-        </el-col>
-        <el-col :span="8">
-          <div class="part">
-            <header class="title">
-              <p class="manageTitle">数据处理</p>
-            </header>
-            <main class="content">
-              <div class="scrollbar">
-                <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>
-                    </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>
-                    </el-col>
-                  </el-row>
-                </template>
-                <template v-else>
-                  <NoData />
-                </template>
-              </div>
-            </main>
-          </div>
-        </el-col>
-        <el-col :span="8">
-          <div class="part">
-            <header class="title">
-              <p class="manageTitle">数据输出</p>
-              <el-button
-                size="small"
-                type="primary"
-                class="btn-white"
-                @click="showOperateDialog('output')"
-              >新增</el-button>
-            </header>
-            <main class="content">
-              <div class="scrollbar">
-                <el-row :gutter="16">
-                  <el-col
-                    v-for="outputTarget in outputList"
-                    :key="outputTarget.serviceOutputID"
-                    :span="24"
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="启动时间"
+                  prop="startTime"
+                >
+                  <el-date-picker
+                    v-model="serviceForm.startTime"
+                    type="datetime"
+                    format="yyyy-MM-dd HH:mm"
+                    value-format="yyyy-MM-dd HH:mm"
+                    placeholder="请选择启动时间"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="停止时间"
+                  prop="stopTime"
+                >
+                  <el-date-picker
+                    v-model="serviceForm.stopTime"
+                    type="datetime"
+                    format="yyyy-MM-dd HH:mm"
+                    value-format="yyyy-MM-dd HH:mm"
+                    placeholder="请选择停止时间"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="失败重试次数"
+                  prop="retryCount"
+                  label-width="100px"
+                >
+                  <el-input
+                    v-model="serviceForm.retryCount"
+                    type="number"
+                    placeholder="请输入重试次数"
+                    clearable
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="循环次数"
+                  prop="loopCount"
+                >
+                  <el-input
+                    v-model="serviceForm.loopCount"
+                    type="number"
+                    placeholder="请输入循环次数"
+                    clearable
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="循环频率"
+                  prop="frequencyCount"
+                >
+                  <el-input
+                    v-model="serviceForm.frequencyCount"
+                    type="number"
+                    placeholder="请输入循环频率"
+                    clearable
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-form-item
+                  label="循环频率单位"
+                  prop="frequencyUnit"
+                  label-width="100px"
+                >
+                  <el-select
+                    v-model="serviceForm.frequencyUnit"
+                    clearable
                   >
-                    <div
-                      class="service-edit-card"
-                      style="height: 160px"
-                    >
-                      <div
-                        class="card-btn-close"
-                        @click="showDeleteDialog(outputTarget, 'output')"
-                      >
-                        <i class="el-icon-close" />
-                      </div>
-                      <div class="card-header">
-                        <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="outputTarget.dataOutputConfig"
-                          >{{ outputTarget.dataOutputConfig }}</div>
-                        </div>
-                        <span>{{ outputTargetDataName(outputTarget.targetdataID) }}</span>
-                      </div>
-                    </div>
-                  </el-col>
-                </el-row>
-              </div>
-            </main>
-          </div>
-        </el-col>
-      </el-row>
-    </div>
-    <Dialog
-      :flag="operateDialogVisible"
-      width="500px"
-    >
-      <template v-if="['node', 'source', 'process'].includes(operateDialogType)">
-        <div class="dialog-checkbox">
-          <div class="title">{{ dataInMap(operateDialogType, 'title') }}</div>
-          <main class="content">
-            <el-checkbox-group v-model="tempCheckedKeys">
-              <el-checkbox
-                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">
+                    <el-option
+                      label="小时"
+                      :value="3600"
+                    />
+                    <el-option
+                      label="分钟"
+                      :value="60"
+                    />
+                    <el-option
+                      label="秒"
+                      :value="1"
+                    />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </main>
+      </div>
+      <div class="service-tables">
+        <div class="service-table-wrapper service-edit-wrapper">
+          <header class="title">
+            <p class="manageTitle">输出</p>
             <el-button
-              size="medium"
+              size="small"
               type="primary"
-              class="r25 r26"
-              @click="checkedSubmitHandler"
-            >提交</el-button>
-            <el-button
-              size="medium"
-              class="r26"
-              @click="hideOperateDialog"
-            >取消</el-button>
-          </div>
-        </div>
-      </template>
-      <template v-if="operateDialogType === 'output'">
-        <div id="dialog-form">
-          <div class="title">数据输出编辑</div>
+              class="btn-white"
+              @click="btnAddClickHandler(1)"
+            >新增</el-button>
+          </header>
           <main class="content">
-            <el-form
-              ref="outputForm"
-              class="output-form"
-              :model="outputForm"
-              label-position="right"
-              label-width="72px"
-              size="mini"
-            >
-              <el-form-item
-                label="协议类型"
-                prop="protocolID"
-              >
-                <el-select v-model="outputForm.protocolID">
-                  <el-option
-                    v-for="item in protocolList"
-                    :key="item.protocolID"
-                    :value="item.protocolID"
-                    :label="item.protocolName"
-                  />
-                </el-select>
-              </el-form-item>
-              <el-form-item
-                label="协议配置"
-                prop="dataOutputConfig"
-              >
-                <el-input
-                  v-model="outputForm.dataOutputConfig"
-                  type="textarea"
-                  placeholder="请输入协议配置"
-                  :autosize="{ minRows: 4, maxRows: 4 }"
-                  resize="none"
-                  clearable
-                />
-              </el-form-item>
-              <el-form-item
-                label="目标数据"
-                prop="targetdataID"
-              >
-                <el-select v-model="outputForm.targetdataID">
-                  <el-option
-                    v-for="item in targetList"
-                    :key="item.targetdataID"
-                    :value="item.targetdataID"
-                    :label="item.tdataName"
-                  />
-                </el-select>
-              </el-form-item>
-              <el-form-item
-                label="输出条件"
-                prop="outputCondition"
-              >
-                <el-input
-                  v-model="outputForm.outputCondition"
-                  type="textarea"
-                  placeholder="请输入输出条件"
-                  :autosize="{ minRows: 4, maxRows: 4 }"
-                  resize="none"
-                  clearable
-                />
-              </el-form-item>
-            </el-form>
+            <DataTable
+              ref="serviceOutputTable"
+              data-id="7"
+              :rows="12"
+              :min-height="70"
+              margin-top="0"
+              :is-btn="false"
+              :is-dialog="false"
+            />
           </main>
-          <div class="foot">
+        </div>
+        <div class="service-table-wrapper service-edit-wrapper">
+          <header class="title">
+            <p class="manageTitle">部署机器</p>
             <el-button
-              size="medium"
+              size="small"
               type="primary"
-              class="r25 r26"
-              @click="outputSubmitHandler"
-            >提交</el-button>
-            <el-button
-              size="medium"
-              class="r26"
-              @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>
+              class="btn-white"
+              @click="btnAddClickHandler(2)"
+            >新增</el-button>
+          </header>
+          <main class="content">
+            <DataTable
+              ref="serviceMachineTable"
+              data-id="3"
+              :rows="12"
+              :min-height="70"
+              margin-top="0"
+              :is-btn="false"
+              :is-dialog="false"
+            />
+          </main>
         </div>
       </div>
-    </Dialog>
+    </div>
   </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 = {
-  node: {
-    title: '部署机器选择',
-    deleteTitle: '机器',
-    key: 'deployNodeID',
-    label: 'deployNodeName',
-    list: 'nodeList',
-    checked: 'checkedNodeKeys',
-    operate: 'updateServiceNode'
-  },
-  source: {
-    title: '源数据',
-    deleteTitle: '源数据',
-    key: 'sourceDataID',
-    label: 'dataName',
-    list: 'sourceList',
-    checked: 'checkedSourceKeys',
-    operate: 'updateServiceSource'
-  },
-  process: {},
-  output: {
-    deleteTitle: '输出目标',
-    key: 'serviceOutputID',
-    list: 'outputList',
-    operate: 'updateServiceOutput'
-  }
-}
+// import NoData from '@/components/nodata'
+// import Dialog from '@/layout/components/Dialog'
+import DataTable from '@/components/Table'
+// import query from './mixins/query'
+// import operate from './mixins/operate'
 
 export default {
-  components: { NoData, Dialog },
-  mixins: [query, operate],
+  components: {
+    // NoData,
+    // Dialog,
+    DataTable
+  },
+  // mixins: [query, operate],
   data() {
     return {
       serviceID: Number(this.$route.query.serviceID),
@@ -492,27 +326,26 @@ export default {
       tempCheckedKeys: [],
       serviceForm: {
         serviceName: '',
-        isAsynchronous: null,
-        serviceDescribe: ''
-      },
-      inputForm: {
-        protocolID: null,
-        threads: null,
-        connectConfig: ''
-      },
-      outputForm: {
-        protocolID: null,
-        dataOutputConfig: '',
-        targetdataID: null,
-        outputCondition: '',
-        serviceOutputID: null
+        serviceType: null,
+        dataSourceID: null,
+        lifeCycleCol: '',
+        serviceDescribe: '',
+        isAsynchronous: 1,
+        computingMethod: '',
+        validationExpression: '',
+        startTime: null,
+        stopTime: null,
+        retryCount: null,
+        loopCount: null,
+        frequencyCount: null,
+        frequencyUnit: null
       },
       targetList: [],
       protocolList: [],
       nodeList: [],
       checkedNodeKeys: [],
       serviceAndNodeList: [],
-      sourceList: [],
+      dataSourceList: [],
       checkedSourceKeys: [],
       serviceAndSourceList: [],
       processList: [],
@@ -520,145 +353,18 @@ export default {
       outputList: []
     }
   },
-  computed: {
-    // 获取各关联项的标题、键名、操作方法等
-    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)
-    },
-    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.sourceDataID))
-    },
-    checkedProcessList() {
-      return this.processList.filter(item => this.checkedProcessKeys.includes(item.processName))
-    },
-    // 从协议列表中根据协议ID获取协议名称
-    outputTargetProtocolName() {
-      return function (protocolID) {
-        return this.protocolList.find(protocol => protocol.protocolID === protocolID).protocolName
-      }
-    },
-    // 从目标数据列表中根据目标数据ID获取目标数据名称
-    outputTargetDataName() {
-      return function (targetdataID) {
-        return this.targetList.find(target => target.targetdataID === targetdataID).tdataName
-      }
-    }
-  },
   methods: {
-    // 服务信息保存
-    async btnSaveClickHandler() {
-      this.$refs['serviceForm'].validate(valid => {
-        if (!valid) return
-      })
-      this.$refs['inputForm'].validate(valid => {
-        if (!valid) return
-      })
-      await this.updateService()
-      this.queryAll()
-    },
-    // 关联编辑-显示弹框
-    showOperateDialog(type) {
-      if (['node', 'source', 'process'].includes(type)) {
-        this.tempCheckedKeys = [...this.dataInMap(type, 'checked')]
-      }
-      this.operateDialogType = type
-    },
-    btnEditClickHandler(obj, type) {
-      // Object.keys(this.outputForm).forEach(key => {
-      //   this.outputForm[key] = obj[key]
-      // })
-      this.outputForm = obj
-      this.showOperateDialog(type)
-    },
-    // 关联编辑-提交
-    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('成功')
-        await this.queryAll()
-        this.hideOperateDialog()
-      } catch (error) {
-        this.$message.error(error)
-      }
-    },
-    // 服务输出项新增/编辑
-    async outputSubmitHandler() {
-      const outputTarget = {
-        ...this.outputForm
-      }
-      try {
-        let message
-        if (outputTarget.serviceOutputID !== null) {
-          message = await this.updateServiceOutput('update', outputTarget)
-        } else {
-          message = await this.updateServiceOutput('create', outputTarget)
-        }
-        this.$message.success(message ?? '成功')
-        await this.queryAll()
-        this.hideOperateDialog()
-      } catch (error) {
-        this.$message.error(error)
+    btnAddClickHandler(flag) {
+      switch (flag) {
+        case 1:
+          this.$refs['serviceOutputTable'].handleAdd()
+          break
+        case 2:
+          this.$refs['serviceMachineTable'].handleAdd()
+          break
+        default:
+          break
       }
-    },
-    // 关联编辑-隐藏弹框
-    hideOperateDialog() {
-      if (this.operateDialogType === 'output') {
-        this.$refs['outputForm'].resetFields()
-      }
-      this.operateDialogType = null
-    },
-    // 关联删除-显示弹框
-    showDeleteDialog(obj, type) {
-      this.delObj = obj
-      this.deleteDialogType = type
-    },
-    // 关联删除-提交
-    async deleteSubmitHandler() {
-      const operate = this.dataInMap(this.deleteDialogType, 'operate')
-      let message
-      try {
-        if (this.deleteDialogType === 'output') {
-          message = await operate('delete', this.delObj)
-        } else {
-          message = await operate('delete', this.delObj[this.dataInMap(this.deleteDialogType, 'key')])
-        }
-        this.$message.success(message ?? '成功')
-        await this.queryAll()
-        this.hideDeleteDialog()
-      } catch (error) {
-        this.$message.error(error)
-      }
-    },
-    // 关联删除-隐藏弹框
-    hideDeleteDialog() {
-      this.deleteDialogType = null
-      this.delObj = {}
     }
   }
 }
@@ -674,17 +380,8 @@ export default {
     padding: 0 24px;
     overflow-x: hidden;
     overflow-y: auto;
-    ::v-deep .part {
-      height: 640px;
+    .service-edit-wrapper {
       padding: 26px 24px 0 24px;
-      background: #ffffff;
-      box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.1);
-      border-radius: 4px;
-      &.part-top {
-        height: 296px;
-        margin-bottom: 24px;
-        overflow: hidden;
-      }
       .title {
         display: flex;
         justify-content: space-between;
@@ -711,171 +408,71 @@ export default {
           }
         }
       }
-      label,
-      span,
-      button,
-      input,
-      optgroup,
-      select,
-      textarea {
-        font-family: Helvetica, Microsoft YaHei;
-        font-size: 14px;
-        font-weight: 400;
-      }
-      label {
-        color: #303133;
-      }
-      input {
-        color: #101116;
-      }
-      .el-input__inner,
-      .el-textarea__inner {
-        padding-left: 8px;
-        padding-right: 8px;
-      }
-      .el-radio {
-        font-weight: 400;
-      }
       .content {
         margin: 0;
-        &:not(.first-content) {
-          height: calc(100% - 32px - 24px);
-        }
-        &.second-content {
-          height: calc(100% - 297px);
-        }
-        > .scrollbar {
-          margin: -12px -24px 0 0;
-          padding: 12px 24px 28px 0;
-          height: calc(100% + 12px);
-          > .el-row > .el-col {
-            margin-bottom: 16px;
-            .service-edit-card {
-              height: 80px;
-              padding: 16px 14px 0 16px;
-              background: #f5f7fa;
-              box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.1);
-              border-radius: 4px;
-              position: relative;
-              font-family: Helvetica, 'Microsoft YaHei';
-              .card-btn-add {
-                margin: -16px -14px 0 -16px;
-                height: calc(100% + 16px);
-                border: 1px dashed #9ebbf7;
-                cursor: pointer;
-                position: relative;
-                .el-icon-plus {
-                  font-size: 32px;
-                  color: #9ebbf7;
-                  position: absolute;
-                  top: 50%;
-                  left: 50%;
-                  margin: -16px -16px;
-                }
-              }
-              .card-btn-close {
-                position: absolute;
-                top: -12px;
-                right: -12px;
-                z-index: 10;
-                width: 24px;
-                height: 24px;
-                line-height: 24px;
-                text-align: center;
-                background: #000000;
-                opacity: 0.8;
-                border-radius: 50%;
-                color: #ffffff;
-                cursor: pointer;
-              }
-              .card-header {
-                display: flex;
-                justify-content: flex-start;
-                color: #101116;
-                font-size: 14px;
-                margin-bottom: 30px;
-                .icon-edit {
-                  width: 14px;
-                  height: 14px;
-                  display: inline-block;
-                  background-repeat: no-repeat;
-                  background-size: cover;
-                  transition: all 0.3s;
-                  margin-left: 16px;
-                  cursor: pointer;
-                  background-image: url('../../../../assets/status/ic_edit_default.png');
-                  &:hover {
-                    background-image: url('../../../../assets/status/ic_edit_hovar.png');
-                  }
-                }
+      }
+    }
+    ::v-deep .service-form-wrapper {
+      background: #ffffff;
+      box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 4px;
+      .service-form {
+        > .el-row {
+          flex-wrap: wrap;
+          > .el-col {
+            .el-form-item {
+              margin-bottom: 25px;
+              .el-form-item__label {
+                padding-right: 16px;
               }
-              .card-main {
-                font-size: 14px;
-                font-family: Helvetica, Microsoft YaHei;
-                color: #101116;
-                .flex {
-                  height: 32px;
-                  margin-bottom: 23px;
-                  .left {
-                    padding-right: 9px;
-                  }
-                  .multiple-ellipsis {
-                    flex: 1;
-                    display: -webkit-box;
-                    overflow: hidden;
-                    text-overflow: ellipsis;
-                    word-break: break-all;
-                    -webkit-box-orient: vertical;
-                    -webkit-line-clamp: 2;
-                  }
-                }
+              .el-input {
+                width: 100%;
               }
             }
           }
         }
-      }
-      &:nth-last-child(1) .content > .scrollbar > .el-row > .el-col {
-        margin-bottom: 24px;
-        &:nth-last-child(1) {
-          margin-bottom: 0;
+        label,
+        span,
+        button,
+        input,
+        optgroup,
+        select,
+        textarea {
+          font-family: Helvetica, Microsoft YaHei;
+          font-size: 14px;
+          font-weight: 400;
         }
-      }
-    }
-  }
-  ::v-deep .service-form {
-    display: flex;
-    flex-wrap: wrap;
-    .el-form-item {
-      margin-bottom: 25px;
-      .el-form-item__label {
-        padding-right: 16px;
-      }
-      &:nth-child(2) {
-        margin-left: 80px;
-        flex: 1;
-        .el-form-item__label {
-          margin-right: 9px;
+        label {
+          color: #303133;
+        }
+        input {
+          color: #101116;
+          &::-webkit-outer-spin-button,
+          &::-webkit-inner-spin-button {
+            -webkit-appearance: none !important;
+          }
+          &[type='‘number’'] {
+            -moz-appearance: textfield !important;
+          }
+        }
+        .el-radio {
+          font-weight: 400;
         }
-      }
-      &:nth-child(3) {
-        width: 100%;
       }
     }
-  }
-  ::v-deep .input-form {
-    display: flex;
-    flex-wrap: wrap;
-    .el-form-item {
-      margin-bottom: 25px;
-      .el-form-item__label {
-        padding-right: 16px;
-      }
-      &:nth-child(2) {
-        margin-left: 54px;
-        flex: 1;
-      }
-      &:nth-child(3) {
-        width: 100%;
+    .service-tables {
+      width: 100%;
+      display: flex;
+      margin: 0 -12px;
+      .service-table-wrapper {
+        padding-left: 12px;
+        padding-right: 12px;
+        &:nth-child(1) {
+          flex: 1 1 624px;
+        }
+        &:nth-child(2) {
+          flex: 0 1 624px;
+        }
       }
     }
   }

+ 194 - 81
src/views/systemSettings/views/serviceManagement/serviceHome.vue

@@ -1,6 +1,6 @@
 <!--
  * @Date: 2022-04-12 17:49:47
- * @LastEditTime: 2022-04-28 15:14:53
+ * @LastEditTime: 2022-06-10 11:30:00
  * @LastEditors: your name
  * @Description: 服务管理-首页
  * have a nice day!
@@ -12,142 +12,257 @@
       <DataTable
         data-id="2"
         :rows="12"
-        labelWidth="110px"
-        :minHeight="70"
         width="800px"
-        :isDialog="false"
-        @handleAdd="handleAdd"
+        label-width="110px"
+        :min-height="70"
+        :is-dialog="false"
+        @handleAdd="showCreateDialog"
+        @handleEdit="btnEditClickHandler"
       />
+      <!--新增弹框-->
+      <Dialog
+        :flag="createDialogVisible"
+        width="600px"
+      >
+        <div class="dialog-create">
+          <div class="title">新增服务</div>
+          <main class="content">
+            <el-form
+              ref="createForm"
+              class="create-form"
+              :model="createForm"
+              :rules="createFormRules"
+              label-position="right"
+              label-width="82px"
+              size="mini"
+            >
+              <el-form-item
+                label="服务名称"
+                prop="serviceName"
+              >
+                <el-input
+                  v-model="createForm.serviceName"
+                  placeholder="请输入服务名称"
+                  clearable
+                />
+              </el-form-item>
+              <el-form-item
+                label="描述"
+                prop="serviceDescribe"
+              >
+                <el-input
+                  v-model="createForm.serviceDescribe"
+                  placeholder="请输入描述"
+                  type="textarea"
+                  :autosize="{ minRows: 4, maxRows: 4 }"
+                  resize="none"
+                  clearable
+                />
+              </el-form-item>
+              <el-form-item label="是否同步">
+                <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="protocolID"
+              >
+                <el-select
+                  v-model="createForm.protocolID"
+                  placeholder="请选择来源"
+                >
+                  <el-option
+                    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="96px"
+              >
+                <el-input
+                  v-model="createForm.threads"
+                  placeholder="请输入并发线程数"
+                  clearable
+                />
+              </el-form-item>
+              <el-form-item
+                label="来源配置"
+                prop="connectConfig"
+              >
+                <el-input
+                  v-model="createForm.connectConfig"
+                  placeholder="请输入来源配置"
+                  type="textarea"
+                  :autosize="{ minRows: 4, maxRows: 4 }"
+                  resize="none"
+                  clearable
+                />
+              </el-form-item>
+            </el-form>
+          </main>
+          <div class="foot">
+            <el-button
+              size="medium"
+              type="primary"
+              class="r25 r26"
+              @click="createSubmitHandler"
+            >提交</el-button>
+            <el-button
+              size="medium"
+              class="r26"
+              @click="hideCreateDialog"
+            >取消</el-button>
+          </div>
+        </div>
+      </Dialog>
     </div>
   </div>
 </template>
 
 <script>
-import Dialog from "@/layout/components/Dialog/index.vue";
-import { GeneralDataReception, Query } from "@/api/dataIntegration";
-import { regular } from "@/utils/validate";
-import DataTable from "@/components/Table";
+import Dialog from '@/layout/components/Dialog/index.vue'
+import { GeneralDataReception, Query } from '@/api/dataIntegration'
+import { regular } from '@/utils/validate'
+import DataTable from '@/components/Table'
 export default {
-  name: "ProtocolHome",
-  components: { Dialog, DataTable },
+  name: 'ProtocolHome',
+  components: {
+    Dialog,
+    DataTable
+  },
   data() {
     return {
       serviceList: [],
       createDialogVisible: false,
       createForm: {
-        serviceName: "",
-        serviceDescribe: "",
+        serviceName: '',
+        serviceDescribe: '',
         isAsynchronous: 0,
-        protocolID: "",
-        threads: "",
-        connectConfig: "",
+        protocolID: '',
+        threads: '',
+        connectConfig: ''
       },
       createFormRules: {
-        serviceName: [
-          { required: true, message: "请输入服务名称", trigger: "blur" },
-        ],
-        protocolID: [
-          { required: true, message: "请选择来源", trigger: "blur" },
-        ],
+        serviceName: [{ required: true, message: '请输入服务名称', trigger: 'blur' }],
+        protocolID: [{ required: true, message: '请选择来源', trigger: 'blur' }],
         threads: [
-          { required: true, message: "请输入并发线程数", trigger: "blur" },
+          { required: true, message: '请输入并发线程数', trigger: 'blur' },
           {
             pattern: regular.positiveInteger,
-            message: "请输入正整数",
-            trigger: ["blur", "change"],
-          },
-        ],
+            message: '请输入正整数',
+            trigger: ['blur', 'change']
+          }
+        ]
       },
       protocolList: [],
       deleteDialogVisible: false,
-      delObj: {},
-    };
+      delObj: {}
+    }
   },
   mounted() {
     // this.getServiceList();
   },
   methods: {
-    // 新增
-    handleAdd() {
-      this.$router.push({
-        path: "/systemSettings/serviceEdit"
-      });
+    // 新增-弹框
+    showCreateDialog() {
+      this.getProtocolList()
+      this.createDialogVisible = true
+    },
+    // 新增-提交
+    createSubmitHandler() {
+      this.$refs['createForm'].validate(valid => {
+        if (valid) {
+          this.createService()
+        }
+      })
+    },
+    // 新增-关闭
+    hideCreateDialog() {
+      this.$refs['createForm'].resetFields()
+      this.createDialogVisible = false
     },
     // 编辑-跳转
-    handleEdit(item) {
+    btnEditClickHandler(item) {
       this.$router.push({
-        path: "/systemSettings/serviceEdit",
-        query: { serviceID: item.serviceID },
-      });
+        path: '/systemSettings/serviceEdit',
+        query: { serviceID: item.serviceID }
+      })
     },
     async getServiceList() {
       try {
         const res = await Query({
           id: 3,
-          dataContent: [],
-        });
+          dataContent: []
+        })
         if (Number(res.code) === 0) {
-          this.serviceList = res.returnData;
+          this.serviceList = res.returnData
         } else {
-          this.$message.error(res.message ?? "失败");
+          this.$message.error(res.message ?? '失败')
         }
       } catch (error) {
-        console.log("错误", error);
+        console.log('错误', error)
       }
     },
     async getProtocolList() {
       try {
         const res = await Query({
           id: 1,
-          dataContent: [],
-        });
+          dataContent: []
+        })
         if (Number(res.code) === 0) {
-          this.protocolList = res.returnData;
+          this.protocolList = res.returnData
         } else {
-          this.$message.error(res.message ?? "失败");
+          this.$message.error(res.message ?? '失败')
         }
       } catch (error) {
-        console.log("错误", error);
+        console.log('错误', error)
       }
     },
     async createService() {
       try {
-        this.createForm["operate"] = 1;
+        this.createForm['operate'] = 1
         const res = await GeneralDataReception({
           serviceId: 3,
-          dataContent: JSON.stringify(this.createForm),
-        });
+          dataContent: JSON.stringify(this.createForm)
+        })
         if (Number(res.code) === 0) {
-          this.$message.success(res.message ?? "成功");
-          this.hideCreateDialog();
-          this.getServiceList();
+          this.$message.success(res.message ?? '成功')
+          this.hideCreateDialog()
+          this.getServiceList()
         } else {
-          this.$message.error(res.message ?? "失败");
+          this.$message.error(res.message ?? '失败')
         }
       } catch (error) {
-        console.log("错误", error);
+        console.log('错误', error)
       }
-    },
-    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);
-      }
-    },
-  },
-};
+    }
+    // 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)
+    //   }
+    // }
+  }
+}
 </script>
 
 <style lang="scss" scoped>
@@ -196,16 +311,14 @@ export default {
             width: 14px;
             height: 14px;
             margin-left: 24px;
-            background: url("../../../../assets/status/ic_edit_default.png")
-              no-repeat;
+            background: url('../../../../assets/status/ic_edit_default.png') no-repeat;
             background-size: 100% 100%;
             cursor: pointer;
             position: relative;
             top: 2px;
           }
           .loger:hover {
-            background: url("../../../../assets/status/ic_edit_hovar.png")
-              no-repeat;
+            background: url('../../../../assets/status/ic_edit_hovar.png') no-repeat;
             background-size: 100% 100%;
           }
         }