@@ -1,10 +1,16 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, onMounted, onUnmounted } from "vue"
|
||||
import Toolbar from "./Toolbar.vue"
|
||||
import "@vue-flow/core/dist/style.css"
|
||||
import "@vue-flow/core/dist/theme-default.css"
|
||||
import "@vue-flow/controls/dist/style.css"
|
||||
import { useVueFlow, VueFlow, type Node, type Edge, MarkerType } from "@vue-flow/core"
|
||||
import {
|
||||
useVueFlow,
|
||||
VueFlow,
|
||||
type Node,
|
||||
type Edge,
|
||||
MarkerType,
|
||||
} from "@vue-flow/core"
|
||||
import { Controls } from "@vue-flow/controls"
|
||||
import { Background } from "@vue-flow/background"
|
||||
|
||||
@@ -13,6 +19,15 @@ import { useHistory } from "./useHistory"
|
||||
import { useFlowOperations } from "./useFlowOperations"
|
||||
import { useCache } from "./useCache"
|
||||
import CustomNode from "./CustomNode.vue"
|
||||
import { useProblemStore } from "oj/store/problem"
|
||||
|
||||
interface Props {
|
||||
readonly?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
readonly: false,
|
||||
})
|
||||
|
||||
// Vue Flow 实例
|
||||
const { addNodes, addEdges, removeNodes, removeEdges } = useVueFlow()
|
||||
@@ -24,15 +39,20 @@ const edges = ref<Edge[]>([])
|
||||
// 历史记录管理
|
||||
const { canUndo, canRedo, saveState, undo, redo } = useHistory()
|
||||
|
||||
const problemStore = useProblemStore()
|
||||
const { problem } = storeToRefs(problemStore)
|
||||
// 缓存管理
|
||||
const { isSaving, lastSaved, hasUnsavedChanges, saveToCache, loadFromCache, clearCache } = useCache(
|
||||
nodes,
|
||||
edges,
|
||||
'flowchart-editor-data'
|
||||
)
|
||||
const { isSaving, lastSaved, hasUnsavedChanges, loadFromCache, clearCache } =
|
||||
useCache(
|
||||
nodes,
|
||||
edges,
|
||||
problem.value?._id
|
||||
? `flowchart-editor-data-problem-${problem.value!._id}`
|
||||
: "flowchart-editor-data",
|
||||
)
|
||||
|
||||
// 拖拽处理
|
||||
const { isDragOver, onDragOver, onDragLeave, onDrop } = useDnD()
|
||||
const { onDragOver, onDragLeave, onDrop } = useDnD()
|
||||
|
||||
// 流程操作
|
||||
const {
|
||||
@@ -41,7 +61,7 @@ const {
|
||||
handleNodeDelete,
|
||||
handleNodeUpdate,
|
||||
clearCanvas,
|
||||
deleteSelected
|
||||
deleteSelected,
|
||||
} = useFlowOperations(
|
||||
nodes,
|
||||
edges,
|
||||
@@ -49,7 +69,7 @@ const {
|
||||
addEdges,
|
||||
removeNodes,
|
||||
removeEdges,
|
||||
saveState
|
||||
saveState,
|
||||
)
|
||||
|
||||
// 拖拽处理包装
|
||||
@@ -96,15 +116,15 @@ const handleClear = () => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.target instanceof HTMLInputElement) return
|
||||
|
||||
if (event.key === 'Delete' || event.key === 'Backspace') {
|
||||
if (event.key === "Delete" || event.key === "Backspace") {
|
||||
deleteSelected()
|
||||
}
|
||||
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
if (event.key === 'z' && !event.shiftKey) {
|
||||
if (event.key === "z" && !event.shiftKey) {
|
||||
event.preventDefault()
|
||||
handleUndo()
|
||||
} else if (event.key === 'z' && event.shiftKey) {
|
||||
} else if (event.key === "z" && event.shiftKey) {
|
||||
event.preventDefault()
|
||||
handleRedo()
|
||||
}
|
||||
@@ -112,32 +132,32 @@ const handleKeyDown = (event: KeyboardEvent) => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown)
|
||||
|
||||
// 从缓存恢复数据
|
||||
loadFromCache()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
document.removeEventListener("keydown", handleKeyDown)
|
||||
})
|
||||
|
||||
// 加载外部数据到编辑器
|
||||
const setFlowchartData = (data: { nodes: Node[], edges: Edge[] }) => {
|
||||
const setFlowchartData = (data: { nodes: Node[]; edges: Edge[] }) => {
|
||||
if (data && data.nodes && data.edges) {
|
||||
// 确保节点数据包含必要的位置信息
|
||||
const processedNodes = data.nodes.map(node => ({
|
||||
const processedNodes = data.nodes.map((node) => ({
|
||||
...node,
|
||||
position: node.position || { x: 0, y: 0 }
|
||||
position: node.position || { x: 0, y: 0 },
|
||||
}))
|
||||
|
||||
|
||||
// 确保边数据包含必要的 handle 信息
|
||||
const processedEdges = data.edges.map(edge => ({
|
||||
const processedEdges = data.edges.map((edge) => ({
|
||||
...edge,
|
||||
sourceHandle: edge.sourceHandle || null,
|
||||
targetHandle: edge.targetHandle || null
|
||||
targetHandle: edge.targetHandle || null,
|
||||
}))
|
||||
|
||||
|
||||
nodes.value = processedNodes
|
||||
edges.value = processedEdges
|
||||
saveState(nodes.value, edges.value)
|
||||
@@ -150,9 +170,9 @@ defineExpose({
|
||||
edges,
|
||||
getFlowchartData: () => ({
|
||||
nodes: nodes.value,
|
||||
edges: edges.value
|
||||
edges: edges.value,
|
||||
}),
|
||||
setFlowchartData
|
||||
setFlowchartData,
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -166,13 +186,14 @@ defineExpose({
|
||||
@drop="handleDrop"
|
||||
@connect="handleConnect"
|
||||
@edge-click="handleEdgeClick"
|
||||
:readonly="readonly"
|
||||
:default-edge-options="{
|
||||
type: 'step',
|
||||
style: {
|
||||
stroke: '#6366f1',
|
||||
strokeWidth: 2.5,
|
||||
style: {
|
||||
stroke: '#6366f1',
|
||||
strokeWidth: 2.5,
|
||||
cursor: 'pointer',
|
||||
filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))'
|
||||
filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))',
|
||||
},
|
||||
markerEnd: {
|
||||
type: MarkerType.ArrowClosed,
|
||||
@@ -204,7 +225,12 @@ defineExpose({
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth"
|
||||
>
|
||||
<path d="M0,0 L0,6 L10,3 z" fill="#6366f1" stroke="#6366f1" strokeWidth="0.5" />
|
||||
<path
|
||||
d="M0,0 L0,6 L10,3 z"
|
||||
fill="#6366f1"
|
||||
stroke="#6366f1"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
</marker>
|
||||
</defs>
|
||||
<template #node-custom="{ data, id, type }">
|
||||
@@ -220,6 +246,8 @@ defineExpose({
|
||||
<Background variant="lines" :gap="20" :size="1" />
|
||||
<Controls />
|
||||
<Toolbar
|
||||
v-if="!readonly"
|
||||
r
|
||||
:can-undo="canUndo"
|
||||
:can-redo="canRedo"
|
||||
:is-saving="isSaving"
|
||||
@@ -241,4 +269,3 @@ defineExpose({
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user