feat(textbooks): add force-graph component and update graph components
- Add force-graph.tsx for new graph visualization - Update graph-toolbar, knowledge-graph, knowledge-point-list, textbook-reader - Update use-graph-data hook and types - Update textbooks error boundary pages
This commit is contained in:
@@ -11,12 +11,14 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/shared/components/ui/select"
|
||||
import type { GraphViewMode } from "../types"
|
||||
import type { GraphLayoutMode, GraphViewMode } from "../types"
|
||||
|
||||
interface GraphToolbarProps {
|
||||
viewMode: GraphViewMode
|
||||
onViewModeChange: (mode: GraphViewMode) => void
|
||||
availableViewModes: GraphViewMode[]
|
||||
layoutMode: GraphLayoutMode
|
||||
onLayoutModeChange: (mode: GraphLayoutMode) => void
|
||||
searchText: string
|
||||
onSearchChange: (text: string) => void
|
||||
onResetView: () => void
|
||||
@@ -30,14 +32,22 @@ const ALL_VIEW_MODES: readonly GraphViewMode[] = [
|
||||
"class-mastery",
|
||||
]
|
||||
|
||||
const ALL_LAYOUT_MODES: readonly GraphLayoutMode[] = ["hierarchical", "force"]
|
||||
|
||||
function isGraphViewMode(value: string): value is GraphViewMode {
|
||||
return ALL_VIEW_MODES.some((mode) => mode === value)
|
||||
}
|
||||
|
||||
function isGraphLayoutMode(value: string): value is GraphLayoutMode {
|
||||
return ALL_LAYOUT_MODES.some((mode) => mode === value)
|
||||
}
|
||||
|
||||
export function GraphToolbar({
|
||||
viewMode,
|
||||
onViewModeChange,
|
||||
availableViewModes,
|
||||
layoutMode,
|
||||
onLayoutModeChange,
|
||||
searchText,
|
||||
onSearchChange,
|
||||
onResetView,
|
||||
@@ -45,15 +55,32 @@ export function GraphToolbar({
|
||||
}: GraphToolbarProps) {
|
||||
const t = useTranslations("textbooks")
|
||||
|
||||
const handleValueChange = (v: string): void => {
|
||||
const handleViewModeChange = (v: string): void => {
|
||||
if (isGraphViewMode(v)) {
|
||||
onViewModeChange(v)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLayoutModeChange = (v: string): void => {
|
||||
if (isGraphLayoutMode(v)) {
|
||||
onLayoutModeChange(v)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2 p-2 border-b bg-background/95 shrink-0">
|
||||
<Select value={viewMode} onValueChange={handleValueChange}>
|
||||
{/* 布局切换:分层有向图 / Obsidian 风格力导向图 */}
|
||||
<Select value={layoutMode} onValueChange={handleLayoutModeChange}>
|
||||
<SelectTrigger className="w-[120px] h-8 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="hierarchical">{t("graph.layout.hierarchical")}</SelectItem>
|
||||
<SelectItem value="force">{t("graph.layout.force")}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select value={viewMode} onValueChange={handleViewModeChange}>
|
||||
<SelectTrigger className="w-[140px] h-8 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
|
||||
Reference in New Issue
Block a user