update
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-10-13 15:18:14 +08:00
parent 854b1f0769
commit 6f1720acd5
17 changed files with 248 additions and 184 deletions

View File

@@ -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>