feat: 初版
knowledge-base / deploy (push) Failing after 11s

This commit is contained in:
2026-06-23 19:09:11 +08:00
commit 73b9c9fb7a
61 changed files with 9549 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
"use client"
import { Star, Code2, Repeat } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { cn } from "@/lib/utils"
import type { KnowledgeItem } from "@/lib/types"
import { DIFFICULTY_META, MASTERY_META } from "@/lib/types"
export function KnowledgeCard({
item,
onOpen,
onToggleFav,
onTagClick,
}: {
item: KnowledgeItem
onOpen: () => void
onToggleFav: () => void
onTagClick: (tag: string) => void
}) {
const diff = DIFFICULTY_META[item.difficulty]
const mastery = MASTERY_META[item.mastery]
return (
<article
onClick={onOpen}
className="group flex cursor-pointer flex-col rounded-xl border border-border bg-card/70 p-4 backdrop-blur-sm transition-colors hover:border-primary/40 hover:bg-card"
>
<div className="flex items-start justify-between gap-2">
<div className="flex items-center gap-2">
<Badge variant="outline" className="font-mono text-[10px] uppercase tracking-wide">
{item.category}
</Badge>
<span
className={cn("inline-flex items-center gap-1 rounded-md border px-2 py-0.5 text-[10px]", mastery.color)}
>
<span className={cn("size-1.5 rounded-full", mastery.dot)} />
{mastery.label}
</span>
</div>
<button
onClick={(e) => {
e.stopPropagation()
onToggleFav()
}}
className="text-muted-foreground transition-colors hover:text-amber-400"
aria-label={item.is_favorite ? "取消收藏" : "收藏"}
>
<Star className={cn("size-4", item.is_favorite && "fill-amber-400 text-amber-400")} />
</button>
</div>
<h3 className="mt-3 text-pretty font-semibold leading-snug group-hover:text-primary">{item.title}</h3>
{item.summary && (
<p className="flex-1 mt-1.5 line-clamp-2 text-sm leading-relaxed text-muted-foreground">{item.summary}</p>
)}
{item.tags.length > 0 && (
<div className="mt-3 flex flex-wrap gap-1.5">
{item.tags.slice(0, 4).map((t) => (
<button
key={t}
onClick={(e) => {
e.stopPropagation()
onTagClick(t)
}}
>
<Badge variant="secondary" className="font-mono text-[10px]">
#{t}
</Badge>
</button>
))}
</div>
)}
<div className="mt-4 flex items-center justify-between border-t border-border/60 pt-3 text-xs text-muted-foreground">
<span className={cn("rounded-md border px-1.5 py-0.5", diff.color)}>{diff.label}</span>
<div className="flex items-center gap-3 font-mono">
{item.code_snippet && <Code2 className="size-3.5" />}
<span className="inline-flex items-center gap-1">
<Repeat className="size-3.5" />
{item.review_count}
</span>
</div>
</div>
</article>
)
}