// ---- selectionSlice ---- // // 拥有 selectedId / openTabIds / keyword + 选择/标签页/搜索关键词相关 action。 // cross-slice 依赖: closeTab 调用 pythonEditorSlice.exitPythonEditor + // editSessionSlice.endEditing + helpers.sessionCache; // switchTab 触发 pythonEditorSlice.savePythonEditor + helpers.applyEditSessionState // (恢复缓存中的 editSession); // openPublishDialog 委托 uiStore。 import type { StateCreator } from "zustand"; import type { ScriptItem } from "~/services/api"; import { applyEditSessionState, bumpEditorOpenRequest, getSelectedId, sessionCache, setSelectedId, } from "./helpers"; import { useUiStore } from "./uiStore"; import type { SelectionSliceActions, SelectionSliceState, } from "./types"; import type { ScriptWorkspaceStore } from "./useScriptWorkspaceStore"; export const createSelectionSlice: StateCreator< ScriptWorkspaceStore, [], [], SelectionSliceState & SelectionSliceActions > = (set, get) => { const initial: SelectionSliceState = { selectedId: null, openTabIds: [], keyword: "", }; return { ...initial, setKeyword: (keyword) => set({ keyword }), selectScript: (id) => { setSelectedId(id); set({ selectedId: id }); }, openTab: (id) => { const current = getSelectedId(); if (current !== id) { bumpEditorOpenRequest(); set({ editorOpenError: null }); } setSelectedId(id); set((state) => ({ selectedId: id, openTabIds: state.openTabIds.includes(id) ? state.openTabIds : [...state.openTabIds, id], })); }, closeTab: async (id, event) => { event?.stopPropagation(); const buffer = get().pythonEditorBuffers[id]; if (buffer?.dirty && !buffer.saving) { const name = get().scripts.find((s) => s.script_id === id)?.script_name ?? "该脚本"; const ok = window.confirm(`当前脚本有未保存修改,确定关闭 "${name}" 吗?`); if (!ok) return; } if (buffer) { get().exitPythonEditor(id); } const editSession = get().editSession; if (editSession?.script_id === id) { await get().endEditing(false, false); } sessionCache.delete(id); set((state) => { const index = state.openTabIds.indexOf(id); if (index === -1) return {}; const newTabs = state.openTabIds.filter((tabId) => tabId !== id); let nextSelected = state.selectedId; if (state.selectedId === id) { const nextId = newTabs[index] ?? newTabs[index - 1] ?? null; setSelectedId(nextId); nextSelected = nextId; } return { openTabIds: newTabs, selectedId: nextSelected }; }); }, switchTab: (id) => { const current = get().selectedId; if (current && current !== id) { const curBuffer = get().pythonEditorBuffers[current]; if (curBuffer?.dirty && !curBuffer.saving) { void get().savePythonEditor(current); } } const selected = getSelectedId(); if (selected !== id) { bumpEditorOpenRequest(); set({ editorOpenError: null }); } setSelectedId(id); set({ selectedId: id }); const cached = sessionCache.get(id); if (cached) { cached.lastActiveTime = Date.now(); // set 来自 StateCreator, 接受 Partial。 // applyEditSessionState 接受更窄的 partial;通过函数协变兼容。 applyEditSessionState( (p) => set(p), cached.session, cached.jupyterUrl, ); } }, openPublishDialog: (script: ScriptItem) => { useUiStore.getState().openPublishDialog(script); }, }; };