chore: init monorepo snapshot

This commit is contained in:
liaibo
2025-11-23 10:55:04 +08:00
commit c70ff52869
941 changed files with 246586 additions and 0 deletions
@@ -0,0 +1,88 @@
import { NextRequest, NextResponse } from "next/server";
import { createSupabaseServerClient } from "@/lib/supabase/server";
type CreateChildPayload = {
parentId: string | null;
title?: string;
blocks?: unknown;
};
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
const supabase = await createSupabaseServerClient();
const {
data: { user },
error: authError,
} = await supabase.auth.getUser();
if (authError || !user) {
return NextResponse.json(
{ message: "未登录无法创建页面" },
{ status: 401 },
);
}
const { parentId, title, blocks }: CreateChildPayload =
await request.json();
if (parentId === undefined) {
return NextResponse.json(
{ message: "缺少 parentId" },
{ status: 400 },
);
}
const siblingQuery = supabase
.from("documents")
.select("id", { count: "exact", head: true })
.eq("user_id", user.id);
if (parentId) {
siblingQuery.eq("parent_id", parentId);
} else {
siblingQuery.is("parent_id", null);
}
const { count: siblingCount = 0, error: countError } =
await siblingQuery;
if (countError) {
return NextResponse.json(
{ message: countError.message },
{ status: 500 },
);
}
const resolvedTitle =
title?.trim() && title.trim().length > 0
? title.trim()
: "未命名页面";
const contentPayload = Array.isArray(blocks) ? blocks : [];
const { data: newDoc, error } = await supabase
.from("documents")
.insert({
user_id: user.id,
parent_id: parentId,
title: resolvedTitle,
content: contentPayload,
sort_order: siblingCount,
})
.select("id, title")
.single();
if (error || !newDoc) {
return NextResponse.json(
{ message: error?.message ?? "创建子页面失败" },
{ status: 500 },
);
}
return NextResponse.json({
pageId: newDoc.id,
title: newDoc.title ?? resolvedTitle,
});
}
@@ -0,0 +1,59 @@
import { createReactBlockSpec } from "@blocknote/react";
import { RiFileTextFill } from "react-icons/ri";
import { useRouter } from "next/navigation";
import type { PropSchema } from "@blocknote/core";
type PageReferenceProps = PropSchema & {
pageId: { default: string };
title: { default: string };
};
const pageReferenceConfig = {
type: "pageReference" as const,
propSchema: {
pageId: { default: "" },
title: { default: "未命名页面" },
},
content: "none" as const,
};
export const pageReferenceBlock = createReactBlockSpec(
pageReferenceConfig,
() => ({
render: ({ block }) => {
const router = useRouter();
const { pageId, title } = block.props;
return (
<div
role="button"
tabIndex={0}
onClick={() => {
if (pageId) {
router.push(`/documents/${pageId}`);
}
}}
onKeyDown={(event) => {
if ((event.key === "Enter" || event.key === " ") && pageId) {
event.preventDefault();
router.push(`/documents/${pageId}`);
}
}}
className="group mt-2 flex items-center gap-3 rounded-[4px] px-4 py-3 text-[#2563eb] hover:bg-[#f5f5f5]"
style={{ fontFamily: "Inter, system-ui, sans-serif" }}
>
<RiFileTextFill className="text-xl" aria-hidden />
<span className="text-base font-medium leading-none">
{title || "未命名页面"}
</span>
<span className="ml-auto text-sm opacity-0 transition-opacity duration-150 group-hover:opacity-100">
</span>
</div>
);
},
}),
);
export const pageReferencePropSchema = pageReferenceConfig.propSchema;
+13
View File
@@ -0,0 +1,13 @@
import { defaultBlockSpecs, defaultStyleSpecs } from "@blocknote/core";
import { BlockNoteSchema } from "@blocknote/core/dist/blocks";
import { pageReferenceBlock } from "./blocks/PageReferenceBlock";
export const customBlockSchema = BlockNoteSchema.create({
blockSpecs: {
...defaultBlockSpecs,
pageReference: pageReferenceBlock,
},
});
export const customStyleSpecs = defaultStyleSpecs;