首次发布git
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
|
||||
export interface Page {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
parentId: string | null;
|
||||
type: "file" | "folder";
|
||||
children?: Page[]; // For tree view structures (virtual field)
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
icon?: string | null;
|
||||
tags?: string[];
|
||||
order?: number;
|
||||
isLocked?: boolean;
|
||||
}
|
||||
|
||||
interface EditorState {
|
||||
pages: Page[];
|
||||
activePageId: string | null;
|
||||
isLoading: boolean;
|
||||
|
||||
// Actions
|
||||
fetchPages: () => Promise<void>;
|
||||
setActivePageId: (id: string | null) => void;
|
||||
addPage: (parentId?: string | null, type?: "file" | "folder", initialData?: { title: string, content: string }, order?: number) => Promise<void>;
|
||||
updatePage: (id: string, data: Partial<Page>) => Promise<void>;
|
||||
deletePage: (id: string) => Promise<void>;
|
||||
movePage: (id: string, parentId: string | null) => Promise<void>;
|
||||
reorderPages: (data: { id: string, order: number }[]) => Promise<void>;
|
||||
}
|
||||
|
||||
export const useEditorStore = create<EditorState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
pages: [],
|
||||
activePageId: null,
|
||||
isLoading: false,
|
||||
|
||||
fetchPages: async () => {
|
||||
set({ isLoading: true });
|
||||
try {
|
||||
const res = await fetch("/api/pages");
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
set({ pages: data });
|
||||
// If no active page, maybe select the first one? Or leave null.
|
||||
// Persistence will handle restoring activePageId if it exists.
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to fetch pages", e);
|
||||
} finally {
|
||||
set({ isLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
setActivePageId: (id) => set({ activePageId: id }),
|
||||
|
||||
addPage: async (parentId = null, type = "file", initialData, order) => {
|
||||
try {
|
||||
const res = await fetch("/api/pages", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
title: initialData?.title || "无标题",
|
||||
content: initialData?.content || "",
|
||||
tags: [],
|
||||
parentId,
|
||||
type,
|
||||
order
|
||||
}),
|
||||
});
|
||||
if (res.ok) {
|
||||
const newPage = await res.json();
|
||||
set((state) => ({
|
||||
pages: [newPage, ...state.pages],
|
||||
activePageId: newPage.id // Auto select new page
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to create page", e);
|
||||
}
|
||||
},
|
||||
|
||||
updatePage: async (id, data) => {
|
||||
// Optimistic update
|
||||
set((state) => ({
|
||||
pages: state.pages.map((p) => (p.id === id ? { ...p, ...data, updatedAt: new Date().toISOString() } : p)),
|
||||
}));
|
||||
|
||||
// Debounce logic could be added here, but for now direct call
|
||||
try {
|
||||
await fetch(`/api/pages/${id}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to update page", e);
|
||||
}
|
||||
},
|
||||
|
||||
movePage: async (id, parentId) => {
|
||||
// Reuse updatePage logic
|
||||
await get().updatePage(id, { parentId });
|
||||
},
|
||||
|
||||
deletePage: async (id) => {
|
||||
// Optimistic delete
|
||||
const currentActive = get().activePageId;
|
||||
set((state) => ({
|
||||
pages: state.pages.filter((p) => p.id !== id),
|
||||
activePageId: currentActive === id ? null : currentActive
|
||||
}));
|
||||
|
||||
try {
|
||||
await fetch(`/api/pages/${id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to delete page", e);
|
||||
// Rollback could be added here
|
||||
}
|
||||
},
|
||||
|
||||
reorderPages: async (updates) => {
|
||||
// Optimistic update
|
||||
set((state) => {
|
||||
const newPages = [...state.pages];
|
||||
updates.forEach(({ id, order }) => {
|
||||
const page = newPages.find(p => p.id === id);
|
||||
if (page) page.order = order;
|
||||
});
|
||||
// Re-sort locally? Or just trust UI to sort based on updated order property
|
||||
// It's safer if 'pages' remains the master list
|
||||
return { pages: newPages };
|
||||
});
|
||||
|
||||
try {
|
||||
await fetch("/api/pages/reorder", {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ updates }),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to reorder pages", e);
|
||||
}
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "editor-storage",
|
||||
partialize: (state) => ({ activePageId: state.activePageId }),
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user