Browse Source

perf: improve flowChart logic

Vben 4 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
     'font-size-base': '14px', //  Main font size
     'border-radius-base': '2px', //  Component/float fillet
     'border-radius-base': '2px', //  Component/float fillet
     'link-color': primary, //   Link color
     '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-base': '#303030',
         // 'border-color-split': '#30363d',
         // 'border-color-split': '#30363d',
         'item-active-bg': '#111b26',
         'item-active-bg': '#111b26',
+        'content-background': '#ffffff0a', //   Link color
       },
       },
     }),
     }),
   ];
   ];

+ 1 - 1
package.json

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

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

@@ -1,17 +1,10 @@
 import { App } from 'vue';
 import { App } from 'vue';
-import control from './src/Control.vue';
-import nodePanel from './src/NodePanel.vue';
 import dataDialog from './src/DataDialog.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) {
   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>
 <template>
-  <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="graphData" />
+  <vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" />
 </template>
 </template>
 
 
 <script lang="ts">
 <script lang="ts">
@@ -12,7 +12,7 @@
       VueJsonPretty,
       VueJsonPretty,
     },
     },
     props: {
     props: {
-      graphData: Object,
+      data: Object,
     },
     },
   });
   });
 </script>
 </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,
   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) {
 function convertFlowElementToEdge(element) {
   const { incoming, outgoing, properties, key } = element;
   const { incoming, outgoing, properties, key } = element;
   const { text, startPoint, endPoint, pointsList, logicFlowType } = properties;
   const { text, startPoint, endPoint, pointsList, logicFlowType } = properties;
@@ -139,8 +50,12 @@ function convertFlowElementToNode(element) {
   return node;
   return node;
 }
 }
 
 
-export function toLogicflowData(data) {
-  const lfData = {
+export function toLogicFlowData(data) {
+  const lfData: {
+    // TODO type
+    nodes: any[];
+    edges: any[];
+  } = {
     nodes: [],
     nodes: [],
     edges: [],
     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';
   @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 {
     &-form-container {
       padding: 16px;
       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/searchreplace';
 import 'tinymce/plugins/spellchecker';
 import 'tinymce/plugins/spellchecker';
 import 'tinymce/plugins/tabfocus';
 import 'tinymce/plugins/tabfocus';
-import 'tinymce/plugins/table';
+// import 'tinymce/plugins/table';
 import 'tinymce/plugins/template';
 import 'tinymce/plugins/template';
 import 'tinymce/plugins/textpattern';
 import 'tinymce/plugins/textpattern';
 import 'tinymce/plugins/visualblocks';
 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
 // colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration
 
 
 export const plugins = [
 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 = [
 export const toolbar = [
   'fontsizeselect lineheight searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample',
   '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 };
 export { tinymce };

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

@@ -35,5 +35,4 @@ export default {
 
 
   time: 'Relative Time',
   time: 'Relative Time',
   cropperImage: 'Cropper Image',
   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: '相对时间',
   time: '相对时间',
   cropperImage: '图片裁剪',
   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

@@ -123,13 +123,6 @@ const menu: MenuModule = {
           content: 'new',
           content: 'new',
         },
         },
       },
       },
-      {
-        path: 'flowChart',
-        name: t('routes.demo.comp.flowChart'),
-        tag: {
-          content: 'new',
-        },
-      },
       {
       {
         path: 'countTo',
         path: 'countTo',
         name: t('routes.demo.comp.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'),
         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',
       path: 'timestamp',
       name: 'TimeDemo',
       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>
 <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>
 </template>
 
 
 <script lang="ts">
 <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 demoData from './dataTurbo.json';
-
-  import { BasicModal, useModal } from '/@/components/Modal';
   export default {
   export default {
-    components: { NodePanel, Control, DataDialog, BasicModal },
+    components: { FlowChart, PageWrapper },
     setup() {
     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>
 </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"
     serialize-javascript "^4.0.0"
     terser "^5.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:
   dependencies:
     nanoid "^3.1.22"
     nanoid "^3.1.22"
     open "^7.4.2"
     open "^7.4.2"
     source-map "^0.7.3"
     source-map "^0.7.3"
     yargs "^16.2.0"
     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"
   version "2.45.2"
   resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48"
   resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48"
   integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==
   integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ==

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