import {
|
defineComponent,
|
SetupContext,
|
onMounted,
|
reactive,
|
ref,
|
computed,
|
provide,
|
} from 'vue'
|
import styles from './G6Flow.module.scss'
|
import {
|
fittingString,
|
getFlowDataToXml,
|
getJsonByXml,
|
getLogicFLowStruct,
|
generateFlowXml,
|
} from './core/transformHelp'
|
import { getFlowXml, getFlowData, saveFlowData } from '@/api/logic-flow'
|
import G6Renderer from './components/Renderer/Renderer'
|
import Canvas from './components/Canvas/Canvas'
|
import { createStore, resetStore } from './core/store'
|
import { FlowType } from './type'
|
import Tools from './components/Tools/Tools'
|
import { cloneDeep, uniqBy } from 'lodash'
|
import { v4 as uuidv4 } from 'uuid'
|
import NodeDrawer from './components/NodeDrawer/NodeDrawer'
|
import EdgeDrawer from './components/EdgeDrawer/EdgeDrawer'
|
import { nodeFontSize } from './components/Nodes'
|
import { ConditionType } from './core/enum'
|
import { ElMessage } from 'element-plus'
|
import { baseStore } from './core/store'
|
import { _t } from '@/libs/Language/Language'
|
|
interface NodeDrawerConfig {
|
visible: boolean
|
title: string
|
model: Record<string, any>
|
}
|
export default defineComponent({
|
name: 'G6Flow',
|
props: {
|
flowType: {
|
type: [String, Number],
|
default: '',
|
},
|
height: {
|
type: [String, Number],
|
default: 750,
|
},
|
isEdit: {
|
type: Boolean,
|
default: false,
|
},
|
flowName: {
|
type: String,
|
},
|
},
|
setup(props, { slots, attrs, expose }: SetupContext) {
|
const {
|
graphEvent,
|
selected,
|
flowBaseConfig,
|
edgeMap,
|
nodeMap,
|
flowConfig,
|
} = createStore()
|
const graphData = ref<FlowType | null>(null)
|
const g6RenderRef = ref<any>()
|
const selectedEdgeToolType = ref<string>('')
|
|
const isEdit = computed(() => {
|
return props.isEdit
|
})
|
const nodeData = ref<Record<string, any>[]>([])
|
const edgeData = ref<Record<string, any>[]>([])
|
const nodeItem = ref<Record<string, any> | null>(null)
|
const nodeDrawerConfig = reactive<NodeDrawerConfig>({
|
visible: false,
|
title: _t('节点配置'),
|
model: {},
|
})
|
provide('flowType', props.flowType)
|
|
const sortNodeDataUniq = (Activities: any[]) => {
|
const data = Activities.sort(
|
(a: { sort: number }, b: { sort: number }) => {
|
return a.sort - b.sort
|
}
|
)
|
return uniqBy(data, 'type')
|
}
|
const initData = async () => {
|
selected.value = null
|
graphData.value = null
|
resetStore()
|
const res = await getFlowXml(props.flowType)
|
const json = getJsonByXml(res.content, props.flowName)
|
flowConfig.type = res.type
|
flowConfig.version = res.version
|
flowBaseConfig.value = {
|
type: res.type,
|
version: flowConfig.version,
|
name: props.flowName,
|
}
|
graphData.value = getLogicFLowStruct(json)
|
|
const data = await Promise.all([
|
getFlowData('Activities'),
|
getFlowData('Transitions'),
|
])
|
|
const Activities = sortNodeDataUniq(data[0].Activities)
|
const Transitions = sortNodeDataUniq(data[1].Transitions)
|
nodeData.value = Activities
|
edgeData.value = Transitions
|
// edgeMap
|
Transitions.forEach((transition) => {
|
edgeMap.set(transition.type, transition)
|
})
|
// nodeMap
|
Activities.forEach((activity) => {
|
nodeMap.set(activity.type, activity)
|
})
|
}
|
|
const onAutoLayout = () => {
|
g6RenderRef.value?.autoLayout()
|
}
|
|
const onDrop = (event: DragEvent) => {
|
if (nodeItem.value) {
|
g6RenderRef.value?.addNode(nodeItem.value, {
|
x: event.x,
|
y: event.y,
|
})
|
}
|
}
|
|
const onDragstart = (node: Event) => {
|
nodeItem.value = node
|
}
|
|
const onToolsEdgeClick = (type: string) => {
|
selectedEdgeToolType.value = type
|
}
|
|
const onCopy = (model: any, isShow: any) => {
|
if (g6RenderRef.value) {
|
const { flowMap, flowNodeMap } = baseStore
|
const graph = g6RenderRef.value.getGraph()
|
const newModel = cloneDeep(model)
|
const label =
|
newModel.properties.Name +
|
'_' +
|
parseInt(String(Math.random() * 10000))
|
newModel.id = uuidv4()
|
newModel.x = model.x + 10
|
newModel.y = model.y + 10
|
newModel.name = label
|
newModel.properties = {
|
...newModel.properties,
|
Name: label,
|
label: label,
|
name: label,
|
oldId: label,
|
}
|
newModel.label = fittingString(label, 195, nodeFontSize + 2)
|
flowMap.set(label, newModel)
|
flowNodeMap.set(newModel.id, newModel)
|
graph?.addItem('node', newModel)
|
}
|
isShow.value = false
|
}
|
|
const onDelete = (model: any, isShow: any) => {
|
if (g6RenderRef.value) {
|
const graph = g6RenderRef.value.getGraph()
|
const item = graph?.findById(model.id)
|
graph?.removeItem(item)
|
}
|
isShow.value = false
|
}
|
|
const onViewDialog = (model: any, isShow: any) => {
|
nodeDrawerConfig.visible = true
|
nodeDrawerConfig.model = model
|
isShow.value = false
|
}
|
|
const clear = () => {
|
nodeDrawerConfig.model = {}
|
graphEvent.clearAllState()
|
graphSave(true)
|
}
|
|
const graphSave = async (isTemp: boolean = false) => {
|
const graph = g6RenderRef.value.getGraph()
|
const xml = generateFlowXml(graph)
|
const data = {
|
...flowConfig,
|
content: xml,
|
version: flowConfig.version || 1,
|
}
|
await saveFlowData(data, isTemp)
|
!isTemp && ElMessage.success(_t('保存成功'))
|
}
|
|
expose({ graphSave })
|
onMounted(initData)
|
|
return () => {
|
if (!graphData.value) return <el-empty description={_t('暂无数据')} />
|
const Drawer = graphEvent.type.value === 'edge' ? EdgeDrawer : NodeDrawer
|
const contextMenu = computed<any[]>(() => {
|
const menu: any[] = [
|
{
|
type: 'view',
|
label: _t('查看属性'),
|
fn: onViewDialog,
|
divided: true,
|
disabled: false,
|
icon: 'viewProps',
|
},
|
]
|
if (isEdit.value) {
|
if (graphEvent.type.value === 'node') {
|
menu.push({
|
label: _t('复制'),
|
fn: onCopy,
|
divided: true,
|
icon: 'copy',
|
type: 'copy',
|
})
|
}
|
menu.push({
|
label: _t('删除'),
|
fn: onDelete,
|
type: 'del',
|
divided: true,
|
disabled: false,
|
icon: 'delete-menu',
|
})
|
}
|
return menu
|
})
|
return (
|
<div class={styles.logicFlow}>
|
{isEdit.value ? (
|
<Tools
|
nodeData={nodeData.value}
|
edgeData={edgeData.value}
|
onDragstart={onDragstart}
|
onEdgeClick={onToolsEdgeClick}
|
/>
|
) : null}
|
|
<Drawer
|
title={nodeDrawerConfig.title}
|
v-model={nodeDrawerConfig.visible}
|
isEdit={isEdit.value}
|
model={
|
nodeDrawerConfig.visible ? nodeDrawerConfig.model : undefined
|
}
|
onConfirm={clear}
|
onClose={clear}
|
graph={g6RenderRef.value?.getGraph()}
|
type={graphEvent.type.value}
|
edgeData={edgeData.value}
|
></Drawer>
|
<Canvas
|
onDrop={onDrop}
|
grid={{ visible: true }}
|
minimap={true}
|
height={props.height}
|
>
|
<G6Renderer
|
ref={g6RenderRef}
|
graphData={graphData.value}
|
drag-node={isEdit.value}
|
click-select={isEdit.value}
|
editing={isEdit.value}
|
zoom-canvas
|
drag-canvas
|
edgeType={!!selectedEdgeToolType.value}
|
create-edge={!!selectedEdgeToolType.value}
|
edgeContextMenu={contextMenu.value}
|
flowName={props.flowName}
|
contextMenu={[...contextMenu.value]}
|
></G6Renderer>
|
</Canvas>
|
</div>
|
)
|
}
|
},
|
})
|