编写生命周期模块 && 业务类型添加查询 && 创建未编写模块的路由配置
已修改13个文件
已添加24个文件
3588 ■■■■■ 文件已修改
Source/plt-web/plt-web-ui/package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/api/modeling/businessType/api.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/api/modeling/lifeCycle/api.js 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/api/modeling/linkType/api.js 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ContextMenu.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ContextMenuItem.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/CustomCommand.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/DetailForm.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/DetailPanel.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/EditorMinimap.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/Icon.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ItemPanel.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/Toolbar.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ToolbarButton.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/flowchartEditor.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/components/flow-cycle/iconfont.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/router/router.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/store/index.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/store/modules/LifeFlow.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/function/fuctionView/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/secure/classification/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/secure/machineClassification/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/ui/dataAuthorization/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/ui/typeAction/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/authority/ui/uiAuthorization/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/attributePool/option.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/businessType/index.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/lifeCycle/index.vue 448 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/linkType/index.vue 526 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/statusPool/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/versioning/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/businessTypeQuery/index.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/linkTypeQuery/index.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/queryDefine/index.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/Action/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/formDefine/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/uiDefine/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/package.json
@@ -28,6 +28,7 @@
    "script-loader": "^0.7.2",
    "vue": "^2.6.10",
    "vue-axios": "^2.1.2",
    "vue-flowchart-editor": "1.0.2",
    "vue-i18n": "^8.7.0",
    "vue-quill-editor": "^3.0.6",
    "vue-router": "^3.0.1",
Source/plt-web/plt-web-ui/src/api/modeling/businessType/api.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
import request from '@/router/axios';
// åˆ—表查询
export function getBizTypes(params) {
  return request({
    url: "/api/btmTypeController/getTreeBizTypes",
    method: "get",
    params
  });
}
Source/plt-web/plt-web-ui/src/api/modeling/lifeCycle/api.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
import request from '@/router/axios';
// åˆ—表查询
export function gridLifeCycle() {
  return request({
    url: "/api/lifeCycleController/gridLifeCycle",
    method: "get",
  });
}
// è·ƒè¿äº‹ä»¶æŸ¥è¯¢
export function getLCEventKeys() {
  return request({
    url: "/api/lifeCycleController/getLCEventKeys",
    method: "get",
  });
}
// åˆ›å»º
export function addLifeCycle(params) {
  return request({
    url: "/api/lifeCycleController/addLifeCycle",
    method: "post",
    data:params
  });
}
// ä¿®æ”¹
export function updateLifeCycle(params) {
  return request({
    url: "/api/lifeCycleController/updateLifeCycle",
    method: "put",
    data:params
  });
}
// åˆ é™¤
export function deleteLifeCycles(data) {
  return request({
    url: "/api/lifeCycleController/deleteLifeCycles",
    method: "delete",
    data:data
  });
}
// å¯¼å…¥
export function exportLifeCycles (params) {
  return request({
    url: '/api/lifeCycleController/exportLifeCycles',
    method: 'get',
    headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
    responseType: 'blob',
    params
  })
}
// æŸ¥çœ‹é€‚用范围
export function getUsedLifeCycleList(params) {
  return request({
    url: "/api/lifeCycleController/getUsedLifeCycleList",
    method: "get",
    params
  });
}
Source/plt-web/plt-web-ui/src/api/modeling/linkType/api.js
@@ -26,6 +26,15 @@
  });
}
// ä¿®å¤
export function repairTable(params) {
  return request({
    url: "/api/linkTypeController/repairTable",
    method: "post",
    data:params
  });
}
// åˆ›å»ºè§†å›¾
export function createView() {
  return request({
@@ -35,17 +44,18 @@
}
// æŸ¥ä¸šåŠ¡ç±»åž‹æŽ¥å£
export function getBizTypes() {
export function getBizTypes(params) {
  return request({
    url: "/api/linkTypeController/expData",
    method: "post",
    url: "/api/btmTypeController/getBizTypes",
    method: "get",
    params
  });
}
// å¯¼å‡º
export function exportStatus  (params) {
export function expData (params) {
  return request({
    url: '/api/statusController/exportStatus',
    url: '/api/linkTypeController/expData',
    method: 'get',
    headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
    responseType: 'blob',
@@ -53,3 +63,21 @@
  })
}
// ä¿å­˜ ä¿®æ”¹ æŽ¥å£
export function addAndEditLink(addFlag,params) {
  return request({
    url: `/api/linkTypeController/addAndEditLink?addFlag=${addFlag}`,
    method: "post",
    data:params
  });
}
// åˆ é™¤æŽ¥å£
export function deleteLink(params) {
  return request({
    url: '/api/linkTypeController/deleteLink',
    method: "delete",
    data:params
  });
}
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ContextMenu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
<template>
  <context-menu class="contextMenu">
    <node-menu>
<!--      <menu-li command="copy" text="拷贝" />-->
      <menu-li command="delete" text="删除" />
    </node-menu>
    <edge-menu>
      <menu-li command="delete" text="删除" />
    </edge-menu>
    <canvas-menu>
      <menu-li command="undo" text="撤销" />
      <menu-li command="redo" text="重做" />
<!--      <menu-li command="pasteHere" icon="paste" text="粘贴到这里" />-->
    </canvas-menu>
  </context-menu>
</template>
<script>
import {
  NodeMenu,
  EdgeMenu,
  GroupMenu,
  MultiMenu,
  CanvasMenu,
  ContextMenu,
} from 'vue-flowchart-editor'
import MenuLi from './ContextMenuItem'
export default {
  name: 'EditorContextMenu',
  components: {
    NodeMenu,
    EdgeMenu,
    GroupMenu,
    MultiMenu,
    CanvasMenu,
    ContextMenu,
    MenuLi,
  },
}
</script>
<style lang="scss" scoped>
.contextMenu {
  display: none;
  overflow: hidden;
  font-size: 12px;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.contextMenu .command.disable .item {
  color: rgba(0, 0, 0, 0.25);
  cursor: auto;
}
.contextMenu .command.disable .item:hover {
  background: #fff;
}
.contextMenu .item {
  display: flex;
  align-items: center;
  padding: 5px 12px;
  cursor: pointer;
  transition: all 0.3s;
  user-select: none;
}
.contextMenu .item:hover {
  background: #e6f7ff;
}
.contextMenu .item i {
  margin-right: 8px;
  margin-top: 3px;
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ContextMenuItem.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
<template>
  <command :name="command">
    <div class="item">
      <icon :type="iconType" :title="text" />
      <span>{{ label }}</span>
    </div>
  </command>
</template>
<script>
import { Command } from 'vue-flowchart-editor'
import Icon from './Icon'
import upperFirst from 'lodash/upperFirst'
export default {
  name: 'EditorContextMenuItem',
  components: {
    Command,
    Icon,
  },
  props: ['command', 'icon', 'text'],
  computed: {
    iconType() {
      return `icon${this.icon || this.command}`
    },
    label() {
      return this.text || upperFirst(this.command)
    },
  },
}
</script>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/CustomCommand.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <div>
    <register-command
      name="generateData"
      :config="generateDataCommandConfig"
      extend="copy"
    />
    <register-command
      name="downloadImage"
      :config="downloadImageCommandConfig"
      extend="copy"
    />
  </div>
</template>
<script>
import { RegisterCommand } from 'vue-flowchart-editor'
export default {
  name: 'CustomCommand',
  components: {
    RegisterCommand,
  },
  inject: ['root'],
  props: ['save', 'download'],
  data() {
    const { propsAPI } = this.root
    const { save, download } = this
    return {
      generateDataCommandConfig: {
        queue: false, // æ˜¯å¦è¿›å…¥åˆ—队,默认为 true
        enable(/* editor */) {
          // å‘½ä»¤æ˜¯å¦å¯ç”¨
          return true
        },
        execute(/* editor */) {
          // æ­£å‘命令逻辑
          console.log('执行正向命令')
          const data = propsAPI.save()
          console.log(data)
          console.log(JSON.stringify(data))
          save(data)
          alert(JSON.stringify(data))
        },
        back(/* editor */) {
          // åå‘命令逻辑
          console.log('执行反向命令')
        },
      },
      downloadImageCommandConfig: {
        queue: false,
        enable() {
          return true
        },
        execute() {
          download()
        },
        back() {},
      },
    }
  },
}
</script>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/DetailForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
<template>
  <div class="right_box">
    <hr/>
    <div v-if="type === 'node'">
      <el-form
        ref="form"
        :model="formModel"
        :rules="rules"
        label-width="80px"
        size="mini"
      >
        <el-form-item label="名称" prop="label">
          <el-input v-model.trim="formModel.label" :maxLength="20" disabled/>
        </el-form-item>
        <el-form-item label="形状">
          <el-select
            v-model="formModel.shape"
            :disabled="!disabledBtn"
            placeholder="请选择形状"
            style="width: 100%"
          >
            <el-option
              v-for="item in shapeTypeList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="颜色">
          <el-input v-model.trim="formModel.color" :disabled="!disabledBtn" clearable/>
        </el-form-item>
        <el-form-item label="宽度" prop="width">
          <el-input v-model.trim.number="formModel.width" :disabled="!disabledBtn" clearable>
            <template slot="prepend">宽</template>
          </el-input>
        </el-form-item>
        <el-form-item label="高度" prop="height">
          <el-input v-model.trim.number="formModel.height" :disabled="!disabledBtn" clearable>
            <template slot="prepend">高</template>
          </el-input>
        </el-form-item>
      </el-form>
    </div>
    <div v-else-if="type === 'edge'">
      <el-form
        :model="formModel"
        :rules="rules"
        label-width="80px"
        size="small"
      >
        <el-form-item label="起始状态">
          <el-input v-model.trim="formModel.source" disabled/>
        </el-form-item>
        <el-form-item label="目标状态">
          <el-input v-model.trim="formModel.target" disabled/>
        </el-form-item>
        <el-form-item label="名称">
          <el-input v-model.trim="formModel.label" :disabled="!disabledBtn"/>
        </el-form-item>
        <el-form-item label="形状">
          <el-select
            v-model="formModel.shape"
            :disabled="!disabledBtn"
            placeholder="请选择形状"
            style="width: 100%"
          >
            <el-option
              v-for="item in lineTypeList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
    </div>
    <div class="btn_box">
      <el-button :disabled="!disabledBtn" size="mini" type="primary" @click="handleSubmit"
      >更新属性
      </el-button
      >
    </div>
  </div>
</template>
<script>
import {cloneDeep} from 'lodash'
export default {
  name: 'EditorDetailForm',
  inject: ['root'],
  props: ['type', 'readOnly'],
  data() {
    return {
      formModel: {},
      fontSize: 12,
      shapeTypeList: [
        {label: '矩形', value: 'flow-rect'},
        {label: '椭圆', value: 'flow-circle'},
        {label: '菱形', value: 'flow-rhombus'},
        {label: '胶囊', value: 'flow-capsule'},
      ],
      lineTypeList: [
        {label: '曲线', value: 'flow-smooth'},
        {label: '折线', value: 'flow-polyline'},
        {label: '圆角折线', value: 'flow-polyline-round'},
      ],
      rules: {
        label: [{required: true, message: '名称不能为空', trigger: 'blur'}],
        width: [
          {required: true, message: '宽度不能为空', trigger: 'blur'},
          {pattern: /^[0-9]+$/, message: '宽度只能为数字', trigger: 'blur'},
        ],
        height: [
          {required: true, message: '高度不能为空', trigger: 'blur'},
          {pattern: /^[0-9]+$/, message: '高度只能为数字', trigger: 'blur'},
        ],
      },
    }
  },
  created() {
    const formModel = this.root.propsAPI.getSelected()[0].getModel()
    this.formModel = Object.assign(
      {width: 80, height: 48},
      {shape: 'flow-smooth'},
      cloneDeep(formModel) // é˜²æ­¢è¯¯ç¼–辑
    )
  },
  computed: {
    disabledBtn() {
      return this.$store.state.flow.methodBtn;
    }
  },
  methods: {
    async handleSubmit() {
      if (this.type === 'node') {
        await this.$refs.form.validate()
      }
      const {getSelected, executeCommand, update} = this.root.propsAPI
      const {formModel} = this
      setTimeout(() => {
        const item = getSelected()[0]
        if (!item) return
        // è‡ªåŠ¨è°ƒæ•´å°ºå¯¸
        const adjustSize = (model) => {
          // if (model.type !== 'node' || model.shape !== 'flow-rect') {
          //   return model
          // }
          const canvas = document.createElement('canvas')
          const canvasContext = canvas.getContext('2d')
          canvasContext.font = this.fontSize + 'px System'
          let label = model.label.replace('\n', '')
          let sourceWidth = this.formModel.width
          let sourceHeight = this.formModel.height
          const spacing = 10
          // èŽ·å–æ–‡å­—å®½åº¦
          const widthWithSpacing = canvasContext.measureText(label).width + spacing
          model.size = `${sourceWidth}*${sourceHeight}` // å…ˆæ¢å¤é»˜è®¤å°ºå¯¸
          if (widthWithSpacing <= sourceWidth) {
            return model
          }
          // è‡ªåŠ¨æŠ˜è¡Œ
          let multilineText = ''
          let multilineCount = 1
          let multilineTextWidth = 0
          for (const char of label) {
            const {width} = canvasContext.measureText(char)
            console.log(multilineTextWidth + width + spacing, 'multilineTextWidth');
            if (multilineTextWidth + width + spacing >= sourceWidth) {
              multilineText += '\n'
              multilineTextWidth = 0
              multilineCount++
            }
            multilineText += char
            multilineTextWidth += width
          }
          return {
            ...model,
            label: multilineText,
            size: `${sourceWidth}*${Math.max(
              sourceHeight,
              this.fontSize * multilineCount * 1.2 + spacing
            )}`,
          }
        }
        const newFormModel = adjustSize(formModel)
        console.log(newFormModel, 'newFormModel')
        executeCommand(() => {
          update(item, newFormModel)
        })
      }, 0)
    },
  },
}
</script>
<style lang="scss" scoped>
.btn_box {
  text-align: center;
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/DetailPanel.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,209 @@
<template>
  <div>
    <div class="tree_data_box">
      <el-form
        ref="form"
        :model="newRowData"
        :rules="rules"
        label-width="80px"
        size="mini"
      >
        <el-form-item label="名称" prop="id">
          <el-input v-model.trim="newRowData.id" :disabled="!disabledBtn" :maxLength="20" clearable/>
        </el-form-item>
        <el-form-item label="标签" prop="name">
          <el-input v-model.trim="newRowData.name" :disabled="!disabledBtn" clearable/>
        </el-form-item>
        <el-form-item label="起始状态" prop="startStatus">
          <el-select
            v-model="newRowData.startStatus"
            :disabled="!disabledBtn"
            placeholder="请选择起始状态"
            style="width: 100%"
          >
            <el-option
              v-for="item in existNodes"
              :key="item.id"
              :label="item.id"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="描述">
          <el-input v-model.trim="newRowData.description" :disabled="!disabledBtn" type="textarea"></el-input>
        </el-form-item>
      </el-form>
    </div>
    <detail-panel>
      <template v-slot="{ status }">
        <node-panel :status="status">
          <detail-form ref="detailFrom" type="node"/>
        </node-panel>
        <edge-panel :status="status">
          <detail-form type="edge"/>
        </edge-panel>
        <group-panel :status="status">
          <detail-form type="group"/>
        </group-panel>
        <div v-if="status === 'edge-selected'" class="event">
          <hr/>
          <h4>跃迁事件</h4>
          <el-select
            ref="mySelect"
            v-model="currentSelectedLine.events"
            :disabled="!disabledBtn"
            multiple
            size="mini"
            style="width: 100%"
            value-key="oid"
            @change="handleChange"
          >
            <el-option
              v-for="(item,index) in newRowData.eventList"
              :key="index"
              :label="item"
              :value="item"
            ></el-option>
          </el-select>
        </div>
      </template>
    </detail-panel>
  </div>
</template>
<script>
// import API from "@/api/modeling/cycle";
import {
  NodePanel,
  EdgePanel,
  GroupPanel,
  MultiPanel,
  CanvasPanel,
  DetailPanel,
} from "vue-flowchart-editor";
import DetailForm from "./DetailForm";
export default {
  name: "EditorDetailPanel",
  components: {
    NodePanel,
    EdgePanel,
    GroupPanel,
    MultiPanel,
    CanvasPanel,
    DetailPanel,
    DetailForm,
  },
  props: ["rowData", "existNodes", "existEdges", "type", "currentSelectedLine"],
  data() {
    return {
      newRowData: {
        startStatus: undefined,
        name: undefined,
        id: undefined,
        remark: undefined,
        saveEventList: []
      },
      rules: {
        name: [{required: true, message: "名称不能为空", trigger: "blur"}],
        id: [
          {required: true, message: "标签不能为空", trigger: "blur"},
          {
            pattern: /^[A-z]+$/g,
            message: "标签只能输入英文",
            trigger: "blur",
          },
        ],
        startStatus: [
          {required: true, message: "起始状态不能为空", trigger: "change"},
        ],
      },
      eventList: [
        {
          oid: '1',
          value: 'xxx',
          eventShowName: 'xxx'
        }
      ],
      edgeEventList: {},
      currentActive: 0,
    };
  },
  created() {
  },
  computed: {
    disabledBtn() {
      return this.$store.state.flow.methodBtn;
    }
  },
  methods: {
    async getNewRowDate() {
      return new Promise((resolve) => {
        this.$refs.form.validate((flag) => {
          if (!flag) {
            resolve(false);
          } else {
            resolve(this.newRowData);
          }
        });
      });
    },
    handleChange(val) {
    }
  },
  watch: {
    rowData: {
      deep: true,
      immediate: true,
      handler(newV) {
        if (
          typeof newV === "object" &&
          newV !== null &&
          Object.keys(this.rowData).length > 0
        ) {
          this.newRowData = Object.assign({}, newV);
        }
      },
    },
    existNodes(newV) {
      const flag = newV.some((item) => item.id === this.newRowData.startStatus);
      if (!flag) {
        this.newRowData.startStatus = undefined;
      }
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep {
  .el-tag.el-tag--info {
    color: #409eff;
    background-color: #ecf5ff;
  }
}
.event {
  margin-top: 20px;
  text-align: center;
}
.flex {
  margin-top: 10px;
  display: flex;
  justify-content: space-between;
}
.red {
  color: red;
}
.active {
  // box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.4)
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/EditorMinimap.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
<template>
  <minimap :height="200" />
</template>
<script>
import { Minimap } from 'vue-flowchart-editor'
export default {
  name: 'EditorMinimap',
  components: { Minimap },
}
</script>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/Icon.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
<template>
  <i class="action" :title="text">
    <svg width="1em" height="1em" fill="currentColor">
      <use :xlink:href="'#' + type" />
    </svg>
  </i>
</template>
<script>
import '../iconfont'
export default {
  name: 'EditorIcon',
  props: ['type', 'text'],
}
</script>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ItemPanel.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
<template>
  <div class="item_panel_box">
    <el-input size="mini" placeholder="输入关键字进行过滤" v-model="filterText">
    </el-input>
    <div class="box_item">
      <item-panel class="item-panel" v-loading="loading">
        <template v-for="(item, index) in nodeItems">
          <item
            :key="index"
            :type="item.type || 'node'"
            :size="item.size || '72*43'"
            :shape="item.shape || 'flow-rect'"
            :model="{
              // must have model property
              color: item.color || '#1890FF',
              label: item.id || '节点'
            }"
          >
            <template v-if="item.src">
              <div class="item item-img">
                <img :src="item.src" :alt="item.id" />
              </div>
            </template>
            <template v-else>
              <div :class="'item item-' + (item.shape || 'flow-rect')">
                <span>{{ item.id }}</span>
              </div>
            </template>
          </item>
        </template>
      </item-panel>
    </div>
  </div>
</template>
<script>
import { Item, ItemPanel } from 'vue-flowchart-editor'
// import { getPage } from '../../../api/omd/status'
export default {
  name: 'EditorItemPanel',
  components: { ItemPanel, Item },
  props: {
    nodeItems:{
      type:Array,
      default:() => [],
    }
  },
  data() {
    return {
      filterText: '',
      loading: false,
    }
  },
  created() {
    this.loading = false
  },
  computed: {
    filterNode() {
      return this.nodeItems.filter(item => item.id.includes(this.filterText))
    }
  },
}
</script>
<style lang="scss" scoped>
.item-panel {
  width: 100%;
  height: 77vh;
  text-align: center;
  overflow-y: scroll;
  display: flex;
  flex-wrap: wrap; /* å…è®¸æ¢è¡Œ */
  justify-content: center; /* å±…中对齐项目 */
  align-items: flex-start; /* ç¡®ä¿é¡¹ç›®åœ¨å®¹å™¨é¡¶éƒ¨å¯¹é½ */
}
.item {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 12px;
  margin: 10px; /* è®¾å®šå¤–边距以确保项目间有间隔 */
  user-select: none;
}
/* é¡¹ç›®ç±»åž‹çš„æ ·å¼ */
.item-flow-rect {
  width: 75px;
  padding: 6px;
  box-sizing: border-box;
  border: 1px solid rgb(24, 144, 255);
  background-color: rgba(24, 144, 255, 0.2);
}
.item-flow-circle {
  width: 70px;
  height: 70px;
  border-radius: 60px;
  border: 1px solid rgb(250, 140, 22);
  background-color: rgba(250, 140, 22, 0.2);
}
.item-flow-rhombus {
  width: 70px;
  height: 70px;
  border: 1px solid rgb(19, 194, 194);
  background-color: rgba(19, 194, 194, 0.2);
  transform: rotate(45deg);
  margin: 25px auto;
  span {
    transform: rotate(-45deg);
  }
}
.item-img {
  max-width: 100px;
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/Toolbar.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
<template>
  <toolbar class="toolbar">
    <template>
      <toolbar-button command="undo" text="撤销"/>
      <toolbar-button command="redo" text="重做"/>
<!--      <toolbar-button command="copy" text="复制"/>-->
<!--      <toolbar-button command="paste" text="粘贴"/>-->
      <div class="split"></div>
    </template>
    <toolbar-button command="zoomIn" icon="zoom-in" text="放大"/>
    <toolbar-button command="zoomOut" icon="zoom-out" text="缩小"/>
    <toolbar-button command="autoZoom" icon="fit" text="自适应"/>
    <toolbar-button command="resetZoom" icon="actual-size" text="实际尺寸"/>
    <template>
      <div class="split"></div>
      <!-- <toolbar-button command="toBack" icon="to-back" text="向下一层" /> -->
      <!-- <toolbar-button command="toFront" icon="to-front" text="向上一层" /> -->
      <!-- <toolbar-button command="addGroup" icon="group" text="编组" /> -->
      <!-- <toolbar-button command="unGroup" icon="ungroup" text="取消编组" /> -->
      <toolbar-button command="selectAll" icon="select-all" text="全选"/>
      <toolbar-button command="multiSelect" icon="select" text="框选"/>
      <div v-if="disabledBtn" class="split"></div>
      <toolbar-button  command="delete" text="删除"/>
      <toolbar-button  command="clear" icon="clear" text="清空画布"/>
    </template>
    <template>
      <div class="split"></div>
      <toolbar-button
        command="downloadImage"
        icon="image"
        text="下载图像"
      />
    </template>
    <!--    <el-button>{{this.$store}}</el-button>-->
    <el-button :disabled="!disabledBtn" icon="el-icon-check" plain size="small" type="success"
               @click="saveClickHandler">保存
    </el-button>
    <el-button :disabled="!disabledBtn" icon="el-icon-close" plain size="small" type="danger"
               @click="removeClickHandler">取消
    </el-button>
    <!-- right toolbar button -->
    <!--  <div class="pull-right">-->
    <!--      <toolbar-button-->
    <!--        command="generateData"-->
    <!--        icon="save"-->
    <!--        text="生成数据"-->
    <!--        label="保存数据"-->
    <!--      />-->
    <!--    </div>-->
  </toolbar>
</template>
<script>
import {Toolbar} from 'vue-flowchart-editor'
import ToolbarButton from './ToolbarButton'
export default {
  name: 'FlowToolbar',
  components: {
    Toolbar,
    ToolbarButton,
  },
  props: ['chartData', 'toggleReadOnly'],
  created() {
  },
  computed: {
    disabledBtn() {
      return this.$store.state.flow.methodBtn;
    }
  },
  methods: {
    // å–消按钮点击
    removeClickHandler() {
      this.$confirm("您确认执行取消操作?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        this.$store.dispatch('updateMethodBtn', false);
        // this.$emit('reset-tree'); // è§¦å‘父组件重置
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消'
        });
      });
    },
    // ä¿å­˜æŒ‰é’®ç‚¹å‡»äº‹ä»¶
    saveClickHandler(){
      this.$emit('handler-save');
    },
  },
}
</script>
<style lang="scss" scoped>
.toolbar {
  display: flex;
  align-items: center;
  height: 27px;
  .split {
    width: 10px;
    height: 100%;
    border-right: 1px solid #eee;
    margin-right: 10px;
  }
  .pull-right {
    display: flex;
    align-items: center;
    margin-left: auto;
  }
  .command {
    margin-right: 15px;
    display: flex;
    color: #333;
    i {
      display: block;
      width: 27px;
      height: 27px;
      margin: 0 6px;
      padding-top: 10px;
      text-align: center;
      border: 1px solid #fff;
      cursor: pointer;
    }
    span {
      display: block;
      font-size: 12px;
      padding-top: 10px;
      margin-left: -6px;
      padding-right: 6px;
      line-height: 20px;
      cursor: pointer;
    }
    &:hover {
      color: #1890ff;
    }
  }
  .disable {
    color: rgba(0, 0, 0, 0.25);
    i {
      cursor: not-allowed;
    }
    span {
      cursor: not-allowed;
    }
    &:hover {
      color: rgba(0, 0, 0, 0.25);
    }
  }
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/components/ToolbarButton.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
<template>
  <command :name="command">
    <icon :type="iconType" :title="text" />
    <span v-if="label">{{ label }}</span>
  </command>
</template>
<script>
import { Command } from 'vue-flowchart-editor'
import Icon from './Icon'
export default {
  name: 'EditorToolbarButton',
  props: ['command', 'icon', 'text', 'label'],
  computed: {
    iconType() {
      return `icon${this.icon || this.command}`
    },
  },
  components: {
    Command,
    Icon,
  },
}
</script>
Source/plt-web/plt-web-ui/src/components/flow-cycle/flowchartEditor.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,279 @@
<template>
  <vue-flowchart-editor ref="flowChart" class="vue-flowchart-editor">
    <div class="vfe-chart">
      <!-- é¡¶éƒ¨èœå• -->
      <div v-if="type !== 'detail'" class="vfe-chart-header">
        <editor-toolbar @handler-save="handlerSave" @reset-tree="handleResetTree"  :chart-data="chartData"/>
      </div>
      <div class="vfe-chart-container">
        <!-- å·¦ä¾§é¡¹ç›®æ  -->
        <div v-if="type !== 'detail'" class="vfe-chart-sidebar">
          <editor-item-panel :node-items="chartDataNodeItems"/>
        </div>
        <!-- ä¸»å›¾è¡¨ -->
        <div class="vfe-chart-main">
          <flow
            :data="chartData"
            :onAfterChange="onAfterChange"
            :onAfterItemSelected="onAfterItemSelected"
          />
          <!-- æç¤ºæ¡† -->
          <div class="tooltip">
            <template v-for="item in tooltipData">
              <p>{{ item.name }}: {{ item.value }}</p>
            </template>
          </div>
        </div>
        <div v-if="type !== 'detail'" class="vfe-chart-panel">
          <div class="vfe-chart-panel-detail">
            <editor-detail-panel
              ref="EditorDetailPanel"
              :currentSelectedLine="currentSelectedLine"
              :existEdges="existEdges"
              :existNodes="existNodes"
              :rowData="rowData"
              :type="type"
            />
          </div>
        </div>
      </div>
    </div>
    <!-- å³é”®èœå• -->
    <editor-context-menu v-if="type !== 'detail'"/>
    <!-- è‡ªå®šä¹‰è¾¹é…ç½® -->
    <register-edge
      :config="customEdgeConfig"
      extend="flow-polyline"
      name="custom-polyline"
    />
    <!-- è‡ªå®šä¹‰å‘½ä»¤ç»„ä»¶ -->
    <custom-command :download="downloadImage"/>
  </vue-flowchart-editor>
</template>
<script>
import VueFlowchartEditor, {Flow, RegisterEdge} from "vue-flowchart-editor";
import EditorToolbar from "./components/Toolbar";
import EditorItemPanel from "./components/ItemPanel";
import EditorDetailPanel from "./components/DetailPanel";
import EditorMinimap from "./components/EditorMinimap";
import EditorContextMenu from "./components/ContextMenu";
import CustomCommand from "./components/CustomCommand";
export default {
  name: "FlowchartEditor",
  components: {
    VueFlowchartEditor,
    Flow,
    EditorToolbar,
    EditorItemPanel,
    EditorDetailPanel,
    EditorMinimap,
    EditorContextMenu,
    CustomCommand,
    RegisterEdge,
  },
  props: ["chartData", "chartDataNodeItems", "saveData", "rowData", "type"],
  data() {
    return {
      // å½“前图表的数据
      flowChartData: {},
      // è‡ªå®šä¹‰è¾¹çš„配置
      customEdgeConfig: {
        getActivedStyle(/*item*/) {
          return {
            lineWidth: 3, // æ´»è·ƒçŠ¶æ€ä¸‹çš„è¾¹æ ·å¼
          };
        },
        getSelectedStyle(/*item*/) {
          return {
            lineWidth: 3, // é€‰ä¸­çŠ¶æ€ä¸‹çš„è¾¹æ ·å¼
          };
        },
      },
      // å·¥å…·æç¤ºæ˜¾ç¤ºå¼€å…³
      tooltipShow: true,
      // å·¥å…·æç¤ºæ•°æ®
      tooltipData: [],
      // å·²å­˜åœ¨çš„节点和边
      existNodes: this.chartData.nodes || [],
      existEdges: this.chartData.edges || [],
      // å½“前选中的边
      currentSelectedLine: {}
    };
  },
  mounted() {
    // ç»„件挂载完成后,自动缩放画布(仅在添加模式下)
    if (this.type === "add") {
      this.$nextTick(() => {
        this.$refs.flowChart.propsAPI.executeCommand("autoZoom");
      });
    }
  },
  methods: {
    update(){
      this.$refs.flowChart.propsAPI.read(this.flowChartData);
    },
    // å¤„理图表数据更改的事件
    onAfterChange(e) {
      try {
        // å¦‚果添加了节点且节点没有被更改过
        if (e.action === "add" && e.model.type === "node") {
          if (!e.model.change) {
            this.$refs.flowChart.propsAPI.remove(e.item); // ç§»é™¤åŽŸæœ‰çš„èŠ‚ç‚¹
            e.model.id = e.model.label; // ä½¿ç”¨æ ‡ç­¾ä½œä¸ºèŠ‚ç‚¹çš„ ID
            e.model.change = true;
            this.$refs.flowChart.propsAPI.add("node", e.model); // æ·»åŠ æ–°çš„èŠ‚ç‚¹
          }
        }
      } catch (err) {
        // å¤„理节点 ID å†²çªé”™è¯¯
        if (
          err.message ===
          `id:${e.model.label} has already been set, please set new one`
        ) {
          this.$message.error("不能添加已存在的节点!");
        }
      }
      // ä¿å­˜å½“前的节点和边数据
      const {nodes, edges} = this.$refs.flowChart.propsAPI.save();
      this.existNodes = nodes || [];
      this.existEdges = edges || [];
    },
    // å¤„理选中线变化的事件 å›žå¡«å½“前线信息
    onAfterItemSelected({item}) {
      if (item.target) {
        // æŸ¥æ‰¾å½“前选中的边
        const currentEdge = this.existEdges.filter(itm => itm.id === item.id)[0] || {};
        if (!Array.isArray(currentEdge.events)) {
          currentEdge.events = []
        }
        this.currentSelectedLine = currentEdge;
      }
    },
    // ä¸‹è½½å›¾ç‰‡
    _downloadImage(data, filename = "flowchart.png") {
      const a = document.createElement("a");
      a.href = data;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
    },
    // è°ƒç”¨ä¸‹è½½å›¾ç‰‡æ–¹æ³•
    downloadImage() {
      const page = this.$refs["flowChart"].propsAPI.editor.getCurrentPage();
      this._downloadImage(page.saveImage().toDataURL("image/png"));
    },
    // èŽ·å–æ–°çš„è¡Œæ•°æ®ï¼ˆä»Žè¯¦ç»†é¢æ¿ä¸­ï¼‰
    getNewRowData() {
      return this.$refs.EditorDetailPanel.getNewRowDate();
    },
    // èŽ·å–å½“å‰å›¾è¡¨çš„æ•°æ®
    getFlowData() {
      return this.$refs.flowChart.propsAPI.save();
    },
    // èŽ·å–è¾¹äº‹ä»¶åˆ—è¡¨ï¼ˆä»Žè¯¦ç»†é¢æ¿ä¸­ï¼‰
    getEdgesEvents() {
      return this.$refs.EditorDetailPanel.edgeEventList;
    },
    // è°ƒç”¨çˆ¶ç»„件重置
    handleResetTree(){
      this.$emit('reset-tree');
    },
    handlerSave(){
      this.$emit('handler-save')
    }
  },
};
</script>
<style lang="scss" scoped>
.vue-flowchart-editor {
  display: flex;
  flex: 1;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: #fff;
}
.vfe-chart {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .vfe-chart-header {
    border: 1px solid #e6e9ed;
    padding: 8px;
  }
  .vfe-chart-container {
    flex: 1;
    display: flex;
    height: 550px;
    overflow: hidden;
    .vfe-chart-main {
      position: relative;
      flex: 1;
      max-height: calc(100% - 5px); // fix scroll show
      .tooltip {
        position: absolute;
        display: none;
        top: 0;
        left: 0;
        width: 100px;
        height: auto;
        padding: 15px;
        border-radius: 10px;
        z-index: 999;
        opacity: 0.8;
        color: #ffffff;
        font-size: 12px;
        background-color: #000;
        p {
          margin: 0;
        }
      }
    }
    .vfe-chart-sidebar {
      margin-top: 10px;
      position: relative;
      display: flex;
      justify-content: center;
      width: 16%;
      background-color: #fafafa;
      border-right: 1px solid #e6e9ed;
    }
    .vfe-chart-panel {
      position: relative;
      width: 300px;
      background-color: #fafafa;
      border-left: 1px solid #e6e9ed;
      overflow-y: scroll;
      .vfe-chart-panel-detail {
        box-sizing: border-box;
        padding: 10px;
      }
    }
  }
}
</style>
Source/plt-web/plt-web-ui/src/components/flow-cycle/iconfont.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
!function(v){var c,h='<svg><symbol id="iconto-back" viewBox="0 0 1024 1024"><path d="M640 726.016l0-86.016 86.016 0 0 86.016-86.016 0zM640 214.016l0-86.016 86.016 0 0 86.016-86.016 0zM214.016 297.984l0 512 512 0 0 86.016-512 0q-36.010667 0-61.013333-25.984t-25.002667-59.989333l0-512 86.016 0zM809.984 726.016l0-86.016 86.016 0q0 34.005333-25.984 59.989333t-59.989333 25.984zM809.984 384l0-86.016 86.016 0 0 86.016-86.016 0zM809.984 553.984l0-84.010667 86.016 0 0 84.010667-86.016 0zM384 726.016q-36.010667 0-61.013333-25.984t-25.002667-59.989333l86.016 0 0 86.016zM553.984 128l0 86.016-84.010667 0 0-86.016 84.010667 0zM809.984 128q34.005333 0 59.989333 25.984t25.984 59.989333l-86.016 0 0-86.016zM553.984 640l0 86.016-84.010667 0 0-86.016 84.010667 0zM384 128l0 86.016-86.016 0q0-34.005333 25.002667-59.989333t61.013333-25.984zM384 470.016l0 84.010667-86.016 0 0-84.010667 86.016 0zM384 297.984l0 86.016-86.016 0 0-86.016 86.016 0z"  ></path></symbol><symbol id="iconfit" viewBox="0 0 1024 1024"><path d="M597.333333 405.376c0-0.128 0.085333-0.256 0.085333-0.384C597.418667 404.821333 597.333333 404.650667 597.333333 404.522667L597.333333 192.768C597.333333 180.522667 606.933333 170.538667 618.666667 170.666667c11.733333-0.042667 21.376 9.813333 21.376 22.144L640.042667 384l191.189333 0c12.16 0 22.186667 9.6 22.101333 21.333333 0 11.733333-9.813333 21.333333-22.186667 21.333333l-211.754667 0c-0.128 0-0.256-0.085333-0.384-0.085333S618.837333 426.666667 618.709333 426.666667c-4.821333 0-9.045333-1.962667-12.629333-4.736-0.853333-0.64-1.749333-0.981333-2.432-1.706667-0.213333-0.213333-0.298667-0.469333-0.512-0.725333C599.68 415.744 597.333333 410.837333 597.333333 405.376zM362.666667 170.666667C350.933333 170.624 341.290667 180.48 341.290667 192.810667L341.290667 384 150.101333 384C137.898667 384 127.914667 393.6 128 405.333333 128 417.066667 137.813333 426.666667 150.186667 426.666667l211.754667 0c0.128 0 0.256-0.085333 0.384-0.085333S362.496 426.666667 362.624 426.666667c4.821333 0 9.045333-1.962667 12.629333-4.736 0.853333-0.64 1.749333-0.981333 2.432-1.706667 0.213333-0.213333 0.298667-0.469333 0.512-0.725333C381.653333 415.744 384 410.837333 384 405.376c0-0.128-0.085333-0.256-0.085333-0.384C383.914667 404.821333 384 404.650667 384 404.522667L384 192.768C384 180.522667 374.4 170.538667 362.666667 170.666667zM831.146667 640l-211.754667 0c-0.128 0-0.256 0.085333-0.384 0.085333S618.837333 640 618.709333 640c-4.821333 0-9.088 2.005333-12.672 4.778667-0.810667 0.597333-1.706667 0.938667-2.389333 1.664-0.213333 0.213333-0.298667 0.469333-0.512 0.725333C599.68 650.922667 597.333333 655.829333 597.333333 661.290667c0 0.128 0.085333 0.256 0.085333 0.384 0 0.170667-0.085333 0.341333-0.085333 0.469333l0 211.797333c0 12.202667 9.6 22.229333 21.333333 22.101333 11.733333 0.042667 21.376-9.813333 21.376-22.144L640.042667 682.666667l191.189333 0c12.16 0 22.186667-9.6 22.101333-21.333333C853.333333 649.6 843.52 640 831.146667 640zM378.154667 647.168c-0.213333-0.256-0.298667-0.512-0.512-0.725333-0.682667-0.725333-1.578667-1.066667-2.389333-1.664C371.712 642.005333 367.445333 640 362.624 640c-0.128 0-0.213333 0.085333-0.341333 0.085333S362.026667 640 361.898667 640L150.186667 640C137.813333 640 128 649.6 128 661.333333 127.914667 673.066667 137.898667 682.666667 150.101333 682.666667l191.189333 0 0 191.189333c0 12.288 9.642667 22.186667 21.376 22.144C374.4 896.128 384 886.144 384 873.898667l0-211.797333c0-0.128-0.085333-0.298667-0.085333-0.469333C383.914667 661.546667 384 661.418667 384 661.290667 384 655.829333 381.653333 650.922667 378.154667 647.168zM490.666667 469.333333c-35.328 0-64 28.672-64 64s28.672 64 64 64 64-28.672 64-64S525.994667 469.333333 490.666667 469.333333z"  ></path></symbol><symbol id="iconpaste" viewBox="0 0 1024 1024"><path d="M776 248 704 248 704 192l99.968 0C819.392 192 832 204.608 832 220.032l0 98.88-56 0L776 248zM255.104 904 184 904 184 248 256 248 256 192 156.032 192C140.608 192 128 204.608 128 220.032l0 712C128 947.392 140.608 960 156.032 960l99.136 0L255.168 904zM640 320 320 320 320 192l64 0L384 120C384 89.216 409.216 64 440 64l72.064 0c30.784 0 56 25.216 56 56L568.064 192 640 192 640 320zM512.128 120.128C512.064 120.064 512 120 512 120L440.064 120.064c0 0 0 0.064-0.064 0.064L440 192l72.064 0 0.064 0L512.128 120.128zM888.256 995.776 888.256 578.88l-182.4-192L351.488 386.88c-18.624 0-31.232 12.608-31.232 28.032l0 580.864c0 15.36 12.608 28.032 28.032 28.032l512 0C875.648 1023.744 888.256 1011.136 888.256 995.776zM824.256 586.88l-129.6 0L694.656 450.88 824.256 586.88zM832.256 970.88 376.256 970.88 376.256 442.88l265.6 0 0 196.864 190.4 0L832.256 970.88z"  ></path></symbol><symbol id="iconactual-size" viewBox="0 0 1024 1024"><path d="M829.013333 810.666667l-640 0c-58.794667 0-106.666667-47.829333-106.666667-106.666667l0-469.333333c0-58.794667 47.872-106.666667 106.666667-106.666667l640 0c58.837333 0 106.666667 47.872 106.666667 106.666667l0 469.333333C935.68 762.837333 887.850667 810.666667 829.013333 810.666667zM189.013333 170.666667c-35.285333 0-64 28.714667-64 64l0 469.333333c0 35.285333 28.714667 64 64 64l640 0c35.285333 0 64-28.714667 64-64l0-469.333333c0-35.285333-28.714667-64-64-64L189.013333 170.666667zM338.346667 640.256c0 11.733333-9.557333 21.333333-21.333333 21.333333s-21.333333-9.6-21.333333-21.333333l0-341.333333c0-11.818667 9.557333-21.333333 21.333333-21.333333s21.333333 9.514667 21.333333 21.333333L338.346667 640.256zM722.346667 640.256c0 11.733333-9.557333 21.333333-21.333333 21.333333s-21.333333-9.6-21.333333-21.333333l0-341.333333c0-11.818667 9.557333-21.333333 21.333333-21.333333s21.333333 9.514667 21.333333 21.333333L722.346667 640.256zM509.013333 341.333333c-23.594667 0-42.666667 19.072-42.666667 42.666667s19.072 42.666667 42.666667 42.666667 42.666667-19.072 42.666667-42.666667S532.565333 341.333333 509.013333 341.333333zM509.013333 512c-23.594667 0-42.666667 19.072-42.666667 42.666667s19.072 42.666667 42.666667 42.666667 42.666667-19.072 42.666667-42.666667S532.565333 512 509.013333 512z"  ></path></symbol><symbol id="iconredo" viewBox="0 0 1024 1024"><path d="M708.16 635.904c-39.36 35.968-48.32 41.344-50.496-25.856-3.968-49.152 0-103.552 0-103.552-1.408-3.072-86.464-35.008-227.072 25.856C290.048 593.28 195.2 783.36 178.432 842.88 177.088 877.248 132.288 943.616 128 841.472c-0.576-166.656 64.512-341.12 230.336-441.152 154.624-93.248 283.264-83.776 297.408-78.848 0.256 1.344 0.64 1.856 1.344 1.024 0.192-0.256-0.384-0.64-1.344-1.024-1.216-6.208 2.496-38.272 2.88-98.56-2.368-54.144 12.096-55.808 49.536-26.944 68.544 56.32 251.776 231.36 251.776 231.36S776.768 580.608 708.16 635.904z"  ></path></symbol><symbol id="iconundo" viewBox="0 0 1024 1024"><path d="M379.776 635.904c39.36 35.968 48.32 41.344 50.496-25.856 3.968-49.152 0-103.552 0-103.552 1.408-3.072 86.464-35.008 227.072 25.856 140.544 60.928 235.456 251.008 252.16 310.528 1.344 34.368 46.144 100.736 50.432-1.344 0.576-166.656-64.512-341.12-230.336-441.152C574.976 307.072 446.4 316.608 432.192 321.472c-0.256 1.344-0.64 1.856-1.344 1.024-0.192-0.256 0.384-0.64 1.344-1.024 1.216-6.208-2.496-38.272-2.88-98.56 2.368-54.144-12.096-55.808-49.536-26.944C311.168 252.288 128 427.264 128 427.264S311.168 580.608 379.776 635.904z"  ></path></symbol><symbol id="icondelete" viewBox="0 0 1024 1024"><path d="M677.647059 256l0-90.352941c0-37.436235-23.461647-60.235294-61.771294-60.235294L408.094118 105.411765c-38.249412 0-61.741176 22.799059-61.741176 60.235294l0 90.352941-180.705882 0 0 60.235294 60.235294 0 0 512c0 54.272 33.972706 90.352941 90.352941 90.352941l391.529412 0c55.085176 0 90.352941-33.490824 90.352941-90.352941l0-512 60.235294 0 0-60.235294L677.647059 256zM406.588235 165.647059l210.823529 0-1.264941 90.352941L406.588235 256 406.588235 165.647059zM737.882353 858.352941l-451.764706 0 0-542.117647 451.764706 0L737.882353 858.352941zM466.823529 376.470588l-58.729412 0-1.505882 391.529412 60.235294 0L466.823529 376.470588zM617.411765 376.470588l-60.235294 0 0 391.529412 60.235294 0L617.411765 376.470588z"  ></path></symbol><symbol id="iconzoom-in" viewBox="0 0 1024 1024"><path d="M1000.146824 957.500235l-311.597176-311.597176c58.729412-68.487529 94.509176-157.214118 94.509176-254.373647 0-215.883294-175.646118-391.529412-391.529412-391.529412-104.628706 0-202.932706 40.719059-276.901647 114.688-73.968941 73.908706-114.627765 172.272941-114.627765 276.841412 0 215.883294 175.646118 391.529412 391.529412 391.529412 97.099294 0 185.886118-35.779765 254.433882-94.509176l311.597176 311.597176 42.586353-42.646588zM391.529412 722.823529c-182.693647 0-331.294118-148.600471-331.294118-331.294118 0-88.545882 34.394353-171.730824 96.978824-234.315294 62.584471-62.524235 145.769412-96.978824 234.315294-96.978824 182.693647 0 331.294118 148.600471 331.294118 331.294118 0 182.693647-148.600471 331.294118-331.294118 331.294118zM421.647059 361.411765l120.470588 0 0 60.235294-120.470588 0 0 120.470588-60.235294 0 0-120.470588-120.470588 0 0-60.235294 120.470588 0 0-120.470588 60.235294 0 0 120.470588z"  ></path></symbol><symbol id="iconzoom-out" viewBox="0 0 1024 1024"><path d="M999.344139 955.925769l-311.084802-311.084802c58.63284-68.374912 94.35377-157.015739 94.35377-253.955368 0-215.528306-175.357294-390.8856-390.8856-390.8856-104.396523 0-202.599013 40.652102-276.50646 114.439276-73.787174 73.84731-114.439276 172.0498-114.37914 276.446324 0 215.528306 175.357294 390.8856 390.8856 390.8856 96.939629 0 185.640592-35.72093 254.015504-94.35377l311.084802 311.084802 42.516326-42.576462zM391.727508 721.634954c-182.333098 0-330.749354-148.356119-330.749354-330.749354-0.060136-88.400282 34.337797-171.448438 96.819356-233.869861 62.421424-62.48156 145.529716-96.879493 233.929998-96.879493 182.333098 0 330.749354 148.356119 330.749354 330.749354 0 182.333098-148.416256 330.749354-330.749354 330.749354zM241.386892 360.817477l300.681231 0 0 60.136246-300.681231 0 0-60.136246z"  ></path></symbol><symbol id="iconcopy" viewBox="0 0 1024 1024"><path d="M880 247.008l-162.016-166.016Q700.992 64 677.984 64h-316.992q-26.016 0-46.016 18.016-16.992 15.008-23.008 36.992H231.968q-43.008 0-73.504 31.008t-30.496 76v627.008q0 44 30.496 75.488T231.968 960h508q43.008 0 73.504-31.488t30.496-75.488v-63.008q23.008-6.016 37.504-25.504t14.496-44.512V287.008q0-24-16-40z m-168-160.992l-3.008-3.008z m98.016 177.984L744 196z m-126.016-116.992l108 110.016h-108V147.008zM676.992 128zM204.992 948q4 0.992 4.992 2.016-2.016-0.992-4.992-2.016z m27.008 4q-6.016 0-12-0.992 4.992 0.992 12 0.992z m543.008-99.008q0 15.008-10.016 25.504t-24.992 10.496H232q-14.016 0-24.512-10.496t-10.496-25.504V225.984q0-15.008 10.496-25.504t24.512-10.496h58.016v531.008q0 30.016 20.992 51.008t50.016 20.992H775.04v60z m52-132.992q0 2.016-2.016 2.016h-464q-2.016 0-2.016-2.016V136.992q0-2.016 2.016-2.016h251.008v156.992q0 15.008 10.016 24.992t24 10.016h180.992v392.992z m9.984 64q4-0.992 8.992-2.016-4.992 0.992-8.992 2.016z m-244-168.992h-107.008q-15.008 0-24.992 10.496t-10.016 24.992 10.016 24.992 24.992 10.496h107.008q14.016 0 24.512-10.496t10.496-24.992-10.496-24.992-24.512-10.496z m107.008-111.008h-214.016q-14.016 0-24.512 10.496t-10.496 24.992 10.496 24.992 24.512 10.496h214.016q14.016 0 24-10.496t10.016-24.992-10.016-24.992-24-10.496z m-240.992 36q0 4 0.992 8-0.992-4-0.992-8zM700 512z m12 52l4-2.016z m-260.992-135.488q0 14.496 10.496 24.992t24.512 10.496h214.016q14.016 0 24-10.496t10.016-24.992-10.016-24.992-24-10.496h-214.016q-14.016 0-24.512 10.496t-10.496 24.992z m8 1.504z"  ></path></symbol><symbol id="iconsave" viewBox="0 0 1024 1024"><path d="M886.4 265.6l-128-128c-6.4-6.4-12.8-9.6-22.4-9.6H160c-19.2 0-32 12.8-32 32v704c0 19.2 12.8 32 32 32h704c19.2 0 32-12.8 32-32V288c0-9.6-3.2-16-9.6-22.4zM352 192h320v256H352V192z m480 640H192V192h96v288c0 19.2 12.8 32 32 32h384c19.2 0 32-12.8 32-32V204.8l96 96V832z"  ></path><path d="M576 256c-19.2 0-32 12.8-32 32v64c0 19.2 12.8 32 32 32s32-12.8 32-32V288c0-19.2-12.8-32-32-32z"  ></path></symbol><symbol id="iconselect-all" viewBox="0 0 1024 1024"><path d="M128 213.333333h85.333333V128c-47.146667 0-85.333333 38.186667-85.333333 85.333333z m0 341.333334h85.333333v-85.333334H128v85.333334z m170.666667 341.333333h85.333333v-85.333333h-85.333333v85.333333zM128 384h85.333333v-85.333333H128v85.333333zM554.666667 128h-85.333334v85.333333h85.333334V128z m256 0v85.333333h85.333333c0-47.146667-38.186667-85.333333-85.333333-85.333333zM213.333333 896v-85.333333H128c0 47.146667 38.186667 85.333333 85.333333 85.333333z m-85.333333-170.666667h85.333333v-85.333333H128v85.333333zM384 128h-85.333333v85.333333h85.333333V128z m85.333333 768h85.333334v-85.333333h-85.333334v85.333333z m341.333334-341.333333h85.333333v-85.333334h-85.333333v85.333334z m0 341.333333c47.146667 0 85.333333-38.186667 85.333333-85.333333h-85.333333v85.333333z m0-512h85.333333v-85.333333h-85.333333v85.333333z m0 341.333333h85.333333v-85.333333h-85.333333v85.333333z m-170.666667 170.666667h85.333333v-85.333333h-85.333333v85.333333z m0-682.666667h85.333333V128h-85.333333v85.333333zM298.666667 725.333333h426.666666V298.666667H298.666667v426.666666z m85.333333-341.333333h256v256H384V384z" fill="" ></path></symbol><symbol id="iconselect" viewBox="0 0 1024 1024"><path d="M324.266667 34.133333h-102.4c-10.24 0-17.066667 6.826667-17.066667 17.066667s6.826667 17.066667 17.066667 17.066667h102.4c10.24 0 17.066667-6.826667 17.066666-17.066667S334.506667 34.133333 324.266667 34.133333zM597.333333 34.133333h-102.4c-10.24 0-17.066667 6.826667-17.066666 17.066667s6.826667 17.066667 17.066666 17.066667h102.4c10.24 0 17.066667-6.826667 17.066667-17.066667s-6.826667-17.066667-17.066667-17.066667zM324.266667 716.8h-102.4c-10.24 0-17.066667 6.826667-17.066667 17.066667s6.826667 17.066667 17.066667 17.066666h102.4c10.24 0 17.066667-6.826667 17.066666-17.066666s-6.826667-17.066667-17.066666-17.066667zM563.2 716.8h-68.266667c-10.24 0-17.066667 6.826667-17.066666 17.066667s6.826667 17.066667 17.066666 17.066666h68.266667c10.24 0 17.066667-6.826667 17.066667-17.066666s-6.826667-17.066667-17.066667-17.066667zM34.133333 597.333333c0 10.24 6.826667 17.066667 17.066667 17.066667s17.066667-6.826667 17.066667-17.066667v-102.4c0-10.24-6.826667-17.066667-17.066667-17.066666s-17.066667 6.826667-17.066667 17.066666v102.4zM51.2 341.333333c10.24 0 17.066667-6.826667 17.066667-17.066666v-102.4c0-10.24-6.826667-17.066667-17.066667-17.066667s-17.066667 6.826667-17.066667 17.066667v102.4c0 10.24 6.826667 17.066667 17.066667 17.066666zM768 477.866667c-10.24 0-17.066667 6.826667-17.066667 17.066666v68.266667c0 10.24 6.826667 17.066667 17.066667 17.066667s17.066667-6.826667 17.066667-17.066667v-68.266667c0-10.24-6.826667-17.066667-17.066667-17.066666zM785.066667 221.866667c0-10.24-6.826667-17.066667-17.066667-17.066667s-17.066667 6.826667-17.066667 17.066667v102.4c0 10.24 6.826667 17.066667 17.066667 17.066666s17.066667-6.826667 17.066667-17.066666v-102.4zM733.866667 102.4h68.266666c10.24 0 17.066667-6.826667 17.066667-17.066667v-68.266666c0-10.24-6.826667-17.066667-17.066667-17.066667h-68.266666c-10.24 0-17.066667 6.826667-17.066667 17.066667v68.266666c0 10.24 6.826667 17.066667 17.066667 17.066667zM85.333333 0h-68.266666C6.826667 0 0 6.826667 0 17.066667v68.266666c0 10.24 6.826667 17.066667 17.066667 17.066667h68.266666c10.24 0 17.066667-6.826667 17.066667-17.066667v-68.266666c0-10.24-6.826667-17.066667-17.066667-17.066667zM85.333333 682.666667h-68.266666c-10.24 0-17.066667 6.826667-17.066667 17.066666v68.266667c0 10.24 6.826667 17.066667 17.066667 17.066667h68.266666c10.24 0 17.066667-6.826667 17.066667-17.066667v-68.266667c0-10.24-6.826667-17.066667-17.066667-17.066666zM1013.76 788.48l-375.466667-204.8c-6.826667-3.413333-13.653333-3.413333-20.48 3.413333-3.413333 3.413333-3.413333 10.24-3.413333 17.066667l170.666667 409.6c3.413333 6.826667 6.826667 10.24 13.653333 10.24s13.653333-3.413333 13.653333-10.24l64.853334-133.12 133.12-64.853333c6.826667-3.413333 10.24-10.24 10.24-13.653334 3.413333-6.826667 0-10.24-6.826667-13.653333z" fill="" ></path></symbol><symbol id="iconto-front" viewBox="0 0 1024 1024"><path d="M128 554.666667h85.333333v-85.333334H128v85.333334z m0 170.666666h85.333333v-85.333333H128v85.333333z m85.333333 170.666667v-85.333333H128c0 47.146667 38.186667 85.333333 85.333333 85.333333zM128 384h85.333333v-85.333333H128v85.333333z m512 512h85.333333v-85.333333h-85.333333v85.333333z m170.666667-768H384c-47.146667 0-85.333333 38.186667-85.333333 85.333333v426.666667c0 47.146667 38.186667 85.333333 85.333333 85.333333h426.666667c47.146667 0 85.333333-38.186667 85.333333-85.333333V213.333333c0-47.146667-38.186667-85.333333-85.333333-85.333333z m0 512H384V213.333333h426.666667v426.666667zM469.333333 896h85.333334v-85.333333h-85.333334v85.333333z m-170.666666 0h85.333333v-85.333333h-85.333333v85.333333z"  ></path></symbol><symbol id="iconimage" viewBox="0 0 1024 1024"><path d="M847.657 64.016H175.703c-61.766 0-111.993 50.227-111.993 111.992v671.954c0 61.765 50.226 111.993 111.993 111.993h671.954c61.765 0 111.992-50.228 111.992-111.993V176.01c0-61.765-50.227-111.993-111.992-111.993z m55.995 783.946c0 30.87-25.127 55.997-55.996 55.997H175.703c-30.87 0-55.996-25.127-55.996-55.997V176.01c0-30.87 25.128-55.996 55.996-55.996h671.954c30.87 0 55.996 25.127 55.996 55.996v671.953zM835.19 544.686l-83.995-55.996c-10.444-6.945-23.54-5.688-32.782 1.722l-0.246-0.3-133.184 106.551-197.435-135.752c-0.083-0.055-0.164-0.055-0.218-0.11-2.297-1.53-4.895-2.379-7.52-3.199-0.874-0.273-1.666-0.875-2.57-1.04-2.378-0.492-4.811-0.218-7.273-0.081-1.121 0.082-2.27-0.218-3.363 0-1.23 0.218-2.35 0.984-3.554 1.394-2.27 0.739-4.566 1.367-6.616 2.707-0.083 0.055-0.192 0.055-0.274 0.11L188.17 572.684c-12.878 8.585-16.35 25.946-7.765 38.824 5.386 8.094 14.273 12.47 23.323 12.47 5.332 0 10.718-1.533 15.503-4.704L371.444 517.81 803.8 815.042a27.793 27.793 0 0 0 15.831 4.923c8.913 0 17.663-4.238 23.105-12.14 8.749-12.74 5.523-30.156-7.219-38.934L633.214 629.802l103.956-83.147 66.959 44.621c4.786 3.172 10.171 4.704 15.503 4.704 9.05 0 17.937-4.374 23.323-12.469 8.584-12.877 5.112-30.24-7.766-38.825zM581.674 427.991c69.476 0 125.992-56.516 125.992-125.99 0-69.477-56.516-125.993-125.992-125.993-69.475 0-125.99 56.516-125.99 125.992s56.516 125.991 125.99 125.991z m0-195.985c38.607 0 69.995 31.387 69.995 69.994s-31.388 69.995-69.995 69.995c-38.606 0-69.995-31.39-69.995-69.995 0-38.607 31.39-69.994 69.995-69.994z"  ></path></symbol><symbol id="iconclear" viewBox="0 0 1024 1024"><path d="M686.464 452.821333c5.461333-15.274667 20.394667-43.690667 40.533333-77.952 14.549333-24.746667 39.466667-55.978667 64.810667-87.466666 6.4-7.978667 13.909333-17.152 22.357333-27.562667l34.304 19.456c-8.533333 10.752-15.914667 19.968-22.186666 27.733333-25.770667 31.914667-50.261333 62.165333-65.024 87.296-8.576 14.634667-15.872 27.562667-21.76 38.741334l116.906666 66.304a77.013333 77.013333 0 0 1 28.970667 106.24l-197.973333 336.810666a80 80 0 0 1-108.245334 28.458667l-411.562666-233.344a77.013333 77.013333 0 0 1-28.970667-106.24l197.973333-336.810667a80 80 0 0 1 108.245334-28.501333l116.821333 66.261333c6.912-10.624 14.634667-23.253333 23.253333-37.888 14.762667-25.173333 29.226667-61.056 44.501334-98.986666 3.712-9.173333 8.106667-20.053333 13.354666-32.725334l34.304 19.456-13.141333 32.853334c-15.061333 37.248-30.165333 74.069333-44.714667 98.816-20.138667 34.261333-37.717333 61.184-48.469333 73.429333l-118.229333-67.029333c-33.152-18.773333-73.301333-11.989333-92.074667 19.882666l-167.552 285.056c-18.773333 31.914667-6.826667 73.088 26.325333 91.904l352.554667 199.893334c33.109333 18.773333 75.050667 8.106667 93.781333-23.765334l167.594667-285.056c18.773333-31.914667 5.034667-69.248-28.117333-88.021333l-118.613334-67.242667z m-43.690667-290.133333c22.613333-36.906667 90.026667-47.786667 146.432-15.786667 56.405333 32 80.554667 94.762667 59.306667 132.437334l-34.304-19.456c9.984-18.944-7.68-57.728-45.056-78.890667-37.290667-21.162667-80.341333-16.810667-92.074667 1.109333l-34.304-19.456zM314.112 418.858667l472.704 267.989333-21.888 37.248L292.224 456.106667l21.888-37.205334z"  ></path></symbol><symbol id="icongroup" viewBox="0 0 1024 1024"><path d="M912 820.1V203.9c28-9.9 48-36.6 48-67.9 0-39.8-32.2-72-72-72-31.3 0-58 20-67.9 48H203.9C194 84 167.3 64 136 64c-39.8 0-72 32.2-72 72 0 31.3 20 58 48 67.9v616.2C84 830 64 856.7 64 888c0 39.8 32.2 72 72 72 31.3 0 58-20 67.9-48h616.2c9.9 28 36.6 48 67.9 48 39.8 0 72-32.2 72-72 0-31.3-20-58-48-67.9zM888 112c13.3 0 24 10.7 24 24s-10.7 24-24 24-24-10.7-24-24 10.7-24 24-24zM136 912c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24z m0-752c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24z m704 680H184V184h656v656z m48 72c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24z"  ></path><path d="M288 474h448c8.8 0 16-7.2 16-16V282c0-8.8-7.2-16-16-16H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16z m56-136h336v64H344v-64zM288 758h448c8.8 0 16-7.2 16-16V566c0-8.8-7.2-16-16-16H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16z m56-136h336v64H344v-64z"  ></path></symbol><symbol id="iconungroup" viewBox="0 0 1024 1024"><path d="M736 550H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16h448c8.8 0 16-7.2 16-16V566c0-8.8-7.2-16-16-16z m-56 136H344v-64h336v64zM888 816c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z m0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24zM736 266H288c-8.8 0-16 7.2-16 16v176c0 8.8 7.2 16 16 16h448c8.8 0 16-7.2 16-16V282c0-8.8-7.2-16-16-16z m-56 136H344v-64h336v64zM888 208c39.8 0 72-32.2 72-72s-32.2-72-72-72-72 32.2-72 72 32.2 72 72 72z m0-96c13.3 0 24 10.7 24 24s-10.7 24-24 24-24-10.7-24-24 10.7-24 24-24zM136 64c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z m0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24zM136 816c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z m0 96c-13.3 0-24-10.7-24-24s10.7-24 24-24 24 10.7 24 24-10.7 24-24 24z"  ></path></symbol></svg>',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!v.__iconfont__svg__cssinject__){v.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(o=c,e=v.document,z=!1,(h=function(){try{e.documentElement.doScroll("left")}catch(c){return void setTimeout(h,50)}t()})(),e.onreadystatechange=function(){"complete"==e.readyState&&(e.onreadystatechange=null,t())});function t(){z||(z=!0,o())}var o,e,z,h}(function(){var c,l,t,o,e,z;(c=document.createElement("div")).innerHTML=h,h=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",t=l,(o=document.body).firstChild?(e=t,(z=o.firstChild).parentNode.insertBefore(e,z)):o.appendChild(t))})}(window);
Source/plt-web/plt-web-ui/src/router/router.js
@@ -16,7 +16,7 @@
Vue.use(VueRouter)
//创建路由
export const createRouter = () => new VueRouter({
  mode:"history", //修改为 history æ¨¡å¼ é»˜è®¤ä¸å¸¦#号
  mode:"hash", //修改为 history æ¨¡å¼ é»˜è®¤ä¸å¸¦#号
  routes: [...PageRouter, ...ViewsRouter],
})
const Router = createRouter() // èŽ·å¾— route å®žä¾‹
Source/plt-web/plt-web-ui/src/store/index.js
@@ -6,6 +6,7 @@
import logs from './modules/logs'
import dict from './modules/dict'
import getters from './getters'
import flow from './modules/LifeFlow'
Vue.use(Vuex)
const store = new Vuex.Store({
@@ -14,7 +15,8 @@
    common,
    logs,
    tags,
    dict
    dict,
    flow
  },
  getters,
})
Source/plt-web/plt-web-ui/src/store/modules/LifeFlow.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
import {setStore, getStore} from '@/util/store'
import user from "@/store/modules/user";
const flow = {
  state: {
    methodBtn: false,
  },
  mutations: {
    setMethodBtn(state, value) {
      state.methodBtn = value;
    }
  },
  actions: {
    // æ›´æ–°ä¿å­˜ å–消按钮
    updateMethodBtn({commit}, value) {
      commit('setMethodBtn', value);
    }
  }
}
export default flow
Source/plt-web/plt-web-ui/src/views/authority/function/fuctionView/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/authority/secure/classification/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/authority/secure/machineClassification/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/authority/ui/dataAuthorization/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/authority/ui/typeAction/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/authority/ui/uiAuthorization/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/attributePool/option.js
@@ -6,6 +6,11 @@
    sortable:true,
  },
  {
    label: '标签',
    prop: 'name',
    sortable: true,
  },
  {
    label: '类型',
    prop: 'attributeDataTypeText',
    sortable:true,
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/businessType/index.vue
@@ -1,13 +1,143 @@
<template>
  <p>业务类型</p>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="deleteClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="upLoadClickHandler">导入
            </el-button>
            <el-button class="miniBtn" icon="el-icon-circle-plus-outline" plain size="small"
                       type="primary" @click="createViewClickHandler">创建视图
            </el-button>
            <el-button class="miniBtn" icon="el-icon-circle-plus-outline" plain size="small"
                       type="primary" @click="checkClickHandler">创建索引
            </el-button>
            <el-button icon="el-icon-menu" plain size="small" style="width: 82px;text-align: center;padding-left: 1px"
                       type="primary" @click="checkClickHandler">一致性检查
            </el-button>
            <el-button class="miniBtn" icon="el-icon-delete" plain size="small"
                       type="danger" @click="checkClickHandler">删除数据
            </el-button>
            <el-button class="smallBtn" plain size="small"
                       type="danger" @click="checkClickHandler">删除全部类型
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘ -->
          <div style="height:  calc(100vh - 330px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
  </el-container>
</template>
<script>
import {getBizTypes} from "@/api/modeling/businessType/api"
export default {
  name: "index"
  name: "index",
  data() {
    return {
      treeOption: {
        height: 'auto',
        defaultExpandAll: false,
        menu: false,
        addBtn: false,
        props: {
          label: 'name',
          value: 'name',
          children: 'children'
        }
      },
      treeData: []
    }
  },
  created() {
    this.getTreeList();
  },
  methods: {
    getTreeList() {
      getBizTypes().then(res => {
        const data = res.data.data.map(item => {
          return item.attributes;
        });
        this.treeData = data;
      })
    }
  }
}
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .el-form-item .el-select {
    width: 100%;
  }
  .headerCon {
    .el-button {
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(10) {
  margin-left: 0;
}
.miniBtn {
  width: 82px;
  text-align: center;
  padding-left: 7px;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/lifeCycle/index.vue
@@ -1,13 +1,455 @@
<template>
  <p>生命周期</p>
  <el-container>
    <el-aside width="15.7%">
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘ -->
          <div style="height:  calc(100vh - 300px);">
            <avue-tree ref="tree" :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
        <CycleFlow
          :key="Reload"
          ref="vueFlowchartEditor"
          :chart-data="nodesEdgesData"
          :chart-data-node-items="flowChartNodeItems"
          :rowData="rowData"
          :type="type"
          class="cycle_flow"
          @save-data="save"
          @reset-tree="handleResetTree"
          @handler-save="handlerSave"
        />
      </basic-container>
    </el-main>
    <upload-file ref="upload" :fileType="upFileType" :fileUrl="fileUrl" :tipList="tipList" title="导入"
                 @updata="getTableList"></upload-file>
    <el-dialog
      v-dialogDrag
      v-loading="checkViewLoading"
      :visible.sync="checkViewVisible"
      append-to-body="true"
      class="avue-dialog"
      title="查看使用范围"
      width="60%"
    >
      <avue-crud
        ref="checkViewCrud"
        :data="checkViewData"
        :option="checkViewOption"
        @search-change="checkHandleSearch"
        @search-reset="checkHandleReset"
      >
      </avue-crud>
    </el-dialog>
  </el-container>
</template>
<script>
import {
  gridLifeCycle,
  getLCEventKeys,
  addLifeCycle,
  updateLifeCycle,
  deleteLifeCycles,
  exportLifeCycles,
  getUsedLifeCycleList
} from '@/api/modeling/lifeCycle/api';
import {gridStatus} from '@/api/modeling/statusPool/api'
import CycleFlow from "@/components/flow-cycle/flowchartEditor.vue";
import func from "@/util/func";
import basicOption from "@/util/basic-option";
export default {
  name: "index"
  name: "index",
  components: {CycleFlow},
  data() {
    return {
      checkViewOption: {
        ...basicOption,
        addBtn: false,
        menu: false,
        searchMenuSpan: 8,
        refreshBtn: false,
        selection: false,
        column: [
          {
            label: '名称',
            prop: 'lifeCycleName',
            sortable: true,
          },
          {
            label: '来源',
            prop: 'source',
            sortable: true,
            search: true
          },
          {
            label: '说明',
            prop: 'desc',
          }
        ]
      },
      checkViewData: [],
      checkViewDataSearch: [],
      checkViewVisible: false,
      checkViewLoading: false,
      tipList: [
        "名称、标签、起始状态不能为空,且名称只能为英文字符",
        "注意配置连接线起始状态以及目标状态名称",
      ],
      upFileType: ['xls', 'xlsx'],
      fileUrl: 'api/lifeCycleController/importLifeCycles',
      eventList: [],
      Reload: Math.random(),
      flowKey: null,
      visible: false,
      type: 'edit',
      nodesEdgesData: {},
      flowChartNodeItems: [], // æµç¨‹èŠ‚ç‚¹æ•°æ®
      rowData: {},
      treeData: [],
      treeOption: {
        height: 'auto',
        defaultExpandAll: false,
        menu: false,
        addBtn: false,
        props: {
          label: 'id',
          value: 'id',
          children: 'children'
        }
      },
    }
  },
  created() {
    this.createdHandler();
  },
  methods: {
    // å·¦ä¾§æ ‘查询
    getTreeList() {
      gridLifeCycle().then(res => {
        const data = res.data.data;
        this.treeData = data;
      }).catch(err => {
        this.$message.error(err)
      });
    },
    // ç”Ÿå‘½å‘¨æœŸçŠ¶æ€æŸ¥è¯¢
    getStatusList() {
      gridStatus().then(res => {
        const data = res.data.data.map(item => {
          return {
            id: item.id,
            name: item.name
          }
        })
        this.flowChartNodeItems = data;
      }).catch(err => {
        this.$message.error(err)
      });
    },
    // è·ƒè¿äº‹ä»¶æŸ¥è¯¢
    getEventsSelect() {
      getLCEventKeys().then(res => {
        const data = res.data.data;
        this.eventList = data;
      }).catch(err => {
        this.$message.error(err)
      });
    },
    // åˆ·æ–°æ•´ä¸ªé¡µé¢æ•°æ®
    createdHandler() {
      this.getTreeList(); // æ ‘查询
      this.getStatusList(); // tag状态池查询
      this.getEventsSelect(); // è·ƒè¿äº‹ä»¶æŸ¥è¯¢
    },
    // è¡Œç‚¹å‡»
    nodeClick(row) {
      console.log(row);
      this.nodesEdgesData = {
        nodes: this.transformNodeData(row.bounds),
        edges: this.transformEdgeData(row.lines)
      };
      this.rowData = {...row, eventList: {...this.eventList}};
      this.$store.dispatch('updateMethodBtn', false);
      this.Reload = Math.random(); // åˆ·æ–°flow图表
    },
    // node节点数据转换
    transformNodeData(nodes) {
      return nodes.map(item => ({
        ...item,
        label: item.name,
        id: item.name,
        color: '#1890FF',
        shape: "flow-rect",
        x: Number(item.cellx),
        y: Number(item.celly),
        width: Number(item.cellw),
        height: Number(item.cellh)
      }));
    },
    // line连接线数据转换
    transformEdgeData(edges) {
      return edges.map(item => ({
        ...item,
        events: item.events.map(item => item.oid), // è·ƒè¿äº‹ä»¶ä¸‹æ‹‰æ¡†ç»‘定,在FlowchartEditor组件onAfterItemSelected方法里查找到对应连接线的信息
        label: item.name, // ç”¨äºŽå³ä¾§è¯¦ç»†ä¿¡æ¯åç§°
        source: item.sourceLifeStatus,
        target: item.targetLifeStatus
      }));
    },
    // åˆ›å»ºæŒ‰é’®
    addClickHandler() {
      this.$store.dispatch('updateMethodBtn', true);
      this.handleResetTree();
    },
    // ä¿®æ”¹æŒ‰é’®
    editClickHandler() {
      if (func.isEmptyObject(this.rowData)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      this.$store.dispatch('updateMethodBtn', Object.keys(this.rowData).length > 0);
    },
    // åˆ é™¤æŒ‰é’®
    delClickHandler() {
      if (func.isEmptyObject(this.rowData)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      const {id, oid, ts} = this.rowData;
      const data = [{id, oid, ts}];
      deleteLifeCycles(data).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.obj);
          this.handleResetTree();
          this.createdHandler();
          this.$store.dispatch('updateMethodBtn', Object.keys(this.rowData).length > 0);
        }
      });
    },
    // å¯¼å‡ºæŒ‰é’®
    exportClickHandler(){
      if (func.isEmptyObject(this.rowData)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      exportLifeCycles({lcNames:this.rowData.id}).then(res => {
        func.downloadFileByBlobHandler(res);
        this.$message.success('导出成功');
      }).catch(err => {
        this.$message.error(err);
      })
    },
    // å¯¼å…¥æŒ‰é’®
    uploadClickHandler(){
      this.$refs.upload.visible = true;
    },
    // æŸ¥çœ‹ä½¿ç”¨èŒƒå›´æŒ‰é’®
    checkViewClickHandler(){
      if (func.isEmptyObject(this.rowData)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      getUsedLifeCycleList({lifeCycleName:this.rowData.id}).then(res => {
        if (res.data.code === 200) {
          this.checkViewVisible = true;
          this.checkViewData = res.data.data;
          this.checkViewDataSearch = res.data.data;
        }
      })
    },
    // æŸ¥çœ‹ä½¿ç”¨èŒƒå›´æŸ¥è¯¢
    checkHandleSearch(params, done) {
      const {source} = params;
      if (!params.source) {
        this.checkViewData = this.checkViewDataSearch;
        return done();
      }
      ;
      this.checkViewData = this.checkViewData.filter(item => {
        return item.source && item.source.includes(source);
      });
      done();
    },
    // æŸ¥çœ‹ä½¿ç”¨èŒƒå›´é‡ç½®
    checkHandleReset() {
      this.checkViewData = this.checkViewDataSearch;
    },
    // å­ç»„件回调保存
    async handlerSave() {
      const newRowData = await this.$refs.vueFlowchartEditor.getNewRowData();
      if (!newRowData) {
        return;
      }
      const flowData = await this.$refs.vueFlowchartEditor.getFlowData() || {};
      const nodes = flowData.nodes || [];
      const edges = flowData.edges || [];
      // æ£€æŸ¥æ˜¯å¦ç»˜åˆ¶äº†è‡³å°‘一个图形
      if (nodes.length <= 0) {
        this.$message.error('请至少绘制一个图形!');
        return;
      }
      // æ£€æŸ¥æ˜¯å¦ç»˜åˆ¶äº†è¿žæŽ¥çº¿
      if (nodes.length > 1 && !edges.length) {
        this.$message.error('请检查是否绘制连接线!');
        return;
      }
      // æ£€æŸ¥æ‰€æœ‰è¿žæŽ¥çº¿çš„名称是否填写
      const hasValidLabels = edges.every(item => item.label && item.label.trim() !== "");
      if (!hasValidLabels) {
        this.$message.error('请检查是否有连接线名称未填写!');
        return;
      }
      // æ£€æŸ¥æ˜¯å¦æœ‰é—漏的连接线
      if (edges.length + 1 < nodes.length) {
        this.$message.error('请检查是否全部绘制连接线!');
        return;
      }
      let params = {...newRowData, ...flowData};
      const transformedData = {
        id: params.id,
        name: params.name,
        startStatus: params.startStatus,
        startStatusName: params.startStatusName,
        description: params.description,
        bounds: params.nodes.map(node => ({
          name: node.id,
          cellx: String(node.x),
          celly: String(node.y),
          cellw: String(node.width),
          cellh: String(node.height),
        })),
        lines: !params.edges ? [] : params.edges.map(edge => ({
          sourceLifeStatus: edge.source,
          targetLifeStatus: edge.target,
          saveEventList: edge.saveEventList,
          name: edge.label
        }))
      };
      const getFunction = Object.keys(this.rowData).length > 0 ? () => updateLifeCycle(transformedData)
        : () => addLifeCycle(transformedData);
      getFunction().then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.obj);
          this.createdHandler();
          // this.handleResetTree();
          this.$store.dispatch('updateMethodBtn', Object.keys(this.rowData).length > 0);
        }
      });
    },
    // é‡ç½®æ ‘和图表
    handleResetTree() {
      this.$refs.tree.setCurrentKey(null);
      this.rowData = {};
      this.nodesEdgesData = {};
      this.Reload = Math.random();
    }
  }
}
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button {
      width: 65px;
      padding-left: 9.5px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
//.headerCon > .el-button:nth-child(6) {
//  margin-left: 0;
//}
.smallBtn {
  width: 77px !important;
  //font-size: 11px !important;
  text-align: center  !important;
  padding-left: 1px  !important;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/linkType/index.vue
@@ -6,20 +6,20 @@
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary">修改
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger">删除
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="deleteClickHandler">删除
            </el-button>
            <el-button icon="el-icon-view" plain size="small" type="primary">查看
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary">导出
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary">导入
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="upLoadClickHandler">导入
            </el-button>
            <el-button icon="el-icon-circle-plus-outline" plain size="small"
            <el-button class="smallBtn" style="padding-left: 7px !important;" icon="el-icon-circle-plus-outline" plain size="small"
                       type="primary" @click="createViewClickHandler">创建视图
            </el-button>
            <el-button icon="el-icon-menu" plain size="small"
            <el-button class="smallBtn" icon="el-icon-menu" plain size="small" style="padding-left: 1px"
                       type="primary" @click="checkClickHandler">一致性检查
            </el-button>
          </div>
@@ -167,23 +167,24 @@
    <!-- åˆ›å»º && ç¼–辑   -->
    <el-dialog
      v-dialogDrag
      :title="title === 'add' ? '创建' : '修改'"
      :visible.sync="visible"
      append-to-body="true"
      class="avue-dialog"
      title="创建"
      width="70%"
      @close="addDialogClose"
    >
      <el-form ref="form" :model="form" :rules="rules" label-width="90px">
        <div class="dialogForm">
          <div class="leftForm">
            <el-form-item label="名称:" prop="name">
              <el-input v-model="form.name"></el-input>
              <el-input v-model="form.name" :readOnly="title === 'edit'"></el-input>
            </el-form-item>
            <el-form-item label="标签:">
              <el-input v-model="form.tag"></el-input>
            </el-form-item>
            <el-form-item label="实现类:">
              <el-input v-model="form.impClass"></el-input>
              <el-input v-model="form.implClass"></el-input>
            </el-form-item>
            <el-form-item label="形状">
              <el-input v-model="form.shape"></el-input>
@@ -195,7 +196,42 @@
          <div class="centerForm">
            <el-form-item label="Form端类型:" label-width="110px">
              <el-input v-model="form.btmItemsFrom"></el-input>
              <!--              <el-button v-if="!form.btmItemsFrom" plain size="mini" type="success"-->
              <!--                         @click="FormItemReferChange('form')">添加-->
              <!--              </el-button>-->
              <!--              <el-input v-if="form.btmItemsFrom" v-model="form.btmItemsFrom"></el-input>-->
              <div style="display: flex; align-items: center">
                <div style="height: 200px; width: 280px; border: 1px solid #bdbbbb;overflow-y: auto">
                  <!-- å†…容 -->
                  <el-table
                    :data="bizFormData"
                    :show-header="false"
                    style="width: 100%">
                    <el-table-column
                      align="center"
                      prop="name">
                    </el-table-column>
                    <el-table-column
                      fixed="right"
                      label="操作"
                      width="60">
                      <template slot-scope="scope">
                        <el-button
                          size="small"
                          style="color:#F56C6C;"
                          type="text"
                          @click.native.prevent="bizTypeDeleteRow('form',scope.$index)">
                          ç§»é™¤
                        </el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
                <el-button plain size="mini" style="margin-left: 5px" type="success"
                           @click="FormItemReferChange('form')">添加
                </el-button>
              </div>
            </el-form-item>
            <el-form-item label="对应关系:" label-width="110px">
              <el-select v-model="form.relationFrom">
@@ -204,13 +240,47 @@
              </el-select>
            </el-form-item>
            <el-form-item label="主类型:" label-width="110px">
              <el-input v-model="form.primitivesFrom"></el-input>
              <el-select v-model="form.primitivesFrom">
                <el-option v-for="(item,index) in bizFormData" :key="index" :label="item.name"
                           :value="item.name"></el-option>
              </el-select>
            </el-form-item>
          </div>
          <div class="rightForm">
            <el-form-item label="To端类型:" label-width="110px">
              <el-input v-model="form.btmItemsTo"></el-input>
              <div style="display: flex; align-items: center">
                <div style="height: 200px; width: 280px; border: 1px solid #bdbbbb;overflow-y: auto">
                  <!-- å†…容 -->
                  <el-table
                    :data="bizToData"
                    :show-header="false"
                    style="width: 100%">
                    <el-table-column
                      align="center"
                      prop="name">
                    </el-table-column>
                    <el-table-column
                      fixed="right"
                      label="操作"
                      width="60">
                      <template slot-scope="scope">
                        <el-button
                          size="small"
                          style="color:#F56C6C;"
                          type="text"
                          @click.native.prevent="bizTypeDeleteRow('to',scope.$index)">
                          ç§»é™¤
                        </el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
                <el-button plain size="mini" style="margin-left: 5px" type="success"
                           @click="FormItemReferChange('to')">添加
                </el-button>
              </div>
            </el-form-item>
            <el-form-item label="对应关系:" label-width="110px">
              <el-select v-model="form.relationTo">
@@ -219,7 +289,10 @@
              </el-select>
            </el-form-item>
            <el-form-item label="主类型:" label-width="110px">
              <el-input v-model="form.primitivesTo"></el-input>
              <el-select v-model="form.primitivesTo">
                <el-option v-for="(item,index) in bizToData" :key="index" :label="item.name"
                           :value="item.name"></el-option>
              </el-select>
            </el-form-item>
          </div>
        </div>
@@ -230,6 +303,7 @@
        <avue-crud
          :data="dialogBottomData"
          :option="dialogBottomOption"
          @row-del="dialogBottomAttrDel"
        >
          <template slot="menuLeft" slot-scope="scope">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="dialogAddClickHandler">增 åŠ 
@@ -288,19 +362,119 @@
        :option="conCheckOption"
        :table-loading="conCheckLoading">
      </avue-crud>
      <span slot="footer" class="dialog-footer">
         <el-button @click="conCheckVisible = false">取 æ¶ˆ</el-button>
         <el-button type="primary" @click="repairClickHandler">ä¿® å¤</el-button>
        </span>
    </el-dialog>
    <!-- form to ç«¯ç±»åž‹å¯¹è¯æ¡†è¡¨æ ¼ -->
    <el-dialog
      v-dialogDrag
      :title="bizTypeTitle === 'form' ? 'Form端类型' : 'To端类型'"
      :visible.sync="bizTypeVisible"
      append-to-body="true"
      class="avue-dialog"
      width="70%"
    >
      <avue-crud
        :key="bizTypeReload"
        ref="bizTypeCrud"
        :data="bizTypeData"
        :option="bizTypeOption"
        :table-loading="bizTypeLoading"
        @search-change="bizTypeHandleSearch"
        @search-reset="bizTypeHandleReset"
        @selection-change="bizTypeSelection"
        @row-click="bizTypeRowClick">
      </avue-crud>
      <span slot="footer" class="dialog-footer">
         <el-button @click="bizTypeVisible = false">取 æ¶ˆ</el-button>
         <el-button type="primary" @click="bizTypeAddHandler">ç¡® å®š</el-button>
        </span>
    </el-dialog>
    <!-- å¯¼å…¥ -->
    <upload-file ref="upload" :fileType="upFileType" :fileUrl="fileUrl" :tipList="tipList" title="导入"
                 @updata="getTreeList"></upload-file>
  </el-container>
</template>
<script>
import {gridLink, getByAttributeNames, checkLinkType, createView} from "@/api/modeling/linkType/api";
import {
  gridLink,
  getByAttributeNames,
  checkLinkType,
  createView,
  getBizTypes,
  addAndEditLink,
  expData,
  repairTable,
  deleteLink
} from "@/api/modeling/linkType/api";
import basicOption from '@/util/basic-option'
import {gridAttribute} from "@/api/modeling/attributePool/api";
import func from "@/util/func";
export default {
  name: "index",
  data() {
    return {
      tipList: [
        "导入链接名称不可为空且链接类型名称只能为英文字母",
        "导入的文件包括属性、业务类型、生命周期等文件",
        "上传的文件为压缩文件,且压缩格式仅能为zip格式"
      ],
      upFileType: ['zip'],
      fileUrl: 'api/linkTypeController/impData',
      title: '',
      bizTypeReload: null,
      bizToData: [],
      bizFormData: [],
      bizTypeList: [],
      bizTypeLoading: false,
      bizTypeData: [],
      bizTypeOption: {
        ...basicOption,
        menu: false,
        addBtn: false,
        index: false,
        refreshBtn: false,
        highlightCurrentRow: true,
        searchMenuSpan: 8,
        searchLabelWidth: 100,
        column: [
          {
            label: '业务类型名',
            prop: 'name',
            sortable: true,
            search: true,
          },
          {
            label: '标签',
            prop: 'label',
            sortable: true,
          },
          {
            label: '父类',
            prop: 'fName',
            sortable: true,
          },
          {
            label: '版本规则',
            prop: 'revRuleName',
            sortable: true,
          },
          {
            label: '生命周期',
            prop: 'lifeCycle',
            sortable: true,
          },
        ]
      },
      bizTypeVisible: false,
      bizTypeTitle: "",
      conDefaultCheckData: [], // ä¿ç•™ä¸Šä¸ªæŽ¥å£è¿”回的数据
      conCheckLoading: false,
      conCheckOption: {
@@ -309,7 +483,21 @@
        addBtn: false,
        index: false,
        selection: false,
        refreshBtn: false
        refreshBtn: false,
        column: [
          {
            label: '类型名',
            prop: 'id',
          },
          {
            label: '操作',
            prop: 'methods',
          },
          {
            label: '状态',
            prop: 'status',
          }
        ]
      },
      conCheckData: [],
      conCheckVisible: false,
@@ -370,7 +558,7 @@
      form: {
        name: '', // åç§°
        tag: '', // æ ‡ç­¾
        impClass: '', // å®žçŽ°ç±»
        implClass: '', // å®žçŽ°ç±»
        shape: '', // å½¢çж
        description: '', // æè¿°
        btmItemsFrom: '', // From端类型列表
@@ -378,7 +566,8 @@
        primitivesFrom: '', // form端主类型
        btmItemsTo: '', // to端类型列表
        relationTo: 'N', // to端对应关系
        primitivesTo: '', // to端主类型
        primitivesTo: '', // to端主类型,
        attributes: []
      },
      dialogBottomOption: {
        ...basicOption,
@@ -486,12 +675,18 @@
        this.treeData = data;
        this.tableLoading = false;
      }).catch(err => {
        this.$message.error(err)
        this.$message.error(err);
      });
    },
    // å¯¼å…¥
    upLoadClickHandler() {
      this.$refs.upload.visible = true;
    },
    // æ ‘点击事件
    nodeClick(row) {
      console.log(row);
      this.nodeRow = row;
      this.getAttrPollData(row); // èŽ·å–å±žæ€§æ± åˆ—è¡¨
    },
@@ -506,8 +701,55 @@
      })
    },
    // åˆ é™¤æŒ‰é’®
    deleteClickHandler() {
      if (func.isEmptyObject(this.nodeRow)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      deleteLink(this.nodeRow).then(res => {
        if (res.data.code === 200) {
          this.$message.success('删除成功');
          this.getTreeList();
        }
      })
    },
    // åˆ›å»ºæŒ‰é’®
    addClickHandler() {
      this.visible = true;
      this.title = 'add';
    },
    // ç¼–辑按钮
    editClickHandler() {
      this.title = 'edit';
      if (func.isEmptyObject(this.nodeRow)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      this.form = {...this.nodeRow}; // æµ…拷贝 è§£å†³å¼•用复制
      console.log(this.nodeRow);
      this.bizFormData = this.form.btmItemsFrom.length > 0 && this.form.btmItemsFrom.map(item => {
        return {
          name: item
        };
      });
      this.bizToData = this.form.btmItemsTo.length > 0 && this.form.btmItemsTo.map(item => {
        return {
          name: item
        };
      });
      if (this.form.attributes.length > 0) {
        let value = this.form.attributes.join(',');
        getByAttributeNames({attrNames: value}).then(res => {
          if (res.data.code === 200) {
            this.dialogBottomData = res.data.data;
          }
        })
      }
      this.visible = true;
    },
@@ -518,18 +760,70 @@
      checkLinkType().then(res => {
        if (res.data.code === 200) {
          const data = res.data.data;
          this.conDefaultCheckData = data;
          data.map(item => {
            // èŽ·å– btmCheckMap å¯¹è±¡çš„属性名
            const keys = Object.keys(item.btmCheckMap);
          this.conDefaultCheckData = data; // ä¿ç•™ä¸€ä»½åŽŸå§‹æ•°æ®
          this.conCheckLoading = false;
            return {
              id: keys[0],
          const outputData = [];
          data.forEach(item => {
            Object.entries(item.btmCheckMap).forEach(([id, methodsArray]) => {
              methodsArray.forEach(methods => {
                // åˆ¤æ–­å‰ç¼€
                const action = methods.startsWith('F_') ? '移除form端业务类型' : '移除to端业务类型';
                const detail = methods.split('_')[1]; // èŽ·å– _ åŽé¢çš„内容
                outputData.push({
                  id: id,
                  methods: `${action}:${detail}`,
                  status: '未修复'
                });
              });
            });
            // å¤„理 dbCheckMap
            Object.entries(item.dbCheckMap).forEach(([id, methods]) => {
              const splitMethods = methods.split('(');
              // åˆ¤æ–­ç¬¬ä¸€ä¸ªç¬¦å·å‰é¢çš„值
              if (splitMethods[0].startsWith('_ADD')) {
                outputData.push({
                  id: id,
                  methods: '增加列(' + splitMethods[1].slice(0, -1) + ')', // ç»“束位置减去)的字符
                  status: '未修复'
                });
              } else if (splitMethods[0].startsWith('_CREATE')) {
                outputData.push({
                  id: id,
                  methods: '创建表(' + splitMethods[1].slice(0, -1) + ')',
                  status: '未修复'
                });
              } else if (splitMethods[0].startsWith('_DROP')) {
                outputData.push({
                  id: id,
                  methods: '移除列(' + splitMethods[1].slice(0, -1) + ')',
                  status: '未修复'
                });
              } else {
                this.$message.error("不支持的 dbCheckMap ç±»åž‹ï¼š " + methods)
            }
          })
            });
          });
          this.conCheckData = outputData;
        }
      }).catch(err => {
        this.$message.error(err)
        this.$message.error(err);
      })
    },
    // ä¿®å¤ä¸€è‡´æ€§æ£€æŸ¥
    repairClickHandler() {
      console.log(this.conDefaultCheckData)
      const params = this.conDefaultCheckData[0];
      repairTable(params).then(res => {
        if (func.isEmptyObject(res.data.obj[0])) {
          this.$message.success('修复成功');
        } else {
          this.$message.error('修复失败,请重新尝试!');
        }
        this.conCheckVisible = false;
      })
    },
@@ -539,7 +833,7 @@
      createView().then(res => {
        if (res.data.code === 200) {
          this.createViewLoading = false;
          this.$message.success(res.data.obj)
          this.$message.success(res.data.obj);
        }
      })
    },
@@ -549,7 +843,7 @@
      this.dialogAttrLoading = true;
      this.attrPollDialogVisible = true;
      this.dialogAttrReload = Math.random(); // å¼ºåˆ¶åˆ·æ–°è¡¨æ ¼ è§£å†³è¡¨æ ¼é”™è¡Œ
      this.getAttrDialogDta()
      this.getAttrDialogDta();
    },
    // æŸ¥è¯¢å±žæ€§æ± åˆ—表数据
@@ -560,7 +854,7 @@
        this.attrPage.total = res.data.total;
        this.dialogAttrLoading = false;
      }).catch(err => {
        this.$message.error(err)
        this.$message.error(err);
      });
    },
@@ -578,6 +872,30 @@
    dialogAttrClose() {
      this.attrPollDialogVisible = false;
      this.searchAttrParams = {};
    },
    // æ¸…空form表单
    resetForm() {
      const form = {
        name: '', // åç§°
        tag: '', // æ ‡ç­¾
        implClass: '', // å®žçŽ°ç±»
        shape: '', // å½¢çж
        description: '', // æè¿°
        btmItemsFrom: '', // From端类型列表
        relationFrom: 'N', // form端对应关系
        primitivesFrom: '', // form端主类型
        btmItemsTo: '', // to端类型列表
        relationTo: 'N', // to端对应关系
        primitivesTo: '', // to端主类型
      };
      this.form = form;
      this.$refs.form.resetFields();
      this.bizFormData = [];
      this.bizToData = [];
      this.dialogBottomData = [];
      console.log(this.form);
      console.log('--', this.nodeRow)
    },
    // æ·»åŠ å±žæ€§æ±  ä¿å­˜
@@ -640,15 +958,146 @@
      this.getAttrDialogDta();
    },
    // å±žæ€§æ± åˆ é™¤
    dialogBottomAttrDel(form, index) {
      this.dialogBottomData.splice(index, 1);
    },
    // åˆ›å»º ç¼–辑 å¯¹è¯æ¡†å…³é—­
    addDialogClose() {
      this.visible = false;
      this.dialogBottomData = [];
      this.resetForm();
    },
    // form to ç±»åž‹blur参照对话框
    FormItemReferChange(val) {
      this.bizTypeTitle = val;
      this.bizTypeLoading = true;
      this.getBizTypeHandler();
      this.bizTypeVisible = true;
      this.bizTypeReload = Math.random(); // å¼ºåˆ¶åˆ·æ–°è¡¨æ ¼ è§£å†³è¡¨æ ¼é”™è¡Œ
    },
    // form to ç±»åž‹è¡¨æ ¼æŸ¥è¯¢
    getBizTypeHandler(params) {
      getBizTypes(params).then(res => {
        if (res.data.code === 200) {
          const data = res.data.data;
          this.bizTypeData = data;
          this.bizTypeLoading = false;
        }
      })
    },
    // form to ç±»åž‹é€‰æ‹©æ¡†
    bizTypeSelection(row) {
      this.bizTypeList = row;
    },
    // form to ç±»åž‹è¡Œç‚¹å‡»
    bizTypeRowClick(row) {
      this.$refs.bizTypeCrud.toggleRowSelection(row);
    },
    // form to ç±»åž‹ä¿å­˜
    bizTypeAddHandler() {
      if (this.bizTypeList.length === 0) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      const data = this.bizTypeList.map(item => ({name: item.name}));
      const dataName = this.bizTypeTitle === 'form' ? 'bizFormData' : 'bizToData';
      let hasDuplicate = false;
      // å…ˆåˆ›å»ºä¸€ä¸ªä¸´æ—¶æ•°ç»„来存储不重复的项
      const newItems = [];
      this.bizTypeList.forEach(item => {
        const exists = this[dataName].some(existingItem => existingItem.name === item.name);
        if (exists) {
          hasDuplicate = true;
          return;
        }
        // å¦‚果没有重复项,则将该项添加到临时数组中
        newItems.push({
          name: item.name,
        });
      });
      if (hasDuplicate) {
        this.$message.error('请检查是否有添加重复项!');
      } else {
        // å¦‚果没有重复项,将新项添加到 dialogBottomData
        this[dataName].push(...newItems);
        this.bizTypeVisible = false;
      }
    },
    // form to ç±»åž‹æœç´¢
    bizTypeHandleSearch(params, done) {
      console.log(params);
      let obj = {
        btmName: params.name
      };
      this.getBizTypeHandler(obj);
      done();
    },
    // form to ç±»åž‹é‡ç½®
    bizTypeHandleReset() {
      this.getBizTypeHandler();
    },
    // form to ç«¯è¡¨æ ¼ç§»é™¤
    bizTypeDeleteRow(val, index) {
      const dataName = val === 'form' ? 'bizFormData' : 'bizToData';
      const primitivesName = val === 'form' ? 'primitivesFrom' : 'primitivesTo';
      this[dataName].splice(index, 1);
      if (this[dataName].length === 0) {
        this.form[primitivesName] = "";
      }
    },
    // åˆ›å»ºç¼–辑 ä¿å­˜
    addDialogSavaHandler() {
      if (this.bizFormData.length <= 0 || this.bizToData.length <= 0) {
        this.$message.error('form端业务类型和to端类型均不能为空!')
        return;
      }
      this.form.btmItemsFrom = this.bizFormData.map(item => item.name);
      this.form.btmItemsTo = this.bizToData.map(item => item.name);
      this.form.attributes = this.dialogBottomData.map(item => item.id);
      let flag = this.title === 'add' ? true : false;
      addAndEditLink(flag, this.form).then(res => {
        if (res.data.code === 200) {
          this.visible = false;
          this.$message.success(res.data.msg);
          this.resetForm();
          this.getTreeList();
        }
      });
    },
    // å¯¼å‡º
    exportClickHandler() {
      if (func.isEmptyObject(this.nodeRow)) {
        this.$message.error('请至少选择一条数据');
        return;
      }
      let name = this.nodeRow.name;
      expData({name: name}).then(res => {
        func.downloadFileByBlobHandler(res);
        this.$message.success('导出成功');
      }).catch(err => {
        this.$message.error(err);
      });
    }
  }
}
@@ -662,6 +1111,12 @@
  .el-form-item .el-select {
    width: 100%;
  }
  .headerCon {
    .el-button {
      width: 82px;
    }
  }
}
@@ -693,9 +1148,20 @@
}
.dialogForm > div {
  width: 28%;
  width: 34%;
  border: 1px solid #eee;
  padding: 25px 20px 5px 10px; /* ä¸Š å³ ä¸‹ å·¦ */
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); /* æ·»åŠ é˜´å½±æ•ˆæžœ */
}
.leftForm {
  width: 19% !important;
  padding: 25px 20px 5px 0px !important;
}
.smallBtn {
  width: 82px !important;
  text-align: center !important;
  padding-left: 0px !important;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/statusPool/index.vue
@@ -15,7 +15,7 @@
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button plain size="small" style="width: 100px;text-align: center" type="primary"
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
@@ -371,6 +371,11 @@
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
@@ -398,4 +403,10 @@
.upload-demo {
  margin-left: 20px;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/modeling/versioning/index.vue
@@ -14,7 +14,7 @@
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button plain size="small" style="width: 100px;text-align: center" type="primary"
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
@@ -305,7 +305,6 @@
    //左侧树查询
    getTreeList() {
      getVersionRuleAllList().then(res => {
        console.log(res);
        const data = res.data.data;
        this.treeData = data;
      }).catch(err => {
@@ -463,6 +462,13 @@
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon {
    .el-button {
      width: 82px;
    }
  }
}
.headerCon {
@@ -487,4 +493,10 @@
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/businessTypeQuery/index.vue
@@ -1,5 +1,45 @@
<template>
  <p>业务类型查询</p>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
@@ -8,6 +48,45 @@
}
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/linkTypeQuery/index.vue
@@ -1,5 +1,45 @@
<template>
  <p>链接类型查询</p>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
@@ -8,6 +48,45 @@
}
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/queryTemplate/queryDefine/index.vue
@@ -1,5 +1,45 @@
<template>
  <p>查询模板定义</p>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
@@ -8,6 +48,45 @@
}
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/Action/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/formDefine/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>
Source/plt-web/plt-web-ui/src/views/modelingMenu/ui/uiDefine/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
<template>
  <el-container>
    <el-aside>
      <basic-container>
        <div ref="TreeBox" style="height: calc(100vh - 144px);!important;">
          <div class="headerCon">
            <el-button icon="el-icon-plus" plain size="small" type="primary" @click="addClickHandler">创建
            </el-button>
            <el-button icon="el-icon-edit" plain size="small" type="primary" @click="editClickHandler">修改
            </el-button>
            <el-button icon="el-icon-delete" plain size="small" type="danger" @click="delClickHandler">删除
            </el-button>
            <el-button icon="el-icon-download" plain size="small" type="primary" @click="exportClickHandler">导出
            </el-button>
            <el-button icon="el-icon-upload2" plain size="small" type="primary" @click="uploadClickHandler">导入
            </el-button>
            <el-button class="smallBtn" plain size="small" type="primary"
                       @click="checkViewClickHandler">查看使用范围
            </el-button>
          </div>
          <!-- å·¦ä¾§æ ‘         -->
          <div style="height:  calc(100vh - 280px);">
            <avue-tree :data="treeData" :option="treeOption" @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span style="font-size: 15px">
              <i class="el-icon-s-promotion"></i>
                {{ (node || {}).label }}
            </span>
          </span>
            </avue-tree>
          </div>
        </div>
      </basic-container>
    </el-aside>
    <el-main>
      <basic-container>
      </basic-container>
    </el-main>
  </el-container>
</template>
<script>
export default {
  name: "index"
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow: auto !important;
  }
  .headerCon{
    .el-button{
      width: 82px;
    }
  }
}
.headerCon {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 5px;
  .el-button + .el-button {
    margin-left: 5px;
  }
  .el-button {
    margin-top: 5px;
  }
}
.headerCon > .el-button:nth-child(4) {
  margin-left: 0;
}
.headerCon > .el-button:nth-child(7) {
  margin-left: 0;
}
.smallBtn {
  width: 82px;
  text-align: center;
  padding-left: 4.5px;
}
</style>