refactor: 适配新工作流预览 由logicflow改为iframe 真服了
This commit is contained in:
parent
2141c93399
commit
8d6ef40d3e
@ -27,7 +27,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "^7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
"@logicflow/core": "^2.0.13",
|
|
||||||
"@tinymce/tinymce-vue": "^6.0.1",
|
"@tinymce/tinymce-vue": "^6.0.1",
|
||||||
"@vben/access": "workspace:*",
|
"@vben/access": "workspace:*",
|
||||||
"@vben/common-ui": "workspace:*",
|
"@vben/common-ui": "workspace:*",
|
||||||
|
@ -94,7 +94,7 @@ export function pageByCurrent(params?: PageQuery) {
|
|||||||
*/
|
*/
|
||||||
export function flowInfo(businessId: string) {
|
export function flowInfo(businessId: string) {
|
||||||
return requestClient.get<FlowInfoResponse>(
|
return requestClient.get<FlowInfoResponse>(
|
||||||
`/workflow/instance/flowImage/${businessId}`,
|
`/workflow/instance/flowHisTaskList/${businessId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,6 @@ export interface Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface FlowInfoResponse {
|
export interface FlowInfoResponse {
|
||||||
image: string;
|
instanceId: string;
|
||||||
list: Flow[];
|
list: Flow[];
|
||||||
defChart: {
|
|
||||||
defJson: Record<string, any>;
|
|
||||||
nodeJsonList: Record<string, any>[];
|
|
||||||
skipJsonList: Record<string, any>[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ import {
|
|||||||
import { renderDict } from '#/utils/render';
|
import { renderDict } from '#/utils/render';
|
||||||
|
|
||||||
import { approvalModal, approvalRejectionModal, flowInterfereModal } from '.';
|
import { approvalModal, approvalRejectionModal, flowInterfereModal } from '.';
|
||||||
import FlowPreview from '../components/flow-preview/index.vue';
|
|
||||||
import ApprovalDetails from './approval-details.vue';
|
import ApprovalDetails from './approval-details.vue';
|
||||||
|
import FlowPreview from './flow-preview.vue';
|
||||||
import { approveWithReasonModal } from './helper';
|
import { approveWithReasonModal } from './helper';
|
||||||
import userSelectModal from './user-select-modal.vue';
|
import userSelectModal from './user-select-modal.vue';
|
||||||
|
|
||||||
@ -443,10 +443,7 @@ async function handleCopy(text: string) {
|
|||||||
/>
|
/>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane key="2" tab="审批流程图">
|
<TabPane key="2" tab="审批流程图">
|
||||||
<FlowPreview
|
<FlowPreview :instance-id="currentFlowInfo.instanceId" />
|
||||||
v-if="currentFlowInfo.defChart"
|
|
||||||
:data="currentFlowInfo.defChart.defJson"
|
|
||||||
/>
|
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
28
apps/web-antd/src/views/workflow/components/flow-preview.vue
Normal file
28
apps/web-antd/src/views/workflow/components/flow-preview.vue
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { stringify } from '@vben/request';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
|
defineOptions({ name: 'FlowPreview' });
|
||||||
|
|
||||||
|
const props = defineProps<{ instanceId: string }>();
|
||||||
|
|
||||||
|
const { clientId } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
|
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
const params = {
|
||||||
|
Authorization: `Bearer ${accessStore.accessToken}`,
|
||||||
|
id: props.instanceId,
|
||||||
|
clientid: clientId,
|
||||||
|
type: 'FlowChart',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iframe地址
|
||||||
|
*/
|
||||||
|
const url = `${import.meta.env.VITE_GLOB_API_URL}/warm-flow-ui/index.html?${stringify(params)}`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<iframe :src="url" class="h-[500px] w-full border"></iframe>
|
||||||
|
</template>
|
@ -1,121 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { ZoomParamType } from '@logicflow/core';
|
|
||||||
|
|
||||||
import { onMounted, shallowRef, useTemplateRef, watch } from 'vue';
|
|
||||||
|
|
||||||
import { usePreferences } from '@vben/preferences';
|
|
||||||
|
|
||||||
import {
|
|
||||||
MinusCircleOutlined,
|
|
||||||
PlusCircleOutlined,
|
|
||||||
ShrinkOutlined,
|
|
||||||
} from '@ant-design/icons-vue';
|
|
||||||
import LogicFlow from '@logicflow/core';
|
|
||||||
|
|
||||||
import Between from './model/between';
|
|
||||||
import End from './model/end';
|
|
||||||
import Parallel from './model/parallel';
|
|
||||||
import Serial from './model/serial';
|
|
||||||
import Skip from './model/skip';
|
|
||||||
import Start from './model/start';
|
|
||||||
import { json2LogicFlowJson } from './model/tool';
|
|
||||||
|
|
||||||
import '@logicflow/core/lib/style/index.css';
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{ data?: object }>(), {
|
|
||||||
data: () => ({}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const container = useTemplateRef('container');
|
|
||||||
const lf = shallowRef<LogicFlow | null>(null);
|
|
||||||
|
|
||||||
function zoomViewport(zoom: ZoomParamType) {
|
|
||||||
if (!lf.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lf.value.zoom(zoom);
|
|
||||||
// 将内容平移至画布中心
|
|
||||||
lf.value.translateCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (props.data && container.value) {
|
|
||||||
const data = json2LogicFlowJson(props.data);
|
|
||||||
lf.value = new LogicFlow({
|
|
||||||
container: container.value,
|
|
||||||
isSilentMode: true,
|
|
||||||
textEdit: false,
|
|
||||||
grid: {
|
|
||||||
size: 20,
|
|
||||||
type: 'dot',
|
|
||||||
config: {
|
|
||||||
color: '#ccc',
|
|
||||||
thickness: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
lf.value.register(Start);
|
|
||||||
lf.value.register(Between);
|
|
||||||
lf.value.register(Serial);
|
|
||||||
lf.value.register(Parallel);
|
|
||||||
lf.value.register(End);
|
|
||||||
lf.value.register(Skip);
|
|
||||||
|
|
||||||
lf.value.render(data);
|
|
||||||
lf.value.translateCenter();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const { isDark } = usePreferences();
|
|
||||||
watch(isDark, (v) => {
|
|
||||||
if (!lf.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lf.value.graphModel.background = {
|
|
||||||
background: v ? '#333' : '#fff',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="flex items-center justify-between py-2">
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<a-button @click="zoomViewport(1)">
|
|
||||||
<template #icon>
|
|
||||||
<ShrinkOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
<a-button @click="zoomViewport(true)">
|
|
||||||
<template #icon>
|
|
||||||
<PlusCircleOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
<a-button @click="zoomViewport(false)">
|
|
||||||
<template #icon>
|
|
||||||
<MinusCircleOutlined />
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-3 font-semibold">
|
|
||||||
<span class="rounded-md border border-[#000] px-2">未办理</span>
|
|
||||||
<span
|
|
||||||
class="rounded-md border border-dashed border-[#ffcd17] bg-[#fff8dc] px-2 dark:text-black"
|
|
||||||
>
|
|
||||||
待办理
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="rounded-md border border-[#9dff00] bg-[#f0ffd9] px-2 dark:text-black"
|
|
||||||
>
|
|
||||||
已完成
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 容器区域 -->
|
|
||||||
<div class="h-[500px] w-full border" ref="container"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,21 +0,0 @@
|
|||||||
import LogicFlow, { RectNode, RectNodeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class BetweenModel extends RectNodeModel {
|
|
||||||
override getNodeStyle() {
|
|
||||||
return super.getNodeStyle();
|
|
||||||
}
|
|
||||||
override initNodeData(data: LogicFlow.NodeConfig) {
|
|
||||||
super.initNodeData(data);
|
|
||||||
this.width = 100;
|
|
||||||
this.height = 80;
|
|
||||||
this.radius = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BetweenView extends RectNode {}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'between',
|
|
||||||
model: BetweenModel,
|
|
||||||
view: BetweenView,
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
import LogicFlow, { CircleNode, CircleNodeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class endModel extends CircleNodeModel {
|
|
||||||
override initNodeData(data: LogicFlow.NodeConfig) {
|
|
||||||
super.initNodeData(data);
|
|
||||||
this.r = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class endView extends CircleNode {}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'end',
|
|
||||||
model: endModel,
|
|
||||||
view: endView,
|
|
||||||
};
|
|
@ -1,59 +0,0 @@
|
|||||||
import type { GraphModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
import LogicFlow, { h, PolygonNode, PolygonNodeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class ParallelModel extends PolygonNodeModel {
|
|
||||||
static extendKey = 'ParallelModel';
|
|
||||||
|
|
||||||
constructor(data: LogicFlow.NodeConfig, graphModel: GraphModel) {
|
|
||||||
if (!data.text) {
|
|
||||||
data.text = '';
|
|
||||||
}
|
|
||||||
if (data.text && typeof data.text === 'string') {
|
|
||||||
data.text = {
|
|
||||||
value: data.text,
|
|
||||||
x: data.x,
|
|
||||||
y: data.y + 40,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
super(data, graphModel);
|
|
||||||
this.points = [
|
|
||||||
[25, 0],
|
|
||||||
[50, 25],
|
|
||||||
[25, 50],
|
|
||||||
[0, 25],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ParallelView extends PolygonNode {
|
|
||||||
static extendKey = 'ParallelNode';
|
|
||||||
|
|
||||||
override getShape() {
|
|
||||||
const { model } = this.props;
|
|
||||||
const { x, y, width, height, points } = model;
|
|
||||||
const style = model.getNodeStyle();
|
|
||||||
return h(
|
|
||||||
'g',
|
|
||||||
{
|
|
||||||
transform: `matrix(1 0 0 1 ${x - width / 2} ${y - height / 2})`,
|
|
||||||
},
|
|
||||||
h('polygon', {
|
|
||||||
...style,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
points,
|
|
||||||
}),
|
|
||||||
h('path', {
|
|
||||||
d: 'm 23,10 0,12.5 -12.5,0 0,5 12.5,0 0,12.5 5,0 0,-12.5 12.5,0 0,-5 -12.5,0 0,-12.5 -5,0 z',
|
|
||||||
...style,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'parallel',
|
|
||||||
view: ParallelView,
|
|
||||||
model: ParallelModel,
|
|
||||||
};
|
|
@ -1,59 +0,0 @@
|
|||||||
import type { GraphModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
import LogicFlow, { h, PolygonNode, PolygonNodeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class SerialModel extends PolygonNodeModel {
|
|
||||||
static extendKey = 'SerialModel';
|
|
||||||
|
|
||||||
constructor(data: LogicFlow.NodeConfig, graphModel: GraphModel) {
|
|
||||||
if (!data.text) {
|
|
||||||
data.text = '';
|
|
||||||
}
|
|
||||||
if (data.text && typeof data.text === 'string') {
|
|
||||||
data.text = {
|
|
||||||
value: data.text,
|
|
||||||
x: data.x,
|
|
||||||
y: data.y + 40,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
super(data, graphModel);
|
|
||||||
this.points = [
|
|
||||||
[25, 0],
|
|
||||||
[50, 25],
|
|
||||||
[25, 50],
|
|
||||||
[0, 25],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SerialView extends PolygonNode {
|
|
||||||
static extendKey = 'SerialNode';
|
|
||||||
|
|
||||||
override getShape() {
|
|
||||||
const { model } = this.props;
|
|
||||||
const { x, y, width, height, points } = model;
|
|
||||||
const style = model.getNodeStyle();
|
|
||||||
return h(
|
|
||||||
'g',
|
|
||||||
{
|
|
||||||
transform: `matrix(1 0 0 1 ${x - width / 2} ${y - height / 2})`,
|
|
||||||
},
|
|
||||||
h('polygon', {
|
|
||||||
...style,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
points,
|
|
||||||
}),
|
|
||||||
h('path', {
|
|
||||||
d: 'm 16,15 7.42857142857143,9.714285714285715 -7.42857142857143,9.714285714285715 3.428571428571429,0 5.714285714285715,-7.464228571428572 5.714285714285715,7.464228571428572 3.428571428571429,0 -7.42857142857143,-9.714285714285715 7.42857142857143,-9.714285714285715 -3.428571428571429,0 -5.714285714285715,7.464228571428572 -5.714285714285715,-7.464228571428572 -3.428571428571429,0 z',
|
|
||||||
...style,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'serial',
|
|
||||||
view: SerialView,
|
|
||||||
model: SerialModel,
|
|
||||||
};
|
|
@ -1,32 +0,0 @@
|
|||||||
import { PolylineEdge, PolylineEdgeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class SkipModel extends PolylineEdgeModel {
|
|
||||||
/**
|
|
||||||
* 重写此方法,使保存数据是能带上锚点数据。
|
|
||||||
*/
|
|
||||||
override getData() {
|
|
||||||
const data = super.getData();
|
|
||||||
data.sourceAnchorId = this.sourceAnchorId;
|
|
||||||
data.targetAnchorId = this.targetAnchorId;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
override getEdgeStyle() {
|
|
||||||
const style = super.getEdgeStyle();
|
|
||||||
const { properties } = this;
|
|
||||||
if (properties.isActived) {
|
|
||||||
style.strokeDasharray = '4 4';
|
|
||||||
}
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
override setAttributes() {
|
|
||||||
this.offset = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'skip',
|
|
||||||
view: PolylineEdge,
|
|
||||||
model: SkipModel,
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
import LogicFlow, { CircleNode, CircleNodeModel } from '@logicflow/core';
|
|
||||||
|
|
||||||
class StartModel extends CircleNodeModel {
|
|
||||||
override initNodeData(data: LogicFlow.NodeConfig) {
|
|
||||||
super.initNodeData(data);
|
|
||||||
this.r = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StartView extends CircleNode {}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
type: 'start',
|
|
||||||
model: StartModel,
|
|
||||||
view: StartView,
|
|
||||||
};
|
|
@ -1,248 +0,0 @@
|
|||||||
/* eslint-disable unicorn/no-array-reduce */
|
|
||||||
const NODE_TYPE_MAP = {
|
|
||||||
0: 'start',
|
|
||||||
1: 'between',
|
|
||||||
2: 'end',
|
|
||||||
3: 'serial',
|
|
||||||
4: 'parallel',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将warm-flow的定义json数据转成LogicFlow支持的数据格式
|
|
||||||
* @param {*} json
|
|
||||||
* @returns LogicFlow的数据
|
|
||||||
*/
|
|
||||||
export const json2LogicFlowJson = (definition: any) => {
|
|
||||||
const graphData: any = {
|
|
||||||
nodes: [],
|
|
||||||
edges: [],
|
|
||||||
};
|
|
||||||
// 解析definition属性
|
|
||||||
graphData.flowCode = definition.flowCode;
|
|
||||||
graphData.flowName = definition.flowName;
|
|
||||||
graphData.version = definition.version;
|
|
||||||
graphData.fromCustom = definition.fromCustom;
|
|
||||||
graphData.fromPath = definition.fromPath;
|
|
||||||
// 解析节点
|
|
||||||
const allSkips = definition.nodeList.reduce((acc: any, node: any) => {
|
|
||||||
if (node.skipList && Array.isArray(node.skipList)) {
|
|
||||||
acc.push(...node.skipList);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
const allNodes = definition.nodeList;
|
|
||||||
// 解析节点
|
|
||||||
if (allNodes.length > 0) {
|
|
||||||
for (let i = 0, len = allNodes.length; i < len; i++) {
|
|
||||||
const node = allNodes[i];
|
|
||||||
const lfNode: any = {
|
|
||||||
text: {},
|
|
||||||
properties: {},
|
|
||||||
};
|
|
||||||
// 处理节点
|
|
||||||
lfNode.type = (NODE_TYPE_MAP as any)[node.nodeType];
|
|
||||||
lfNode.id = node.nodeCode;
|
|
||||||
const coordinate = node.coordinate;
|
|
||||||
if (coordinate) {
|
|
||||||
const attr = coordinate.split('|');
|
|
||||||
const nodeXy = attr[0].split(',');
|
|
||||||
lfNode.x = Number.parseInt(nodeXy[0]);
|
|
||||||
lfNode.y = Number.parseInt(nodeXy[1]);
|
|
||||||
if (attr.length === 2) {
|
|
||||||
const textXy = attr[1].split(',');
|
|
||||||
lfNode.text.x = Number.parseInt(textXy[0]);
|
|
||||||
lfNode.text.y = Number.parseInt(textXy[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lfNode.text.value = node.nodeName;
|
|
||||||
lfNode.properties.nodeRatio = node.nodeRatio.toString();
|
|
||||||
lfNode.properties.permissionFlag = node.permissionFlag;
|
|
||||||
lfNode.properties.anyNodeSkip = node.anyNodeSkip;
|
|
||||||
lfNode.properties.listenerType = node.listenerType;
|
|
||||||
lfNode.properties.listenerPath = node.listenerPath;
|
|
||||||
lfNode.properties.formCustom = node.formCustom;
|
|
||||||
lfNode.properties.formPath = node.formPath;
|
|
||||||
lfNode.properties.ext = {};
|
|
||||||
if (node.ext && typeof node.ext === 'string') {
|
|
||||||
try {
|
|
||||||
node.ext = JSON.parse(node.ext);
|
|
||||||
node.ext.forEach((e: any) => {
|
|
||||||
lfNode.properties.ext[e.code] = String(e.value).includes(',')
|
|
||||||
? e.value.split(',')
|
|
||||||
: String(e.value);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error parsing JSON:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lfNode.properties.style = {};
|
|
||||||
if (node.status === 2) {
|
|
||||||
lfNode.properties.style.fill = '#F0FFD9';
|
|
||||||
lfNode.properties.style.stroke = '#9DFF00';
|
|
||||||
}
|
|
||||||
if (node.status === 1) {
|
|
||||||
lfNode.properties.style.fill = '#FFF8DC';
|
|
||||||
lfNode.properties.style.stroke = '#FFCD17';
|
|
||||||
}
|
|
||||||
graphData.nodes.push(lfNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allSkips.length > 0) {
|
|
||||||
// 处理边
|
|
||||||
let skipEle = null;
|
|
||||||
let edge: any = {};
|
|
||||||
for (let j = 0, lenn = allSkips.length; j < lenn; j++) {
|
|
||||||
skipEle = allSkips[j];
|
|
||||||
edge = {
|
|
||||||
text: {},
|
|
||||||
properties: {},
|
|
||||||
};
|
|
||||||
edge.id = skipEle.id;
|
|
||||||
edge.type = 'skip';
|
|
||||||
edge.sourceNodeId = skipEle.nowNodeCode;
|
|
||||||
edge.targetNodeId = skipEle.nextNodeCode;
|
|
||||||
edge.text = { value: skipEle.skipName };
|
|
||||||
edge.properties.skipCondition = skipEle.skipCondition;
|
|
||||||
edge.properties.skipName = skipEle.skipName;
|
|
||||||
edge.properties.skipType = skipEle.skipType;
|
|
||||||
const expr = skipEle.expr;
|
|
||||||
if (expr) {
|
|
||||||
edge.properties.expr = skipEle.expr;
|
|
||||||
}
|
|
||||||
const coordinate = skipEle.coordinate;
|
|
||||||
if (coordinate) {
|
|
||||||
const coordinateXy = coordinate.split('|');
|
|
||||||
edge.pointsList = [];
|
|
||||||
coordinateXy[0].split(';').forEach((item: any) => {
|
|
||||||
const pointArr = item.split(',');
|
|
||||||
edge.pointsList.push({
|
|
||||||
x: Number.parseInt(pointArr[0]),
|
|
||||||
y: Number.parseInt(pointArr[1]),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
edge.startPoint = edge.pointsList[0];
|
|
||||||
edge.endPoint = edge.pointsList[edge.pointsList.length - 1];
|
|
||||||
if (coordinateXy.length > 1) {
|
|
||||||
const textXy = coordinateXy[1].split(',');
|
|
||||||
edge.text.x = Number.parseInt(textXy[0]);
|
|
||||||
edge.text.y = Number.parseInt(textXy[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
graphData.edges.push(edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(graphData);
|
|
||||||
return graphData;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将LogicFlow的数据转成warm-flow的json定义文件
|
|
||||||
* @param {*} data(...definitionInfo,nodes,edges)
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const logicFlowJsonToWarmFlow = (data: any) => {
|
|
||||||
// 先构建成流程对象
|
|
||||||
const definition: any = {
|
|
||||||
nodeList: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据节点的类型值,获取key
|
|
||||||
* @param {*} mapValue 节点类型映射
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const getNodeTypeValue = (mapValue: any) => {
|
|
||||||
for (const key in NODE_TYPE_MAP) {
|
|
||||||
if ((NODE_TYPE_MAP as any)[key] === mapValue) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 根据节点的编码,获取节点的类型
|
|
||||||
* @param {*} nodeCode 当前节点名称
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const getNodeType = (nodeCode: any) => {
|
|
||||||
for (const node of definition.nodeList) {
|
|
||||||
if (nodeCode === node.nodeCode) {
|
|
||||||
return node.nodeType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 拼接skip坐标
|
|
||||||
* @param {*} edge logicFlow的edge
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const getCoordinate = (edge: any) => {
|
|
||||||
let coordinate = '';
|
|
||||||
for (let i = 0; i < edge.pointsList.length; i++) {
|
|
||||||
coordinate = `${
|
|
||||||
coordinate + Number.parseInt(edge.pointsList[i].x)
|
|
||||||
},${Number.parseInt(edge.pointsList[i].y)}`;
|
|
||||||
if (i !== edge.pointsList.length - 1) {
|
|
||||||
coordinate = `${coordinate};`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (edge.text) {
|
|
||||||
coordinate = `${coordinate}|${Number.parseInt(edge.text.x)},${Number.parseInt(edge.text.y)}`;
|
|
||||||
}
|
|
||||||
return coordinate;
|
|
||||||
};
|
|
||||||
// 流程定义
|
|
||||||
definition.id = data.id;
|
|
||||||
definition.flowCode = data.flowCode;
|
|
||||||
definition.flowName = data.flowName;
|
|
||||||
definition.version = data.version;
|
|
||||||
definition.fromCustom = data.fromCustom;
|
|
||||||
definition.fromPath = data.fromPath;
|
|
||||||
// 流程节点
|
|
||||||
data.nodes.forEach((anyNode: any) => {
|
|
||||||
const node: any = {};
|
|
||||||
node.nodeType = getNodeTypeValue(anyNode.type);
|
|
||||||
node.nodeCode = anyNode.id;
|
|
||||||
if (anyNode.text) {
|
|
||||||
node.nodeName = anyNode.text.value;
|
|
||||||
}
|
|
||||||
node.permissionFlag = anyNode.properties.permissionFlag;
|
|
||||||
node.nodeRatio = anyNode.properties.nodeRatio;
|
|
||||||
node.anyNodeSkip = anyNode.properties.anyNodeSkip;
|
|
||||||
node.listenerType = anyNode.properties.listenerType;
|
|
||||||
node.listenerPath = anyNode.properties.listenerPath;
|
|
||||||
node.formCustom = anyNode.properties.formCustom;
|
|
||||||
node.formPath = anyNode.properties.formPath;
|
|
||||||
node.ext = [];
|
|
||||||
for (const key in anyNode.properties.ext) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(anyNode.properties.ext, key)) {
|
|
||||||
const e = anyNode.properties.ext[key];
|
|
||||||
node.ext.push({ code: key, value: Array.isArray(e) ? e.join(',') : e });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.ext = JSON.stringify(node.ext);
|
|
||||||
node.coordinate = `${anyNode.x},${anyNode.y}`;
|
|
||||||
if (anyNode.text && anyNode.text.x && anyNode.text.y) {
|
|
||||||
node.coordinate = `${node.coordinate}|${anyNode.text.x},${anyNode.text.y}`;
|
|
||||||
}
|
|
||||||
node.handlerType = anyNode.properties.handlerType;
|
|
||||||
node.handlerPath = anyNode.properties.handlerPath;
|
|
||||||
node.version = definition.version;
|
|
||||||
node.skipList = [];
|
|
||||||
data.edges.forEach((anyEdge: any) => {
|
|
||||||
if (anyEdge.sourceNodeId === anyNode.id) {
|
|
||||||
const skip: any = {};
|
|
||||||
skip.skipType = anyEdge.properties.skipType;
|
|
||||||
skip.skipCondition = anyEdge.properties.skipCondition;
|
|
||||||
skip.skipName = anyEdge?.text?.value || anyEdge.properties.skipName;
|
|
||||||
skip.nowNodeCode = anyEdge.sourceNodeId;
|
|
||||||
skip.nowNodeType = getNodeType(skip.nowNodeCode);
|
|
||||||
skip.nextNodeCode = anyEdge.targetNodeId;
|
|
||||||
skip.nextNodeType = getNodeType(skip.nextNodeCode);
|
|
||||||
skip.coordinate = getCoordinate(anyEdge);
|
|
||||||
node.skipList.push(skip);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
definition.nodeList.push(node);
|
|
||||||
});
|
|
||||||
return JSON.stringify(definition);
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user