Browse Source

perf: improve flowChart logic

Vben 3 years ago
parent
commit
e1bc33f5c5
44 changed files with 414 additions and 660 deletions
  1. 1 0
      build/generate/generateModifyVars.ts
  2. 1 0
      build/vite/plugin/theme.ts
  3. 1 1
      package.json
  4. 3 10
      src/components/FlowChart/index.ts
  5. 0 150
      src/components/FlowChart/src/Control.vue
  6. 2 2
      src/components/FlowChart/src/DataDialog.vue
  7. 156 0
      src/components/FlowChart/src/FlowChartToolbar.vue
  8. 0 145
      src/components/FlowChart/src/NodePanel.vue
  9. 6 91
      src/components/FlowChart/src/adpterForTurbo.ts
  10. BIN
      src/components/FlowChart/src/assets/background/bpmn-end.png
  11. BIN
      src/components/FlowChart/src/assets/background/bpmn-exclusiveGateway.png
  12. BIN
      src/components/FlowChart/src/assets/background/bpmn-start.png
  13. BIN
      src/components/FlowChart/src/assets/background/bpmn-user.png
  14. BIN
      src/components/FlowChart/src/assets/background/click.png
  15. BIN
      src/components/FlowChart/src/assets/background/download.png
  16. BIN
      src/components/FlowChart/src/assets/background/end.png
  17. BIN
      src/components/FlowChart/src/assets/background/push.png
  18. BIN
      src/components/FlowChart/src/assets/background/start.png
  19. BIN
      src/components/FlowChart/src/assets/background/time.png
  20. BIN
      src/components/FlowChart/src/assets/background/user.png
  21. 0 5
      src/components/FlowChart/src/assets/iconfont/iconfont.css
  22. BIN
      src/components/FlowChart/src/assets/iconfont/iconfont.eot
  23. 0 8
      src/components/FlowChart/src/assets/iconfont/iconfont.js
  24. 0 58
      src/components/FlowChart/src/assets/iconfont/iconfont.json
  25. 0 25
      src/components/FlowChart/src/assets/iconfont/iconfont.svg
  26. BIN
      src/components/FlowChart/src/assets/iconfont/iconfont.ttf
  27. BIN
      src/components/FlowChart/src/assets/iconfont/iconfont.woff
  28. BIN
      src/components/FlowChart/src/assets/iconfont/iconfont.woff2
  29. 11 0
      src/components/FlowChart/src/enum.ts
  30. 124 0
      src/components/FlowChart/src/index.vue
  31. 14 0
      src/components/FlowChart/src/types.ts
  32. 17 0
      src/components/FlowChart/src/useFlowContext.ts
  33. 4 18
      src/components/Table/src/BasicTable.vue
  34. 3 3
      src/components/Tinymce/src/tinymce.ts
  35. 0 1
      src/locales/lang/en/routes/demo/comp.ts
  36. 4 0
      src/locales/lang/en/routes/demo/flow.ts
  37. 0 1
      src/locales/lang/zh_CN/routes/demo/comp.ts
  38. 4 0
      src/locales/lang/zh_CN/routes/demo/flow.ts
  39. 0 7
      src/router/menus/modules/demo/comp.ts
  40. 18 0
      src/router/menus/modules/demo/flow.ts
  41. 1 8
      src/router/routes/modules/demo/comp.ts
  42. 27 0
      src/router/routes/modules/demo/flow.ts
  43. 12 122
      src/views/demo/comp/flow-chart/index.vue
  44. 5 5
      yarn.lock

+ 1 - 0
build/generate/generateModifyVars.ts

@@ -32,5 +32,6 @@ export function generateModifyVars(dark = false) {
     'font-size-base': '14px', //  Main font size
     'border-radius-base': '2px', //  Component/float fillet
     'link-color': primary, //   Link color
+    'content-background': '#fafafa', //   Link color
   };
 }

+ 1 - 0
build/vite/plugin/theme.ts

@@ -53,6 +53,7 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
         'border-color-base': '#303030',
         // 'border-color-split': '#30363d',
         'item-active-bg': '#111b26',
+        'content-background': '#ffffff0a', //   Link color
       },
     }),
   ];

+ 1 - 1
package.json

@@ -101,7 +101,7 @@
     "prettier": "^2.2.1",
     "pretty-quick": "^3.1.0",
     "rimraf": "^3.0.2",
-    "rollup-plugin-visualizer": "5.3.6",
+    "rollup-plugin-visualizer": "5.3.4",
     "stylelint": "^13.12.0",
     "stylelint-config-prettier": "^8.0.2",
     "stylelint-config-standard": "^21.0.0",

+ 3 - 10
src/components/FlowChart/index.ts

@@ -1,17 +1,10 @@
 import { App } from 'vue';
-import control from './src/Control.vue';
-import nodePanel from './src/NodePanel.vue';
 import dataDialog from './src/DataDialog.vue';
+import flowChart from './src/index.vue';
 
-export const Control = Object.assign(control, {
+export const FlowChart = Object.assign(flowChart, {
   install(app: App) {
-    app.component(control.name, control);
-  },
-});
-
-export const NodePanel = Object.assign(nodePanel, {
-  install(app: App) {
-    app.component(nodePanel.name, nodePanel);
+    app.component(flowChart.name, flowChart);
   },
 });
 

+ 0 - 150
src/components/FlowChart/src/Control.vue

@@ -1,150 +0,0 @@
-<template>
-  <div class="control-container">
-    <!-- 功能按钮 -->
-    <ul>
-      <li
-        v-for="(item, key) in titleLists"
-        :key="key"
-        :title="item.text"
-        @mouseenter.prevent="onEnter(key)"
-        @mouseleave.prevent="focusIndex = -1"
-      >
-        <a-button
-          :disabled="item.disabled"
-          :style="{ cursor: item.disabled === false ? 'pointer' : 'not-allowed' }"
-          @click="onControl(item, key)"
-        >
-          <span :class="'iconfont ' + item.icon"></span>
-          <p>{{ item.text }}</p>
-        </a-button>
-      </li>
-    </ul>
-  </div>
-</template>
-
-<script lang="ts">
-  import { defineComponent, ref, unref, onMounted } from 'vue';
-
-  export default defineComponent({
-    name: 'Control',
-    props: {
-      lf: Object || String,
-      catTurboData: Boolean,
-    },
-    emits: ['catData'],
-    setup(props, { emit }) {
-      let focusIndex = ref(-1);
-      let titleLists = ref([
-        {
-          icon: 'icon-zoom-out-hs',
-          text: '缩小',
-          disabled: false,
-        },
-        {
-          icon: 'icon-enlarge-hs',
-          text: '放大',
-          disabled: false,
-        },
-        {
-          icon: 'icon-full-screen-hs',
-          text: '适应',
-          disabled: false,
-        },
-        {
-          icon: 'icon-previous-hs',
-          text: '上一步',
-          disabled: true,
-        },
-        {
-          icon: 'icon-next-step-hs',
-          text: '下一步',
-          disabled: true,
-        },
-        {
-          icon: 'icon-download-hs',
-          text: '下载图片',
-          disabled: false,
-        },
-        {
-          icon: 'icon-watch-hs',
-          text: '查看数据',
-          disabled: false,
-        },
-      ]);
-
-      const onControl = (item, key) => {
-        ['zoom', 'zoom', 'resetZoom', 'undo', 'redo', 'getSnapshot'].forEach((v, i) => {
-          let domControl = props.lf;
-          if (key === 1) {
-            domControl.zoom(true);
-          }
-          if (key === 6) {
-            emit('catData');
-          }
-          if (key === i) {
-            domControl[v]();
-          }
-        });
-      };
-
-      const onEnter = (key) => {
-        focusIndex.value = key;
-      };
-
-      onMounted(() => {
-        props.lf.on('history:change', ({ data: { undoAble, redoAble } }) => {
-          unref(titleLists)[3].disabled = !undoAble;
-          unref(titleLists)[4].disabled = !redoAble;
-        });
-      });
-
-      return {
-        focusIndex,
-        titleLists,
-        onControl,
-        onEnter,
-      };
-    },
-  });
-</script>
-
-<style scoped>
-  @import './assets/iconfont/iconfont.css';
-
-  .control-container {
-    position: absolute;
-    right: 20px;
-    background: hsla(0, 0%, 100%, 0.8);
-    box-shadow: 0 1px 4px rgb(0 0 0 / 30%);
-  }
-
-  .iconfont {
-    font-size: 25px;
-  }
-
-  .control-container p {
-    margin: 0;
-    font-size: 12px;
-  }
-
-  .control-container ul {
-    display: flex;
-    justify-content: space-around;
-    align-items: center;
-    margin: 2px;
-  }
-
-  .control-container ul li {
-    width: 60px;
-    text-align: center;
-  }
-
-  .control-container ul li button {
-    width: 100%;
-    height: 60px;
-    padding: 0;
-    background-color: transparent;
-    border: none;
-    outline: none;
-  }
-</style>

+ 2 - 2
src/components/FlowChart/src/DataDialog.vue

@@ -1,5 +1,5 @@
 <template>
-  <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="graphData" />
+  <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" />
 </template>
 
 <script lang="ts">
@@ -12,7 +12,7 @@
       VueJsonPretty,
     },
     props: {
-      graphData: Object,
+      data: Object,
     },
   });
 </script>

+ 156 - 0
src/components/FlowChart/src/FlowChartToolbar.vue

@@ -0,0 +1,156 @@
+<template>
+  <div :class="`${prefixCls}-toolbar`" class="flex items-center px-2 py-1">
+    <template v-for="(item, index) in toolbarItemList" :key="item.type || index">
+      <Tooltip placement="bottom" v-bind="item.disabled ? { visible: false } : {}">
+        <template #title>{{ item.tooltip }}</template>
+        <span :class="`${prefixCls}-toolbar__icon`" v-if="item.icon" @click="onControl(item)">
+          <Icon
+            :icon="item.icon"
+            :class="item.disabled ? 'cursor-not-allowed disabeld' : 'cursor-pointer'"
+          />
+        </span>
+      </Tooltip>
+      <Divider v-if="item.separate" type="vertical" />
+    </template>
+  </div>
+</template>
+<script lang="ts">
+  import type { ToolbarConfig } from './types';
+
+  import { defineComponent, ref, onUnmounted, unref, nextTick, watchEffect } from 'vue';
+  import { Divider, Tooltip } from 'ant-design-vue';
+  import { Icon } from '/@/components/Icon';
+
+  import { useFlowChartContext } from './useFlowContext';
+  import { ToolbarTypeEnum } from './enum';
+
+  export default defineComponent({
+    name: 'FlowChartToolbar',
+    components: { Icon, Divider, Tooltip },
+    props: {
+      prefixCls: String,
+    },
+    setup(_, { emit }) {
+      const toolbarItemList = ref<ToolbarConfig[]>([
+        {
+          type: ToolbarTypeEnum.ZOOM_IN,
+          icon: 'codicon:zoom-out',
+          tooltip: '缩小',
+        },
+        {
+          type: ToolbarTypeEnum.ZOOM_OUT,
+          icon: 'codicon:zoom-in',
+          tooltip: '放大',
+        },
+        {
+          type: ToolbarTypeEnum.RESET_ZOOM,
+          icon: 'codicon:screen-normal',
+          tooltip: '重置比例',
+        },
+        { separate: true },
+        {
+          type: ToolbarTypeEnum.UNDO,
+          icon: 'ion:arrow-undo-outline',
+          tooltip: '后退',
+          disabled: true,
+        },
+        {
+          type: ToolbarTypeEnum.REDO,
+          icon: 'ion:arrow-redo-outline',
+          tooltip: '前进',
+          disabled: true,
+        },
+        { separate: true },
+        {
+          type: ToolbarTypeEnum.SNAPSHOT,
+          icon: 'ion:download-outline',
+          tooltip: '下载',
+        },
+        {
+          type: ToolbarTypeEnum.VIEW_DATA,
+          icon: 'carbon:document-view',
+          tooltip: '查看数据',
+        },
+      ]);
+
+      const { logicFlow } = useFlowChartContext();
+
+      function onHistoryChange({ data: { undoAble, redoAble } }) {
+        const itemsList = unref(toolbarItemList);
+        const undoIndex = itemsList.findIndex((item) => item.type === ToolbarTypeEnum.UNDO);
+        const redoIndex = itemsList.findIndex((item) => item.type === ToolbarTypeEnum.REDO);
+        if (undoIndex !== -1) {
+          unref(toolbarItemList)[undoIndex].disabled = !undoAble;
+        }
+        if (redoIndex !== -1) {
+          unref(toolbarItemList)[redoIndex].disabled = !redoAble;
+        }
+      }
+
+      const onControl = (item) => {
+        const lf = unref(logicFlow);
+        if (!lf) {
+          return;
+        }
+        switch (item.type) {
+          case ToolbarTypeEnum.ZOOM_IN:
+            lf.zoom();
+            break;
+          case ToolbarTypeEnum.ZOOM_OUT:
+            lf.zoom(true);
+            break;
+          case ToolbarTypeEnum.RESET_ZOOM:
+            lf.resetZoom();
+            break;
+          case ToolbarTypeEnum.UNDO:
+            lf.undo();
+            break;
+          case ToolbarTypeEnum.REDO:
+            lf.redo();
+            break;
+          case ToolbarTypeEnum.SNAPSHOT:
+            lf.getSnapshot();
+            break;
+          case ToolbarTypeEnum.VIEW_DATA:
+            emit('catData');
+            break;
+        }
+      };
+
+      watchEffect(async () => {
+        if (unref(logicFlow)) {
+          await nextTick();
+          unref(logicFlow)?.on('history:change', onHistoryChange);
+        }
+      });
+
+      onUnmounted(() => {
+        unref(logicFlow)?.off('history:change', onHistoryChange);
+      });
+      return { toolbarItemList, onControl };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  @prefix-cls: ~'@{namespace}-flow-chart-toolbar';
+
+  .@{prefix-cls} {
+    height: 36px;
+    background: @content-background;
+    border-bottom: 1px solid @border-color-base;
+
+    .disabeld {
+      color: @disabled-color;
+    }
+
+    &__icon {
+      display: inline-block;
+      padding: 2px 4px;
+      margin-right: 10px;
+
+      &:hover {
+        color: @primary-color;
+      }
+    }
+  }
+</style>

+ 0 - 145
src/components/FlowChart/src/NodePanel.vue

@@ -1,145 +0,0 @@
-<template>
-  <!-- 左侧bpmn元素选择器 -->
-  <div class="node-panel">
-    <div
-      class="node-item"
-      v-for="item in nodeList"
-      :key="item.text"
-      @mousedown="nodeDragNode(item)"
-    >
-      <div class="node-item-icon" :class="item.class">
-        <div v-if="item.type === 'user' || item.type === 'time'" class="shape"></div>
-      </div>
-      <span class="node-label">{{ item.text }}</span>
-    </div>
-  </div>
-</template>
-
-<script lang="ts">
-  import { defineComponent, ref, unref } from 'vue';
-  export default defineComponent({
-    name: 'NodePanel',
-    props: {
-      lf: Object,
-      nodeList: Array,
-    },
-    setup(props) {
-      let node = ref({
-        type: 'rect',
-        property: {
-          a: 'efrwe',
-          b: 'wewe',
-        },
-      });
-      let properties = ref({
-        a: 'efrwe',
-        b: 'wewe',
-      });
-
-      const nodeDragNode = (item) => {
-        props.lf.dnd.startDrag({
-          type: item.type,
-          properties: unref(properties),
-        });
-      };
-
-      return {
-        node,
-        properties,
-        nodeDragNode,
-      };
-    },
-  });
-</script>
-
-<style scoped>
-  .node-panel {
-    position: absolute;
-    top: 100px;
-    left: 50px;
-    z-index: 101;
-    width: 70px;
-    padding: 20px 10px;
-    text-align: center;
-    background-color: white;
-    border-radius: 6px;
-    box-shadow: 0 0 10px 1px rgb(228, 224, 219);
-  }
-
-  .node-item {
-    margin-bottom: 20px;
-  }
-
-  .node-item-icon {
-    display: flex;
-    height: 30px;
-    background-size: cover;
-    flex-wrap: wrap;
-    justify-content: center;
-  }
-
-  .node-label {
-    margin-top: 5px;
-    font-size: 12px;
-    user-select: none;
-  }
-
-  .node-start {
-    background: url('./background/start.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-rect {
-    border: 1px solid black;
-  }
-
-  .node-user {
-    background: url('./background/user.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-time {
-    background: url('./background/time.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-push {
-    background: url('./background/push.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-download {
-    background: url('./background/download.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-click {
-    background: url('./background/click.png') no-repeat;
-    background-size: cover;
-  }
-
-  .node-end {
-    background: url('./background/end.png') no-repeat;
-    background-size: cover;
-  }
-
-  .bpmn-start {
-    cursor: grab;
-    background: url('./assets/background/bpmn-start.png') center center no-repeat;
-  }
-
-  .bpmn-end {
-    cursor: grab;
-    background: url('./assets/background/bpmn-end.png') center center no-repeat;
-  }
-
-  .bpmn-user {
-    cursor: grab;
-    background: url('./assets/background/bpmn-user.png') center center no-repeat;
-  }
-
-  .bpmn-exclusiveGateway {
-    cursor: grab;
-    background: url('./assets/background/bpmn-exclusiveGateway.png') center center no-repeat;
-  }
-</style>

+ 6 - 91
src/components/FlowChart/src/adpterForTurbo.ts

@@ -7,95 +7,6 @@ const TurboType = {
   EXCLUSIVE_GATEWAY: 6,
 };
 
-function getTurboType(type) {
-  switch (type) {
-    case 'bpmn:sequenceFlow':
-      return TurboType.SEQUENCE_FLOW;
-    case 'bpmn:startEvent':
-      return TurboType.START_EVENT;
-    case 'bpmn:endEvent':
-      return TurboType.END_EVENT;
-    case 'bpmn:userTask':
-      return TurboType.USER_TASK;
-    case 'bpmn:serviceTask':
-      return TurboType.SERVICE_TASK;
-    case 'bpmn:exclusiveGateway':
-      return TurboType.EXCLUSIVE_GATEWAY;
-    default:
-      return type;
-  }
-}
-
-function convertNodeToTurboElement(node) {
-  const { id, type, x, y, text = '', properties } = node;
-  return {
-    incoming: [],
-    outgoing: [],
-    dockers: [],
-    type: getTurboType(node.type),
-    properties: {
-      ...properties,
-      name: (text && text.value) || '',
-      x: x,
-      y: y,
-      text,
-      logicFlowType: type,
-    },
-    key: id,
-  };
-}
-
-function convertEdgeToTurboElement(edge) {
-  const {
-    id,
-    type,
-    sourceNodeId,
-    targetNodeId,
-    startPoint,
-    endPoint,
-    pointsList,
-    text = '',
-    properties,
-  } = edge;
-  return {
-    incoming: [sourceNodeId],
-    outgoing: [targetNodeId],
-    type: getTurboType(type),
-    dockers: [],
-    properties: {
-      ...properties,
-      name: (text && text.value) || '',
-      text,
-      startPoint,
-      endPoint,
-      pointsList,
-      logicFlowType: type,
-    },
-    key: id,
-  };
-}
-
-export function toTurboData(data) {
-  const nodeMap = new Map();
-  const turboData = {
-    flowElementList: [],
-  };
-  data.nodes.forEach((node) => {
-    const flowElement = convertNodeToTurboElement(node);
-    turboData.flowElementList.push(flowElement);
-    nodeMap.set(node.id, flowElement);
-  });
-  data.edges.forEach((edge) => {
-    const flowElement = convertEdgeToTurboElement(edge);
-    const sourceElement = nodeMap.get(edge.sourceNodeId);
-    sourceElement.outgoing.push(flowElement.key);
-    const targetElement = nodeMap.get(edge.targetNodeId);
-    targetElement.incoming.push(flowElement.key);
-    turboData.flowElementList.push(flowElement);
-  });
-  return turboData;
-}
-
 function convertFlowElementToEdge(element) {
   const { incoming, outgoing, properties, key } = element;
   const { text, startPoint, endPoint, pointsList, logicFlowType } = properties;
@@ -139,8 +50,12 @@ function convertFlowElementToNode(element) {
   return node;
 }
 
-export function toLogicflowData(data) {
-  const lfData = {
+export function toLogicFlowData(data) {
+  const lfData: {
+    // TODO type
+    nodes: any[];
+    edges: any[];
+  } = {
     nodes: [],
     edges: [],
   };

BIN
src/components/FlowChart/src/assets/background/bpmn-end.png


BIN
src/components/FlowChart/src/assets/background/bpmn-exclusiveGateway.png


BIN
src/components/FlowChart/src/assets/background/bpmn-start.png


BIN
src/components/FlowChart/src/assets/background/bpmn-user.png


BIN
src/components/FlowChart/src/assets/background/click.png


BIN
src/components/FlowChart/src/assets/background/download.png


BIN
src/components/FlowChart/src/assets/background/end.png


BIN
src/components/FlowChart/src/assets/background/push.png


BIN
src/components/FlowChart/src/assets/background/start.png


BIN
src/components/FlowChart/src/assets/background/time.png


BIN
src/components/FlowChart/src/assets/background/user.png


File diff suppressed because it is too large
+ 0 - 5
src/components/FlowChart/src/assets/iconfont/iconfont.css


BIN
src/components/FlowChart/src/assets/iconfont/iconfont.eot


File diff suppressed because it is too large
+ 0 - 8
src/components/FlowChart/src/assets/iconfont/iconfont.js


+ 0 - 58
src/components/FlowChart/src/assets/iconfont/iconfont.json

@@ -1,58 +0,0 @@
-{
-  "id": "2491438",
-  "name": "liu'c'tu",
-  "font_family": "iconfont",
-  "css_prefix_text": "icon-",
-  "description": "",
-  "glyphs": [
-    {
-      "icon_id": "755619",
-      "name": "自适应图标",
-      "font_class": "full-screen-hs",
-      "unicode": "e656",
-      "unicode_decimal": 58966
-    },
-    {
-      "icon_id": "14445801",
-      "name": "查看",
-      "font_class": "watch-hs",
-      "unicode": "e766",
-      "unicode_decimal": 59238
-    },
-    {
-      "icon_id": "9712640",
-      "name": "下载",
-      "font_class": "download-hs",
-      "unicode": "e6af",
-      "unicode_decimal": 59055
-    },
-    {
-      "icon_id": "1029099",
-      "name": "放大",
-      "font_class": "enlarge-hs",
-      "unicode": "e765",
-      "unicode_decimal": 59237
-    },
-    {
-      "icon_id": "20017362",
-      "name": "上一步",
-      "font_class": "previous-hs",
-      "unicode": "e84c",
-      "unicode_decimal": 59468
-    },
-    {
-      "icon_id": "1010015",
-      "name": "缩小",
-      "font_class": "zoom-out-hs",
-      "unicode": "e744",
-      "unicode_decimal": 59204
-    },
-    {
-      "icon_id": "20017363",
-      "name": "下一步",
-      "font_class": "next-step-hs",
-      "unicode": "e84b",
-      "unicode_decimal": 59467
-    }
-  ]
-}

File diff suppressed because it is too large
+ 0 - 25
src/components/FlowChart/src/assets/iconfont/iconfont.svg


BIN
src/components/FlowChart/src/assets/iconfont/iconfont.ttf


BIN
src/components/FlowChart/src/assets/iconfont/iconfont.woff


BIN
src/components/FlowChart/src/assets/iconfont/iconfont.woff2


+ 11 - 0
src/components/FlowChart/src/enum.ts

@@ -0,0 +1,11 @@
+export enum ToolbarTypeEnum {
+  ZOOM_IN = 'zoomIn',
+  ZOOM_OUT = 'zoomOut',
+  RESET_ZOOM = 'resetZoom',
+
+  UNDO = 'undo',
+  REDO = 'redo',
+
+  SNAPSHOT = 'snapshot',
+  VIEW_DATA = 'viewData',
+}

+ 124 - 0
src/components/FlowChart/src/index.vue

@@ -0,0 +1,124 @@
+<template>
+  <div class="h-full" :class="prefixCls">
+    <FlowChartToolbar :prefixCls="prefixCls" v-if="toolbar" />
+    <div ref="lfElRef" class="h-full"></div>
+  </div>
+</template>
+<script lang="ts">
+  import type { Definition } from '@logicflow/core';
+
+  import { defineComponent, ref, onMounted, unref, nextTick, computed, watch } from 'vue';
+
+  import FlowChartToolbar from './FlowChartToolbar.vue';
+  import LogicFlow from '@logicflow/core';
+  import { Snapshot, BpmnElement, Menu, DndPanel } from '@logicflow/extension';
+
+  import { useDesign } from '/@/hooks/web/useDesign';
+  import { createFlowChartContext } from './useFlowContext';
+
+  import { toLogicFlowData } from './adpterForTurbo';
+
+  import '@logicflow/core/dist/style/index.css';
+  import '@logicflow/extension/lib/style/index.css';
+  export default defineComponent({
+    name: 'FlowChart',
+    components: { FlowChartToolbar },
+    props: {
+      flowOptions: {
+        type: Object as PropType<Definition>,
+        default: () => {},
+      },
+
+      data: {
+        type: Object as PropType<any>,
+        default: () => {},
+      },
+
+      toolbar: {
+        type: Boolean,
+        default: true,
+      },
+    },
+    setup(props) {
+      const lfElRef = ref<ElRef>(null);
+
+      const lfInstance = ref<Nullable<LogicFlow>>(null);
+
+      const { prefixCls } = useDesign('flow-chart');
+      createFlowChartContext({
+        logicFlow: (lfInstance as unknown) as LogicFlow,
+      });
+
+      const getFlowOptions = computed(() => {
+        const { flowOptions } = props;
+
+        const defaultOptions: Partial<Definition> = {
+          grid: true,
+          background: {
+            color: '#f7f9ff',
+          },
+          keyboard: {
+            enabled: true,
+          },
+          ...flowOptions,
+        };
+        return defaultOptions as Definition;
+      });
+
+      watch(
+        () => props.data,
+        () => {
+          onRender();
+        }
+      );
+
+      watch(
+        () => props.flowOptions,
+        (options) => {
+          unref(lfInstance)?.updateEditConfig(options);
+        }
+      );
+
+      // init logicFlow
+      async function init() {
+        await nextTick();
+
+        const lfEl = unref(lfElRef);
+        if (!lfEl) {
+          return;
+        }
+
+        // Canvas configuration
+        LogicFlow.use(Snapshot);
+        // Use the bpmn plug-in to introduce bpmn elements, which can be used after conversion in turbo
+        LogicFlow.use(BpmnElement);
+        // Start the right-click menu
+        LogicFlow.use(Menu);
+        LogicFlow.use(DndPanel);
+        lfInstance.value = new LogicFlow({
+          ...unref(getFlowOptions),
+          container: lfEl,
+        });
+        unref(lfInstance)?.setDefaultEdgeType('line');
+        onRender();
+      }
+
+      async function onRender() {
+        await nextTick();
+        const lf = unref(lfInstance);
+        if (!lf) {
+          return;
+        }
+        const lFData = toLogicFlowData(props.data);
+        lf.render(lFData);
+      }
+
+      onMounted(init);
+
+      return {
+        prefixCls,
+        lfElRef,
+      };
+    },
+  });
+</script>

+ 14 - 0
src/components/FlowChart/src/types.ts

@@ -0,0 +1,14 @@
+import { NodeConfig } from '@logicflow/core';
+import { ToolbarTypeEnum } from './enum';
+
+export interface NodeItem extends NodeConfig {
+  icon: string;
+}
+
+export interface ToolbarConfig {
+  type?: string | ToolbarTypeEnum;
+  tooltip?: string | boolean;
+  icon?: string;
+  disabled?: boolean;
+  separate?: boolean;
+}

+ 17 - 0
src/components/FlowChart/src/useFlowContext.ts

@@ -0,0 +1,17 @@
+import type LogicFlow from '@logicflow/core';
+
+import { provide, inject } from 'vue';
+
+const key = Symbol('flow-chart');
+
+type Instance = {
+  logicFlow: LogicFlow;
+};
+
+export function createFlowChartContext(instance: Instance) {
+  provide(key, instance);
+}
+
+export function useFlowChartContext(): Instance {
+  return inject(key) as Instance;
+}

+ 4 - 18
src/components/Table/src/BasicTable.vue

@@ -298,27 +298,13 @@
 
   @prefix-cls: ~'@{namespace}-basic-table';
 
-  html[data-theme='light'] {
-    .@{prefix-cls} {
-      &-row__striped {
-        td {
-          background-color: #fafafa;
-        }
-      }
-    }
-  }
-
-  html[data-theme='dark'] {
-    .@{prefix-cls} {
-      &-row__striped {
-        td {
-          background-color: rgb(255 255 255 / 4%);
-        }
+  .@{prefix-cls} {
+    &-row__striped {
+      td {
+        background-color: content-background;
       }
     }
-  }
 
-  .@{prefix-cls} {
     &-form-container {
       padding: 16px;
 

+ 3 - 3
src/components/Tinymce/src/tinymce.ts

@@ -25,7 +25,7 @@ import 'tinymce/plugins/save';
 import 'tinymce/plugins/searchreplace';
 import 'tinymce/plugins/spellchecker';
 import 'tinymce/plugins/tabfocus';
-import 'tinymce/plugins/table';
+// import 'tinymce/plugins/table';
 import 'tinymce/plugins/template';
 import 'tinymce/plugins/textpattern';
 import 'tinymce/plugins/visualblocks';
@@ -38,12 +38,12 @@ import 'tinymce/plugins/wordcount';
 // colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration
 
 export const plugins = [
-  'advlist anchor autolink autosave code codesample  directionality  fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template  textpattern visualblocks visualchars wordcount',
+  'advlist anchor autolink autosave code codesample  directionality  fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus  template  textpattern visualblocks visualchars wordcount',
 ];
 
 export const toolbar = [
   'fontsizeselect lineheight searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample',
-  'hr bullist numlist link  preview anchor pagebreak insertdatetime media table  forecolor backcolor fullscreen',
+  'hr bullist numlist link  preview anchor pagebreak insertdatetime media  forecolor backcolor fullscreen',
 ];
 
 export { tinymce };

+ 0 - 1
src/locales/lang/en/routes/demo/comp.ts

@@ -35,5 +35,4 @@ export default {
 
   time: 'Relative Time',
   cropperImage: 'Cropper Image',
-  flowChart: 'Flow Chart',
 };

+ 4 - 0
src/locales/lang/en/routes/demo/flow.ts

@@ -0,0 +1,4 @@
+export default {
+  name: 'Graphics editor',
+  flowChart: 'FlowChart',
+};

+ 0 - 1
src/locales/lang/zh_CN/routes/demo/comp.ts

@@ -34,5 +34,4 @@ export default {
 
   time: '相对时间',
   cropperImage: '图片裁剪',
-  flowChart: '流程图',
 };

+ 4 - 0
src/locales/lang/zh_CN/routes/demo/flow.ts

@@ -0,0 +1,4 @@
+export default {
+  name: '图形编辑器',
+  flowChart: '流程图',
+};

+ 0 - 7
src/router/menus/modules/demo/comp.ts

@@ -124,13 +124,6 @@ const menu: MenuModule = {
         },
       },
       {
-        path: 'flowChart',
-        name: t('routes.demo.comp.flowChart'),
-        tag: {
-          content: 'new',
-        },
-      },
-      {
         path: 'countTo',
         name: t('routes.demo.comp.countTo'),
       },

+ 18 - 0
src/router/menus/modules/demo/flow.ts

@@ -0,0 +1,18 @@
+import type { MenuModule } from '/@/router/types';
+import { t } from '/@/hooks/web/useI18n';
+
+const menu: MenuModule = {
+  orderNo: 5000,
+  menu: {
+    name: t('routes.demo.flow.name'),
+    path: '/flow',
+
+    children: [
+      {
+        path: 'flowChart',
+        name: t('routes.demo.flow.flowChart'),
+      },
+    ],
+  },
+};
+export default menu;

+ 1 - 8
src/router/routes/modules/demo/comp.ts

@@ -240,14 +240,7 @@ const comp: AppRouteModule = {
         title: t('routes.demo.comp.cropperImage'),
       },
     },
-    {
-      path: 'flowChart',
-      name: 'flowChartDemo',
-      component: () => import('/@/views/demo/comp/flow-chart/index.vue'),
-      meta: {
-        title: t('routes.demo.comp.flowChart'),
-      },
-    },
+
     {
       path: 'timestamp',
       name: 'TimeDemo',

+ 27 - 0
src/router/routes/modules/demo/flow.ts

@@ -0,0 +1,27 @@
+import type { AppRouteModule } from '/@/router/types';
+
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const charts: AppRouteModule = {
+  path: '/flow',
+  name: 'FlowDemo',
+  component: LAYOUT,
+  redirect: '/flow/flowChart',
+  meta: {
+    icon: 'tabler:chart-dots',
+    title: t('routes.demo.flow.name'),
+  },
+  children: [
+    {
+      path: 'flowChart',
+      name: 'flowChartDemo',
+      component: () => import('/@/views/demo/comp/flow-chart/index.vue'),
+      meta: {
+        title: t('routes.demo.flow.flowChart'),
+      },
+    },
+  ],
+};
+
+export default charts;

+ 12 - 122
src/views/demo/comp/flow-chart/index.vue

@@ -1,133 +1,23 @@
 <template>
-  <div class="logic-flow-view">
-    <!-- 辅助工具栏 -->
-    <Control class="demo-control" v-if="lf" :lf="lf" :catTurboData="false" @catData="catData" />
-    <!-- 节点面板 -->
-    <NodePanel :lf="lf" :nodeList="nodeList" />
-    <!-- 画布 -->
-    <div id="LF-Turbo"></div>
-    <!-- 数据查看面板 -->
-    <BasicModal @register="register" title="数据">
-      <DataDialog :graphData="graphData" />
-    </BasicModal>
-  </div>
+  <PageWrapper
+    title="流程图"
+    content="简单流程图示例,具体功能需要自己完善"
+    contentFullHeight
+    fixedHeight
+  >
+    <FlowChart :data="demoData" />
+  </PageWrapper>
 </template>
 
 <script lang="ts">
-  import { ref, unref, onMounted } from 'vue';
-  import LogicFlow from '@logicflow/core';
-  import { Snapshot, BpmnElement, Menu } from '@logicflow/extension';
-  import '@logicflow/core/dist/style/index.css';
-  import '@logicflow/extension/lib/style/index.css';
-  import { Control, NodePanel, DataDialog } from '/@/components/FlowChart';
+  import { FlowChart } from '/@/components/FlowChart';
+  import { PageWrapper } from '/@/components/Page';
 
-  import { toLogicflowData } from '/@/components/FlowChart/src/adpterForTurbo';
-  import { BpmnNode } from '/@/components/FlowChart/src/config';
   import demoData from './dataTurbo.json';
-
-  import { BasicModal, useModal } from '/@/components/Modal';
   export default {
-    components: { NodePanel, Control, DataDialog, BasicModal },
+    components: { FlowChart, PageWrapper },
     setup() {
-      let lf = ref(null);
-      let graphData = ref(null);
-      let config = ref({
-        grid: true,
-        background: {
-          color: '#f7f9ff',
-        },
-        keyboard: {
-          enabled: true,
-        },
-      });
-      let nodeList = BpmnNode;
-
-      const [register, { openModal }] = useModal();
-
-      function initLf() {
-        // 画布配置
-        LogicFlow.use(Snapshot);
-        // 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
-        LogicFlow.use(BpmnElement);
-        // 启动右键菜单
-        LogicFlow.use(Menu);
-        const domLf = new LogicFlow({
-          ...unref(config),
-          container: document.querySelector('#LF-Turbo'),
-        });
-        lf.value = domLf;
-        // 设置边类型bpmn:sequenceFlow为默认类型
-        unref(lf).setDefaultEdgeType('bpmn:sequenceFlow');
-        onRender();
-      }
-
-      function onRender() {
-        // Turbo数据转换为LogicFlow内部识别的数据结构
-        const lFData = toLogicflowData(demoData);
-        lf.value.render(lFData);
-      }
-
-      function catData() {
-        graphData.value = unref(lf).getGraphData();
-        openModal();
-      }
-
-      onMounted(() => {
-        initLf();
-      });
-
-      return {
-        lf,
-        graphData,
-        config,
-        nodeList,
-        catData,
-        register,
-        openModal,
-      };
+      return { demoData };
     },
   };
 </script>
-
-<style scoped>
-  #LF-Turbo {
-    width: 100vw;
-    height: 85%;
-    outline: none;
-  }
-
-  .logic-flow-view {
-    position: relative;
-    height: 100%;
-  }
-
-  .demo-title {
-    margin: 20px;
-    text-align: center;
-  }
-
-  .demo-control {
-    position: absolute;
-    top: 10px;
-    right: 20px;
-    z-index: 2;
-  }
-
-  .time-plus {
-    cursor: pointer;
-  }
-
-  .add-panel {
-    position: absolute;
-    z-index: 11;
-    padding: 10px 5px;
-    background-color: white;
-  }
-
-  .el-drawer__body {
-    z-index: 3;
-    height: 80%;
-    margin-top: -30px;
-    overflow: auto;
-  }
-</style>

+ 5 - 5
yarn.lock

@@ -7719,17 +7719,17 @@ rollup-plugin-terser@^7.0.0:
     serialize-javascript "^4.0.0"
     terser "^5.0.0"
 
-rollup-plugin-visualizer@5.3.6:
-  version "5.3.6"
-  resolved "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.3.6.tgz#df6317b242f4aa58b6a03261335dbc64ea6fe0df"
-  integrity sha512-USIyYkzRuvIJZyUoFWSvejy/c8F9jm9mHbyB+01oE7m0Vc0Ll67HlZgRsY59IqU/j/qF1adPsXKSDkEXS6tzfg==
+rollup-plugin-visualizer@5.3.4:
+  version "5.3.4"
+  resolved "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.3.4.tgz#216300acca6e31b139be92eed98280c5662a5818"
+  integrity sha512-n3wYwKrZ3nhYJj8apzFuxmiu4y+ygDNJYLqQCOxludg3Pnhkql9WYc8iupgsMI+jGREA0dFsfDlzDAKcmXZIMQ==
   dependencies:
     nanoid "^3.1.22"
     open "^7.4.2"
     source-map "^0.7.3"
     yargs "^16.2.0"
 
-rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0, rollup@^2.45.2:
+rollup@^2.25.0, rollup@^2.38.5, rollup@^2.44.0:
   version "2.45.2"
   resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48"
   integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==

Some files were not shown because too many files changed in this diff