双向删除同步
This commit is contained in:
@@ -1,40 +1,31 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { DocumentRecord, DocumentNode } from "@/lib/documents";
|
||||
import type { SidebarSectionId, TrashRecord } from "@/components/sidebar/types";
|
||||
import type { Database } from "@/types/supabase";
|
||||
import type { MediaAsset } from "@/types/media";
|
||||
import { buildDocumentTree } from "@/lib/documents";
|
||||
|
||||
type TypedClient = SupabaseClient<Database>;
|
||||
|
||||
export interface SidebarSectionSnapshot {
|
||||
id: SidebarSectionId;
|
||||
title: string;
|
||||
icon?: string;
|
||||
nodes: DocumentNode[];
|
||||
export interface SidebarDataset {
|
||||
documents: DocumentRecord[];
|
||||
trashedDocuments: TrashRecord[];
|
||||
/**
|
||||
* 仅依据远端 mindmap_data 判定的页面 id 列表;本地文件检测由服务器侧辅助完成
|
||||
*/
|
||||
mindmapDocs: string[];
|
||||
mediaAssets?: MediaAsset[];
|
||||
}
|
||||
|
||||
export interface FlattenedTreeNode {
|
||||
node: DocumentNode;
|
||||
depth: number;
|
||||
parentId: string | null;
|
||||
}
|
||||
|
||||
const SECTION_META: Record<SidebarSectionId, { title: string; icon: string }> = {
|
||||
starred: { title: "星标置顶", icon: "star" },
|
||||
public: { title: "公共页面", icon: "globe" },
|
||||
shared: { title: "共享页面", icon: "users" },
|
||||
private: { title: "私有 / 我的页面", icon: "lock" },
|
||||
templates: { title: "模板中心", icon: "grid" },
|
||||
};
|
||||
|
||||
export async function fetchSidebarDataset(
|
||||
client: TypedClient,
|
||||
workspaceId: string,
|
||||
): Promise<{ documents: DocumentRecord[]; trashedDocuments: TrashRecord[] }> {
|
||||
): Promise<SidebarDataset> {
|
||||
const { data: documentRows, error } = await client
|
||||
.from("documents")
|
||||
.select(
|
||||
"id,title,parent_id,sort_order,is_starred,access_scope,is_template,created_at,updated_at,workspace_id",
|
||||
"id,title,parent_id,sort_order,is_starred,access_scope,is_template,created_at,updated_at,workspace_id,mindmap_data",
|
||||
)
|
||||
.eq("workspace_id", workspaceId)
|
||||
.is("deleted_at", null)
|
||||
@@ -78,9 +69,26 @@ export async function fetchSidebarDataset(
|
||||
access_scope: (row.access_scope ?? "private") as DocumentRecord["access_scope"],
|
||||
}));
|
||||
|
||||
const mindmapDocs =
|
||||
documentRows?.filter((row) => row.mindmap_data != null).map((row) => row.id) ?? [];
|
||||
|
||||
const { data: assetRows, error: assetError } = await client
|
||||
.from("media_assets")
|
||||
.select("*")
|
||||
.eq("workspace_id", workspaceId)
|
||||
.order("created_at", { ascending: false });
|
||||
|
||||
if (assetError) {
|
||||
throw new Error(`获取附件列表失败:${assetError.message}`);
|
||||
}
|
||||
|
||||
const mediaAssets: MediaAsset[] = (assetRows ?? []) as MediaAsset[];
|
||||
|
||||
return {
|
||||
documents,
|
||||
trashedDocuments,
|
||||
mindmapDocs,
|
||||
mediaAssets,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -107,8 +115,8 @@ export function flattenDocumentTree(
|
||||
expanded: Set<string>,
|
||||
depth = 0,
|
||||
parentId: string | null = null,
|
||||
): FlattenedTreeNode[] {
|
||||
const list: FlattenedTreeNode[] = [];
|
||||
): Array<{ node: DocumentNode; depth: number; parentId: string | null }> {
|
||||
const list: Array<{ node: DocumentNode; depth: number; parentId: string | null }> = [];
|
||||
nodes.forEach((node) => {
|
||||
list.push({ node, depth, parentId });
|
||||
if (node.children.length > 0 && expanded.has(node.id)) {
|
||||
@@ -118,12 +126,29 @@ export function flattenDocumentTree(
|
||||
return list;
|
||||
}
|
||||
|
||||
const SECTION_META: Record<SidebarSectionId, { title: string; icon: string }> = {
|
||||
starred: { title: "星标置顶", icon: "star" },
|
||||
public: { title: "公共页面", icon: "globe" },
|
||||
shared: { title: "共享页面", icon: "users" },
|
||||
private: { title: "私有 / 我的页面", icon: "lock" },
|
||||
templates: { title: "模板中心", icon: "grid" },
|
||||
};
|
||||
|
||||
type SidebarSectionSnapshot = {
|
||||
id: SidebarSectionId;
|
||||
title: string;
|
||||
icon?: string;
|
||||
nodes: DocumentNode[];
|
||||
};
|
||||
|
||||
export function buildSidebarSections(records: DocumentRecord[]): SidebarSectionSnapshot[] {
|
||||
const tree = buildDocumentTree(records);
|
||||
return buildSidebarSectionsFromTree(tree);
|
||||
}
|
||||
|
||||
export function buildSidebarSectionsFromTree(tree: DocumentNode[]): SidebarSectionSnapshot[] {
|
||||
export function buildSidebarSectionsFromTree(
|
||||
tree: DocumentNode[],
|
||||
): SidebarSectionSnapshot[] {
|
||||
const sections: Array<{ id: SidebarSectionId; predicate: NodePredicate }> = [
|
||||
{ id: "starred", predicate: (node) => Boolean(node.is_starred) },
|
||||
{ id: "public", predicate: (node) => node.access_scope === "public" },
|
||||
|
||||
Reference in New Issue
Block a user