| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <template>
- <div class="flow-container">
- <el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" fullscreen>
- <template #header>
- <div style="color: #fff">
- <span>{{ props.title }}</span>
- </div>
- </template>
- <div class="f-content">
- <div class="f-container">
- <div class="f-switch">
- <el-switch v-model="state.value2" @change="change" class="mb-2" active-text="打开框选" inactive-text="关闭框选" />
- </div>
- <PanelControl v-if="lf" :lf="lf" @catData="getData"></PanelControl>
- <div class="f-container-c" ref="container" id="container"></div>
- <PanelNode v-if="lf" :lf="lf"></PanelNode>
- <el-drawer title="属性" v-model="drawer" :direction="direction" size="500px" :before-close="handleClose">
- <PropertyDialog v-if="drawer" :nodeData="state.nodeData" :lf="lf" @setPropertiesFinish="handleClose"></PropertyDialog>
- </el-drawer>
- <el-dialog
- title="数据"
- v-model="dataVisible"
- width="50%">
- <PanelDataDialog :graphData="state.graphData"></PanelDataDialog>
- </el-dialog>
- </div>
- </div>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="cancel">取 消</el-button>
- <el-button type="primary" @click="submit">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { reactive, ref, nextTick } from 'vue';
- import LogicFlow from '@logicflow/core';
- import '@logicflow/core/dist/style/index.css';
- import { BpmnElement, InsertNodeInPolyline, Menu, MiniMap, SelectionSelect, Snapshot } from '@logicflow/extension';
- import '@logicflow/extension/lib/style/index.css';
- import { ElMessageBox } from 'element-plus';
- import RegisterEdge from './LogicFlow/Register/RegisterEdge';
- import RegisterNode from './LogicFlow/Register/RegisterNode';
- import PanelNode from './LogicFlow/Panel/PanelNode.vue';
- import PanelControl from './LogicFlow/Panel/PanelControl.vue';
- import PanelDataDialog from './LogicFlow/Panel/PanelDataDialog.vue';
- import PropertyDialog from './LogicFlow/Property/PropertyDialog.vue';
- // 接口
- import { getAPI } from '/@/utils/axios-utils';
- import { ApprovalFlowApi } from '/@/api-services/api';
- import { ApprovalFlowOutput, UpdateApprovalFlowInput } from '/@/api-services/models';
- var props = defineProps({
- title: {
- type: String,
- default: '',
- },
- });
- const emit = defineEmits(['reloadTable', 'updateFlow']);
- const flowData = ref({});
- const lf = ref<InstanceType<typeof LogicFlow>>();
- const drawer = ref(false);
- const direction = ref('rtl');
- const dataVisible = ref(false);
- const state = reactive({
- loading: false,
- isShowDialog: false,
- ruleSource: {} as UpdateApprovalFlowInput,
- nodeData: {},
- graphData: {},
- });
- const openDialog = (row: ApprovalFlowOutput) => {
- state.ruleSource = row as UpdateApprovalFlowInput;
- // 初始化数据
- if (state.ruleSource.flowJson) {
- flowData.value = JSON.parse(state.ruleSource.flowJson);
- } else {
- flowData.value = {
- nodes: [],
- edges: [],
- };
- }
- state.isShowDialog = true;
- nextTick(() => {
- // 初始化画布
- initGraph();
- });
- console.log('open');
- };
- const closeDialog = () => {
- emit('reloadTable');
- state.isShowDialog = false;
- console.log('close');
- };
- const cancel = () => {
- state.isShowDialog = false;
- console.log('cancel');
- };
- // 保存流程设计
- const submit = async () => {
- flowData.value = lf.value?.getGraphData();
- state.ruleSource.flowJson = JSON.stringify(flowData.value);
- await getAPI(ApprovalFlowApi).apiApprovalFlowUpdatePost(state.ruleSource);
- emit('updateFlow', flowData.value);
- closeDialog();
- };
- const initGraph = () => {
- // 初始化画布
- const container: HTMLElement = document.querySelector('#container')!;
- // 配置项
- const config = {
- stopScrollGraph: true, // 禁止鼠标滚动移动画布
- stopZoomGraph: true, // 禁止缩放
- metaKeyMultipleSelected: true,
- // 背景网格大小
- grid: {
- size: 10,
- type: 'dot',
- },
- // 快捷键
- keyboard: {
- enabled: true,
- },
- // 辅助线
- snapline: true,
- };
- lf.value = new LogicFlow({
- ...config,
- plugins: [
- BpmnElement,
- // 作栋节点自动插入边
- InsertNodeInPolyline,
- // 右键菜单
- Menu,
- // 迷你图
- MiniMap,
- // 框选
- SelectionSelect,
- // 快照
- Snapshot
- ],
- container: container,
- width: container.clientWidth,
- height: container.clientHeight,
- });
- // 设置主题
- lf.value.setTheme({
- snapline: {
- stroke: '#1E90FF', // 对齐线颜色
- strokeWidth: 1, // 对齐线宽度
- },
- });
- // 注册自定义节点
- RegisterNode.Register(lf.value);
- // 注册自定义边
- RegisterEdge.Register(lf.value);
- // 监听节点点击事件
- lf.value.on('node:click', ({ data }) => {
- state.nodeData = data;
- drawer.value = true;
- });
- // 监听边点击事件
- lf.value.on('edge:click', ({ data }) => {
- state.nodeData = data;
- drawer.value = true;
- });
- // 渲染数据
- lf.value.render(flowData.value);
- // 画布居中
- lf.value.focusOn({ coordinate: { x: 300, y: 300 } });
- };
- // 框选
- const change = (val: boolean) => {
- if (val) {
- lf.value?.extension.selectionSelect.openSelectionSelect();
- } else {
- lf.value?.extension.selectionSelect.closeSelectionSelect();
- }
- };
- // 获取数据
- const getData = () => {
- var data = lf.value?.getGraphData();
- state.graphData = data;
- dataVisible.value = true;
- };
- // 关闭属性界面提醒
- const handleClose = (done: () => void) => {
- ElMessageBox.confirm('确认要关闭当前属性编辑?')
- .then(() => {
- done();
- })
- .catch(() => {
- // catch error
- });
- };
- defineExpose({ openDialog });
- </script>
- <style scoped lang="scss">
- :deep(.el-tabs__nav-scroll) {
- width: 70%;
- margin: 0 auto;
- }
- .flow-container {
- :deep(.el-dialog) {
- .el-dialog__header {
- display: none !important;
- }
- .el-dialog__body {
- max-height: calc(100vh - 45px) !important;
- }
- }
- }
- .f-content {
- display: flex;
- flex-grow: 1;
- z-index: 1;
- margin: -2px -19px -20px -19px;
- height: calc(100vh - 100px) !important;
- .f-container {
- flex-grow: 1;
- position: relative;
- .f-switch {
- position: absolute;
- z-index: 2;
- top: -22px;
- left: 5px;
- .el-switch {
- margin-right: 10px;
- }
- }
- .el-drawer {
- height: 80%;
- overflow: auto;
- margin-top: -30px;
- z-index: !important;
- }
- .f-container-c {
- position: absolute;
- width: 100%;
- height: 100%;
- }
- }
- }
- </style>
|