fix(流程图编辑器): 换题草稿串题、第一步撤销不了、历史存的是改动前的状态
## 换题时画布不跟着换 storage key 是按题目 ID 算的 computed。`useStorage` 确实会 watch key,但它只把 新 key 的内容读进 `storedData`,**不会回填 `nodes`/`edges`**,而 `loadFromCache()` 只在 onMounted 调一次。于是同名路由换参数(题目 → 题目,组件不重新挂载)时, 画布上还留着上一题的图;学生一动,防抖保存就把上一题的内容写进**这一题的 key**, 把原本存着的草稿覆盖掉。 补一个 key 的 watch,重新载入并在载不到时清空画布。这里依赖 `useStorage` 内部 对 key 的 watch 先于本 watch 执行 —— 两者都是 pre flush,且 useStorage 在上方 先创建,pre 队列按创建顺序跑,此刻 `storedData` 已经是新 key 的数据。 实测(router.push 直接切题):修复前 1003 的画布上挂着 1002 的节点,修复后 1003 是空的、1002 的草稿完好。 **需要说明**:今天的 UI 走不到这条路 —— 题目页没有「下一题」入口,题单和比赛 切题都要先回列表页(不同路由、组件会重新挂载)。所以这条目前是加固,一旦以后 加了题内切题入口就立刻变成必需品。 ## 撤销少一步、存的还是旧状态 `historyIndex` 从 -1 开始,而 `canUndo` 要求 `index > 0`,第一步操作永远撤销 不了。补 `resetHistory`,挂载时和换题后各播一次初始快照(换题不重建的话,一次 撤销会把上一题的图还原到这一题里)。 `addEdges` / `removeNodes` / `removeEdges` 之后紧接着 `saveState(nodes.value, edges.value)` —— 而 vue-flow 的 store → v-model 回写走的是 `watchPausable` (pre flush,异步),此刻读到的还是**改动前**的数组,存进历史整体错开一步。 画布上的 `handleDrop` 早就 `await nextTick()` 了,这几处一直漏了; `clearCanvas` 因为是直接赋值 model ref(同步)反而是对的 —— 所以这套行为一直 是「有时对有时错」,更难排查。 顺带:`handleNodeDelete` 里手动删相连边是多余的,`removeNodes` 的 `removeConnectedEdges` 默认就是 true;`deleteSelected` 在什么都没选中时不再 白记一条历史。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5f0fe713dc
commit
5480abaaea
4 files changed
+55
-17
No files matched your search
@@ -38,7 +38,7 @@ const nodes = ref([]) as Ref<Node[]>
|
||||
const edges = ref([]) as Ref<Edge[]>
|
||||
|
||||
// 历史记录管理
|
||||
const { canUndo, canRedo, saveState, undo, redo } = useHistory()
|
||||
const { canUndo, canRedo, resetHistory, saveState, undo, redo } = useHistory()
|
||||
|
||||
const problemStore = useProblemStore()
|
||||
const { problem } = storeToRefs(problemStore)
|
||||
@@ -55,7 +55,11 @@ const {
|
||||
saveToCache,
|
||||
loadFromCache,
|
||||
clearCache,
|
||||
} = useCache(nodes, edges, cacheKey)
|
||||
} = useCache(nodes, edges, cacheKey, () => {
|
||||
// 换题后画布已经被换成新题的草稿,历史必须跟着重建,
|
||||
// 否则一次撤销就会把上一题的图还原到这一题里
|
||||
resetHistory(nodes.value, edges.value)
|
||||
})
|
||||
|
||||
// 拖拽处理
|
||||
const { onDragOver, onDragLeave, onDrop, isDragOver, screenDragPos } = useDnD()
|
||||
@@ -148,8 +152,10 @@ const handleKeyDown = (event: KeyboardEvent) => {
|
||||
onMounted(() => {
|
||||
document.addEventListener("keydown", handleKeyDown)
|
||||
|
||||
// 从缓存恢复数据
|
||||
// 从缓存恢复数据,并把当前画布作为历史起点,
|
||||
// 否则第一步操作没有可回退的目标,撤销按钮一直是灰的
|
||||
loadFromCache()
|
||||
resetHistory(nodes.value, edges.value)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
Reference in new issue
Block a user