import { useState, useEffect, useCallback } from "react" import { useReactTable, getCoreRowModel, flexRender, type ColumnDef, } from "@tanstack/react-table" import { Search, Pencil, Eye } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { fetchKnowledgeCards, updateKnowledgeCard } from "@/lib/api/knowledge-card-api" import type { KnowledgeCardItem, UpdateKnowledgeCardData } from "@/lib/api/knowledge-card-api" import { fetchCategories } from "@/lib/api/category-api" import type { Category } from "@/types/category" const BASIC_MAX = 100 const DEEP_MAX = 300 type CardStatus = "all" | "complete" | "incomplete" function getCardStatus(item: KnowledgeCardItem): "complete" | "incomplete" { return item.summary && item.summary.trim().length > 0 ? "complete" : "incomplete" } export default function KnowledgeCardsPage() { const [cards, setCards] = useState([]) const [categories, setCategories] = useState([]) const [loading, setLoading] = useState(true) const [search, setSearch] = useState("") const [statusFilter, setStatusFilter] = useState("all") // 编辑对话框 const [editOpen, setEditOpen] = useState(false) const [editingCard, setEditingCard] = useState(null) const [editForm, setEditForm] = useState({ summary: "", deepDive: "", sourceRef: "" }) const [submitting, setSubmitting] = useState(false) // 详情对话框 const [detailOpen, setDetailOpen] = useState(false) const [detailCard, setDetailCard] = useState(null) useEffect(() => { fetchCategories({}).then((res) => setCategories(res.data)) }, []) const loadCards = useCallback(async () => { setLoading(true) try { const res = await fetchKnowledgeCards({ search: search || undefined, status: statusFilter, }) setCards(res.data) } catch { setCards([]) } finally { setLoading(false) } }, [search, statusFilter]) useEffect(() => { loadCards() }, [loadCards]) function getCategoryName(categoryId: string): string { return categories.find((c) => c.id === categoryId)?.name ?? categoryId } function openEdit(card: KnowledgeCardItem) { setEditingCard(card) setEditForm({ summary: card.summary, deepDive: card.deepDive || "", sourceRef: card.sourceRef || "", }) setEditOpen(true) } function openDetail(card: KnowledgeCardItem) { setDetailCard(card) setDetailOpen(true) } async function handleSave() { if (!editingCard) return setSubmitting(true) try { await updateKnowledgeCard(editingCard.id, editForm) setEditOpen(false) await loadCards() } finally { setSubmitting(false) } } const columns: ColumnDef[] = [ { accessorKey: "questionStem", header: "关联题目", cell: ({ row }) => { const stem = row.original.questionStem return ( {stem.length > 60 ? stem.slice(0, 60) + "..." : stem} ) }, }, { accessorKey: "categoryId", header: "分类", cell: ({ row }) => ( {getCategoryName(row.original.categoryId)} ), }, { id: "basicStatus", header: "基础卡", cell: ({ row }) => { const hasBasic = row.original.summary?.trim().length > 0 return ( {hasBasic ? `${row.original.summary.length} 字` : "未填写"} ) }, }, { id: "deepStatus", header: "深度卡", cell: ({ row }) => { const hasDeep = (row.original.deepDive?.trim().length ?? 0) > 0 return ( {hasDeep ? `${row.original.deepDive!.length} 字` : "未填写"} ) }, }, { id: "completeness", header: "完成度", cell: ({ row }) => { const status = getCardStatus(row.original) return ( {status === "complete" ? "完整" : "待补充"} ) }, }, { accessorKey: "updatedAt", header: "更新时间", cell: ({ row }) => ( {new Date(row.original.updatedAt).toLocaleDateString("zh-CN")} ), }, { id: "actions", header: "操作", cell: ({ row }) => (
), }, ] const table = useReactTable({ data: cards, columns, getCoreRowModel: getCoreRowModel(), }) // 统计 const totalCards = cards.length const completeCards = cards.filter((c) => getCardStatus(c) === "complete").length return ( <>
{/* 页面头部 */}

知识卡管理

管理{totalCards} 张知识卡,{completeCards} 张已完成,{totalCards - completeCards} 张待补充

{/* 筛选栏 */}
setSearch(e.target.value)} />
{/* 表格 */}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ))} ))} {loading ? ( 加载中... ) : cards.length === 0 ? ( 暂无知识卡数据 ) : ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) )}
{/* 查看详情 */} 知识卡详情 {detailCard && (

{detailCard.questionStem}

所有用户

{detailCard.summary || 未填写}

{detailCard.deepDive && (
Pro 用户

{detailCard.deepDive}

)} {detailCard.sourceRef && (

{detailCard.sourceRef}

)}
)}
{/* 编辑对话框 */} 编辑知识卡 编辑知识卡内容。基础版所有用户可见,深度版仅 Pro 用户可见。
{editingCard && (

{editingCard.questionStem}

)}
BASIC_MAX ? "text-destructive font-medium" : "text-muted-foreground"}`}> {editForm.summary.length}/{BASIC_MAX}