
大家好,我是人月聊IT。
今天继续分享基于AI辅助构建知识体系,实现可视化知识体系。即如何用一套结构化的YAML数据模型驱动AI生成任意领域的知识图谱,再将其渲染为四大可视化视图,构建一个从知识建模到交互浏览的完整闭环。
无论是在校学生系统学习一门学科,还是职场人士跨界进入一个新领域,我们都会遇到同一个问题:知识以碎片化的形式散落在各个角落——教材的目录结构、论文的引用网络、网课的章节安排、博客的知识点拆解——这些信息孤立存在,彼此之间缺少统一的组织框架。
传统的解决方式是绘制一张思维导图。但问题在于:
我决定从数据层入手,重新思考这个问题。核心思路分两步:
第一步:设计一套领域无关的 YAML 结构化规范,精确定义知识体系的层级结构、多维分类、关联语义和场景组装方案。这份规范本身可以作为 AI 的系统提示词,驱动 AI 为任意领域生成结构化的知识图谱数据。
第二步:基于这套规范,构建一个纯前端的可视化浏览平台。平台不包含任何领域特定的硬编码——加载金融学的 YAML 数据就展示金融学知识体系,加载机器学习的 YAML 数据就展示机器学习知识体系。
两个阶段产出的关系可以概括为:规范定义格式 → AI 生成数据 → 平台消费数据 → 用户浏览知识。
在知识表示领域,常见的格式有 JSON、RDF/OWL、XML 等。我选择 YAML 的原因是:
> 和 | 多行语法比 JSON 的转义优雅得多# 注释,可以在数据文件中嵌入说明、修订记录和交叉引用标注维度 | 阶段一:知识建模 | 阶段二:可视化平台 |
|---|---|---|
输入 | 领域参考资料(教材/论文/考纲) + KSB-YAML 规范 | 5 个 YAML 文件(用户通过文件夹选择器加载) |
输出 | 结构化的 YAML 数据文件 | 四视图联动的交互式可视化 |
核心角色 | AI(Claude/GPT 等大模型)作为内容生成器 | 纯前端 SPA 作为数据消费者 |
通用性 | 规范独立于任何具体领域 | 平台不硬编码任何领域特定内容 |
可复用性 | 同一套规范可复用于金融/ML/法学等任意领域 | 同一套代码可加载任意符合规范的 YAML 数据 |
┌─────────────────────┐
│ KSB-YAML 规范文档 │ ← 作为 AI 系统提示词
│ (2100 行 Schema) │
└─────────┬───────────┘
│ 输入
▼
┌─────────────────────┐
│ 大语言模型 (AI) │ ← 配合领域参考资料
│ 生成知识体系数据 │
└─────────┬───────────┘
│ 输出
▼
┌─────────────────────────────────────────┐
│ 5 份 YAML 文件 │
│ domain.yaml · dimensions.yaml │
│ relation_types.yaml · knowledge_points │
│ .yaml · scenarios.yaml │
└─────────┬───────────────────────────────┘
│ File System Access API
▼
┌─────────────────────────────────────────┐
│ 知识体系可视化浏览平台 (React + D3) │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐ │
│ │思维导图│ │矩阵图 │ │网络图 │ │学习路线│ │
│ └──────┘ └──────┘ └──────┘ └────────┘ │
│ ← 跨视图协同联动 → │
└─────────────────────────────────────────┘
我借鉴了项目管理领域 PMBOK 的"知识领域 × 过程组"双维交叉思想,将知识体系建模为由树到网、由粗到细的三层递进结构:
第一层:知识树(广度覆盖)
自顶向下逐层分解:领域 → 分支(6-12个) → 子主题(20-45个) → 知识点(50-100个)
回答「这个领域有哪些大块知识?」
→ 对应思维导图视图
第二层:知识矩阵(多维分类)
任意两个维度(如"知识领域 × 学习阶段")交叉形成网格
回答「如何多维度分类与交叉定位?」
→ 对应多维矩阵视图
第三层:知识网络(关联成网)
知识点作为节点,7 种语义关联作为边,构成有向/无向混合网络
回答「知识点之间如何关联?学习顺序如何展开?」
→ 对应知识网络图 + 学习路线图
三层之间通过统一的配色方案和ID 命名规范保持一致性——同一分支的颜色在树、矩阵和图谱中保持统一。
在规范设计过程中,我确立了五条核心原则:
原则一:自顶向下逐层分解。知识从最抽象的领域概念出发,逐层分解到最小可学习单元。分解深度控制在 1~4 级,一级分支不超过 12 个(符合认知负荷理论中的 7±2 原则)。
原则二:知识是多维的。"一级分解"只是分类的一个维度。知识还可以按学习阶段(基础→进阶→高级)、应用场景(商业银行/投资银行/资产管理)、难度层级等维度进行交叉分类。
原则三:知识点之间是多维关联的。连线不是同一类关系。依赖类(前导依赖、约束条件)、结构类(组成包含)、扩展类(扩展外延、演进发展)、参照类(类比参照、对比区分)——七大关系各有明确的语义。
原则四:知识应支持场景化组装。学习路线不是知识树的简单遍历。面向不同的学习目标(速成入门 vs 系统掌握)或岗位角色,需要从知识网络中组装出不同的学习路径。组装的核心依据是前导依赖关系。
原则五:知识点的描述需要结构化。每个知识点至少包含:身份信息(ID/名称/层级)、分类信息(多维度 Tag)、语义信息(定义/描述/实例/要点)、度量信息(难度/重要度/枢纽度/学习时长)、关联信息(关系列表)。
五个 YAML 文件之间存在严格的引用依赖:
┌──────────────┐
│ domain.yaml │ 领域元信息、粒度约束
└──────┬───────┘
│ 引用(领域ID前缀)
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌────────────────┐ ┌──────────────────┐
│dimensions.yaml│ │relation_types │ │knowledge_points │
│维度 + 取值 │ │.yaml │ │.yaml │
│ │ │边的语义+样式 │ │节点 + 关联 │
└──────┬───────┘ └──────┬─────────┘ └────────┬─────────┘
│ │ │
│ ┌────────────┘ │
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────┐
│ scenarios.yaml │
│ 学习路线(引用知识库中的节点 ID) │
└──────────────────────────────────────────────────┘
knowledge_points.yaml 是核心数据文件——所有其他文件都直接或间接与之关联。每个知识点的 tags 字段引用 dimensions.yaml 中的维度取值,relations[].type 引用 relation_types.yaml 中的关系类型,而 scenarios.yaml 通过知识点 ID 引用需要编排的节点序列。
这是整个规范中最具创新性的部分。传统的知识图谱将所有连线视为同质的"关联",而我区分了七种具有明确语义的关系:
关联类别 | 关系类型 | 核心语义 | 学习路线行为 | 可视化样式 |
|---|---|---|---|---|
依赖类 | depends 前导依赖 | "必须先学 A 才能理解 B" | reverse(反转方向) | 蓝实线 + 箭头 |
依赖类 | constrains 约束关系 | "A 的适用范围受 B 约束" | reverse | 红点线 + 箭头 |
结构类 | contains 组成包含 | "B 由 A 作为部件组成" | reverse | 灰蓝实线 + 箭头 |
扩展类 | extends 扩展外延 | "B 是 A 的深化和特化" | keep_direction | 深紫虚线 + 箭头 |
演进类 | evolved 演进发展 | "B 由 A 历史演进而来" | keep_direction | 紫红实线 + 箭头 |
参照类 | analogy 类比参照 | "A 与 B 结构相似可类比" | keep_as_reference | 绿点线无箭头 |
参照类 | contrast 对比区分 | "A 与 B 易混淆需对比" | keep_as_reference | 橙虚线无箭头 |
关键在于 learning_path_behavior 字段——它决定了关系在学习路线图中的处理方式:
这种精细的语义设计使得从知识网络中推导学习路线成为可能——详见下文 §5.4 的"路线边推导算法"。

我将完整的 KSB-YAML 规范整理成了一份 2100 行的提示词文档,包含:
然后将规范文档 + 7 份参考资料(5 本经典教材 + CFA Level I-III 考纲 + FRM 考纲)作为输入,驱动 AI 按以下步骤分阶段产出:
Step 1: 领域界定 → 确认金融学的定义、边界、受众 → 产出 domain.yaml
Step 2: 维度设计 → 识别 3 个有效维度(知识领域/学习阶段/应用场景),确定主维度取值(10 个分支)→ 产出 dimensions.yaml
Step 3: 关系类型定义 → 确定金融领域的 7 种关联类型,为每种定义视觉样式 → 产出 relation_types.yaml
Step 4: 知识点树构建 → 先列出 10 个一级分支,逐分支展开二级(32 个)和三级(55 个),为每个节点编写完整元信息 → 产出 knowledge_points.yaml
Step 5: 学习路线设计 → 基于前导依赖拓扑排序,设计 3 条差异化路线 → 产出 scenarios.yaml
Step 6: 自查 → 逐项检查跨文件引用完整性、网络密度(平均度 ≥2、孤岛 ≤5%)
最终产出的数据质量经过严格校验:
有了高质量的结构化数据,下一步是构建一个能消费这些数据并渲染为可视化视图的平台。技术选型上我做了几个关键决策:
决策 | 选择 | 理由 |
|---|---|---|
框架 | React 18 + TypeScript | 组件化开发、强类型保障 97 个节点的复杂数据流 |
构建 | Vite 5 | 开发时 HMR 极速热更新,构建产物 456KB 合理 |
样式 | Tailwind CSS | 原子化 CSS 适合 IDE 三栏布局的快速搭建 |
图表 | D3.js v7(原生) | 不使用 React-D3 桥接库,D3 完全控制 SVG 渲染 |
学习路线布局 | dagre 独立版 | 避免 dagre-d3 的 D3 v5 依赖与主项目 D3 v7 冲突 |
矩阵视图 | 纯 React + Tailwind | 多维矩阵本质是条件筛选 + 网格排列,无需 D3 |
状态管理 | Zustand | 轻量(<1KB)、无 boilerplate、支持 selector 防重渲染 |
图标 | lucide-react | 与 Tailwind 生态配套,tree-shakable |
关键架构原则:
KnowledgeBase 对象,包含所有原始数据 + 4 个派生结构(tree / graph / knowledgePointMap / scenarioPresenceMap)。所有视图组件只读取这同一份数据,不各自维护副本。focusNodeId),驱动所有其他视图同步高亮定位。这是跨视图协同的核心机制。dimensions.yaml 动态读取,所有标签从 knowledgePointMap 动态获取,所有边样式从 relation_types.yaml 动态渲染。文件加载流程是平台的第一道关卡:
用户点击「选择文件夹」
│
▼
File System Access API: showDirectoryPicker()
│
▼
遍历目录中所有 .yaml / .yml 文件,读取为文本
│
├── domain.yaml → js-yaml.load() → DomainInfo
├── dimensions.yaml → js-yaml.load() → Dimension[]
├── relation_types.yaml → js-yaml.load() → RelationType[]
├── knowledge_points.yaml → js-yaml.load() → KnowledgePoint[]
└── scenarios.yaml → js-yaml.load() → Scenario[]
│
▼
parseAllYamlFiles() → 校验 + 转换
│
├── 校验:ID 唯一性、跨文件引用完整性、必填字段
├── buildColorMap:从 dimensions.yaml 主维度取值中提取颜色映射
├── buildTree:从 knowledge_points 按 parent 字段构建 TreeNode 森林
├── buildGraph:从 knowledge_points[].relations[] 构建 {nodes, edges}
├── buildScenarioPresence:知识点 ID → 路线出现位置索引
└── knowledgePointMap:Map<id, KnowledgePoint> 快速查找
│
▼
存入 Zustand Store → 触发视图渲染
解析器同时运行一致性校验,检查:
parent 引用是否有效relations[].target 是否指向存在的知识点relations[].type 是否在 relation_types.yaml 中有定义\$、\> 等 AI 生成 YAML 的常见错误)精确定位文件名+行号
页面采用经典的三栏 IDE 布局,灵感来源于 VS Code 的界面结构:
┌──────────────────────────────────────────────────────────────────┐
│ 🔵 金融学知识体系 [选择文件夹] [导图|矩阵|图谱|路线] 🔍🌙 │
├────────────┬──────────────────────────────────────┬──────────────┤
│ 🔍 搜索 │ │ 📋 节点详情 │
│ 📁 知识树 │ 主视图区域 (60%) │ 名称/定义 │
│ ├─金融市场│ │ 难度★★★★☆ │
│ ├─货币银行│ ┌──────────────────────────┐ │ 🔗 关联关系 │
│ ├─公司金融│ │ 当前激活的视图 │ │ → 前导依赖 │
│ │ ... │ │ (思维导图/矩阵/图谱/路线) │ │ → 扩展外延 │
│ │ │ │ │ │ 📚 所属路线 │
│ │ 🔍 筛选 │ └──────────────────────────┘ │ │
│ │ 领域:[│ │ [导图中查看]│
│ │ 阶段:[│ │ [图谱中查看]│
│ │ 难度:│ │ [路线中查看]│
│ │ 路线:[│ │ │
├────────────┴──────────────────────────────────────┴──────────────┤
│ 💡 焦点:期权 | 视图:知识网络图 | 节点:97 | 边:128 | 金融速成 │
└──────────────────────────────────────────────────────────────────┘
左侧栏 (w-72, 可折叠) 主视图 (flex-1) 右侧栏 (w-80, 可折叠)
左侧栏包含三部分:
右侧详情面板:双击节点打开,四个标签页切换(📊指标 / 🔗关联 / 💡示例 / 📚资源),底部三个快捷跳转按钮。
底部状态栏:实时显示焦点节点面包屑、当前视图名、统计数据、加载来源。
未加载数据前,主视图显示引导页面——一个大号文件夹图标、"加载知识体系以开始浏览"标题、"选择文件夹"和"选择多个文件"两个按钮,以及 5 个支持格式的说明。
整个平台对所有边界情况做了防御性处理:
constrains 和 evolved)
这是用户打开平台后看到的第一屏,回答"这个领域有哪些大块知识?"
布局算法采用了经典的中心双侧树:
children_order 排序d3.tree().nodeSize([VGAP, HSTEP]) 计算节点位置d3.hierarchy 构建父子层级,separation 参数控制间距nodeSize([28, 190]) 设定兄弟节点间距 28px、层级间距 190pxxx = side * d3.y(水平深度方向)、yy = d3.x(垂直广度方向)yy -= mid节点样式按深度分层:
#1a237e,rx=12 胶囊形,drop-shadow 投影,白色粗体字◂/▸/▾连线使用 Cubic Bezier 曲线。关键公式:控制点偏移量 c = max(28, dx * 0.42),确保短距离连线平滑自然。连线颜色继承目标节点的分支颜色。
交互:
scaleExtent([0.3, 3.0]))焦点高亮:焦点节点金色描边 2.5px + drop-shadow 发光,其他节点样式不变。点击展开/折叠时使用 renderVersion 计数器触发重绘,保证视图与数据状态同步。

矩阵视图回答"哪些知识点属于『金融市场 × 基础入门 × 商业银行场景』?"
机制:
Select 下拉菜单选择行/列维度(从 dimensions.yaml 动态生成)#f1f5f9 → #1e293b)单元格内容以列表形式展示每个知识点(名称 + 难度星级),底部显示汇总(节点数 + 平均难度)。单元格背景根据密度映射:密度 < 平均×0.5 → 最浅色,密度 > 平均×1.5 → 最深色。
交互链:悬停单元格 → Tooltip 统计 → 单击 → 全局筛选联动 → 双击 → 跳转知识网络图并预筛选。

网络图是四个视图中交互最丰富的,使用 D3 力导向模拟(Force Simulation)将知识点和关联关系展现在二维平面上。
力导向参数:
simulation
.force('link', forceLink(edges).distance(80))
.force('charge', forceManyBody().strength(-200))
.force('center', forceCenter(width/2, height/2))
.force('collision', forceCollide().radius(d => d.radius + 5))
.force('x', forceX(width/2).strength(0.03))
.force('y', forceY(height/2).strength(0.03))
charge(-200):节点互相排斥,避免重叠collision(radius+5):硬碰撞检测,节点间至少 5px 间距center + 弱 x/y 引力:防止节点飘散到画布之外视觉编码(全部从 YAML 动态读取):
属性 | 来源 | 公式/值 |
|---|---|---|
节点半径 | importance | 6 + importance × 14(范围 6~20px) |
节点填充色 | tags[primaryDim] → knowledgeAreaColors | 10 色分支色板 |
边颜色 | relation_types.yaml → visual.color | 7 种颜色 |
边线型 | relation_types.yaml → visual.line_style | solid / dashed / dotted |
边粗细 | relation.weight | weight × 3 + 1(范围 1~4px) |
边箭头 | relation_types.yaml → visual.arrow | 仅 depends/constrains/contains/extends/evolved |
焦点高亮的层级衰减:
关系类型筛选:顶部 Badge 组显示每种关系的颜色标记 + 中文名 + 边数。0 边的类型(如当前的 constrains 和 evolved)灰化禁用。可多选,未选中类型的边降透明度至 0.05。

学习路线图是整个平台算法最复杂的视图。它的核心挑战在于:**scenarios.yaml 只给出每阶段的知识点有序列表,并不直接定义节点之间的连线**。所有边都必须从全局关系图中反向推导得出。
路线边推导算法(这是本视图最关键的一步):
输入:
- scenario(路线,含 phases[].knowledge_points 有序列表)
- knowledgePointMap(每个 KP 的 relations[])
- relationTypeMap(含 learning_path_behavior)
- scenarioPresenceMap(定位节点所属阶段)
1. 收拢路线全部知识点:S = ∪ phase.knowledge_points
2. 遍历全局关系,仅保留两端都在本路线内的关系:
对每条 KP A 的 relation (target=B, type=T):
- 仅当 A∈S 且 B∈S 才纳入
- 按 rtMap[T].learning_path_behavior 决定路线箭头方向:
reverse(depends/constrains/contains)
→ 路线箭头 B → A(先学 B 再学 A)
keep_direction(extends/evolved)
→ 路线箭头 A → B(深化方向)
keep_as_reference(analogy/contrast)
→ 虚线弱显示,不纳入主线
3. 叠加 key_dependencies(显式学习顺序,优先级最高)
每条 {from, to, reason} 直接生成边 from → to
若与第 2 步推导边方向冲突,以 key_dependencies 为准
4. 跨阶段判定:
两端分属不同 phase → 标记为跨阶段边 → 加粗 + 阶段边界色
5. 去重:key = source→target,同 key 保留 weight 最高者
布局:使用 dagre 的 LR-DAG 模式(rankdir: LR,从左到右),每个阶段一个竖条背景(8 色浅色渐变),节点按 phases[].knowledge_points 列表顺序排列。
视觉元素:
交互:场景下拉切换 → 整图重新布局;前置要求胶囊组(可点击跳转);关联路线链接;阶段标题显示时长。

整个平台的协同机制建立在 Zustand Store 中的一个全局 focusNodeId 状态上:
用户点击节点 "期权"(在思维导图中)
│
▼
store.setFocusNode("fin_derivatives_options")
│
├──→ MindMapView: 金色脉动高亮节点 + 展开父链路径
├──→ MatrixView: 高亮该节点所在的行(知识领域)+ 列(学习阶段)
├──→ GraphView: 焦点节点 scale 1.3x 发光 + 1阶邻居高亮 + 画布自动居中
├──→ LearningPathView: 蓝色前导链(你从哪来)+ 绿色后续链(你到哪去)
├──→ KnowledgeTree: 自动展开到焦点节点层级,蓝色左边框高亮
└──→ StatusBar: 更新面包屑「金融衍生品 › 期权」
每个视图通过 Zustand selector 订阅 focusNodeId,变化时通过 D3 refs 做增量更新(修改不透明度和描边),而非重新创建整个 SVG。
<App>
├── <Toolbar /> ← 顶部工具栏(视图切换 / 文件夹选择 / 搜索 / 主题)
├── <div.flex-1>
│ ├── <LeftSidebar> ← 左侧导航栏
│ │ ├── <KnowledgeTreeNav /> ← 知识树递归导航 + 搜索
│ │ ├── <FilterPanel /> ← 维度筛选 Checkbox + Slider
│ │ └── <ScenarioSelector /> ← 路线 Radio 选择
│ ├── <MainContent> ← 主视图区
│ │ ├── <EmptyState /> ← 未加载引导
│ │ ├── <MindMapView /> ← D3 中心双侧树
│ │ ├── <MatrixView /> ← 纯 React 网格
│ │ ├── <GraphView /> ← D3 力导向图
│ │ └── <LearningPathView /> ← dagre LR-DAG
│ └── <RightPanel> ← 右侧详情面板
│ └── <NodeDetailCard /> ← 4 标签页详情
└── <StatusBar /> ← 底部状态栏
这是一个经过深思熟虑的模式选择。我放弃了 react-d3-tree 等第三方桥接库(因为它们大多依赖旧版 D3 或封装不完整),转而使用最原生的集成方式:
const MindMapView: React.FC = () => {
const svgRef = useRef<SVGSVGElement>(null);
const zoomGRef = useRef<SVGGElement>(null);
const gRef = useRef<SVGGElement>(null);
const zoomRef = useRef<d3.ZoomBehavior>(null);
// 初始化 D3(数据变化时完整重绘)
useEffect(() => {
if (!knowledgeBase) return;
renderTree(); // 清除旧内容 + 重新布局 + 绘制
}, [knowledgeBase, renderVersion]);
return (
<div className="w-full h-full">
<svg ref={svgRef} style={{ width: '100%', height: '100%' }}>
<g ref={zoomGRef}> {/* zoom 控制层 */}
<g ref={gRef} /> {/* 内容层 */}
</g>
</svg>
</div>
);
};
关键要点:
<g> 结构:外层 zoomG 承载 D3 zoom 的 transform,内层 g 承载所有绘图内容100% × 100% 填满父容器,通过 viewBox 映射内容坐标空间useRef 中,按钮通过 zoomRef.current.scaleBy() 调用,避免组件重渲染svg.on('.zoom', null) 清除旧 handler,防止事件重复绑定我选择了 Zustand 而非 Redux,因为:
KnowledgeBase + 几个 UI 状态)useStore(s => s.focusNodeId)),避免不必要的重渲染showDirectoryPicker() 仅在 Chromium 内核浏览器中可用。平台设计了三级降级方案:
层级 | 方案 | 兼容性 |
|---|---|---|
主方案 | File System Access API (showDirectoryPicker) | Chrome / Edge |
Fallback 1 | 拖拽文件夹(DataTransferItem.webkitGetAsEntry) | Chrome / Edge / Firefox 部分 |
Fallback 2 | <input type="file" multiple> 多文件选择器 | 100% 浏览器 |
错误处理也做了精细的分级:
教训一:D3 + React 的双层 <g> 结构陷阱
开发过程中最隐蔽的 bug 是 SVG 中缺少 <g ref={gRef}> 元素。我在 JSX 中只写了 <svg ref={svgRef}>,但 D3 渲染函数和 zoom 配置都依赖 d3.select(gRef.current) 来获取绘制容器。由于 gRef.current 始终为 null,所有 D3 操作(append/attr/selectAll)都变成了空操作——没有任何错误信息,只是屏幕上什么都不显示。排查这个问题花了相当长时间。
教训二:参考实现的价值
思维导图的第一版实现存在严重的布局错位——节点文字方向混乱、连线生硬、根节点被遮挡。后来找到了一个参考 HTML 文件(knowledge_top.html),完整分析了它的布局算法和视觉设计,发现关键差异在三个方面:
d3.tree().nodeSize() 后做坐标映射(xx = side * y, yy = x),而非手动递归计算text-anchor: middle 居中,方向感由侧边颜色条和折叠指示器表达viewBox 而非显式 width/height,配合 100% 容器填充完整重写后效果立刻正确。
教训三:数据驱动的开发顺序
正确的开发顺序应该是:先验证数据层完整性 → 再构建可视化。项目初期我先写了所有四个视图的代码框架,但直到运行 YAML 解析器端到端测试才发现数据层的几个问题(折叠层级错误、孤立节点、关系去重 bug)。如果先构建一个命令行数据校验工具,开发效率会高很多。
在整个开发过程中,AI 辅助在以下几个方面发挥了巨大作用:
gRef.current === null 是根源但 AI 也存在明显的局限:复杂的状态管理逻辑(展开/折叠/Zoom 联动)需要开发者手动设计;性能优化(避免不必要的重渲染)需要开发者对 React 渲染机制有深入理解。
指标 | 数据 |
|---|---|
知识点总数 | 97 个(Level 1×10 + Level 2×32 + Level 3×55) |
关联关系 | 128 条(7 种类型:depends 46 / contains 49 / extends 8 / contrast 7 / analogy 1 / constrains 0 / evolved 0) |
学习路线 | 3 条(速成 35 节点 / 系统 83 节点 / 从业者 53 节点) |
分类维度 | 3 个(知识领域 10 取值 × 学习阶段 3 取值 × 应用场景 5 取值) |
前端代码 | 43 个 TypeScript/React 源文件 |
构建产物 | 456KB JS + 22KB CSS(gzip 后约 149KB,首屏加载 < 2s) |
TypeScript 编译 | 0 错误 |
Vite 构建 | 850ms 完成生产构建 |
虽然当前加载的是金融学数据,但平台的设计保证了它完全独立于任何具体领域。以下是验证方法:
这是因为:
knowledge_points WHERE level=1 动态决定dimensions.yaml 动态生成values[].color 动态读取scenarios.yaml 动态渲染