使用openai进行了代码review

This commit is contained in:
2026-02-24 11:33:08 +08:00
parent 9efdf060f5
commit 0c97f02e51
32 changed files with 1499 additions and 969 deletions
+64 -54
View File
@@ -1,15 +1,28 @@
"use client";
"use client";
import { Page, useEditorStore } from "@/lib/store";
import { ChevronRight, FileText, Folder, FolderOpen, MoreHorizontal, Trash2, FilePlus, FolderPlus, Download, Upload } from "lucide-react";
import { cn } from "@/lib/utils";
import { useState } from "react";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { exportPageAsMarkdown, exportFolderAsZip } from "@/lib/export";
import { useRouter, usePathname } from "next/navigation";
import { useImport } from "@/components/import-context";
import { useSortable, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
ChevronRight,
FileText,
Folder,
FolderOpen,
MoreHorizontal,
Trash2,
FilePlus,
FolderPlus,
Download,
Upload,
} from "lucide-react";
import { Page, useEditorStore } from "@/lib/store";
import { cn } from "@/lib/utils";
import { exportPageAsMarkdown, exportFolderAsZip } from "@/lib/export";
import { useImport } from "@/components/import-context";
import { useConfirm } from "@/components/confirm-provider";
interface TreeViewProps {
pages: Page[];
@@ -17,33 +30,32 @@ interface TreeViewProps {
level?: number;
}
function TreeNode({ node, pages, level, expanded, toggleExpand }: {
node: Page,
pages: Page[],
level: number,
expanded: Record<string, boolean>,
toggleExpand: (id: string) => void
function TreeNode({
node,
pages,
level,
expanded,
toggleExpand,
}: {
node: Page;
pages: Page[];
level: number;
expanded: Record<string, boolean>;
toggleExpand: (id: string) => void;
}) {
const { activePageId, setActivePageId, addPage, deletePage } = useEditorStore();
const router = useRouter();
const pathname = usePathname();
const { triggerImport } = useImport();
const confirm = useConfirm();
const isFolder = node.type === 'folder';
const hasChildren = pages.some(p => p.parentId === node.id);
const isFolder = node.type === "folder";
const hasChildren = pages.some((p) => p.parentId === node.id);
const isExpanded = expanded[node.id];
// DnD Hooks - Sorting
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging,
} = useSortable({
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: node.id,
data: { type: node.type, title: node.title, parentId: node.parentId }
data: { type: node.type, title: node.title, parentId: node.parentId },
});
const style = {
@@ -60,17 +72,16 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
"group flex items-center justify-between px-2 py-1 text-sm rounded-md transition-colors cursor-pointer select-none border border-transparent",
activePageId === node.id
? "bg-accent text-accent-foreground font-medium"
: "text-muted-foreground hover:bg-muted/50 hover:text-foreground",
// Use simple hover effect for "drop over" visual or rely on drag overlay
: "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
)}
onClick={() => {
setActivePageId(node.id);
if (pathname !== '/') router.push('/');
if (pathname !== "/") router.push("/");
}}
>
<div className="flex items-center gap-1.5 flex-1 min-w-0">
<button
onPointerDown={(e) => e.stopPropagation()} // Prevent drag start on expand button
onPointerDown={(e) => e.stopPropagation()}
onClick={(e) => {
e.stopPropagation();
toggleExpand(node.id);
@@ -102,7 +113,7 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<button
onPointerDown={(e) => e.stopPropagation()} // Prevent drag
onPointerDown={(e) => e.stopPropagation()}
className="opacity-100 lg:opacity-0 lg:group-hover:opacity-100 p-1 hover:bg-muted-foreground/20 rounded text-muted-foreground transition-opacity"
>
<MoreHorizontal size={14} />
@@ -114,13 +125,10 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
className="flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent cursor-pointer outline-none"
onClick={(e) => {
e.stopPropagation();
const targetParentId = node.type === 'folder' ? node.id : node.parentId;
// If creating sibling (node.type !== 'folder'), insert after current node
// Note: Order might be float/int. We just increment for now.
// Ideally we'd find the mid-point, but simpler logic: just +1 and let sort handle basic "after"
const order = node.type === 'folder' ? undefined : (node.order || 0) + 1;
addPage(targetParentId, 'file', undefined, order);
if (node.type === 'folder') toggleExpand(node.id);
const targetParentId = node.type === "folder" ? node.id : node.parentId;
const order = node.type === "folder" ? undefined : (node.order || 0) + 1;
addPage(targetParentId, "file", undefined, order);
if (node.type === "folder") toggleExpand(node.id);
}}
>
<FilePlus size={14} />
@@ -130,10 +138,10 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
className="flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent cursor-pointer outline-none"
onClick={(e) => {
e.stopPropagation();
const targetParentId = node.type === 'folder' ? node.id : node.parentId;
const order = node.type === 'folder' ? undefined : (node.order || 0) + 1;
addPage(targetParentId, 'folder', undefined, order);
if (node.type === 'folder') toggleExpand(node.id);
const targetParentId = node.type === "folder" ? node.id : node.parentId;
const order = node.type === "folder" ? undefined : (node.order || 0) + 1;
addPage(targetParentId, "folder", undefined, order);
if (node.type === "folder") toggleExpand(node.id);
}}
>
<FolderPlus size={14} />
@@ -143,9 +151,9 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
className="flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent cursor-pointer outline-none"
onClick={(e) => {
e.stopPropagation();
const targetParentId = node.type === 'folder' ? node.id : node.parentId;
const targetParentId = node.type === "folder" ? node.id : node.parentId;
triggerImport(targetParentId);
if (node.type === 'folder') toggleExpand(node.id);
if (node.type === "folder") toggleExpand(node.id);
}}
>
<Upload size={14} />
@@ -155,7 +163,7 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
className="flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent cursor-pointer outline-none"
onClick={(e) => {
e.stopPropagation();
if (node.type === 'folder') {
if (node.type === "folder") {
exportFolderAsZip(node.id, pages, node.title);
} else {
exportPageAsMarkdown(node);
@@ -168,9 +176,16 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
<DropdownMenu.Separator className="h-px bg-muted my-1" />
<DropdownMenu.Item
className="flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-red-50 text-red-600 cursor-pointer outline-none"
onClick={(e) => {
onClick={async (e) => {
e.stopPropagation();
if (confirm("确定要删除吗?此操作无法撤销。")) {
const ok = await confirm({
title: "确认删除",
description: "此操作无法撤销。",
confirmText: "删除",
cancelText: "取消",
tone: "danger",
});
if (ok) {
deletePage(node.id);
}
}}
@@ -191,27 +206,22 @@ function TreeNode({ node, pages, level, expanded, toggleExpand }: {
}
export function TreeView({ pages, parentId, level = 0 }: TreeViewProps) {
// Sort nodes by order field
const nodes = pages
.filter(p => p.parentId === parentId)
.filter((p) => p.parentId === parentId)
.sort((a, b) => (a.order || 0) - (b.order || 0));
// Simple state for expansion
const [expanded, setExpanded] = useState<Record<string, boolean>>({});
const toggleExpand = (id: string) => {
setExpanded(prev => ({ ...prev, [id]: !prev[id] }));
setExpanded((prev) => ({ ...prev, [id]: !prev[id] }));
};
if (nodes.length === 0) return null;
return (
<SortableContext
items={nodes.map(n => n.id)}
strategy={verticalListSortingStrategy}
>
<SortableContext items={nodes.map((n) => n.id)} strategy={verticalListSortingStrategy}>
<div className="flex flex-col gap-0.5">
{nodes.map(node => (
{nodes.map((node) => (
<TreeNode
key={node.id}
node={node}