xuezizhuo před 2 roky
rodič
revize
92adde35bc
35 změnil soubory, kde provedl 7336 přidání a 415 odebrání
  1. 2 0
      ruoyi-ui/package.json
  2. 17 0
      ruoyi-ui/src/api/dataEngine/index.js
  3. 1 0
      ruoyi-ui/src/assets/styles/sidebar.scss
  4. 7 2
      ruoyi-ui/src/layout/components/AppMain.vue
  5. 1 1
      ruoyi-ui/src/layout/components/Navbar.vue
  6. 2 2
      ruoyi-ui/src/layout/components/TagsView/index.vue
  7. 4 4
      ruoyi-ui/src/layout/index.vue
  8. 3 2
      ruoyi-ui/src/store/index.js
  9. 194 0
      ruoyi-ui/src/store/modules/flow.js
  10. 13 0
      ruoyi-ui/src/utils/index.js
  11. 99 0
      ruoyi-ui/src/views/dataEngine/datamodeling/index.vue
  12. 0 0
      ruoyi-ui/src/views/dataEngine/datamodeling/mysqlUpdate.vue
  13. 0 182
      ruoyi-ui/src/views/system/PortalEngine/index.vue
  14. 14 4
      ruoyi-ui/src/views/system/data/index.vue
  15. 388 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigEdge/index.vue
  16. 467 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigGrid/index.vue
  17. 83 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigGrid/method.js
  18. 412 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigNode/index.vue
  19. 21 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigNode/method.js
  20. 16 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/index.css
  21. 48 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/index.vue
  22. 213 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/components/ToolBar/index.vue
  23. 13 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-1.js
  24. 16 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-2.js
  25. 1190 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-3.js
  26. 142 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-4.js
  27. 1021 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data.js
  28. 580 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/index.js
  29. 226 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/ports.js
  30. 536 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/graph/shape.js
  31. 49 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/index.css
  32. 104 0
      ruoyi-ui/src/views/system/processModeling/flow-x6/index.vue
  33. 106 0
      ruoyi-ui/src/views/system/processModeling/index.vue
  34. 259 218
      ruoyi-ui/src/views/tool/build/index.vue
  35. 1089 0
      sql/ry-vue2023-6-19-3.sql

+ 2 - 0
ruoyi-ui/package.json

@@ -36,6 +36,7 @@
     "url": "https://gitee.com/y_project/RuoYi-Vue.git"
   },
   "dependencies": {
+    "@antv/x6": "^1.34.2",
     "@riophae/vue-treeselect": "0.4.0",
     "axios": "0.24.0",
     "clipboard": "2.0.8",
@@ -45,6 +46,7 @@
     "file-saver": "2.0.5",
     "fuse.js": "6.4.3",
     "highlight.js": "9.18.5",
+    "insert-css": "^2.0.0",
     "js-beautify": "1.13.0",
     "js-cookie": "3.0.1",
     "jsencrypt": "3.0.0-rc.1",

+ 17 - 0
ruoyi-ui/src/api/dataEngine/index.js

@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+export function tableInfoList() {
+  return request({
+    url: '/tableInfo/tableInfoList?databaseName=zkqy-call',
+    method: 'get',
+    baseURL:process.env.VUE_APP_BASE_API2
+  })
+}
+
+export function removeTable(tableName) {
+  return request({
+    url: '/tableInfo/removeTable/' + tableName,
+    method: 'get',
+    baseURL:process.env.VUE_APP_BASE_API2
+  })
+}

+ 1 - 0
ruoyi-ui/src/assets/styles/sidebar.scss

@@ -1,3 +1,4 @@
+
 #app {
 
   .main-container {

+ 7 - 2
ruoyi-ui/src/layout/components/AppMain.vue

@@ -26,11 +26,12 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss" >
 .app-main {
   /* 50= navbar  50  */
   min-height: calc(100vh - 50px);
-  width: 100%;
+  //+++++++++++
+  width: 88%;
   position: relative;
   overflow: hidden;
 }
@@ -43,6 +44,10 @@ export default {
   .app-main {
     /* 84 = navbar + tags-view = 50 + 34 */
     min-height: calc(100vh - 84px);
+
+
+    //+++++++++++
+    position:fixed;
   }
 
   .fixed-header + .app-main {

+ 1 - 1
ruoyi-ui/src/layout/components/Navbar.vue

@@ -112,7 +112,7 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 .navbar {
   height: 50px;
   overflow: hidden;

+ 2 - 2
ruoyi-ui/src/layout/components/TagsView/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="tags-view-container" class="tags-view-container">
+  <!-- <div id="tags-view-container" class="tags-view-container">
     <scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll">
       <router-link
         v-for="tag in visitedViews"
@@ -25,7 +25,7 @@
       <li v-if="!isLastView()" @click="closeRightTags"><i class="el-icon-right"></i> 关闭右侧</li>
       <li @click="closeAllTags(selectedTag)"><i class="el-icon-circle-close"></i> 全部关闭</li>
     </ul>
-  </div>
+  </div> -->
 </template>
 
 <script>

+ 4 - 4
ruoyi-ui/src/layout/index.vue

@@ -153,7 +153,7 @@ export default {
 .combar {
   position: fixed;
   display: block;
-  width: 100%;
+  width: 90%;
   z-index: 1;
   background: #fff;
 }
@@ -195,11 +195,11 @@ export default {
 }
 
 .bar {
-  width: 800px;
+  width: 43.75rem;
   height: 10px;
   text-align: center;
   line-height: 100px;
-  /* position: fixed; */
+  position: fixed;
 }
 
 .imgg {
@@ -215,7 +215,7 @@ export default {
   font-size: 30px;
   color: #003e8a;
   font-weight: bolder;
-  margin-left: -400px;
+  margin-left: -335px;
 }
 
 .app-wrapper {

+ 3 - 2
ruoyi-ui/src/store/index.js

@@ -7,7 +7,7 @@ import tagsView from './modules/tagsView'
 import permission from './modules/permission'
 import settings from './modules/settings'
 import getters from './getters'
-
+import flow from './modules/flow'
 Vue.use(Vuex)
 
 const store = new Vuex.Store({
@@ -17,7 +17,8 @@ const store = new Vuex.Store({
     user,
     tagsView,
     permission,
-    settings
+    settings,
+    flow
   },
   getters
 })

+ 194 - 0
ruoyi-ui/src/store/modules/flow.js

@@ -0,0 +1,194 @@
+export default {
+  namespaced: true,
+  state: {
+    // 网格
+    showGrid: false,
+    type: 'mesh',
+    size: 10,
+    color: '#e5e5e5',
+    thickness: 1,
+    colorSecond: '#d0d0d0',
+    thicknessSecond: 1,
+    factor: 4,
+    bgColor: '#e5e5e5',
+    showImage: false,
+    repeat: 'watermark',
+    angle: 30,
+    position: 'center',
+    bgSize: JSON.stringify({ width: 150, height: 150 }),
+    opacity: 0.9,
+    //  线条
+    strokeWidth: 1,
+    outStrokeWidth: 1,
+    stroke: '#cfe7f2',
+    outStroke: '#456d89',
+    strokeDasharray: 1,
+    animation: 0,
+    connector: 'normal',
+    edgeRouter: 'metro',
+    edgeOffset: 32,
+    edgeDirection: 'H',
+    label:'',
+    endArrow: true,
+   
+
+
+    // 节点属性
+    nodeStroke: '#5F95FF',
+    nodeStrokeWidth: 1,
+    nodeFill: '#ffffff',
+    // nodeImageWidth: 60,
+    // nodeImageHeight: 60,
+    portId: '',
+    portX: 0,
+    portY: 0,
+    portColor: '#5F95FF',
+    portFill: '#FFF',
+    ZIndex: 0,
+    nodeFontSize: 12,
+    nodeColor: '#080808',
+    // 业务数据
+    nodeStatus: 0,
+    nodePointCode: '52',
+    nodeFieldName: 'fieldName1',
+
+    nodeType: '' // 节点类型(text、image)
+  },
+  mutations: {
+    updateshowGrid(state, showGrid) {
+      state.showGrid = showGrid
+    },
+    updatetype(state, type) {
+      state.type = type
+    },
+    updatesize(state, size) {
+      state.size = size
+    },
+    updatecolor(state, color) {
+      state.color = color
+    },
+    updatethickness(state, thickness) {
+      state.thickness = thickness
+    },
+    updatecolorSecond(state, colorSecond) {
+      state.colorSecond = colorSecond
+    },
+    updatethicknessSecond(state, thicknessSecond) {
+      state.thicknessSecond = thicknessSecond
+    },
+    updatefactor(state, factor) {
+      state.factor = factor
+    },
+    updatebgColor(state, bgColor) {
+      state.bgColor = bgColor
+    },
+    updateshowImage(state, showImage) {
+      state.showImage = showImage
+    },
+    updaterepeat(state, repeat) {
+      state.repeat = repeat
+    },
+    updateangle(state, angle) {
+      state.angle = angle
+    },
+    updateposition(state, position) {
+      state.position = position
+    },
+    updatebgSize(state, bgSize) {
+      state.bgSize = bgSize
+    },
+    updateopacity(state, opacity) {
+      state.opacity = opacity
+    },
+
+
+    updatestrokeWidth(state, strokeWidth) {
+      state.strokeWidth = strokeWidth
+    },
+    updateoutStrokeWidth(state, outStrokeWidth) {
+      state.outStrokeWidth = outStrokeWidth
+    },
+    updatestroke(state, stroke) {
+      state.stroke = stroke
+    },
+    updateoutStroke(state, outStroke) {
+      state.outStroke = outStroke
+    },
+    updatestrokeDasharray(state, strokeDasharray) {
+      state.strokeDasharray = strokeDasharray
+    },
+    updateanimation(state, animation) {
+      state.animation = animation
+    },
+    updateconnector(state, connector) {
+      state.connector = connector
+    },
+    updateedgeRouter(state, edgeRouter) {
+      state.edgeRouter = edgeRouter
+    },
+    updateedgeOffset(state, edgeOffset) {
+      state.edgeOffset = edgeOffset
+    },
+    updateedgeDirection(state, edgeDirection) {
+      state.edgeDirection = edgeDirection
+    },
+    updatelabel(state, label) {
+      state.label = label
+    },
+    
+
+    updatenodeStroke(state, nodeStroke) {
+      state.nodeStroke = nodeStroke
+    },
+    updatenodeStrokeWidth(state, nodeStrokeWidth) {
+      state.nodeStrokeWidth = nodeStrokeWidth
+    },
+    updatenodeFill(state, nodeFill) {
+      state.nodeFill = nodeFill
+    },
+    // updatenodeImageWidth(state, nodeImageWidth) {
+    //   state.nodeImageWidth = nodeImageWidth
+    // },
+    // updatenodeImageHeight(state, nodeImageHeight) {
+    //   state.nodeImageHeight = nodeImageHeight
+    // },
+    updateportId(state, portId) {
+      state.portId = portId
+    },
+    updateportX(state, portX) {
+      state.portX = portX
+    },
+    updateportY(state, portY) {
+      state.portY = portY
+    },
+    updateportColor(state, portColor) {
+      state.portColor = portColor
+    },
+    updateportFill(state, portFill) {
+      state.portFill = portFill
+    },
+    updateZIndex(state, ZIndex) {
+      state.ZIndex = ZIndex
+    },
+    updatenodeFontSize(state, nodeFontSize) {
+      state.nodeFontSize = nodeFontSize
+    },
+    updatenodeColor(state, nodeColor) {
+      state.nodeColor = nodeColor
+    },
+    updatenodeStatus(state, nodeStatus) {
+      state.nodeStatus = nodeStatus
+    },
+    updatenodePointCode(state, nodePointCode) {
+      state.nodePointCode = nodePointCode
+    },
+    updatenodeFieldName(state, nodeFieldName) {
+      state.nodeFieldName = nodeFieldName
+    },
+
+
+    updatenodeType(state, nodeType) {
+      state.nodeType = nodeType
+    }
+  }
+}

+ 13 - 0
ruoyi-ui/src/utils/index.js

@@ -1,5 +1,12 @@
 import { parseTime } from './ruoyi'
 
+
+// export const $ = name => document.querySelector(name)
+
+// export const getContainerSize = dom => ({ width: dom.getBoundingClientRect().width, height: dom.getBoundingClientRect().height })
+
+// export const getImg = name => require(`../assets/${ name }`)
+
 /**
  * 表格时间格式化
  */
@@ -388,3 +395,9 @@ export function isNumberStr(str) {
   return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
 }
  
+
+
+export const $ = name => document.querySelector(name)
+
+export const getContainerSize = dom => ({ width: dom.getBoundingClientRect().width, height: dom.getBoundingClientRect().height })
+

+ 99 - 0
ruoyi-ui/src/views/dataEngine/datamodeling/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="app-container">
+
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="表名称" prop="tableName">
+        <el-input v-model="queryParams.tableName" placeholder="请输入表名称" clearable @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="表描述" prop="tableComment">
+        <el-input v-model="queryParams.tableComment" placeholder="请输入表描述" clearable @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+  
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          >新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="aaaList">
+      <el-table-column label="表名称" align="center" prop="tableName" />
+      <el-table-column label="表描述" align="center" prop="tableComment" />
+      <el-table-column label="创建时间" align="center" prop="createTime" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
+  </div>
+</template>
+  
+<script>
+import { tableInfoList,removeTable } from '@/api/dataEngine/index'
+export default {
+  name: "Aaa",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      showSearch: true,
+      aaaList: [],
+      total: 10,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        tableName: null,
+        tableComment: null
+      }
+    }
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    getList() {
+      this.loading = true;
+      tableInfoList().then(response => {
+        this.aaaList = response.data;
+        this.loading = false;
+      });
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.$router.push("/data/datasheet/mysql")
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const tableNames = row.tableName;
+      this.$modal.confirm('是否确认删除"' + tableNames + '"表?').then(function () {
+        return removeTable(tableNames);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => { });
+    },
+  }
+}
+</script>
+  

+ 0 - 0
ruoyi-ui/src/views/dataEngine/datamodeling/mysqlUpdate.vue


+ 0 - 182
ruoyi-ui/src/views/system/PortalEngine/index.vue

@@ -1,182 +0,0 @@
-<template>
-  <div class="engine-container">
-    <div class="portal">
-      <div class="portalmen">租户管理</div>
-      <div class="portalexp">
-        <download-excel
-          class="export-excel-wrapper"
-          :data="tableData"
-          :fields="json_fields"
-          :header="title"
-          name="租户管理.xls"
-        >
-          <!-- 上面可以自定义自己的样式,还可以引用其他组件button -->
-          <el-button type="success" class="excel">导出</el-button>
-        </download-excel>
-        <!-- <el-button round class="export">导出</el-button> -->
-        <el-button type="primary" round >+新建租户</el-button>
-      </div>
-    </div>
-
-    <div class="portalcon">
-      <div class="portalconTop">
-        <div class="left">
-          <el-input
-            placeholder="搜索您的客户..."
-            prefix-icon="el-icon-search"
-            v-model="input2"
-            style="width: 200px; margin-right: 15px"
-          >
-          </el-input>
-          <!-- <el-input
-            placeholder="筛选"
-            v-model="input2"
-            style="width: 200px; margin-right: 15px"
-          >
-          </el-input>
-          <el-date-picker v-model="value1" type="date" placeholder="选择日期">
-          </el-date-picker> -->
-        </div>
-        <div class="right">
-          <!-- <el-col :span="1.5"> -->
-            <!-- <el-button
-              plain
-              @click="handleAdd"
-              v-hasPermi="['system:user:add']"
-              style="
-                border-radius: 15px;
-                margin-right: 20px;
-                border: 0px solid #fff;
-              "
-              >新增</el-button
-            > -->
-          <!-- </el-col> -->
-          <el-col :span="1.5">
-            <el-button
-              type="primary"
-              plain
-              icon="el-icon-delete"
-              size="mini"
-              :disabled="multiple"
-              @click="handleDelete"
-              v-hasPermi="['system:user:remove']"
-            ></el-button>
-          </el-col>
-        </div>
-      </div>
-      <div class="portalconBottom">
-        <el-table :data="tableData" stripe style="width: 100%">
-          <el-table-column type="selection" width="55"> </el-table-column>
-          <el-table-column prop="tenantName" label="租户" width="180">
-          </el-table-column>
-          <el-table-column prop="tenantCode" label="租户编号" width="180">
-          </el-table-column>
-          <el-table-column prop="owner" label="负责人"> </el-table-column>
-          <el-table-column prop="contactInfo" label="联系方式" width="180">
-          </el-table-column>
-          <el-table-column prop="address" label="地址" width="180">
-          </el-table-column>
-          <el-table-column prop="createTime" label="有效期" width="180">
-          </el-table-column>
-          <el-table-column label="状态" width="180"> </el-table-column>
-          <el-table-column label="操作" width="180"> </el-table-column>
-        </el-table>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-// 引入请求方法
-import { getTenant } from "@/api/system/PortalEngine";
-
-// 我把步骤写在这里,然后你按照流程,自己写一边
-// 1.创建api。js文件,引入相应的请求方法
-// 2.引入后,在页面创建后调用方法,传递参数,
-// 3.在请求方法响应后,编辑自己的业务逻辑
-export default {
-  data() {
-    return {
-      tableData: [],
-      title: "租户管理",
-      json_fields: {
-        租户: "tenantName",
-        租户编号: "tenantCode",
-        负责人: "owner",
-        联系方式: "contactInfo",
-        地址: "address",
-        有效期: "createTime",
-      },
-      exportSheet: '租户管理',
-      exportHeader: '这是表格的标题',
-      exportFooter: '这是表格的页脚',
-      exportDefaultValue: '这是一个默认的数据'
-
-    };
-  },
-  // 页面创建后调用
-  mounted() {
-    // 调用请求的方法,.then是什么方法,一会儿自己百度。
-    getTenant({
-      // 参数
-      tenantName: "",
-      createTime: "",
-      tenantName: "",
-      tenantName: "",
-    }).then((res) => {
-      console.log(res);
-      this.tableData = res.rows;
-      // this.tableData = 后端返回的数据,就是最大的那个数据,赋值给前面的就可以了。
-      //  前面  =    后面
-    });
-  },
-  // 方法调用
-  methods: {
-    handleSelectionChange(val) {
-      this.multipleSelection = val;
-    },
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.excel{
-  float: right;
-}
-.export-excel-wrapper{
-  float: left;
-  padding-right: 20px;
-}
-.engine-container {
-  background-color: #f5f5fa;
-  padding: 40px 60px 40px 40px;
-}
-.portal {
-  width: 1200px;
-  height: 30px;
-  margin-bottom: 20px;
-  /* background-color: #f0f811; */
-  /* float: left; */
-}
-.portalmen {
-  font-size: 26px;
-  font-weight: bolder;
-  float: left;
-}
-.portalexp {
-  float: right;
-}
-.export {
-  margin-right: 20px;
-}
-.portalcon {
-  height: 800px;
-  background-color: #fff;
-}
-.left {
-  float: left;
-}
-.right {
-  float: right;
-}
-</style>

+ 14 - 4
ruoyi-ui/src/views/system/data/index.vue

@@ -209,7 +209,8 @@ export default {
 .dataconfig {
   background-color: #f5f5fa;
   font-size: 26px;
-  margin: 20px 0px 0px 20px;
+  /* margin: 20px 0px 0px 20px; */
+  padding: 15px 0px 0px 15px;
 }
 .title {
   margin: 15px 0px 20px 0px;
@@ -224,18 +225,27 @@ export default {
     text-align: left;
     padding: 10px 0 9px 0 !important;
 }
-/* .content {
+.content {
   width: 800px;
   margin: 0 auto;
-  height: 650px;
+  height: 700px;
   border: 2px solid #fff;
   border-radius: 15px;
   background-color: #fff;
+ 
+}
+
+
+/* .el-form el-form--label-top{
+  margin: 0 auto;
 } */
 .contenttil{
  width: 400px;
- height: 650px;
+ height: 700px;
  margin:0 auto;
+ background-color: #fff;
+ border: 2px solid #fff;
+ border-radius: 15px;
 }
 .title {
   color: #3366ff;

+ 388 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigEdge/index.vue

@@ -0,0 +1,388 @@
+<template>
+  <div style="width: 100%;height: 100%;">
+    <el-tabs>
+      <el-tab-pane label="线条">
+        <el-row>
+          <el-col :span="8">线边的宽度</el-col>
+          <el-col :span="12">
+            <el-slider
+              :min="1"
+              :max="25"
+              :step="1"
+              size="mini"
+              v-model="strokeWidth"
+              @change="onStrokeWidthChange"
+            />
+          </el-col>
+          <el-col :span="2">
+            <div class="result">{{ strokeWidth }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">外线边的宽度</el-col>
+          <el-col :span="12">
+            <el-slider
+              :min="1"
+              :max="25"
+              :step="1"
+              size="mini"
+              v-model="outStrokeWidth"
+              @change="onOutStrokeWidthChange"
+            />
+          </el-col>
+          <el-col :span="2">
+            <div class="result">{{ outStrokeWidth }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">线条颜色</el-col>
+          <el-col :span="14">
+            <el-input
+              type="color"
+              v-model="stroke"
+              size="mini"
+              style="width: 100%"
+              @change="onStrokeChange"
+            />
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">外线条的颜色</el-col>
+          <el-col :span="14">
+            <el-input
+              type="color"
+              v-model="outStroke"
+              size="mini"
+              style="width: 100%"
+              @change="onOutStrokeChange"
+            />
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">虚线</el-col>
+          <el-col :span="12">
+            <el-slider
+              :min="0"
+              :max="10"
+              :step="1"
+              size="mini"
+              v-model="strokeDasharray"
+              @change="onStrokeDasharray"
+            />
+          </el-col>
+          <el-col :span="2">
+            <div class="result">{{ strokeDasharray }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">动画</el-col>
+          <el-col :span="12">
+            <el-slider
+              :min="0"
+              :max="50"
+              :step="1"
+              size="mini"
+              v-model="animation"
+              @change="onAnimation"
+            />
+          </el-col>
+          <el-col :span="2">
+            <div class="result">{{ animation }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">连接方式</el-col>
+          <el-col :span="14">
+            <el-select
+              style="width: 100%"
+              size="mini"
+              v-model="connector"
+              @change="onConnectorChange"
+            >
+              <el-option value="normal">Normal</el-option>
+              <el-option value="smooth">Smooth</el-option>
+              <el-option value="rounded">Rounded</el-option>
+              <el-option value="jumpover">Jumpover</el-option>
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">路由</el-col>
+          <el-col :span="14">
+            <el-select
+              style="width: 100%"
+              size="mini"
+              v-model="edgeRouter"
+              @change="onEdgeRouter"
+            >
+              <el-option value="normal">Normal</el-option>
+              <el-option value="orth">Orth</el-option>
+              <el-option value="oneSide">OneSide</el-option>
+              <el-option value="manhattan">Manhattan</el-option>
+              <el-option value="metro">Metro</el-option>
+              <el-option value="er">Er</el-option>
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row v-show="edgeRouter == 'er'">
+          <el-col :span="8">Edge Offset</el-col>
+          <el-col :span="12">
+            <el-slider
+              :min="8"
+              :max="64"
+              :step="1"
+              size="mini"
+              v-model="edgeOffset"
+            />
+          </el-col>
+          <el-col :span="2">
+            <div class="result">{{ edgeOffset }}</div>
+          </el-col>
+        </el-row>
+        <el-row v-show="edgeRouter == 'er'">
+          <el-col :span="8">边的描述</el-col>
+          <el-col :span="14">
+            <el-select
+              style="width: 100%"
+              size="mini"
+              v-model="edgeDirection"
+            >
+              <el-option value="L">L</el-option>
+              <el-option value="R">R</el-option>
+              <el-option value="H">H</el-option>
+              <el-option value="T">T</el-option>
+              <el-option value="B">B</el-option>
+              <el-option value="V">V</el-option>
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>节点层级</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='0' :max='100' :step='1' v-model="ZIndex" style="width: 100%"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{ ZIndex }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">标签</el-col>
+          <el-col :span="14">
+            <el-input
+              v-model="label"
+              size="mini"
+              style="width: 100%"
+              @change="onLabelChange"
+            />
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+<script>
+import FlowGraph from "../../../graph";
+export default {
+  name: 'index',
+  data() {
+    return {
+      curCell: null
+    }
+  },
+  computed: {
+    strokeWidth: {
+      get() {
+        return this.$store.state.flow.strokeWidth
+      },
+      set(val) {
+        this.$store.commit('flow/updatestrokeWidth', val)
+      }
+    },
+    outStrokeWidth: {
+      get() {
+        return this.$store.state.flow.outStrokeWidth
+      },
+      set(val) {
+        this.$store.commit('flow/updateoutStrokeWidth', val)
+      }
+    },
+    stroke: {
+      get() {
+        return this.$store.state.flow.stroke
+      },
+      set(val) {
+        this.$store.commit('flow/updatestroke', val)
+      }
+    },
+    outStroke: {
+      get() {
+        return this.$store.state.flow.outStroke
+      },
+      set(val) {
+        this.$store.commit('flow/updateoutStroke', val)
+      }
+    },
+    strokeDasharray: {
+      get() {
+        return this.$store.state.flow.strokeDasharray
+      },
+      set(val) {
+        this.$store.commit('flow/updatestrokeDasharray', val)
+      }
+    },
+    animation: {
+      get() {
+        return this.$store.state.flow.animation
+      },
+      set(val) {
+        this.$store.commit('flow/updateanimation', val)
+      }
+    },
+    connector: {
+      get() {
+        return this.$store.state.flow.connector
+      },
+      set(val) {
+        this.$store.commit('flow/updateconnector', val)
+      }
+    },
+    edgeRouter: {
+      get() {
+        return this.$store.state.flow.edgeRouter
+      },
+      set(val) {
+        this.$store.commit('flow/updateedgeRouter', val)
+      }
+    },
+    edgeOffset: {
+      get() {
+        return this.$store.state.flow.edgeOffset
+      },
+      set(val) {
+        this.$store.commit('flow/updateedgeOffset', val)
+      }
+    },
+    edgeDirection: {
+      get() {
+        return this.$store.state.flow.edgeDirection
+      },
+      set(val) {
+        this.$store.commit('flow/updateedgeDirection', val)
+      }
+    },
+    ZIndex: {
+      get() {
+        return this.$store.state.flow.ZIndex
+      },
+      set(val) {
+        this.$store.commit('flow/updateZIndex', val)
+      }
+    },
+    label: {
+      get() {
+        return this.$store.state.flow.label
+      },
+      set(val) {
+        this.$store.commit('flow/updatelabel', val)
+      }
+    }
+  },
+  props: { id: String },
+  watch: {
+    id: {
+      handler() {
+        const { graph } = FlowGraph;
+        const cell = graph.getCellById(this.id);
+        if (!cell || !cell.isEdge()) {
+          return;
+        }
+        this.curCell = cell;
+        this.ZIndex = cell.getZIndex()
+        const connector = cell.getConnector() || {
+          name: "normal",
+        };
+        this.stroke = cell.attr("line/stroke");
+        this.strokeWidth = cell.attr("line/strokeWidth");
+        this.connector = connector.name;
+        this.label = (cell.getLabels()[0]?.attrs)?.text?.text || "";
+      },
+      deep: false,
+      immediate: false
+    },
+    edgeOffset: {
+      handler() {
+        this.curCell?.prop('router/args', { offset: this.edgeOffset, direction: this.edgeDirection })
+      },
+      immediate: false
+    },
+    edgeDirection: {
+      handler() {
+        this.curCell?.prop('router/args', { offset: this.edgeOffset, direction: this.edgeDirection })
+      },
+      immediate: false
+    },
+    ZIndex: {
+      handler() {
+        if(this.curCell) {
+          this.curCell?.setZIndex(this.ZIndex)
+        }
+      },
+      immediate: false
+    }
+  },
+  methods: {
+    // 线边的宽度
+    onStrokeWidthChange() {
+      this.curCell?.attr("line/strokeWidth", this.strokeWidth);
+      console.log(this.curCell, '----->>>')
+    },
+    // 外线边的宽度
+    onOutStrokeWidthChange() {
+      this.curCell?.attr("outline/strokeWidth", this.outStrokeWidth);
+    },
+    // 线边颜色
+    onStrokeChange() {
+      this.curCell?.attr("line/stroke", this.stroke);
+    },
+    // 外线边颜色
+    onOutStrokeChange() {
+      this.curCell?.attr("outline/stroke", this.outStroke);
+    },
+    // 虚线
+    onStrokeDasharray() {
+      this.curCell?.attr("line/strokeDasharray", this.strokeDasharray);
+    },
+    // 动画
+    onAnimation() {
+      this.curCell?.attr("line/style/animation", `ant-line ${this.animation}s infinite linear`);
+    },
+    // 连接方式
+    onConnectorChange () {
+      this.curCell?.setConnector(this.connector);
+    },
+    // 路由
+    onEdgeRouter () {
+      this.curCell?.setRouter({ name: this.edgeRouter })
+    },
+    onLabelChange() {
+      this.curCell.setLabels([
+        {
+          attrs: {
+            text: {
+              text: this.label,
+            },
+          },
+          position: {
+            distance: 0.5,
+          },
+        },
+      ]);
+    }
+  }
+}
+</script>
+<style scoped>
+.el-row {
+  margin-bottom: 5px;
+}
+</style>>

+ 467 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigGrid/index.vue

@@ -0,0 +1,467 @@
+<template>
+  <div style="width: 100%;height: 100%;">
+    <el-tabs v-model="activeName">
+      <el-tab-pane label="网格" name="1">
+        <el-row align="middle">
+          <el-col :span='24'>
+            <el-checkbox v-model="showGrid">
+            Show Grid
+            </el-checkbox>
+          </el-col>
+        </el-row>
+        <el-row align="middle" v-show="showGrid">
+          <el-col :span='10'>Grid Type</el-col>
+          <el-col :span='12'>
+            <el-select style="width: 100%" v-model="type">
+              <el-option :value="GRID_TYPE.DOT">Dot</el-option>
+              <el-option :value="GRID_TYPE.FIXED_DOT">Fixed Dot</el-option>
+              <el-option :value="GRID_TYPE.MESH">Mesh</el-option>
+              <el-option :value="GRID_TYPE.DOUBLE_MESH">Double Mesh</el-option>
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row align="middle" v-show="showGrid">
+          <el-col :span='10'>Grid Size</el-col>
+          <el-col :span='10'>
+            <el-slider :min='1' :max='20' :step='1' v-model="size" />
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{size}}</div>
+          </el-col>
+        </el-row>
+        <div v-if="type === 'doubleMesh' && showGrid">
+          <el-row align="middle">
+            <el-col :span='10'>Primary Color</el-col>
+            <el-col :span='12'>
+              <el-input
+                  type="color"
+                  v-model="color"
+                  style="width: 100%"
+              />
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='10'>Primary Thickness</el-col>
+            <el-col :span='10'>
+              <el-slider :min='0.5' :max='10' :step='0.5 ' v-model="thickness" />
+            </el-col>
+            <el-col :span=2>
+              <div class="result">{{ thickness.toFixed(1) }}</div>
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='10'>Secondary Color</el-col>
+            <el-col :span='12'>
+              <el-input type="color" v-model="colorSecond" style="width: 100%" />
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='10'>Secondary Thickness</el-col>
+            <el-col :span='10'>
+              <el-slider
+                  :min='0.5'
+                  :max='10'
+                  :step='0.5'
+                  v-model="thicknessSecond"
+                />
+            </el-col>
+            <el-col :span=2>
+              <div class="result">{{ thicknessSecond.toFixed(1) }}</div>
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='10'>Scale Factor</el-col>
+            <el-col :span='10'>
+              <el-slider
+                  :min='1'
+                  :max='10'
+                  :step='1'
+                  v-model="factor"
+                />
+            </el-col>
+            <el-col :span='2'>
+              <div class="result">{{ factor }}</div>
+            </el-col>
+          </el-row>
+        </div>
+        <div v-else>
+          <el-row align="middle" v-show="showGrid">
+            <el-col :span='10'>Grid Color</el-col>
+            <el-col :span='12'>
+              <el-input type="color" v-model="color" style="width: 100%" />
+            </el-col>
+          </el-row>
+          <el-row align="middle" v-show="showGrid">
+            <el-col :span='10'>Thickness</el-col>
+            <el-col :span='10'>
+              <el-slider :min='0.5' :max='10' :step='0.5' v-model="thickness" />
+            </el-col>
+            <el-col :span=1>
+              <div class="result">{{thickness.toFixed(1)}}</div>
+            </el-col>
+          </el-row>
+        </div>
+      </el-tab-pane>
+
+      <el-tab-pane label="背景" name="2">
+        <el-row align="middle">
+          <el-col :span=6>Color</el-col>
+          <el-col :span=14>
+            <el-input type="color" v-model="bgColor" style= "width: 100%" />
+          </el-col>
+        </el-row>
+        <el-row align="middle">
+          <el-col :span="14" :offset="6">
+            <el-checkbox v-model="showImage">
+            Show Image
+            </el-checkbox>
+          </el-col>
+        </el-row>
+        <div v-if="showImage">
+          <el-row align="middle">
+            <el-col :span='6'>Repeat</el-col>
+            <el-col :span='14'>
+              <el-select style="width: 100%" v-model="repeat">
+                <el-option :value="REPEAT_TYPE.NO_REPEAT">No Repeat</el-option>
+                <el-option :value="REPEAT_TYPE.REPEAT">Repeat</el-option>
+                <el-option :value="REPEAT_TYPE.REPEAT_X">Repeat X</el-option>
+                <el-option :value="REPEAT_TYPE.REPEAT_Y">Repeat Y</el-option>
+                <el-option :value="REPEAT_TYPE.ROUND">Round</el-option>
+                <el-option :value="REPEAT_TYPE.SPACE">Space</el-option>
+                <el-option :value="REPEAT_TYPE.FLIPX">Flip X</el-option>
+                <el-option :value="REPEAT_TYPE.FLIPY">Flip Y</el-option>
+                <el-option :value="REPEAT_TYPE.FLIPXY">Flip XY</el-option>
+                <el-option :value="REPEAT_TYPE.WATERMARK">Watermark</el-option>
+              </el-select>
+            </el-col>
+          </el-row>
+          <div v-if="repeat === 'watermark'">
+            <el-row align="middle">
+              <el-col :span='16' :offset='6' style="font-size: 12px">
+                Watermark Angle
+              </el-col>
+              <el-col :span='14' :offset='6'>
+                <el-slider :min='0' :max='360' :step='1' v-model="angle" />
+              </el-col>
+              <el-col :span=2>
+                <div class="result">{{angle}}</div>
+              </el-col>
+            </el-row>
+          </div>
+
+          <el-row align="middle">
+            <el-col :span='6'>Position</el-col>
+            <el-col :span='14'>
+              <el-select style="width: 100%" v-model="position">
+                <el-option value="center">center</el-option>
+                <el-option value="left">left</el-option>
+                <el-option value="right">right</el-option>
+                <el-option value="top">top</el-option>
+                <el-option value="bottom">bottom</el-option>
+                <el-option value="50px 50px">50px 50px</el-option>
+                <el-option :value="JSON.stringify({ x: 50, y: 50 })">
+                  {`{ x: 50, y: 50 }`}
+                </el-option>
+              </el-select>
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='6'>Size</el-col>
+            <el-col :span='14'>
+              <el-select style="width: 100%" v-model="bgSize" >
+                <el-option value="auto auto">auto auto</el-option>
+                <el-option value="cover">cover</el-option>
+                <el-option value="contain">contain</el-option>
+                <el-option value="30px 30px">30px 30px</el-option>
+                <el-option value="100% 100%">100% 100%</el-option>
+                <el-option :value="JSON.stringify({ width: 150, height: 150 })">
+                  {`{width: 150, height: 150 }`}
+                </el-option>
+              </el-select>
+            </el-col>
+          </el-row>
+          <el-row align="middle">
+            <el-col :span='6'>Opacity</el-col>
+            <el-col :span='12'>
+              <el-slider
+                  :min='0.05'
+                  :max='1'
+                  :step='0.05'
+                  v-model="opacity"
+                />
+            </el-col>
+            <el-col :span=4>
+              <div class="result">{{ opacity.toFixed(2) }}</div>
+            </el-col>
+          </el-row>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div> 
+</template>
+
+<script>
+import GridOption from './method'
+const GRID_TYPE_ENUM = {
+  DOT : 'dot',
+  FIXED_DOT : 'fixedDot',
+  MESH : 'mesh',
+  DOUBLE_MESH : 'doubleMesh',
+}
+const REPEAT_TYPE_ENUM = {
+  NO_REPEAT : 'no-repeat',
+  REPEAT : 'repeat',
+  REPEAT_X : 'repeat-x',
+  REPEAT_Y : 'repeat-y',
+  ROUND : 'round',
+  SPACE : 'space',
+  FLIPX : 'flipX',
+  FLIPY : 'flipY',
+  FLIPXY : 'flipXY',
+  WATERMARK : 'watermark',
+}
+export default {
+  data() {
+    return {
+      GRID_TYPE: GRID_TYPE_ENUM,
+      REPEAT_TYPE: REPEAT_TYPE_ENUM,
+      activeName: '1'
+    }
+  },
+  computed: {
+    showGrid: {
+      get() {
+        return this.$store.state.flow.showGrid
+      },
+      set(val) {
+        this.$store.commit('flow/updateshowGrid', val)
+      }
+    },
+    type: {
+      get() {
+        return this.$store.state.flow.type
+      },
+      set(val) {
+        this.$store.commit('flow/updatetype', val)
+      }
+    },
+    size: {
+      get() {
+        return this.$store.state.flow.size
+      },
+      set(val) {
+        this.$store.commit('flow/updatesize', val)
+      }
+    },
+    color: {
+      get() {
+        return this.$store.state.flow.color
+      },
+      set(val) {
+        this.$store.commit('flow/updatecolor', val)
+      }
+    },
+    thickness: {
+      get() {
+        return this.$store.state.flow.thickness
+      },
+      set(val) {
+        this.$store.commit('flow/updatethickness', val)
+      }
+    },
+    colorSecond: {
+      get() {
+        return this.$store.state.flow.colorSecond
+      },
+      set(val) {
+        this.$store.commit('flow/updatecolorSecond', val)
+      }
+    },
+    thicknessSecond: {
+      get() {
+        return this.$store.state.flow.thicknessSecond
+      },
+      set(val) {
+        this.$store.commit('flow/updatethicknessSecond', val)
+      }
+    },
+    factor: {
+      get() {
+        return this.$store.state.flow.factor
+      },
+      set(val) {
+        this.$store.commit('flow/updatefactor', val)
+      }
+    },
+    bgColor: {
+      get() {
+        return this.$store.state.flow.bgColor
+      },
+      set(val) {
+        this.$store.commit('flow/updatebgColor', val)
+      }
+    },
+    showImage: {
+      get() {
+        return this.$store.state.flow.showImage
+      },
+      set(val) {
+        this.$store.commit('flow/updateshowImage', val)
+      }
+    },
+    repeat: {
+      get() {
+        return this.$store.state.flow.repeat
+      },
+      set(val) {
+        this.$store.commit('flow/updaterepeat', val)
+      }
+    },
+    angle: {
+      get() {
+        return this.$store.state.flow.angle
+      },
+      set(val) {
+        this.$store.commit('flow/updateangle', val)
+      }
+    },
+    position: {
+      get() {
+        return this.$store.state.flow.position
+      },
+      set(val) {
+        this.$store.commit('flow/updateposition', val)
+      }
+    },
+    bgSize: {
+      get() {
+        return this.$store.state.flow.bgSize
+      },
+      set(val) {
+        this.$store.commit('flow/updatebgSize', val)
+      }
+    },
+    opacity: {
+      get() {
+        return this.$store.state.flow.opacity
+      },
+      set(val) {
+        this.$store.commit('flow/updateopacity', val)
+      }
+    }
+  },
+  watch: {
+    'showGrid': {
+      handler() {
+        GridOption.isShowGrid(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'type': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'color': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'thickness': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'thicknessSecond': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'colorSecond': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'factor': {
+      handler() {
+        GridOption.gridOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'bgColor': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'showImage': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'repeat': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'angle': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'bgSize': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'position': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'opacity': {
+      handler() {
+        GridOption.backGroundOpt(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+    'size': {
+      handler() {
+        GridOption.setGridSize(this.$store.state.flow)
+      },
+      immediate: false,
+      deep: false
+    },
+  },
+  created() {
+    GridOption.gridOpt(this.$store.state.flow)
+    GridOption.setGridSize(this.$store.state.flow)
+    GridOption.backGroundOpt(this.$store.state.flow)
+    GridOption.isShowGrid(this.$store.state.flow)
+  }
+}
+</script>

+ 83 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigGrid/method.js

@@ -0,0 +1,83 @@
+import FlowGraph from "../../../graph";
+
+const tryToJSON = (val) => {
+    try {
+        return JSON.parse(val)
+    } catch (error) {
+        return val
+    }
+}
+
+export default class GridOption {
+    // 绘制网格
+    static gridOpt(globalGridAttr) {
+        let options
+        if (globalGridAttr.type === 'doubleMesh') {
+            options = {
+                type: globalGridAttr.type,
+                args: [
+                    {
+                        color: globalGridAttr.color,
+                        thickness: globalGridAttr.thickness,
+                    },
+                    {
+                        color: globalGridAttr.colorSecond,
+                        thickness: globalGridAttr.thicknessSecond,
+                        factor: globalGridAttr.factor,
+                    },
+                ],
+            }
+        } else {
+            options = {
+                type: globalGridAttr.type,
+                args: [
+                    {
+                        color: globalGridAttr.color,
+                        thickness: globalGridAttr.thickness,
+                    },
+                ],
+            }
+        }
+        const { graph } = FlowGraph
+        graph.drawGrid(options)
+    }
+
+    // 设置网格大小
+    static setGridSize(globalGridAttr) {
+        const { graph } = FlowGraph
+        graph.setGridSize(globalGridAttr.size)
+    }
+
+    // 获取网格大小
+    static getGridSize() {
+        const { graph } = FlowGraph
+        graph.getGridSize()
+    }
+
+    // 重绘背景
+    static backGroundOpt(globalGridAttr) {
+        const options = {
+            color: globalGridAttr.bgColor,
+            // image: globalGridAttr.showImage ? 'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*o-MuTpQaj7EAAAAAAAAAAABkARQnAQ' : undefined,
+            // image: globalGridAttr.showImage ? require('../../../../../assets/logo.png') : undefined,
+            // image: undefined,
+            repeat: globalGridAttr.repeat,
+            angle: globalGridAttr.angle,
+            size: tryToJSON(globalGridAttr.bgSize),
+            position: tryToJSON(globalGridAttr.position),
+            opacity: globalGridAttr.opacity,
+        }
+        const { graph } = FlowGraph
+        graph.drawBackground(options)
+    }
+
+    // 是否显示网格
+    static isShowGrid({ showGrid }) {
+        const { graph } = FlowGraph
+        if(showGrid) {
+            graph.showGrid()
+        } else {
+            graph.hideGrid()
+        }
+    }
+}

+ 412 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigNode/index.vue

@@ -0,0 +1,412 @@
+<template>
+  <div style="width: 100%;height: 100%;">
+    <el-tabs v-model="activeName">
+      <el-tab-pane label="节点" name="1">
+        <!-- 调节边框的颜色  对无边框的不起作用 -->
+        <el-row v-show="nodeType == 'text'">
+          <el-col :span='10'>Border Color</el-col>
+          <el-col :span='14'>
+            <el-input size="mini" type="color" v-model="nodeStroke" style="width: 100%" @change="onStrokeChange"/>
+          </el-col>
+        </el-row>
+        <!-- 调节边框的宽度  对无边框的不起作用 -->
+        <el-row v-show="nodeType == 'text'">
+          <el-col :span='8'>Border Width</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='1' :max='5' :step='1' v-model="nodeStrokeWidth" @change="onStrokeWidthChange"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{nodeStrokeWidth}}</div>
+          </el-col>
+        </el-row>
+        <!-- 填充颜色  对image不起作用 -->
+        <el-row v-show="nodeType == 'text'">
+          <el-col :span='8'>Fill isTransparent</el-col>
+          <el-col :span='14'>
+            <el-switch v-model="isNodeFill" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
+          </el-col>
+        </el-row>
+        <el-row v-show="nodeType == 'text' && !isNodeFill">
+          <el-input size="mini" type="color" v-model="nodeFill" style="width: 100%" @change="onFillChange"/>
+        </el-row>
+        <!-- <el-row>
+          <el-col :span='8'>Image Width</el-col>
+          <el-col :span='14'>
+            <el-slider :min='20' :max='300' :step='20' v-model="nodeImageWidth" style="width: 100%" @change="onImageWidth"/>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>Image Height</el-col>
+          <el-col :span='14'>
+            <el-slider :min='20' :max='300' :step='20' v-model="nodeImageHeight" style="width: 100%" @change="onImageHeight"/>
+          </el-col>
+        </el-row> -->
+        <el-row v-show="nodeType == 'image'">
+          <el-col :span='8'>Port ID</el-col>
+          <el-col :span='14'>
+            <el-select size="mini" v-model="portId" placeholder="请选择">
+              <el-option label="top" value="port1" />
+              <el-option label="right" value="port2" />
+              <el-option label="bottom" value="port3" />
+              <el-option label="left" value="port4" />
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row v-show="portId">
+          <el-col :span='8'>Port Left</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='-5' :max='100' :step='1' v-model="portX" style="width: 100%"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{ portX }}</div>
+          </el-col>
+        </el-row>
+        <el-row v-show="portId">
+          <el-col :span='8'>Port Top</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='-5' :max='100' :step='1' v-model="portY" style="width: 100%"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{ portY }}</div>
+          </el-col>
+        </el-row>
+        <el-row v-show="portId">
+          <el-col :span='10'>Port Color</el-col>
+          <el-col :span='14'>
+            <el-input size="mini" type="color" v-model="portColor" style="width: 100%" @change="onPortColorChange"/>
+          </el-col>
+        </el-row>
+        <el-row v-show="portId">
+          <el-col :span='10'>Port Fill</el-col>
+          <el-col :span='14'>
+            <el-input size="mini" type="color" v-model="portFill" style="width: 100%" @change="onPortFillChange"/>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>Node ZIndex</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='0' :max='100' :step='1' v-model="ZIndex" style="width: 100%"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{ ZIndex }}</div>
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+      <el-tab-pane label="文本" name="2">
+        <el-row>
+          <el-col :span='8'>Font Size</el-col>
+          <el-col :span='12'>
+            <el-slider size="mini" :min='8' :max='16' :step='1' v-model="nodeFontSize" @change="onFontSizeChange"/>
+          </el-col>
+          <el-col :span='2'>
+            <div class="result">{{ nodeFontSize }}</div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>Font Color</el-col>
+          <el-col :span='14'>
+            <el-input size="mini" type="color" v-model="nodeColor" style="width: 100%" @change="onColorChange"/>
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+      <el-tab-pane v-if="nodeType == 'text'" label="属性" name="3">
+        <el-row>
+          <el-col :span='8'>Status</el-col>
+          <el-col :span='14'>
+            <el-select size="mini" @change="onNodeStatusChange" v-model="nodeStatus" placeholder="请选择">
+              <el-option label="停止" :value="0" />
+              <el-option label="运行" :value="1" />
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>PointCode</el-col>
+          <el-col :span='14'>
+            <el-select size="mini" @change="onNodePointCode" v-model="nodePointCode" placeholder="请选择">
+              <el-option label="52" value="52" />
+              <el-option label="51" value="51" />
+            </el-select>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span='8'>FieldName</el-col>
+          <el-col :span='14'>
+            <el-select size="mini" @change="onNodeFieldName" v-model="nodeFieldName" placeholder="请选择">
+              <el-option label="fieldName1" value="fieldName1" />
+              <el-option label="fieldName2" value="fieldName2" />
+            </el-select>
+          </el-col>
+        </el-row>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+<script>
+import { nodeOpt } from "./method";
+export default {
+  data() {
+    return {
+      curCel: null,
+      activeName: '1',
+      isNodeFill: false
+    }
+  },
+  props: { id: String },
+  watch: {
+    id: {
+      handler() {
+        this.curCel = nodeOpt(this.id, this.$store.state.flow)
+        if(this.curCel) {
+          this.ZIndex = this.curCel.getZIndex()
+          this.isNodeFill = false
+          if(this.nodeType == 'text') {
+            this.curCel?.setData({
+              status: this.nodeStatus ?? 0,
+              pointCode: this.nodePointCode ?? '',
+              fieldName: this.nodeFieldName ?? ''
+            })
+          }
+        }
+      },
+      immediate: false,
+      deep: true
+    },
+    portId: {
+      handler() {
+        if(this.portId) {
+          const { x, y } = this.curCel?.getPortProp(this.portId)?.args
+          if(x && y) {
+            this.portX = parseInt(x.slice(0, -1))
+            this.portY = parseInt(y.slice(0, -1))
+          }
+        }
+      },
+      immediate: false
+    },
+    portX: {
+      handler() {
+        this.curCel?.setPortProp(this.portId, 'args', { x: this.portX + '%', y: this.portY + '%' })
+      },
+      immediate: false
+    },
+    portY: {
+      handler() {
+        this.curCel?.setPortProp(this.portId, 'args', { x: this.portX + '%', y: this.portY + '%' })
+      },
+      immediate: false
+    },
+    ZIndex: {
+      handler() {
+        if(this.curCel) {
+          this.curCel?.setZIndex(this.ZIndex)
+        }
+      },
+      immediate: false
+    },
+    isNodeFill: {
+      handler() {
+        if(this.isNodeFill) {
+          this.curCel?.attr('body/fill', 'transparent')
+        } else {
+          this.curCel?.attr('body/fill', '#fff')
+        }
+      },
+      immediate: true
+    }
+  },
+  computed: {
+    nodeStroke: {
+      get() {
+        return this.$store.state.flow.nodeStroke
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeStroke', val)
+      }
+    },
+    nodeStrokeWidth: {
+      get() {
+        return this.$store.state.flow.nodeStrokeWidth
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeStrokeWidth', val)
+      }
+    },
+    nodeFill: {
+      get() {
+        return this.$store.state.flow.nodeFill
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeFill', val)
+      }
+    },
+    // nodeImageWidth: {
+    //   get() {
+    //     return this.$store.state.flow.nodeImageWidth
+    //   },
+    //   set(val) {
+    //     this.$store.commit('flow/updatenodeImageWidth', val)
+    //   }
+    // },
+    // nodeImageHeight: {
+    //   get() {
+    //     return this.$store.state.flow.nodeImageHeight
+    //   },
+    //   set(val) {
+    //     this.$store.commit('flow/updatenodeImageHeight', val)
+    //   }
+    // },
+    portId: {
+      get() {
+        return this.$store.state.flow.portId
+      },
+      set(val) {
+        this.$store.commit('flow/updateportId', val)
+      }
+    },
+    portX: {
+      get() {
+        return this.$store.state.flow.portX
+      },
+      set(val) {
+        this.$store.commit('flow/updateportX', val)
+      }
+    },
+    portY: {
+      get() {
+        return this.$store.state.flow.portY
+      },
+      set(val) {
+        this.$store.commit('flow/updateportY', val)
+      }
+    },
+    portColor: {
+      get() {
+        return this.$store.state.flow.portColor
+      },
+      set(val) {
+        this.$store.commit('flow/updateportColor', val)
+      }
+    },
+    portFill: {
+      get() {
+        return this.$store.state.flow.portFill
+      },
+      set(val) {
+        this.$store.commit('flow/updateportFill', val)
+      }
+    },
+    ZIndex: {
+      get() {
+        return this.$store.state.flow.ZIndex
+      },
+      set(val) {
+        this.$store.commit('flow/updateZIndex', val)
+      }
+    },
+    nodeFontSize: {
+      get() {
+        return this.$store.state.flow.nodeFontSize
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeFontSize', val)
+      }
+    },
+    nodeColor: {
+      get() {
+        return this.$store.state.flow.nodeColor
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeColor', val)
+      }
+    },
+    nodeStatus: {
+      get() {
+        return this.$store.state.flow.nodeStatus
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeStatus', val)
+      }
+    },
+    nodePointCode: {
+      get() {
+        return this.$store.state.flow.nodePointCode
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodePointCode', val)
+      }
+    },
+    nodeFieldName: {
+      get() {
+        return this.$store.state.flow.nodeFieldName
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeFieldName', val)
+      }
+    },
+    nodeType: {
+      get() {
+        return this.$store.state.flow.nodeType
+      },
+      set(val) {
+        this.$store.commit('flow/updatenodeType', val)
+      }
+    },
+  },
+  methods: {
+    onStrokeChange () {
+      this.curCel?.attr('body/stroke', this.nodeStroke)
+    },
+
+    onStrokeWidthChange () {
+      this.curCel?.attr('body/strokeWidth', this.nodeStrokeWidth)
+    },
+
+    onFillChange () {
+      this.curCel?.attr('body/fill', this.nodeFill)
+    },
+
+    // onImageWidth (e) {
+    //   this.curCel?.attr('image/width', this.nodeImageWidth)
+    // },
+
+    // onImageHeight (e) {
+    //   this.curCel?.attr('image/height', this.nodeImageHeight)
+    // },
+
+    onPortColorChange() {
+      this.curCel?.setPortProp(this.portId, ['attrs', 'circle', 'stroke'], this.portColor)
+    },
+
+    onPortFillChange() {
+      this.curCel?.setPortProp(this.portId, ['attrs', 'circle', 'fill'], this.portFill)
+    },
+
+    onFontSizeChange () {
+      this.curCel?.attr('text/fontSize', this.nodeFontSize)
+    },
+
+    onColorChange () {
+      this.curCel?.attr('text/fill', this.nodeColor)
+    },
+
+    onNodeStatusChange () {
+      // this.curCel?.attr('data/status', this.nodeStatus)
+      this.curCel?.setData({ status: this.nodeStatus })
+    },
+    onNodePointCode () {
+      // this.curCel?.attr('data/pointCode', this.nodePointCode)
+      this.curCel?.setData({ pointCode: this.nodePointCode })
+    },
+    onNodeFieldName () {
+      // this.curCel?.attr('data/fieldName', this.nodeFieldName)
+      this.curCel?.setData({ fieldName: this.nodeFieldName })
+    }
+  }
+}
+</script>
+
+<style scoped>
+.el-row {
+  margin-bottom: 5px;
+}
+</style>

+ 21 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/ConfigNode/method.js

@@ -0,0 +1,21 @@
+import FlowGraph from "../../../graph";
+import Store from '../../../../../../../store'
+
+export function nodeOpt(id){
+    let curCel = null;
+    if (id) {
+        const { graph } = FlowGraph
+        const cell = graph.getCellById(id)
+        if (!cell || !cell.isNode()) {
+            return
+        }
+        curCel = cell
+        Store.commit('flow/updatenodeStroke', cell.attr('body/stroke'))
+        Store.commit('flow/updatenodeStrokeWidth', cell.attr('body/strokeWidth'))
+        Store.commit('flow/updatenodeFill', cell.attr('body/fill'))
+        Store.commit('flow/updatenodeFontSize', cell.attr('text/fontSize'))
+        Store.commit('flow/updatenodeColor', cell.attr('text/fill'))
+        Store.commit('flow/updateportId', '')
+    }
+    return curCel;
+}

+ 16 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/index.css

@@ -0,0 +1,16 @@
+.config .ant-row {
+  line-height: 32px;
+  margin: 8px 0;
+}
+.config .ant-row .result {
+  background: #eee;
+  color: #333333;
+  padding: 3px 7px;
+  border-radius: 10px;
+  display: inline-block;
+  font-size: 12px;
+  margin-left: 8px;
+  line-height: 1.25;
+  margin-top: 8px;
+}
+

+ 48 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ConfigPanel/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <div class="config" style="width: 100%;height: 100%;">
+    <config-grid :id="id" v-show="type === 'grid'" />
+    <config-node :id="id" v-show="type === 'node'" />
+    <config-edge :id="id" v-show="type === 'edge'" />
+  </div>
+</template>
+
+<script>
+import ConfigGrid from './ConfigGrid/index.vue'
+import ConfigNode from './ConfigNode/index.vue'
+import ConfigEdge from './ConfigEdge/index.vue'
+import FlowGraph from '../../graph'
+import './index.css'
+export default {
+  data() {
+    return {
+      type: 'grid',
+      id: '',
+    }
+  },
+  components:{
+    ConfigGrid,
+    ConfigNode,
+    ConfigEdge
+  },
+  created() {
+    this.boundEvent()
+  },
+  methods: {
+    // 待优化
+    boundEvent() {
+      const { graph } = FlowGraph
+      graph.on('blank:click', () => {
+        this.type = "grid"
+      })
+      graph.on('cell:mousedown', ({ cell }) => {
+        this.type = cell.isNode() ? "node" : "edge"
+        this.id = cell.id
+        if(this.type == "node") {
+          let nodeType = cell['attrs']['image'] && cell['attrs']['image']['xlink:href'] ? 'image' : 'text'
+          this.$store.commit('flow/updatenodeType', nodeType)
+        }
+      })
+    }
+  }
+}
+</script>

+ 213 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/components/ToolBar/index.vue

@@ -0,0 +1,213 @@
+<template>
+  <div class="bar">
+    <el-tooltip class="item" effect="dark" content="清除 (Cmd + D)" placement="bottom">
+      <el-button name="delete" @click="handleClick" class="item-space" size="small" >
+        清除
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="撤销 (Cmd + Z)" placement="bottom">
+      <el-button :disabled="!canUndo" name="undo" @click="handleClick" class="item-space" size="small" >
+        撤销
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="Redo (Cmd + Shift + Z)" placement="bottom">
+      <el-button :disabled="!canRedo" name="redo" @click="handleClick" class="item-space" size="small" >
+        redo
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="复制 (Cmd + Shift + Z)" placement="bottom">
+      <el-button name="copy" @click="handleClick" class="item-space" size="small" >
+        复制
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="剪切 (Cmd + X)" placement="bottom">
+      <el-button name="cut" @click="handleClick" class="item-space" size="small" >
+        剪切
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="粘贴 (Cmd + V)" placement="bottom">
+      <el-button name="paste" @click="handleClick" class="item-space" size="small" >
+        粘贴
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="保存PNG (Cmd + S)" placement="bottom">
+      <el-button name="savePNG" @click="handleClick" class="item-space" size="small">
+        保存PNG
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="保存SVG (Cmd + S)" placement="bottom">
+      <el-button name="saveSVG" @click="handleClick" class="item-space" size="small">
+        保存SVG
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="打印 (Cmd + P)" placement="bottom">
+      <el-button name="print" @click="handleClick" class="item-space" size="small">
+        打印
+      </el-button>
+    </el-tooltip>
+
+    <el-tooltip class="item" effect="dark" content="导出 (Cmd + P)" placement="bottom">
+      <el-button name="toJSON" @click="handleClick" class="item-space" size="small">
+        存储
+      </el-button>
+    </el-tooltip>
+
+  </div>
+</template>
+<script>
+import FlowGraph from '../../graph'
+import { DataUri } from '@antv/x6'
+export default {
+  data() {
+    return {
+      canUndo: null,
+      canRedo: null
+    }
+  },
+  created() {
+    this.myInit()
+  },
+  methods: {
+    myInit() {
+      const { graph } = FlowGraph
+      const { history } = graph
+      this.canUndo = history.canUndo()
+      this.canRedo = history.canRedo()
+      history.on('change', () => {
+      this.canUndo = history.canUndo()
+      this.canRedo = history.canRedo()
+    })
+    graph.bindKey('ctrl+z', () => {
+      if (history.canUndo()) {
+        history.undo()
+      }
+      return false
+    })
+    graph.bindKey('ctrl+shift+z', () => {
+      if (history.canRedo()) {
+        history.redo()
+      }
+      return false
+    })
+    graph.bindKey('ctrl+d', () => {
+      graph.clearCells()
+      return false
+    })
+    graph.bindKey('ctrl+s', () => {
+      graph.toPNG((datauri) => {
+        DataUri.downloadDataUri(datauri, 'chart.png')
+      })
+      return false
+    })
+    graph.bindKey('ctrl+p', () => {
+      graph.printPreview()
+      return false
+    })
+    graph.bindKey('ctrl+c', this.copy)
+    graph.bindKey('ctrl+v', this.paste)
+    graph.bindKey('ctrl+x', this.cut)
+    },
+    copy() {
+      const { graph } = FlowGraph
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.copy(cells)
+      }
+      return false
+    },
+
+    cut () {
+      const { graph } = FlowGraph
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.cut(cells)
+      }
+      return false
+    },
+
+    paste () {
+      const { graph } = FlowGraph
+      if (!graph.isClipboardEmpty()) {
+        const cells = graph.paste({ offset: 32 })
+        graph.cleanSelection()
+        graph.select(cells)
+      }
+      return false
+    },
+
+    handleClick(event) {
+      const { graph } = FlowGraph
+      const name = (event.currentTarget).name
+      switch (name) {
+        case 'undo':
+          graph.history.undo()
+          break
+        case 'redo':
+          graph.history.redo()
+          break
+        case 'delete':
+          graph.clearCells()
+          break
+        case 'savePNG':
+          graph.toPNG((dataUri) => {
+            // 下载
+            DataUri.downloadDataUri(dataUri, 'chartx.png')
+          }, {
+            backgroundColor:'white',
+            padding: {
+              top: 20,
+              right: 30,
+              bottom: 40,
+              left: 50,
+            },
+            quality:1
+          })
+          break
+        case 'saveSVG':
+          graph.toSVG((dataUri) => {
+            // 下载
+            DataUri.downloadDataUri(DataUri.svgToDataUrl(dataUri), 'chart.svg')
+          })
+          break
+        case 'print':
+          graph.printPreview()
+          break
+        case 'copy':
+          this.copy()
+          break
+        case 'cut':
+          this.cut()
+          break
+        case 'paste':
+          this.paste()
+          break
+        case 'toJSON':
+          console.log(graph.toJSON())
+          window.localStorage.setItem('graphJson', JSON.stringify(graph.toJSON()))
+          // graph.fromJSON({cells:[graph.toJSON().cells[0],graph.toJSON().cells[1]]})
+          break
+        default:
+          break
+      }
+    }
+  }
+}
+</script>
+<style scoped>
+.bar{
+  width: 100%;
+  z-index: 99999;
+  margin-right:16px;
+}
+.item-space{
+  margin-left:16px;
+}
+</style>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 13 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-1.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 16 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-2.js


+ 1190 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-3.js

@@ -0,0 +1,1190 @@
+const graphData = {
+  cells: [
+    {
+      position: {
+        x: 420,
+        y: 160,
+      },
+      size: {
+        width: 80,
+        height: 42,
+      },
+      attrs: {
+        text: {
+          text: '起始节点',
+        },
+        body: {
+          rx: 24,
+          ry: 24,
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: '45726225-0a03-409e-8475-07da4b8533c5',
+          },
+          {
+            group: 'right',
+            id: '06111939-bf01-48d9-9f54-6465d9d831c6',
+          },
+          {
+            group: 'bottom',
+            id: '6541f8dc-e48b-4b8c-a105-2ab3a47f1f21',
+          },
+          {
+            group: 'left',
+            id: '54781206-573f-4982-a21e-5fac1e0e8a60',
+          },
+        ],
+      },
+      id: '8650a303-3568-4ff2-9fac-2fd3ae7e6f2a',
+      zIndex: 1,
+    },
+
+  
+
+
+
+    {
+      position: {
+        x: 420,
+        y: 250,
+      },
+      size: {
+        width: 80,
+        height: 42,
+      },
+      attrs: {
+        text: {
+          text: '流程节点',
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: 'd1346f43-969a-4201-af5d-d09b7ef79980',
+          },
+          {
+            group: 'right',
+            id: 'd561926a-3a24-449a-abb1-0c20bc89947e',
+          },
+          {
+            group: 'bottom',
+            id: '0cbde5df-ef35-410e-b6c3-a6b1f5561e3f',
+          },
+          {
+            group: 'left',
+            id: '2fceb955-f7af-41ac-ac02-5a2ea514544e',
+          },
+        ],
+      },
+      id: '7b6fd715-83e6-4053-8c2b-346e6a857bf3',
+      zIndex: 2,
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          strokeDasharray: 0,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '00f3c401-8bad-46b9-b692-232aa011d4c5',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 3,
+      source: {
+        cell: '8650a303-3568-4ff2-9fac-2fd3ae7e6f2a',
+        port: '6541f8dc-e48b-4b8c-a105-2ab3a47f1f21',
+      },
+      target: {
+        cell: '7b6fd715-83e6-4053-8c2b-346e6a857bf3',
+        port: 'd1346f43-969a-4201-af5d-d09b7ef79980',
+      },
+    },
+    {
+      position: {
+        x: 425,
+        y: 371,
+      },
+      size: {
+        width: 70,
+        height: 70,
+      },
+      attrs: {
+        text: {
+          text: '链接节点',
+        },
+        body: {
+          rx: 35,
+          ry: 35,
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: '089ce61a-4b17-4ed8-9c3f-5b905f484425',
+          },
+          {
+            group: 'right',
+            id: 'fd4b8c95-d1eb-41ea-b3e1-15135814b292',
+          },
+          {
+            group: 'bottom',
+            id: '9bb8ec19-b1e2-432d-8735-b008da064948',
+          },
+          {
+            group: 'left',
+            id: 'fbf8759a-1059-47bb-b556-f0a4477e48d3',
+          },
+        ],
+      },
+      id: '762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc',
+      zIndex: 4,
+    },
+    {
+      angle: 45,
+      position: {
+        x: 310,
+        y: 380,
+      },
+      size: {
+        width: 52,
+        height: 52,
+      },
+      attrs: {
+        text: {
+          text: '判断节点',
+          transform: 'rotate(-45deg)',
+        },
+        'edit-text': {
+          style: {
+            transform: 'rotate(-45deg)',
+          },
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: {
+              name: 'top',
+              args: {
+                dx: -26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: {
+              name: 'right',
+              args: {
+                dy: -26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: {
+              name: 'bottom',
+              args: {
+                dx: 26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: {
+              name: 'left',
+              args: {
+                dy: 26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: 'c133349e-4a4a-4d7d-9b38-26c36b3e68c5',
+          },
+          {
+            group: 'right',
+            id: 'af190d15-b0f1-4f92-85bc-e0c4df83e2a7',
+          },
+          {
+            group: 'bottom',
+            id: 'c51a4f3b-759b-47ed-9d80-fa4f6c114e64',
+          },
+          {
+            group: 'left',
+            id: 'c241a7e4-12d3-4dde-9694-0f0e5f7b9a91',
+          },
+        ],
+      },
+      id: 'ef3865af-8a91-4164-8466-3f6b4315070f',
+      zIndex: 5,
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '9031a1ee-8deb-4b1e-90e6-96d40d3a8515',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 7,
+      source: {
+        cell: 'ef3865af-8a91-4164-8466-3f6b4315070f',
+        port: 'af190d15-b0f1-4f92-85bc-e0c4df83e2a7',
+      },
+      target: {
+        cell: '762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc',
+        port: 'fbf8759a-1059-47bb-b556-f0a4477e48d3',
+      },
+    },
+    {
+      angle: 45,
+      position: {
+        x: 566,
+        y: 380,
+      },
+      size: {
+        width: 52,
+        height: 52,
+      },
+      attrs: {
+        text: {
+          text: '判断节点',
+          transform: 'rotate(-45deg)',
+        },
+        'edit-text': {
+          style: {
+            transform: 'rotate(-45deg)',
+          },
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: {
+              name: 'top',
+              args: {
+                dx: -26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: {
+              name: 'right',
+              args: {
+                dy: -26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: {
+              name: 'bottom',
+              args: {
+                dx: 26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: {
+              name: 'left',
+              args: {
+                dy: 26,
+              },
+            },
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: 'c133349e-4a4a-4d7d-9b38-26c36b3e68c5',
+          },
+          {
+            group: 'right',
+            id: 'af190d15-b0f1-4f92-85bc-e0c4df83e2a7',
+          },
+          {
+            group: 'bottom',
+            id: 'c51a4f3b-759b-47ed-9d80-fa4f6c114e64',
+          },
+          {
+            group: 'left',
+            id: 'c241a7e4-12d3-4dde-9694-0f0e5f7b9a91',
+          },
+        ],
+      },
+      id: '9be960d0-fb75-49b1-8131-abc05b5991bd',
+      zIndex: 9,
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '8af8b072-dfb9-458a-b15e-dd5d4c1863bd',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 10,
+      source: {
+        cell: '7b6fd715-83e6-4053-8c2b-346e6a857bf3',
+        port: 'd561926a-3a24-449a-abb1-0c20bc89947e',
+      },
+      target: {
+        cell: '9be960d0-fb75-49b1-8131-abc05b5991bd',
+        port: 'c133349e-4a4a-4d7d-9b38-26c36b3e68c5',
+      },
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '58874c23-da0b-46e6-9124-5154e8570bfd',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 11,
+      source: {
+        cell: '9be960d0-fb75-49b1-8131-abc05b5991bd',
+        port: 'c241a7e4-12d3-4dde-9694-0f0e5f7b9a91',
+      },
+      target: {
+        cell: '762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc',
+        port: 'fd4b8c95-d1eb-41ea-b3e1-15135814b292',
+      },
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '13d78262-f889-4e6f-9980-29f9e2d87c8f',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 12,
+      source: {
+        cell: '7b6fd715-83e6-4053-8c2b-346e6a857bf3',
+        port: '2fceb955-f7af-41ac-ac02-5a2ea514544e',
+      },
+      target: {
+        cell: 'ef3865af-8a91-4164-8466-3f6b4315070f',
+        port: 'c133349e-4a4a-4d7d-9b38-26c36b3e68c5',
+      },
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '9c7b7539-2f82-478d-a592-60dfceede791',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 13,
+      source: {
+        cell: '7b6fd715-83e6-4053-8c2b-346e6a857bf3',
+        port: '0cbde5df-ef35-410e-b6c3-a6b1f5561e3f',
+      },
+      target: {
+        cell: '762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc',
+        port: '089ce61a-4b17-4ed8-9c3f-5b905f484425',
+      },
+    },
+    {
+      position: {
+        x: 420,
+        y: 497,
+      },
+      size: {
+        width: 80,
+        height: 42,
+      },
+      attrs: {
+        text: {
+          text: '流程节点',
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: 'd1346f43-969a-4201-af5d-d09b7ef79980',
+          },
+          {
+            group: 'right',
+            id: 'd561926a-3a24-449a-abb1-0c20bc89947e',
+          },
+          {
+            group: 'bottom',
+            id: '0cbde5df-ef35-410e-b6c3-a6b1f5561e3f',
+          },
+          {
+            group: 'left',
+            id: '2fceb955-f7af-41ac-ac02-5a2ea514544e',
+          },
+        ],
+      },
+      id: 'c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5',
+      zIndex: 14,
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: '9dfeb591-70e1-4b52-a463-3078a6fde579',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 15,
+      source: {
+        cell: '762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc',
+        port: '9bb8ec19-b1e2-432d-8735-b008da064948',
+      },
+      target: {
+        cell: 'c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5',
+        port: 'd1346f43-969a-4201-af5d-d09b7ef79980',
+      },
+    },
+    {
+      position: {
+        x: 420,
+        y: 616,
+      },
+      size: {
+        width: 80,
+        height: 42,
+      },
+      attrs: {
+        text: {
+          text: '结束节点',
+        },
+        body: {
+          rx: 24,
+          ry: 24,
+        },
+      },
+      shape: 'flow-chart-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: '45726225-0a03-409e-8475-07da4b8533c5',
+          },
+          {
+            group: 'right',
+            id: '06111939-bf01-48d9-9f54-6465d9d831c6',
+          },
+          {
+            group: 'bottom',
+            id: '6541f8dc-e48b-4b8c-a105-2ab3a47f1f21',
+          },
+          {
+            group: 'left',
+            id: '54781206-573f-4982-a21e-5fac1e0e8a60',
+          },
+        ],
+      },
+      id: '5ac48b64-d507-4006-954b-f8fbf8016ad2',
+      zIndex: 16,
+    },
+    {
+      shape: 'edge',
+      attrs: {
+        line: {
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          targetMarker: {
+            name: 'classic',
+            size: 8,
+          },
+        },
+      },
+      id: 'f847f055-9073-4c8e-92c5-8124597d1e7e',
+      router: {
+        name: 'manhattan',
+      },
+      zIndex: 17,
+      source: {
+        cell: 'c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5',
+        port: '0cbde5df-ef35-410e-b6c3-a6b1f5561e3f',
+      },
+      target: {
+        cell: '5ac48b64-d507-4006-954b-f8fbf8016ad2',
+        port: '45726225-0a03-409e-8475-07da4b8533c5',
+      },
+    },
+    {
+      position: {
+        x: 660,
+        y: 190,
+      },
+      size: {
+        width: 200,
+        height: 60,
+      },
+      shape: 'flow-chart-animate-text',
+      id: '0698a6d6-4f48-42e3-ab59-5ff5713a63ea',
+      zIndex: 20,
+    },
+    {
+      position: {
+        x: 660,
+        y: 292,
+      },
+      size: {
+        width: 200,
+        height: 60,
+      },
+      shape: 'flow-chart-image-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: 'a48f4c0f-fa60-4ea6-8a9c-1046a3cbf0a0',
+          },
+          {
+            group: 'right',
+            id: 'e05f9fde-c5f3-47ea-920c-a210c4fc3501',
+          },
+          {
+            group: 'bottom',
+            id: '183117cc-26d8-4241-95b4-d83d95010224',
+          },
+          {
+            group: 'left',
+            id: 'ad9ffaa5-9c34-4aa8-a311-4b58b56cd0f6',
+          },
+        ],
+      },
+      id: '229d844a-be25-414a-b044-ae3a6c63ce74',
+      zIndex: 21,
+    },
+    {
+      position: {
+        x: 660,
+        y: 404,
+      },
+      size: {
+        width: 200,
+        height: 68,
+      },
+      shape: 'flow-chart-title-rect',
+      ports: {
+        groups: {
+          top: {
+            position: 'top',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          right: {
+            position: 'right',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          bottom: {
+            position: 'bottom',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+          left: {
+            position: 'left',
+            attrs: {
+              circle: {
+                r: 3,
+                magnet: true,
+                stroke: '#5F95FF',
+                strokeWidth: 1,
+                fill: '#fff',
+                style: {
+                  visibility: 'hidden',
+                },
+              },
+            },
+          },
+        },
+        items: [
+          {
+            group: 'top',
+            id: '739f9eec-ef8f-4f2e-b328-6b7e0793d582',
+          },
+          {
+            group: 'right',
+            id: '5786e655-df1d-419e-92e2-db91b3c4506c',
+          },
+          {
+            group: 'bottom',
+            id: 'e74c9676-4c27-474f-be96-be4568ed55d0',
+          },
+          {
+            group: 'left',
+            id: '007fa7ae-aa47-4faf-925c-779c35db4f5f',
+          },
+        ],
+      },
+      id: '4197e369-2948-4209-8e13-0dd6dedd07b4',
+      zIndex: 22,
+    },
+    
+  ],
+}
+
+export default graphData

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 142 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data-custom-4.js


+ 1021 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/data/data.js

@@ -0,0 +1,1021 @@
+export default {
+  "cells": [
+    {
+      "position": {
+        "x": 420,
+        "y": 160
+      },
+      "size": {
+        "width": 80,
+        "height": 42
+      },
+      "attrs": {
+        "text": {
+          "text": "起始节点"
+        },
+        "body": {
+          "rx": 24,
+          "ry": 24
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": "top",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": "right",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": false,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": "bottom",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": "left",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "45726225-0a03-409e-8475-07da4b8533c5"
+          },
+          {
+            "group": "right",
+            "id": "06111939-bf01-48d9-9f54-6465d9d831c6"
+          },
+          {
+            "group": "bottom",
+            "id": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
+          },
+          {
+            "group": "left",
+            "id": "54781206-573f-4982-a21e-5fac1e0e8a60"
+          }
+        ]
+      },
+      "id": "8650a303-3568-4ff2-9fac-2fd3ae7e6f2a",
+      "zIndex": 1,
+      "data": {
+        "status": 1,
+        "pointCode": "52",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "position": {
+        "x": 420,
+        "y": 250
+      },
+      "size": {
+        "width": 80,
+        "height": 42
+      },
+      "attrs": {
+        "text": {
+          "text": "流程节点"
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": "top",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": "right",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": "bottom",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": "left",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "d1346f43-969a-4201-af5d-d09b7ef79980"
+          },
+          {
+            "group": "right",
+            "id": "d561926a-3a24-449a-abb1-0c20bc89947e"
+          },
+          {
+            "group": "bottom",
+            "id": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
+          },
+          {
+            "group": "left",
+            "id": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
+          }
+        ]
+      },
+      "id": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
+      "zIndex": 2,
+      "data": {
+        "status": 0,
+        "pointCode": "51",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          },
+          "strokeDasharray": 0
+        }
+      },
+      "id": "00f3c401-8bad-46b9-b692-232aa011d4c5",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 3,
+      "source": {
+        "cell": "8650a303-3568-4ff2-9fac-2fd3ae7e6f2a",
+        "port": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
+      },
+      "target": {
+        "cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
+        "port": "d1346f43-969a-4201-af5d-d09b7ef79980"
+      }
+    },
+    {
+      "position": {
+        "x": 425,
+        "y": 371
+      },
+      "size": {
+        "width": 70,
+        "height": 70
+      },
+      "attrs": {
+        "text": {
+          "text": "链接节点"
+        },
+        "body": {
+          "rx": 35,
+          "ry": 35
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": "top",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": "right",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": "bottom",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": "left",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "089ce61a-4b17-4ed8-9c3f-5b905f484425"
+          },
+          {
+            "group": "right",
+            "id": "fd4b8c95-d1eb-41ea-b3e1-15135814b292"
+          },
+          {
+            "group": "bottom",
+            "id": "9bb8ec19-b1e2-432d-8735-b008da064948"
+          },
+          {
+            "group": "left",
+            "id": "fbf8759a-1059-47bb-b556-f0a4477e48d3"
+          }
+        ]
+      },
+      "id": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
+      "zIndex": 4,
+      "data": {
+        "status": 0,
+        "pointCode": "51",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "angle": 45,
+      "position": {
+        "x": 310,
+        "y": 380
+      },
+      "size": {
+        "width": 52,
+        "height": 52
+      },
+      "attrs": {
+        "text": {
+          "text": "判断节点",
+          "transform": "rotate(-45deg)"
+        },
+        "edit-text": {
+          "style": {
+            "transform": "rotate(-45deg)"
+          }
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": {
+              "name": "top",
+              "args": {
+                "dx": -26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": {
+              "name": "right",
+              "args": {
+                "dy": -26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": {
+              "name": "bottom",
+              "args": {
+                "dx": 26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": {
+              "name": "left",
+              "args": {
+                "dy": 26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
+          },
+          {
+            "group": "right",
+            "id": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
+          },
+          {
+            "group": "bottom",
+            "id": "c51a4f3b-759b-47ed-9d80-fa4f6c114e64"
+          },
+          {
+            "group": "left",
+            "id": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
+          }
+        ]
+      },
+      "id": "ef3865af-8a91-4164-8466-3f6b4315070f",
+      "zIndex": 5,
+      "data": {
+        "status": 0,
+        "pointCode": "51",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "9031a1ee-8deb-4b1e-90e6-96d40d3a8515",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 7,
+      "source": {
+        "cell": "ef3865af-8a91-4164-8466-3f6b4315070f",
+        "port": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
+      },
+      "target": {
+        "cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
+        "port": "fbf8759a-1059-47bb-b556-f0a4477e48d3"
+      }
+    },
+    {
+      "angle": 45,
+      "position": {
+        "x": 566,
+        "y": 380
+      },
+      "size": {
+        "width": 52,
+        "height": 52
+      },
+      "attrs": {
+        "text": {
+          "text": "判断节点",
+          "transform": "rotate(-45deg)"
+        },
+        "edit-text": {
+          "style": {
+            "transform": "rotate(-45deg)"
+          }
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": {
+              "name": "top",
+              "args": {
+                "dx": -26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": {
+              "name": "right",
+              "args": {
+                "dy": -26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": {
+              "name": "bottom",
+              "args": {
+                "dx": 26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": {
+              "name": "left",
+              "args": {
+                "dy": 26
+              }
+            },
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
+          },
+          {
+            "group": "right",
+            "id": "af190d15-b0f1-4f92-85bc-e0c4df83e2a7"
+          },
+          {
+            "group": "bottom",
+            "id": "c51a4f3b-759b-47ed-9d80-fa4f6c114e64"
+          },
+          {
+            "group": "left",
+            "id": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
+          }
+        ]
+      },
+      "id": "9be960d0-fb75-49b1-8131-abc05b5991bd",
+      "zIndex": 9,
+      "data": {
+        "status": 0,
+        "pointCode": "51",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "8af8b072-dfb9-458a-b15e-dd5d4c1863bd",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 10,
+      "source": {
+        "cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
+        "port": "d561926a-3a24-449a-abb1-0c20bc89947e"
+      },
+      "target": {
+        "cell": "9be960d0-fb75-49b1-8131-abc05b5991bd",
+        "port": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "58874c23-da0b-46e6-9124-5154e8570bfd",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 11,
+      "source": {
+        "cell": "9be960d0-fb75-49b1-8131-abc05b5991bd",
+        "port": "c241a7e4-12d3-4dde-9694-0f0e5f7b9a91"
+      },
+      "target": {
+        "cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
+        "port": "fd4b8c95-d1eb-41ea-b3e1-15135814b292"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "13d78262-f889-4e6f-9980-29f9e2d87c8f",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 12,
+      "source": {
+        "cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
+        "port": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
+      },
+      "target": {
+        "cell": "ef3865af-8a91-4164-8466-3f6b4315070f",
+        "port": "c133349e-4a4a-4d7d-9b38-26c36b3e68c5"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "9c7b7539-2f82-478d-a592-60dfceede791",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 13,
+      "source": {
+        "cell": "7b6fd715-83e6-4053-8c2b-346e6a857bf3",
+        "port": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
+      },
+      "target": {
+        "cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
+        "port": "089ce61a-4b17-4ed8-9c3f-5b905f484425"
+      }
+    },
+    {
+      "position": {
+        "x": 420,
+        "y": 497
+      },
+      "size": {
+        "width": 80,
+        "height": 42
+      },
+      "attrs": {
+        "text": {
+          "text": "流程节点"
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": "top",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": "right",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": "bottom",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": "left",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "d1346f43-969a-4201-af5d-d09b7ef79980"
+          },
+          {
+            "group": "right",
+            "id": "d561926a-3a24-449a-abb1-0c20bc89947e"
+          },
+          {
+            "group": "bottom",
+            "id": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
+          },
+          {
+            "group": "left",
+            "id": "2fceb955-f7af-41ac-ac02-5a2ea514544e"
+          }
+        ]
+      },
+      "id": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
+      "zIndex": 14,
+      "data": {
+        "status": 0,
+        "pointCode": "51",
+        "fieldName": "fieldName2"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "9dfeb591-70e1-4b52-a463-3078a6fde579",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 15,
+      "source": {
+        "cell": "762cbe4d-fd2b-4cb2-95bb-fae3cb9ef7fc",
+        "port": "9bb8ec19-b1e2-432d-8735-b008da064948"
+      },
+      "target": {
+        "cell": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
+        "port": "d1346f43-969a-4201-af5d-d09b7ef79980"
+      }
+    },
+    {
+      "position": {
+        "x": 420,
+        "y": 616
+      },
+      "size": {
+        "width": 80,
+        "height": 42
+      },
+      "attrs": {
+        "text": {
+          "text": "结束节点"
+        },
+        "body": {
+          "rx": 24,
+          "ry": 24
+        }
+      },
+      "visible": true,
+      "shape": "flow-chart-rect",
+      "ports": {
+        "groups": {
+          "top": {
+            "position": "top",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "right": {
+            "position": "right",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "bottom": {
+            "position": "bottom",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          },
+          "left": {
+            "position": "left",
+            "attrs": {
+              "circle": {
+                "r": 3,
+                "magnet": true,
+                "stroke": "#5F95FF",
+                "strokeWidth": 1,
+                "fill": "#fff",
+                "style": {
+                  "visibility": "hidden"
+                }
+              }
+            }
+          }
+        },
+        "items": [
+          {
+            "group": "top",
+            "id": "45726225-0a03-409e-8475-07da4b8533c5"
+          },
+          {
+            "group": "right",
+            "id": "06111939-bf01-48d9-9f54-6465d9d831c6"
+          },
+          {
+            "group": "bottom",
+            "id": "6541f8dc-e48b-4b8c-a105-2ab3a47f1f21"
+          },
+          {
+            "group": "left",
+            "id": "54781206-573f-4982-a21e-5fac1e0e8a60"
+          }
+        ]
+      },
+      "id": "5ac48b64-d507-4006-954b-f8fbf8016ad2",
+      "zIndex": 16,
+      "data": {
+        "status": 1,
+        "pointCode": "52",
+        "fieldName": "fieldName1"
+      }
+    },
+    {
+      "shape": "edge",
+      "attrs": {
+        "line": {
+          "stroke": "#5F95FF",
+          "strokeWidth": 1,
+          "targetMarker": {
+            "name": "classic",
+            "size": 8
+          }
+        }
+      },
+      "id": "f847f055-9073-4c8e-92c5-8124597d1e7e",
+      "router": {
+        "name": "manhattan"
+      },
+      "zIndex": 17,
+      "source": {
+        "cell": "c7b4dfb0-2cc1-4ce1-839d-22b13bdf86e5",
+        "port": "0cbde5df-ef35-410e-b6c3-a6b1f5561e3f"
+      },
+      "target": {
+        "cell": "5ac48b64-d507-4006-954b-f8fbf8016ad2",
+        "port": "45726225-0a03-409e-8475-07da4b8533c5"
+      }
+    }
+  ]
+}

+ 580 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/index.js

@@ -0,0 +1,580 @@
+import {Graph, Addon, FunctionExt, Shape} from '@antv/x6'
+import './shape'
+import { customPorts ,basicPorts} from './ports'
+// import { getImg } from '../../../utils'
+import graphData from './data/data'
+const insertCss = require('insert-css')
+
+insertCss(`
+  @keyframes ant-line {
+    to {
+        stroke-dashoffset: -1000
+    }
+  }
+`)
+
+export default class FlowGraph {
+  static graph = null
+  static stencil = null
+
+  /**
+   * 初始化方法
+   * @param {*} dom 画板容器
+   * @param {*} width 容器宽度
+   * @param {*} height 容器高度
+   * @param {*} flag 默认为true,传入false只实例化画板
+   * @returns 
+   */
+  static init(dom, width = 1200, height = 900, flag = true) {
+    // 初始化 流程图画板
+    this.graph = new Graph({
+      background: {
+        color: '#e5e5e5' // 设置画布背景颜色
+      },
+      container: dom,
+      width: width,
+      height: height,
+      autoResize: true,
+      grid: {
+        size: 10,
+        visible: true,
+        type: 'doubleMesh',
+        args: [
+          {
+            color: '#cccccc',
+            thickness: 1,
+          },
+          {
+            color: '#5F95FF',
+            thickness: 1,
+            factor: 4,
+          },
+        ],
+      },
+      scroller: {
+        enabled: false,
+        pageVisible: false,
+        pageBreak: false,
+        pannable: false,
+      },
+      // 开启画布缩放
+      mousewheel: {
+        enabled: true,
+        modifiers: ['ctrl', 'meta'],
+        minScale: 0.5,
+        maxScale: 2,
+      },
+      interacting: {
+        nodeMovable: true, //节点是否可以被移动。
+        edgeMovable: false, //边是否可以被移动。
+        edgeLabelMovable: false, //边的标签是否可以被移动。
+        arrowheadMovable: false, //边的起始/终止箭头是否可以被移动
+        vertexMovable: true, //边的路径点是否可以被移动。
+        vertexAddable: true, //是否可以添加边的路径点。
+        vertexDeletable: true, //边的路径点是否可以被删除。
+      },
+      connecting: {
+        anchor: 'center',
+        connectionPoint: 'anchor',
+        allowBlank: true,
+        highlight: true,
+        snap: true, // 是否自动吸附
+        allowMulti: true, // 是否允许在相同的起始节点和终止之间创建多条边
+        allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)
+        allowBlank: false, // 是否允许连接到空白点
+        allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点,
+        allowEdge: false, // 是否允许边链接到另一个边
+        highlight: true, // 拖动边时,是否高亮显示所有可用的连接桩或节点
+        connectionPoint: "anchor", // 指定连接点
+        anchor: "center", // 指定被连接的节点的锚点
+        createEdge() {
+          // X6 的 Shape 命名空间中内置 Edge、DoubleEdge、ShadowEdge 三种边
+          return new Shape.DoubleEdge({
+            attrs: {
+              // line: {
+              //   // stroke: '#5F95FF',
+              //   // strokeWidth: 4,
+              //   // targetMarker: {
+              //   //   name: 'classic',
+              //   //   size: 8,
+              //   // },
+              //   stroke: '#1890ff',
+              //   strokeDasharray: 5,
+              //   targetMarker: null,//block classic diamond cross async path circle circlePlus ellipse
+              //   style: {
+              //     animation: 'ant-line 30s infinite linear',
+              //   },
+              // },
+              line: {
+                strokeWidth: 1,
+                stroke: 'rgba(95,149,255)',
+                strokeDasharray: 0,
+                style: {
+                  animation: 'ant-line 0s infinite linear',
+                },
+                targetMarker: {
+                  "name": "classic",//这个是三角样式
+                  "size": 8 ,//三角形的大小    
+                  'stroke': 'rgba(95,149,255)', 
+                }, // 去掉箭头
+                
+              },
+              outline: {
+                stroke: 'rgba(95,149,255)',
+                strokeWidth: 1,
+              }
+            },
+            router: {
+              name: 'metro',
+              args: {
+                offset: 32,
+                direction: 'H'
+              }
+            }
+          })
+        },
+        validateConnection({
+          sourceView,
+          targetView,
+          sourceMagnet,
+          targetMagnet,
+        }) {
+          if (sourceView === targetView) {
+            return false
+          }
+          if (!sourceMagnet) {
+            return false
+          }
+          if (!targetMagnet) {
+            return false
+          }
+          return true
+        },
+      },
+      highlighting: {
+        magnetAvailable: {
+          name: 'stroke',
+          args: {
+            padding: 4,
+            attrs: {
+              strokeWidth: 1,
+              stroke: 'rgba(223,234,255)',
+            },
+          },
+        },
+      },
+      // 开启拖拽平移(防止冲突,按下修饰键并点击鼠标才能触发画布拖拽)
+      panning: {
+        enabled: true,
+        modifiers: 'shift',
+      },
+      resizing: true,
+      rotating: true,
+      selecting: {
+        enabled: true,
+        multiple: true,
+        rubberband: true,
+        movable: true,
+        showNodeSelectionBox: true,
+      },
+      snapline: true,
+      history: true,
+      clipboard: {
+        enabled: true,
+      },
+      keyboard: {
+        enabled: true,
+      },
+      embedding: {
+        enabled: true,
+        findParent({ node }) {
+          const bbox = node.getBBox()
+          return this.getNodes().filter((node) => {
+            // 只有 data.parent 为 true 的节点才是父节点
+            const data = node.getData()
+            if (data && data.parent) {
+              const targetBBox = node.getBBox()
+              return bbox.isIntersectWithRect(targetBBox)
+            }
+            return false
+          })
+        },
+      },
+    })
+    if(!flag) {
+      // this.graph.centerContent()
+      this.graph.hideGrid() // 返显渲染的时候 隐藏网格
+      return this.graph
+    }
+    this.initStencil()
+    this.initShape()
+    this.initGraphShape()
+    this.initEvent()
+    return this.graph
+  }
+  // 初始化根节点
+  static initStencil() {
+    this.stencil = new Addon.Stencil({
+      target: this.graph,
+      stencilGraphWidth: 280,
+      search: { rect: true },
+      collapsable: true,
+      groups: [
+        {
+          name: 'basic',
+          title: '基础节点',
+          graphHeight: 280,
+        },
+        // {
+        //   name: 'custom-image',
+        //   title: '系统设计图',
+        //   graphHeight: 600
+        // },
+        // {
+        //   name: 'combination',
+        //   title: '组合节点',
+        //   layoutOptions: {
+        //     columns: 1,
+        //     marginX: 60,
+        //   },
+        //   graphHeight: 260,
+        // },
+        // {
+        //   name: 'group',
+        //   title: '节点组',
+        //   graphHeight: 100,
+        //   layoutOptions: {
+        //     columns: 1,
+        //     marginX: 60,
+        //   },
+        // },
+      ],
+    })
+    const stencilContainer = document.querySelector('#stencil')
+    stencilContainer?.appendChild(this.stencil.container)
+  }
+  // 初始化具体每个根节点下不同类型节点
+  static initShape() {
+    const { graph } = this
+    // 基础节点
+    const r1 = graph.createNode({
+      shape: 'flow-chart-rect',
+      attrs: {
+        body: {
+          rx: 24,
+          ry: 24,
+        },
+        text: {
+          text: '起始节点',
+        },
+        
+      },
+    })
+    const r2 = graph.createNode({
+      shape: 'flow-chart-rect',
+      attrs: {
+        text: {
+          text: '流程节点',
+        },
+      },
+    })
+    const r3 = graph.createNode({
+      shape: 'flow-chart-rect',
+      width: 52,
+      height: 52,
+      angle: 45,
+      attrs: {
+        'edit-text': {
+          style: {
+            transform: 'rotate(-45deg)',
+          },
+        },
+        text: {
+          text: '判断节点',
+          transform: 'rotate(-45deg)',
+        },
+      },
+      ports: {
+        groups: {
+          top: {
+            position: {
+              name: 'top',
+              args: {
+                dx: -26,
+              },
+            },
+          },
+          right: {
+            position: {
+              name: 'right',
+              args: {
+                dy: -26,
+              },
+            },
+          },
+          bottom: {
+            position: {
+              name: 'bottom',
+              args: {
+                dx: 26,
+              },
+            },
+          },
+          left: {
+            position: {
+              name: 'left',
+              args: {
+                dy: 26,
+              },
+            },
+          },
+        },
+      },
+    })
+    const r4 = graph.createNode({
+      shape: 'flow-chart-rect',
+      width: 70,
+      height: 70,
+      attrs: {
+        body: {
+          rx: 35,
+          ry: 35,
+        },
+        text: {
+          text: '联系节点',
+        },
+      },
+    })
+    const r5 = graph.createNode({
+      shape: 'flow-chart-rect',
+      width:60,
+      height:60,
+      attrs: {
+        body: {
+          refPoints: '10,0 40,0 30,20 0,20',
+          stroke: 'rgba(95,149,255)',  // 边框颜色
+          strokeWidth: 1,
+        },
+      },
+      label: '数据节点',
+      
+    })
+    const r6 = graph.createNode({
+      shape: 'flow-chart-rect',
+      width: 80,
+      height: 50,
+      attrs: {
+        body: {
+          rx: 10, // 圆角矩形
+          ry: 10,
+          strokeWidth: 1,
+          stroke: 'rgba(95,149,255)',
+        },
+  
+      },
+      label: '连接节点',
+    })
+// 这里创新新的节点+++++++++++++
+
+
+
+    // 组合节点
+    const c1 = graph.createNode({
+      shape: 'flow-chart-image-rect',
+    })
+    const c2 = graph.createNode({
+      shape: 'flow-chart-title-rect',
+    })
+    const c3 = graph.createNode({
+      shape: 'flow-chart-animate-text',
+    })
+    // 节点组
+    const g1 = graph.createNode({
+      shape: 'groupNode',
+      attrs: {
+        text: {
+          text: 'Group Name',
+        },
+      },
+      data: {
+        parent: true,
+      },
+    })
+    // 这4个现在没有注入,需要的时候,在用
+
+    // 系统设计图
+    // const imgs = [
+    //   {
+    //     image: getImg('ldb.png')
+    //   },
+    //   {
+    //     image: getImg('wft1.png')
+    //   },
+    //   {
+    //     image: getImg('wft2.png')
+    //   },
+    //   {
+    //     image: getImg('wft3.png')
+    //   },
+    //   {
+    //     image: getImg('wft4.png')
+    //   },
+    //   {
+    //     image: getImg('wft5.png')
+    //   },
+    //   {
+    //     image: getImg('lqt.png')
+    //   },
+    //   {
+    //     image: getImg('lqb-o.png')
+    //   },
+    //   {
+    //     image: getImg('ldb-o.png')
+    //   },
+    //   {
+    //     image: getImg('bh.png')
+    //   },
+    //   {
+    //     image: getImg('f1.png')
+    //   },
+    //   {
+    //     image: getImg('f2.png')
+    //   },
+    //   {
+    //     image: getImg('f3.png')
+    //   },
+    // ]
+    // const imgNodes = imgs.map(item => {
+    //   return graph.createNode({
+    //     // shape: 'flow-chart-image-rect-custom',
+    //     // attrs: {
+    //     //   image: {
+    //     //     'xlink:href': item.image,
+    //     //   }
+    //     // }
+    //     shape: 'image', //可选值:Rect Circle Ellipse Polygon Polyline Path Image HTML TextBlock BorderedImage EmbeddedImage InscribedImage Cylinder
+    //     imageUrl: item.image,
+    //     attrs: {
+    //       image: {
+    //         // fill: 'yellow',
+    //       },
+    //     },
+    //     width: 52,
+    //     height: 52,
+    //     ports: { ...customPorts }
+    //   })
+    // })
+    this.stencil.load([r1, r2, r3, r4,r5,r6], 'basic')
+    // 这里需要注入新增节点,+++++++++++++++++
+
+
+
+    // this.stencil.load(imgNodes, 'custom-image')
+    // this.stencil.load([c1, c2, c3], 'combination')
+    // this.stencil.load([g1], 'group')
+  }
+
+  // 根据json渲染节点和边
+  static initGraphShape(gd = graphData) {
+    this.graph.fromJSON(gd)
+  }
+
+  // 连接桩显示时机
+  static showPorts(ports, show) {
+    for (let i = 0, len = ports.length; i < len; i = i + 1) {
+      ports[i].style.visibility = show ? 'visible' : 'hidden'
+    }
+  }
+  
+  // 事件相关
+  static initEvent() {
+    const { graph } = this
+    const container = document.getElementById('container')
+    // 右键编辑文本
+    graph.on('node:contextmenu', ({ cell, view }) => {
+      console.log(view.container)
+      const oldText = cell.attr('text/text')
+      cell.attr('text/style/display', 'none')
+      const elem = view.container.querySelector('.x6-edit-text')
+      if (elem) {
+        elem.innerText = oldText
+        elem.focus()
+      }
+      const onBlur = () => {
+        cell.attr('text/text', elem.innerText)
+        cell.attr('text/style/display', 'inline-block')
+      }
+      if(elem){
+        elem.addEventListener('blur', () => {
+          onBlur()
+          elem.removeEventListener('blur', onBlur)
+        })
+      }
+    })
+    // 鼠标移入 显示连接桩
+    graph.on('node:mouseenter', FunctionExt.debounce(() => {
+      const ports = container.querySelectorAll('.x6-port-body')
+      this.showPorts(ports, true)
+    }), 500,)
+    // 鼠标移出 隐藏连接桩
+    graph.on('node:mouseleave', () => {
+      const ports = container.querySelectorAll('.x6-port-body')
+      this.showPorts(ports, false)
+    })
+
+    graph.on('node:collapse', ({ node, e }) => {
+      e.stopPropagation()
+      node.toggleCollapse()
+      const collapsed = node.isCollapsed()
+      const cells = node.getDescendants()
+      cells.forEach(n => {
+        if (collapsed) {
+          n.hide()
+        } else {
+          n.show()
+        }
+      })
+    })
+    // backspace
+    graph.bindKey('delete', () => {
+      const cells = graph.getSelectedCells()
+      if (cells.length) {
+        graph.removeCells(cells)
+      }
+    })
+    // 鼠标动态添加/删除小工具。
+    graph.on('edge:mouseenter', ({ cell }) => {
+      /**
+       * EdgeTool
+       * vertices 路径点工具,在路径点位置渲染一个小圆点,拖动小圆点修改路径点位置,双击小圆点删除路径点,在边上单击添加路径点。
+       * segments 线段工具。在边的每条线段的中心渲染一个工具条,可以拖动工具条调整线段两端的路径点的位置。
+       * boundary 根据边的包围盒渲染一个包围边的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。
+       * button 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。
+       * button-remove 在指定的位置处,渲染一个删除按钮,点击时删除对应的边。
+       * source-arrowhead-和-target-arrowhead 在边的起点或终点渲染一个图形(默认是箭头),拖动该图形来修改边的起点或终点。
+       * edge-editor 提供边上文本编辑功能。
+       */
+      cell.addTools([
+        {
+          name: 'vertices',
+          args: {
+            attrs: { fill: '#007acc' },
+            // 移动路径点过程中的吸附半径。当路径点与邻近的路径点的某个坐标 (x, y) 距离在半径范围内时,将当前路径点的对应坐标 (x, y) 吸附到邻居路径的路径点。
+            snapRadius: 20,
+            // 在边上按下鼠标时,是否可以添加新的路径点。
+            addable: true,
+            // 是否可以通过双击移除路径点。
+            removable: true,
+            // 是否自动移除冗余的路径点。
+            removeRedundancies: true,
+            // 是否阻止工具上的鼠标事件冒泡到边视图上。阻止后鼠标与工具交互时将不会触发边的 mousedown、mousemove 和 mouseup 事件。
+            stopPropagation: false,
+          }
+        }
+      ])
+    })
+    graph.on('edge:mouseleave', ({ cell }) => {
+      cell.removeTools()
+    })
+  }
+}

+ 226 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/ports.js

@@ -0,0 +1,226 @@
+export const basicPorts = {
+  groups: {
+    top: {
+      position: 'top',
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          },
+        },
+      },
+    },
+    right: {
+      position: 'right',
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          },
+        },
+      },
+    },
+    bottom: {
+      position: 'bottom',
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          },
+        },
+      },
+    },
+    left: {
+      position: 'left',
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          },
+        },
+      },
+    },
+  },
+  items: [
+    {
+      group: 'top',
+    },
+    {
+      group: 'right',
+    },
+    {
+      group: 'bottom',
+    },
+    {
+      group: 'left',
+    }
+  ]
+}
+
+export const customPorts = {
+  groups: {
+    top: {
+      position: {
+        name: 'absolute',
+      }
+    },
+    right: {
+      position: {
+        name: 'absolute',
+      }
+    },
+    bottom: {
+      position: {
+        name: 'absolute',
+      }
+    },
+    left: {
+      position: {
+        name: 'absolute',
+      }
+    }
+  },
+  items: [
+    {
+      id: 'port1',
+      group: 'top',
+      // 通过 args 指定绝对位置
+      args: {
+        x: '50%',
+        y: '0%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          },
+        },
+      },
+    },
+    {
+      id: 'port2',
+      group: 'right',
+      args: {
+        x: '100%',
+        y: '50%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          }
+        },
+      }
+    },
+    {
+      id: 'port3',
+      group: 'bottom',
+      args: {
+        x: '50%',
+        y: '100%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          }
+        }
+      }
+    },
+    {
+      id: 'port4',
+      group: 'left',
+      args: {
+        x: '0%',
+        y: '50%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          }
+        }
+      }
+    },
+    {
+      id: 'port3',
+      group: 'bottom',
+      args: {
+        x: '50%',
+        y: '100%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          }
+        }
+      }
+    },
+    {
+      id: 'port4',
+      group: 'left',
+      args: {
+        x: '0%',
+        y: '50%',
+      },
+      attrs: {
+        circle: {
+          r: 4,
+          magnet: true,
+          stroke: '#5F95FF',
+          strokeWidth: 1,
+          fill: '#fff',
+          style: {
+            visibility: 'hidden',
+          }
+        }
+      }
+    }
+  ]
+}

+ 536 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/graph/shape.js

@@ -0,0 +1,536 @@
+import { Graph, Dom, Node } from '@antv/x6'
+import { basicPorts, customPorts } from './ports'
+
+// 基础节点
+export const FlowChartRect = Graph.registerNode('flow-chart-rect', {
+  inherit: 'rect',
+  width: 80,
+  height: 42,
+  attrs: {
+    body: {
+      stroke: '#5F95FF',
+      strokeWidth: 1,
+      fill: '#ffffff',
+    },
+    fo: {
+      refWidth: '100%',
+      refHeight: '100%',
+    },
+    foBody: {
+      xmlns: Dom.ns.xhtml,
+      style: {
+        width: '100%',
+        height: '100%',
+        display: 'flex',
+        justifyContent: 'center',
+        alignItems: 'center',
+      },
+    },
+    'edit-text': {
+      contenteditable: 'true',
+      class: 'x6-edit-text',
+      style: {
+        width: '100%',
+        textAlign: 'center',
+        fontSize: 12,
+        color: 'rgba(0,0,0,0.85)',
+      },
+    },
+    
+    text: {
+      fontSize: 12,
+      fill: '#080808',
+    },
+  },
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'text',
+      selector: 'text',
+    },
+    {
+      tagName: 'foreignObject',
+      selector: 'fo',
+      children: [
+        {
+          ns: Dom.ns.xhtml,
+          tagName: 'body',
+          selector: 'foBody',
+          children: [
+            {
+              tagName: 'div',
+              selector: 'edit-text',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  ports: { ...basicPorts },
+})
+// export const FlowPolygon = Graph.registerNode('polygon', {
+//   inherit: 'rect',
+//   width: 80,
+//   height: 42,
+//   attrs: {
+//     body: {
+//       stroke: '#5F95FF',
+//       strokeWidth: 1,
+//       fill: '#ffffff',
+//     },
+//     fo: {
+//       refWidth: '100%',
+//       refHeight: '100%',
+//     },
+//     foBody: {
+//       xmlns: Dom.ns.xhtml,
+//       style: {
+//         width: '100%',
+//         height: '100%',
+//         display: 'flex',
+//         justifyContent: 'center',
+//         alignItems: 'center',
+//       },
+//     },
+//     'edit-text': {
+//       contenteditable: 'true',
+//       class: 'x6-edit-text',
+//       style: {
+//         width: '100%',
+//         textAlign: 'center',
+//         fontSize: 12,
+//         color: 'rgba(0,0,0,0.85)',
+//       },
+//     },
+    
+//     text: {
+//       fontSize: 12,
+//       fill: '#080808',
+//     },
+//   },
+//   markup: [
+//     {
+//       tagName: 'rect',
+//       selector: 'body',
+//     },
+//     {
+//       tagName: 'text',
+//       selector: 'text',
+//     },
+//     {
+//       tagName: 'foreignObject',
+//       selector: 'fo',
+//       children: [
+//         {
+//           ns: Dom.ns.xhtml,
+//           tagName: 'body',
+//           selector: 'foBody',
+//           children: [
+//             {
+//               tagName: 'div',
+//               selector: 'edit-text',
+//             },
+//           ],
+//         },
+//       ],
+//     },
+//   ],
+//   ports: { ...basicPorts },
+// })
+// export const FlowRect = Graph.registerNode('rect', {
+//   inherit: 'rect',
+//   width: 80,
+//   height: 42,
+//   attrs: {
+//     body: {
+//       stroke: '#5F95FF',
+//       strokeWidth: 1,
+//       fill: '#ffffff',
+//     },
+//     fo: {
+//       refWidth: '100%',
+//       refHeight: '100%',
+//     },
+//     foBody: {
+//       xmlns: Dom.ns.xhtml,
+//       style: {
+//         width: '100%',
+//         height: '100%',
+//         display: 'flex',
+//         justifyContent: 'center',
+//         alignItems: 'center',
+//       },
+//     },
+//     'edit-text': {
+//       contenteditable: 'true',
+//       class: 'x6-edit-text',
+//       style: {
+//         width: '100%',
+//         textAlign: 'center',
+//         fontSize: 12,
+//         color: 'rgba(0,0,0,0.85)',
+//       },
+//     },
+    
+//     text: {
+//       fontSize: 12,
+//       fill: '#080808',
+//     },
+//   },
+//   markup: [
+//     {
+//       tagName: 'rect',
+//       selector: 'body',
+//     },
+//     {
+//       tagName: 'text',
+//       selector: 'text',
+//     },
+//     {
+//       tagName: 'foreignObject',
+//       selector: 'fo',
+//       children: [
+//         {
+//           ns: Dom.ns.xhtml,
+//           tagName: 'body',
+//           selector: 'foBody',
+//           children: [
+//             {
+//               tagName: 'div',
+//               selector: 'edit-text',
+//             },
+//           ],
+//         },
+//       ],
+//     },
+//   ],
+//   ports: { ...basicPorts },
+// })
+// 组合节点
+export const FlowChartImageRect = Graph.registerNode('flow-chart-image-rect', {
+  inherit: 'rect',
+  width: 200,
+  height: 60,
+  attrs: {
+    body: {
+      stroke: '#5F95FF',
+      strokeWidth: 1,
+      fill: 'rgba(95,149,255,0.05)',
+    },
+    image: {
+      'xlink:href':
+        'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
+      width: 16,
+      height: 16,
+      x: 12,
+      y: 12,
+    },
+    title: {
+      text: 'Node',
+      refX: 40,
+      refY: 14,
+      fill: 'rgba(0,0,0,0.85)',
+      fontSize: 12,
+      'text-anchor': 'start',
+    },
+    text: {
+      text: 'this is content text',
+      refX: 40,
+      refY: 38,
+      fontSize: 12,
+      fill: 'rgba(0,0,0,0.6)',
+      'text-anchor': 'start',
+    },
+  },
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'image',
+      selector: 'image',
+    },
+    {
+      tagName: 'text',
+      selector: 'title',
+    },
+    {
+      tagName: 'text',
+      selector: 'text',
+    },
+  ],
+  ports: { ...basicPorts },
+})
+
+export const FlowChartTitleRect = Graph.registerNode('flow-chart-title-rect', {
+  inherit: 'rect',
+  width: 200,
+  height: 68,
+  attrs: {
+    body: {
+      stroke: '#5F95FF',
+      strokeWidth: 1,
+      fill: 'rgba(95,149,255,0.05)',
+    },
+    head: {
+      refWidth: '100%',
+      stroke: 'transparent',
+      height: 28,
+      fill: 'rgb(95,149,255)',
+    },
+    image: {
+      'xlink:href':
+        'https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png',
+      height: 16,
+      x: 6,
+      y: 6,
+    },
+    title: {
+      text: 'Node',
+      refX: 30,
+      refY: 9,
+      fill: '#ffffff',
+      fontSize: 12,
+      'text-anchor': 'start',
+    },
+    text: {
+      text: 'this is content text',
+      refX: 8,
+      refY: 45,
+      fontSize: 12,
+      fill: 'rgba(0,0,0,0.6)',
+      'text-anchor': 'start',
+    },
+  },
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'rect',
+      selector: 'head',
+    },
+    {
+      tagName: 'image',
+      selector: 'image',
+    },
+    {
+      tagName: 'text',
+      selector: 'title',
+    },
+    {
+      tagName: 'text',
+      selector: 'text',
+    },
+  ],
+  ports: { ...basicPorts },
+})
+
+export const FlowChartAnimateText = Graph.registerNode('flow-chart-animate-text', {
+  inherit: 'rect',
+  width: 200,
+  height: 60,
+  attrs: {
+    body: {
+      stroke: '#5F95FF',
+      strokeWidth: 1,
+      fill: 'rgba(95,149,255,0.05)',
+    },
+    text1: {
+      class: 'animate-text1',
+      text: 'AntV X6',
+      fontSize: 32,
+    },
+    text2: {
+      class: 'animate-text2',
+      text: 'AntV X6',
+      fontSize: 32,
+    },
+  },
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'text',
+      selector: 'text1',
+    },
+    {
+      tagName: 'text',
+      selector: 'text2',
+    },
+  ],
+})
+
+// 自定义 系统设计图
+export const FlowChartImageRectCustom = Graph.registerNode('flow-chart-image-rect-custom', {
+  inherit: 'rect',
+  width: 80,
+  height: 80,
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'image',
+    },
+    {
+      tagName: 'text',
+      selector: 'label',
+    }
+  ],
+  attrs: {
+    body: {
+      // 节点线的颜色
+      stroke: 'transparent',
+      // 背景填充色
+      fill: 'transparent',
+    },
+    // 自定义图片
+    image: {
+      width: 60,
+      height: 60,
+      refX: 0,
+      refY: 0,
+    },
+    label: {
+      refX: 3,
+      refY: 2,
+      textAnchor: 'left',
+      textVerticalAnchor: 'top',
+      fontSize: 12,
+      fill: 'black',
+    },
+    'edit-text': {
+      contenteditable: 'true',
+      class: 'x6-edit-text',
+      style: {
+        width: '100%',
+        textAlign: 'center',
+        fontSize: 12,
+        color: 'rgba(0,0,0,0.85)'
+      },
+    },
+    text: {
+      fontSize: 12,
+      fill: '#080808',
+    },
+  },
+  ports: { ...customPorts },
+})
+
+// 节点组
+export class NodeGroup extends Node {
+  collapsed = true
+
+  postprocess() {
+    this.toggleCollapse(true)
+  }
+
+  isCollapsed() {
+    return this.collapsed
+  }
+
+  toggleCollapse(collapsed) {
+    const target = collapsed == null ? !this.collapsed : collapsed
+    if (target) {
+      this.attr('buttonSign', { d: 'M 1 5 9 5 M 5 1 5 9' })
+      this.resize(200, 40)
+    } else {
+      this.attr('buttonSign', { d: 'M 2 5 8 5' })
+      this.resize(240, 240)
+    }
+    this.collapsed = target
+  }
+}
+
+NodeGroup.config({
+  shape: 'rect',
+  markup: [
+    {
+      tagName: 'rect',
+      selector: 'body',
+    },
+    {
+      tagName: 'image',
+      selector: 'image',
+    },
+    {
+      tagName: 'text',
+      selector: 'text',
+    },
+    {
+      tagName: 'g',
+      selector: 'buttonGroup',
+      children: [
+        {
+          tagName: 'rect',
+          selector: 'button',
+          attrs: {
+            'pointer-events': 'visiblePainted',
+          },
+        },
+        {
+          tagName: 'path',
+          selector: 'buttonSign',
+          attrs: {
+            fill: 'none',
+            'pointer-events': 'none',
+          },
+        },
+      ],
+    },
+  ],
+  attrs: {
+    body: {
+      refWidth: '100%',
+      refHeight: '100%',
+      strokeWidth: 1,
+      fill: 'rgba(95,149,255,0.05)',
+      stroke: '#5F95FF',
+    },
+    image: {
+      'xlink:href':
+        'https://gw.alipayobjects.com/mdn/rms_0b51a4/afts/img/A*X4e0TrDsEiIAAAAAAAAAAAAAARQnAQ',
+      width: 16,
+      height: 16,
+      x: 8,
+      y: 12,
+    },
+    text: {
+      fontSize: 12,
+      fill: 'rgba(0,0,0,0.85)',
+      refX: 30,
+      refY: 15,
+    },
+    buttonGroup: {
+      refX: '100%',
+      refX2: -25,
+      refY: 13,
+    },
+    button: {
+      height: 14,
+      width: 16,
+      rx: 2,
+      ry: 2,
+      fill: '#f5f5f5',
+      stroke: '#ccc',
+      cursor: 'pointer',
+      event: 'node:collapse',
+    },
+    buttonSign: {
+      refX: 3,
+      refY: 2,
+      stroke: '#808080',
+    },
+  },
+})
+
+Graph.registerNode('groupNode', NodeGroup)

+ 49 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/index.css

@@ -0,0 +1,49 @@
+.flow {
+  width: 100%;
+  height: 50rem;
+}
+
+.content {
+  width: 100%;
+  height: 50rem;
+  display: flex;
+}
+
+#stencil {
+  width: 20%;
+  height: 50rem;
+  position: relative;
+  border-right: 1px solid rgba(0, 0, 0, 0.08);
+  box-sizing: border-box;
+}
+
+.panel {
+  width: 69%;
+  height: 50rem;
+}
+
+.panel .toolbar {
+  width: 100%;
+  height: 2.4375rem;
+  display: flex;
+  align-items: center;
+  background-color: #f7f9fb;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+}
+
+.panel #container {
+  width: 100%;
+  height: calc(800px - 38px);
+}
+
+
+.config {
+  width: 15%;
+  height: 100%;
+  padding: 0 10px;
+  border-left: 1px solid rgba(0, 0, 0, 0.08);
+  box-sizing: border-box;
+}
+
+
+

+ 104 - 0
ruoyi-ui/src/views/system/processModeling/flow-x6/index.vue

@@ -0,0 +1,104 @@
+<template>
+  <div class="flow">
+    <div class="content">
+      <!--左侧工具栏-->
+      <div id="stencil" />
+      <div class="panel">
+        <!--流程图工具栏-->
+        <div class="toolbar">
+          <tool-bar v-if="isReady" />
+        </div>
+        <!--流程图画板-->
+        <div id="container" />
+      </div>
+      <!--右侧工具栏-->
+      <div class="config">
+        <config-panel v-if="isReady" />
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import "./index.css";
+import FlowGraph from "./graph";
+import ToolBar from "./components/ToolBar/index.vue";
+import ConfigPanel from "./components/ConfigPanel/index.vue";
+import { $, getContainerSize } from "../../../../utils";
+export default {
+  data() {
+    return {
+      isReady: false,
+      destroyFn: null,
+    };
+  },
+  components: { ToolBar, ConfigPanel },
+  mounted() {
+    this.destroyFn = this.initGraph();
+  },
+  destroyed() {
+    // this.destroyFn();
+  },
+  methods: {
+    initGraph() {
+      const graph = FlowGraph.init(
+        $("#container"),
+        $("#container").getBoundingClientRect().width,
+        $("#container").getBoundingClientRect().height
+      );
+      this.isReady = true;
+      const resizeFn = () => {
+        const { width, height } = getContainerSize($(".panel"));
+        graph.resize(width, height - 38);
+      };
+      resizeFn();
+      window.addEventListener("resize", resizeFn);
+      return () => {
+        window.removeEventListener("resize", resizeFn);
+        graph.dispose();
+      };
+    },
+  },
+};
+</script>
+<style>
+.x6-widget-snapline-vertical {
+  border-right-color: #ff4e50 !important;
+}
+.x6-widget-snapline-horizontal {
+  border-bottom-color: #ff4e50 !important;
+}
+.x6-widget-selection-box {
+  border: 1px dashed #5f95ff;
+  margin-top: -3px;
+  margin-left: -3px;
+}
+.x6-widget-selection-inner {
+  border: 1px dashed #5f95ff;
+}
+
+@keyframes stroke {
+  100% {
+    stroke-dashoffset: -400;
+  }
+}
+.animate-text1,
+.animate-text2,
+.animate-text3,
+.animate-text4 {
+  font-weight: bold;
+  fill: none;
+  stroke-width: 2px;
+  stroke-dasharray: 90 310;
+  animation: stroke 3s infinite linear;
+}
+.animate-text1 {
+  stroke: #873bf4;
+  text-shadow: 0 0 2px #873bf4;
+  animation-delay: -1.5s;
+}
+.animate-text2 {
+  stroke: #ff6e06;
+  text-shadow: 0 0 2px #ff6e06;
+  animation-delay: -3s;
+}
+</style>

+ 106 - 0
ruoyi-ui/src/views/system/processModeling/index.vue

@@ -0,0 +1,106 @@
+
+<template>
+  <div class="index">
+    <div id="flow-image">
+      <el-tooltip class="item" effect="dark" content="编辑图形" placement="right">
+        <el-button style="position: absolute; top: 2px; right: 2px;z-index: 9999;" @click="$router.push('/flow-x6')"><i class="el-icon-edit-outline"></i></el-button>
+      </el-tooltip>
+      <el-button style="position: absolute; top: 2px; right: 60px;z-index: 9999;" @click="editFlowData">Edit Data</el-button>
+      <div id="flow-container"></div>
+    </div>
+  </div>
+</template>
+<script>
+import FlowGraph from './flow-x6/graph'
+import { $, getContainerSize } from '../../../utils'
+export default {
+  mounted() {
+    this.getFlowJson()
+  },
+  destroyed() {
+    const { graph } = FlowGraph
+    // 销毁画布,资源回收
+    if(graph) graph.dispose()
+    // 移除监听
+    window.removeEventListener('resize', this.resizeFn)
+  },
+  methods:{
+    // 去后台拿json
+    getFlowJson() {
+      setTimeout(() => {
+        const graphJson = JSON.parse(window.localStorage.getItem('graphJson'))
+        if(graphJson) {
+          this.initFlowImage(graphJson)
+        } else {
+          this.$router.push('/flow-x6')
+        }
+      }, 300)
+    },
+    // 根据json渲染
+    initFlowImage(graphJson) {
+      // 初始化画板
+      const graph = FlowGraph.init($('#flow-container'), $('#flow-container').getBoundingClientRect().width, $('#flow-container').getBoundingClientRect().height, false)
+      // 渲染操作
+      graph.fromJSON(graphJson)
+
+      // 监听数据改变事件
+      graph.getNodes().forEach(node => {
+        if(node.getData()) {
+          node.on("change:data", ({ cell, current }) => {
+            // current 就是我们绑定的 业务属性data
+            if(current.status == 0) {
+              cell.attr('body/fill', 'red')
+              cell.attr('text/fill', '#fff')
+              cell.attr('text/text', '100℃')
+            } else {
+              cell.attr('body/fill', 'green')
+              cell.attr('text/fill', '#080808')
+              cell.attr('text/text', '150℃')
+            }
+          })
+        }
+      })
+      window.addEventListener('resize', this.resizeFn)
+    },
+    // 改变状态
+    editFlowData() {
+      const { graph } = FlowGraph
+      graph.getNodes().forEach(node => {
+        if(node.getData()) {
+          let curStatus = node.getData().status
+          node.setData({
+            status: curStatus == 0 ? 1 : 0
+          })
+        }
+      })
+    },
+    resizeFn() {
+      setTimeout(() => {
+        const { width, height } = getContainerSize($('#flow-image'))
+        this.graph.resize(width, height)
+      }, 100)
+    }
+  }
+}
+</script>
+<style scoped>
+.index {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+#flow-image {
+  width: 80%;
+  height: 90%;
+  position: relative;
+}
+#flow-container {
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+</style>

+ 259 - 218
ruoyi-ui/src/views/tool/build/index.vue

@@ -2,11 +2,9 @@
   <div class="container">
     <div class="left-board">
       <div class="logo-wrapper">
-        <div class="logo">
-          <img :src="logo" alt="logo"> Form Generator
-        </div>
+        <div class="logo"><img :src="logo" alt="logo" /> Form Generator</div>
       </div>
-      <el-scrollbar class="left-scrollbar">
+     <el-scrollbar class="left-scrollbar">
         <div class="components-list">
           <div class="components-title">
             <svg-icon icon-class="component" />输入型组件
@@ -21,7 +19,9 @@
             @end="onEnd"
           >
             <div
-              v-for="(element, index) in inputComponents" :key="index" class="components-item"
+              v-for="(element, index) in inputComponents"
+              :key="index"
+              class="components-item"
               @click="addComponent(element)"
             >
               <div class="components-body">
@@ -58,12 +58,18 @@
             <svg-icon icon-class="component" /> 布局型组件
           </div>
           <draggable
-            class="components-draggable" :list="layoutComponents"
-            :group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent"
-            draggable=".components-item" :sort="false" @end="onEnd"
+            class="components-draggable"
+            :list="layoutComponents"
+            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
+            :clone="cloneComponent"
+            draggable=".components-item"
+            :sort="false"
+            @end="onEnd"
           >
             <div
-              v-for="(element, index) in layoutComponents" :key="index" class="components-item"
+              v-for="(element, index) in layoutComponents"
+              :key="index"
+              class="components-item"
               @click="addComponent(element)"
             >
               <div class="components-body">
@@ -73,7 +79,7 @@
             </div>
           </draggable>
         </div>
-      </el-scrollbar>
+      </el-scrollbar> 
     </div>
 
     <div class="center-board">
@@ -81,10 +87,20 @@
         <el-button icon="el-icon-download" type="text" @click="download">
           导出vue文件
         </el-button>
-        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
+        <el-button
+          class="copy-btn-main"
+          icon="el-icon-document-copy"
+          type="text"
+          @click="copy"
+        >
           复制代码
         </el-button>
-        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
+        <el-button
+          class="delete-btn"
+          icon="el-icon-delete"
+          type="text"
+          @click="empty"
+        >
           清空
         </el-button>
       </div>
@@ -96,7 +112,12 @@
             :disabled="formConf.disabled"
             :label-width="formConf.labelWidth + 'px'"
           >
-            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
+            <draggable
+              class="drawing-board"
+              :list="drawingList"
+              :animation="340"
+              group="componentsGroup"
+            >
               <draggable-item
                 v-for="(element, index) in drawingList"
                 :key="element.renderKey"
@@ -131,28 +152,38 @@
       :show-file-name="showFileName"
       @confirm="generate"
     />
-    <input id="copyNode" type="hidden">
+    <input id="copyNode" type="hidden" />
   </div>
 </template>
 
 <script>
-import draggable from 'vuedraggable'
-import beautifier from 'js-beautify'
-import ClipboardJS from 'clipboard'
-import render from '@/utils/generator/render'
-import RightPanel from './RightPanel'
-import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config'
-import { beautifierConf, titleCase } from '@/utils/index'
-import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
-import { makeUpJs } from '@/utils/generator/js'
-import { makeUpCss } from '@/utils/generator/css'
-import drawingDefault from '@/utils/generator/drawingDefault'
-import logo from '@/assets/logo/logo.png'
-import CodeTypeDialog from './CodeTypeDialog'
-import DraggableItem from './DraggableItem'
+import draggable from "vuedraggable";
+import beautifier from "js-beautify";
+import ClipboardJS from "clipboard";
+import render from "@/utils/generator/render";
+import RightPanel from "./RightPanel";
+import {
+  inputComponents,
+  selectComponents,
+  layoutComponents,
+  formConf,
+} from "@/utils/generator/config";
+import { beautifierConf, titleCase } from "@/utils/index";
+import {
+  makeUpHtml,
+  vueTemplate,
+  vueScript,
+  cssStyle,
+} from "@/utils/generator/html";
+import { makeUpJs } from "@/utils/generator/js";
+import { makeUpCss } from "@/utils/generator/css";
+import drawingDefault from "@/utils/generator/drawingDefault";
+import logo from "@/assets/logo/logo.png";
+import CodeTypeDialog from "./CodeTypeDialog";
+import DraggableItem from "./DraggableItem";
 
-let oldActiveId
-let tempActiveData
+let oldActiveId;
+let tempActiveData;
 
 export default {
   components: {
@@ -160,7 +191,7 @@ export default {
     render,
     RightPanel,
     CodeTypeDialog,
-    DraggableItem
+    DraggableItem,
   },
   data() {
     return {
@@ -179,208 +210,214 @@ export default {
       dialogVisible: false,
       generateConf: null,
       showFileName: false,
-      activeData: drawingDefault[0]
-    }
+      activeData: drawingDefault[0],
+    };
   },
   created() {
     // 防止 firefox 下 拖拽 会新打卡一个选项卡
-    document.body.ondrop = event => {
-      event.preventDefault()
-      event.stopPropagation()
-    }
+    document.body.ondrop = (event) => {
+      event.preventDefault();
+      event.stopPropagation();
+    };
   },
   watch: {
     // eslint-disable-next-line func-names
-    'activeData.label': function (val, oldVal) {
+    "activeData.label": function (val, oldVal) {
       if (
-        this.activeData.placeholder === undefined
-        || !this.activeData.tag
-        || oldActiveId !== this.activeId
+        this.activeData.placeholder === undefined ||
+        !this.activeData.tag ||
+        oldActiveId !== this.activeId
       ) {
-        return
+        return;
       }
-      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
+      this.activeData.placeholder =
+        this.activeData.placeholder.replace(oldVal, "") + val;
     },
     activeId: {
       handler(val) {
-        oldActiveId = val
+        oldActiveId = val;
       },
-      immediate: true
-    }
+      immediate: true,
+    },
   },
   mounted() {
-    const clipboard = new ClipboardJS('#copyNode', {
-      text: trigger => {
-        const codeStr = this.generateCode()
+    const clipboard = new ClipboardJS("#copyNode", {
+      text: (trigger) => {
+        const codeStr = this.generateCode();
         this.$notify({
-          title: '成功',
-          message: '代码已复制到剪切板,可粘贴。',
-          type: 'success'
-        })
-        return codeStr
-      }
-    })
-    clipboard.on('error', e => {
-      this.$message.error('代码复制失败')
-    })
+          title: "成功",
+          message: "代码已复制到剪切板,可粘贴。",
+          type: "success",
+        });
+        return codeStr;
+      },
+    });
+    clipboard.on("error", (e) => {
+      this.$message.error("代码复制失败");
+    });
   },
   methods: {
     activeFormItem(element) {
-      this.activeData = element
-      this.activeId = element.formId
+      this.activeData = element;
+      this.activeId = element.formId;
     },
     onEnd(obj, a) {
       if (obj.from !== obj.to) {
-        this.activeData = tempActiveData
-        this.activeId = this.idGlobal
+        this.activeData = tempActiveData;
+        this.activeId = this.idGlobal;
       }
     },
     addComponent(item) {
-      const clone = this.cloneComponent(item)
-      this.drawingList.push(clone)
-      this.activeFormItem(clone)
+      const clone = this.cloneComponent(item);
+      this.drawingList.push(clone);
+      this.activeFormItem(clone);
     },
     cloneComponent(origin) {
-      const clone = JSON.parse(JSON.stringify(origin))
-      clone.formId = ++this.idGlobal
-      clone.span = formConf.span
-      clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件
-      if (!clone.layout) clone.layout = 'colFormItem'
-      if (clone.layout === 'colFormItem') {
-        clone.vModel = `field${this.idGlobal}`
-        clone.placeholder !== undefined && (clone.placeholder += clone.label)
-        tempActiveData = clone
-      } else if (clone.layout === 'rowFormItem') {
-        delete clone.label
-        clone.componentName = `row${this.idGlobal}`
-        clone.gutter = this.formConf.gutter
-        tempActiveData = clone
+      const clone = JSON.parse(JSON.stringify(origin));
+      clone.formId = ++this.idGlobal;
+      clone.span = formConf.span;
+      clone.renderKey = +new Date(); // 改变renderKey后可以实现强制更新组件
+      if (!clone.layout) clone.layout = "colFormItem";
+      if (clone.layout === "colFormItem") {
+        clone.vModel = `field${this.idGlobal}`;
+        clone.placeholder !== undefined && (clone.placeholder += clone.label);
+        tempActiveData = clone;
+      } else if (clone.layout === "rowFormItem") {
+        delete clone.label;
+        clone.componentName = `row${this.idGlobal}`;
+        clone.gutter = this.formConf.gutter;
+        tempActiveData = clone;
       }
-      return tempActiveData
+      return tempActiveData;
     },
     AssembleFormData() {
       this.formData = {
         fields: JSON.parse(JSON.stringify(this.drawingList)),
-        ...this.formConf
-      }
+        ...this.formConf,
+      };
     },
     generate(data) {
-      const func = this[`exec${titleCase(this.operationType)}`]
-      this.generateConf = data
-      func && func(data)
+      const func = this[`exec${titleCase(this.operationType)}`];
+      this.generateConf = data;
+      func && func(data);
     },
     execRun(data) {
-      this.AssembleFormData()
-      this.drawerVisible = true
+      this.AssembleFormData();
+      this.drawerVisible = true;
     },
     execDownload(data) {
-      const codeStr = this.generateCode()
-      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
-      this.$download.saveAs(blob, data.fileName)
+      const codeStr = this.generateCode();
+      const blob = new Blob([codeStr], { type: "text/plain;charset=utf-8" });
+      this.$download.saveAs(blob, data.fileName);
     },
     execCopy(data) {
-      document.getElementById('copyNode').click()
+      document.getElementById("copyNode").click();
     },
     empty() {
-      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
+      this.$confirm("确定要清空所有组件吗?", "提示", { type: "warning" }).then(
         () => {
-          this.drawingList = []
+          this.drawingList = [];
         }
-      )
+      );
     },
     drawingItemCopy(item, parent) {
-      let clone = JSON.parse(JSON.stringify(item))
-      clone = this.createIdAndKey(clone)
-      parent.push(clone)
-      this.activeFormItem(clone)
+      let clone = JSON.parse(JSON.stringify(item));
+      clone = this.createIdAndKey(clone);
+      parent.push(clone);
+      this.activeFormItem(clone);
     },
     createIdAndKey(item) {
-      item.formId = ++this.idGlobal
-      item.renderKey = +new Date()
-      if (item.layout === 'colFormItem') {
-        item.vModel = `field${this.idGlobal}`
-      } else if (item.layout === 'rowFormItem') {
-        item.componentName = `row${this.idGlobal}`
+      item.formId = ++this.idGlobal;
+      item.renderKey = +new Date();
+      if (item.layout === "colFormItem") {
+        item.vModel = `field${this.idGlobal}`;
+      } else if (item.layout === "rowFormItem") {
+        item.componentName = `row${this.idGlobal}`;
       }
       if (Array.isArray(item.children)) {
-        item.children = item.children.map(childItem => this.createIdAndKey(childItem))
+        item.children = item.children.map((childItem) =>
+          this.createIdAndKey(childItem)
+        );
       }
-      return item
+      return item;
     },
     drawingItemDelete(index, parent) {
-      parent.splice(index, 1)
+      parent.splice(index, 1);
       this.$nextTick(() => {
-        const len = this.drawingList.length
+        const len = this.drawingList.length;
         if (len) {
-          this.activeFormItem(this.drawingList[len - 1])
+          this.activeFormItem(this.drawingList[len - 1]);
         }
-      })
+      });
     },
     generateCode() {
-      const { type } = this.generateConf
-      this.AssembleFormData()
-      const script = vueScript(makeUpJs(this.formData, type))
-      const html = vueTemplate(makeUpHtml(this.formData, type))
-      const css = cssStyle(makeUpCss(this.formData))
-      return beautifier.html(html + script + css, beautifierConf.html)
+      const { type } = this.generateConf;
+      this.AssembleFormData();
+      const script = vueScript(makeUpJs(this.formData, type));
+      const html = vueTemplate(makeUpHtml(this.formData, type));
+      const css = cssStyle(makeUpCss(this.formData));
+      return beautifier.html(html + script + css, beautifierConf.html);
     },
     download() {
-      this.dialogVisible = true
-      this.showFileName = true
-      this.operationType = 'download'
+      this.dialogVisible = true;
+      this.showFileName = true;
+      this.operationType = "download";
     },
     run() {
-      this.dialogVisible = true
-      this.showFileName = false
-      this.operationType = 'run'
+      this.dialogVisible = true;
+      this.showFileName = false;
+      this.operationType = "run";
     },
     copy() {
-      this.dialogVisible = true
-      this.showFileName = false
-      this.operationType = 'copy'
+      this.dialogVisible = true;
+      this.showFileName = false;
+      this.operationType = "copy";
     },
     tagChange(newTag) {
-      newTag = this.cloneComponent(newTag)
-      newTag.vModel = this.activeData.vModel
-      newTag.formId = this.activeId
-      newTag.span = this.activeData.span
-      delete this.activeData.tag
-      delete this.activeData.tagIcon
-      delete this.activeData.document
-      Object.keys(newTag).forEach(key => {
-        if (this.activeData[key] !== undefined
-          && typeof this.activeData[key] === typeof newTag[key]) {
-          newTag[key] = this.activeData[key]
+      newTag = this.cloneComponent(newTag);
+      newTag.vModel = this.activeData.vModel;
+      newTag.formId = this.activeId;
+      newTag.span = this.activeData.span;
+      delete this.activeData.tag;
+      delete this.activeData.tagIcon;
+      delete this.activeData.document;
+      Object.keys(newTag).forEach((key) => {
+        if (
+          this.activeData[key] !== undefined &&
+          typeof this.activeData[key] === typeof newTag[key]
+        ) {
+          newTag[key] = this.activeData[key];
         }
-      })
-      this.activeData = newTag
-      this.updateDrawingList(newTag, this.drawingList)
+      });
+      this.activeData = newTag;
+      this.updateDrawingList(newTag, this.drawingList);
     },
     updateDrawingList(newTag, list) {
-      const index = list.findIndex(item => item.formId === this.activeId)
+      const index = list.findIndex((item) => item.formId === this.activeId);
       if (index > -1) {
-        list.splice(index, 1, newTag)
+        list.splice(index, 1, newTag);
       } else {
-        list.forEach(item => {
-          if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
-        })
+        list.forEach((item) => {
+          if (Array.isArray(item.children))
+            this.updateDrawingList(newTag, item.children);
+        });
       }
-    }
-  }
-}
+    },
+  },
+};
 </script>
 
-<style lang='scss'>
-.editor-tabs{
+<style lang="scss">
+.editor-tabs {
   background: #121315;
-  .el-tabs__header{
+  .el-tabs__header {
     margin: 0;
     border-bottom-color: #121315;
-    .el-tabs__nav{
+    .el-tabs__nav {
       border-color: #121315;
     }
   }
-  .el-tabs__item{
+  .el-tabs__item {
     height: 32px;
     line-height: 32px;
     color: #888a8e;
@@ -389,15 +426,15 @@ export default {
     margin-right: 5px;
     user-select: none;
   }
-  .el-tabs__item.is-active{
+  .el-tabs__item.is-active {
     background: #1e1e1e;
-    border-bottom-color: #1e1e1e!important;
+    border-bottom-color: #1e1e1e !important;
     color: #fff;
   }
-  .el-icon-edit{
+  .el-icon-edit {
     color: #f1fa8c;
   }
-  .el-icon-document{
+  .el-icon-document {
     color: #a95812;
   }
 }
@@ -413,24 +450,24 @@ export default {
   overflow-x: hidden !important;
   margin-bottom: 0 !important;
 }
-.center-tabs{
-  .el-tabs__header{
-    margin-bottom: 0!important;
+.center-tabs {
+  .el-tabs__header {
+    margin-bottom: 0 !important;
   }
-  .el-tabs__item{
+  .el-tabs__item {
     width: 50%;
     text-align: center;
   }
-  .el-tabs__nav{
+  .el-tabs__nav {
     width: 100%;
   }
 }
-.reg-item{
+.reg-item {
   padding: 12px 6px;
   background: #f8f8f8;
   position: relative;
   border-radius: 4px;
-  .close-btn{
+  .close-btn {
     position: absolute;
     right: -6px;
     top: -6px;
@@ -445,16 +482,16 @@ export default {
     z-index: 1;
     cursor: pointer;
     font-size: 12px;
-    &:hover{
-      background: rgba(210, 23, 23, 0.5)
+    &:hover {
+      background: rgba(210, 23, 23, 0.5);
     }
   }
-  & + .reg-item{
+  & + .reg-item {
     margin-top: 18px;
   }
 }
-.action-bar{
-  & .el-button+.el-button {
+.action-bar {
+  & .el-button + .el-button {
     margin-left: 15px;
   }
   & i {
@@ -465,37 +502,37 @@ export default {
   }
 }
 
-.custom-tree-node{
+.custom-tree-node {
   width: 100%;
   font-size: 14px;
-  .node-operation{
+  .node-operation {
     float: right;
   }
-  i[class*="el-icon"] + i[class*="el-icon"]{
+  i[class*="el-icon"] + i[class*="el-icon"] {
     margin-left: 6px;
   }
-  .el-icon-plus{
-    color: #409EFF;
+  .el-icon-plus {
+    color: #409eff;
   }
-  .el-icon-delete{
+  .el-icon-delete {
     color: #157a0c;
   }
 }
 
-.left-scrollbar .el-scrollbar__view{
+.left-scrollbar .el-scrollbar__view {
   overflow-x: hidden;
 }
 
-.el-rate{
+.el-rate {
   display: inline-block;
   vertical-align: text-top;
 }
-.el-upload__tip{
+.el-upload__tip {
   line-height: 1.2;
 }
 
 $selectedColor: #f6f7ff;
-$lighterBlue: #409EFF;
+$lighterBlue: #409eff;
 
 .container {
   position: relative;
@@ -514,14 +551,14 @@ $lighterBlue: #409EFF;
     transition: transform 0ms !important;
   }
 }
-.components-draggable{
+.components-draggable {
   padding-bottom: 20px;
 }
-.components-title{
+.components-title {
   font-size: 14px;
   color: #222;
   margin: 6px 2px;
-  .svg-icon{
+  .svg-icon {
     color: #666;
     font-size: 18px;
   }
@@ -534,7 +571,7 @@ $lighterBlue: #409EFF;
   cursor: move;
   border: 1px dashed $selectedColor;
   border-radius: 3px;
-  .svg-icon{
+  .svg-icon {
     color: #777;
     font-size: 15px;
   }
@@ -554,7 +591,7 @@ $lighterBlue: #409EFF;
   top: 0;
   height: 100vh;
 }
-.left-scrollbar{
+.left-scrollbar {
   height: calc(100vh - 42px);
   overflow: hidden;
 }
@@ -571,7 +608,7 @@ $lighterBlue: #409EFF;
   margin: 0 350px 0 260px;
   box-sizing: border-box;
 }
-.empty-info{
+.empty-info {
   position: absolute;
   top: 46%;
   left: 0;
@@ -581,27 +618,27 @@ $lighterBlue: #409EFF;
   color: #ccb1ea;
   letter-spacing: 4px;
 }
-.action-bar{
+.action-bar {
   position: relative;
   height: 42px;
   text-align: right;
   padding: 0 15px;
-  box-sizing: border-box;;
+  box-sizing: border-box;
   border: 1px solid #f1e8e8;
   border-top: none;
   border-left: none;
-  .delete-btn{
-    color: #F56C6C;
+  .delete-btn {
+    color: #f56c6c;
   }
 }
-.logo-wrapper{
+.logo-wrapper {
   position: relative;
   height: 42px;
   background: #fff;
   border-bottom: 1px solid #f1e8e8;
   box-sizing: border-box;
 }
-.logo{
+.logo {
   position: absolute;
   left: 12px;
   top: 6px;
@@ -610,16 +647,16 @@ $lighterBlue: #409EFF;
   font-weight: 600;
   font-size: 17px;
   white-space: nowrap;
-  > img{
+  > img {
     width: 30px;
     height: 30px;
     vertical-align: top;
   }
-  .github{
+  .github {
     display: inline-block;
     vertical-align: sub;
     margin-left: 15px;
-    > img{
+    > img {
       height: 22px;
     }
   }
@@ -662,32 +699,33 @@ $lighterBlue: #409EFF;
     background-color: $selectedColor;
   }
   .active-from-item {
-    & > .el-form-item{
+    & > .el-form-item {
       background: $selectedColor;
       border-radius: 6px;
     }
-    & > .drawing-item-copy, & > .drawing-item-delete{
+    & > .drawing-item-copy,
+    & > .drawing-item-delete {
       display: initial;
     }
-    & > .component-name{
+    & > .component-name {
       color: $lighterBlue;
     }
   }
-  .el-form-item{
+  .el-form-item {
     margin-bottom: 15px;
   }
 }
-.drawing-item{
+.drawing-item {
   position: relative;
   cursor: move;
-  &.unfocus-bordered:not(.activeFromItem) > div:first-child  {
+  &.unfocus-bordered:not(.activeFromItem) > div:first-child {
     border: 1px dashed #ccc;
   }
-  .el-form-item{
+  .el-form-item {
     padding: 12px 10px;
   }
 }
-.drawing-row-item{
+.drawing-row-item {
   position: relative;
   cursor: move;
   box-sizing: border-box;
@@ -698,19 +736,19 @@ $lighterBlue: #409EFF;
   .drawing-row-item {
     margin-bottom: 2px;
   }
-  .el-col{
+  .el-col {
     margin-top: 22px;
   }
-  .el-form-item{
+  .el-form-item {
     margin-bottom: 0;
   }
-  .drag-wrapper{
+  .drag-wrapper {
     min-height: 80px;
   }
-  &.active-from-item{
+  &.active-from-item {
     border: 1px dashed $lighterBlue;
   }
-  .component-name{
+  .component-name {
     position: absolute;
     top: 0;
     left: 0;
@@ -720,17 +758,20 @@ $lighterBlue: #409EFF;
     padding: 0 6px;
   }
 }
-.drawing-item, .drawing-row-item{
+.drawing-item,
+.drawing-row-item {
   &:hover {
-    & > .el-form-item{
+    & > .el-form-item {
       background: $selectedColor;
       border-radius: 6px;
     }
-    & > .drawing-item-copy, & > .drawing-item-delete{
+    & > .drawing-item-copy,
+    & > .drawing-item-delete {
       display: initial;
     }
   }
-  & > .drawing-item-copy, & > .drawing-item-delete{
+  & > .drawing-item-copy,
+  & > .drawing-item-delete {
     display: none;
     position: absolute;
     top: -10px;
@@ -744,23 +785,23 @@ $lighterBlue: #409EFF;
     cursor: pointer;
     z-index: 1;
   }
-  & > .drawing-item-copy{
+  & > .drawing-item-copy {
     right: 56px;
     border-color: $lighterBlue;
     color: $lighterBlue;
     background: #fff;
-    &:hover{
+    &:hover {
       background: $lighterBlue;
       color: #fff;
     }
   }
-  & > .drawing-item-delete{
+  & > .drawing-item-delete {
     right: 24px;
-    border-color: #F56C6C;
-    color: #F56C6C;
+    border-color: #f56c6c;
+    color: #f56c6c;
     background: #fff;
-    &:hover{
-      background: #F56C6C;
+    &:hover {
+      background: #f56c6c;
       color: #fff;
     }
   }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1089 - 0
sql/ry-vue2023-6-19-3.sql


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů