"use client" import { memo } from "react" import { Handle, Position, type NodeProps } from "@xyflow/react" import { useTranslations } from "next-intl" import { cn } from "@/shared/lib/utils" import type { GraphNodeData, MasteryLevel } from "../types" import type { GraphLayoutNodeData } from "../graph-layout" import { NODE_WIDTH } from "../graph-layout" /** 根据掌握度计算色彩等级 */ function getMasteryLevel(mastery: number | null): MasteryLevel { if (mastery === null) return "unassessed" if (mastery < 60) return "low" if (mastery < 85) return "medium" return "high" } const MASTERY_COLORS: Record = { low: "border-red-500 bg-red-50 dark:bg-red-950/30", medium: "border-yellow-500 bg-yellow-50 dark:bg-yellow-950/30", high: "border-green-500 bg-green-50 dark:bg-green-950/30", unassessed: "border-border bg-card", } const MASTERY_BAR_COLORS: Record = { low: "bg-red-500", medium: "bg-yellow-500", high: "bg-green-500", unassessed: "bg-muted", } function GraphKpNodeComponent({ data, selected }: NodeProps) { const t = useTranslations("textbooks") const nodeData = data as unknown as GraphLayoutNodeData const { kp } = nodeData const graphData = (data as unknown as { graphData?: GraphNodeData }).graphData const mastery = graphData?.mastery ?? null const masteryLevel = getMasteryLevel(mastery?.masteryLevel ?? null) const showMastery = graphData?.viewMode === "student-mastery" || graphData?.viewMode === "class-mastery" return (
{kp.name} {/* 任意值 text-[10px]:图谱节点空间受限,text-xs(12px) 过大 */} {kp.questionCount > 0 && ( {kp.questionCount} {t("graph.node.questions")} )}
{showMastery && (
{t("graph.node.mastery")} {mastery ? `${Math.round(mastery.masteryLevel)}%` : t("graph.detail.masteryNotAssessed")}
)} {kp.chapterTitle && (
{kp.chapterTitle}
)}
) } export const GraphKpNode = memo(GraphKpNodeComponent)