docs(architecture): update impact map, data, troubleshooting, add mockups
Some checks failed
Security / deep-security-scan (push) Failing after 2m10s
DR Drill / dr-drill (push) Failing after 1m32s
CI / scheduled-backup (push) Failing after 31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled

- Update 004_architecture_impact_map.md and 005_architecture_data.json

- Remove obsolete _update_004.cjs helper script

- Update troubleshooting/known-issues.md

- Add docs/mockups/ directory
This commit is contained in:
SpecialX
2026-07-04 23:02:14 +08:00
parent e962b67050
commit d1ad7a1f75
8 changed files with 3324 additions and 104 deletions

View File

@@ -0,0 +1,637 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>备课编辑器 · 正文节点布局对比</title>
<style>
:root {
--bg: #f6f7f9;
--surface: #ffffff;
--surface-low: #f0f2f5;
--surface-high: #e7e9ee;
--outline: #d1d5db;
--outline-strong: #9ca3af;
--on-surface: #1f2937;
--on-surface-variant: #6b7280;
--primary: #1976d2;
--primary-soft: rgba(25, 118, 210, 0.12);
--anchor: #f59e0b;
--node-objective: #4caf50;
--node-teach: #1976d2;
--node-exercise: #9c27b0;
--node-summary: #ff9800;
--node-textbook: #455a64;
--radius: 10px;
--shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
--shadow-lg: 0 10px 30px rgba(0,0,0,0.10), 0 3px 8px rgba(0,0,0,0.06);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
background: var(--bg);
color: var(--on-surface);
line-height: 1.55;
-webkit-font-smoothing: antialiased;
}
.page {
max-width: 1400px;
margin: 0 auto;
padding: 40px 24px 80px;
}
header.page-head {
margin-bottom: 32px;
}
header.page-head h1 {
font-size: 28px;
font-weight: 700;
margin: 0 0 8px;
letter-spacing: -0.01em;
}
header.page-head p {
margin: 0;
color: var(--on-surface-variant);
font-size: 15px;
max-width: 720px;
}
.layout-grid {
display: grid;
grid-template-columns: 1fr;
gap: 40px;
}
@media (min-width: 1100px) {
.layout-grid { grid-template-columns: 1fr 1fr 1fr; gap: 24px; }
}
.option {
background: var(--surface);
border-radius: 16px;
box-shadow: var(--shadow);
overflow: hidden;
display: flex;
flex-direction: column;
}
.option-head {
padding: 20px 20px 16px;
border-bottom: 1px solid var(--outline);
}
.option-tag {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--primary);
background: var(--primary-soft);
padding: 4px 10px;
border-radius: 999px;
margin-bottom: 10px;
}
.option-title {
font-size: 18px;
font-weight: 700;
margin: 0 0 6px;
}
.option-sub {
font-size: 13px;
color: var(--on-surface-variant);
margin: 0;
line-height: 1.5;
}
.option-body {
padding: 20px;
flex: 1;
display: flex;
flex-direction: column;
gap: 16px;
}
/* 共用 wireframe 样式 */
.wireframe {
background: var(--surface-low);
border: 1px solid var(--outline);
border-radius: 8px;
aspect-ratio: 4 / 3;
display: flex;
flex-direction: column;
overflow: hidden;
font-size: 10px;
color: var(--on-surface-variant);
position: relative;
}
.wf-toolbar {
height: 16px;
background: var(--surface);
border-bottom: 1px solid var(--outline);
display: flex;
align-items: center;
padding: 0 6px;
gap: 4px;
flex-shrink: 0;
}
.wf-toolbar .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--outline-strong); }
.wf-toolbar .pill { width: 18px; height: 7px; border-radius: 3px; background: var(--surface-high); }
.wf-toolbar .pill.accent { background: var(--primary-soft); }
.wf-area { flex: 1; display: flex; position: relative; overflow: hidden; }
.wf-sidebar {
width: 22%;
background: var(--surface);
border-right: 1px solid var(--outline);
padding: 6px 4px;
display: flex;
flex-direction: column;
gap: 3px;
flex-shrink: 0;
}
.wf-side-item {
height: 8px;
border-radius: 3px;
background: var(--surface-high);
padding: 0 3px;
display: flex;
align-items: center;
gap: 3px;
font-size: 7px;
}
.wf-side-item.active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.wf-side-item .ico { width: 5px; height: 5px; border-radius: 1px; flex-shrink: 0; }
.wf-main { flex: 1; position: relative; overflow: hidden; }
.wf-right {
width: 26%;
background: var(--surface);
border-left: 1px solid var(--outline);
padding: 6px;
display: flex;
flex-direction: column;
gap: 4px;
flex-shrink: 0;
}
.wf-right .field { height: 7px; border-radius: 2px; background: var(--surface-high); }
.wf-right .field.short { width: 60%; }
.wf-right .field.tall { height: 28px; }
.wf-label {
font-size: 7px;
color: var(--on-surface-variant);
font-weight: 600;
margin-bottom: 2px;
}
/* 节点小卡片(画布模式) */
.wf-node {
position: absolute;
background: var(--surface);
border: 1.5px solid var(--outline-strong);
border-radius: 4px;
padding: 3px 5px;
font-size: 7px;
box-shadow: 0 1px 2px rgba(0,0,0,0.08);
display: flex;
align-items: center;
gap: 3px;
white-space: nowrap;
}
.wf-node .ndot { width: 4px; height: 4px; border-radius: 50%; flex-shrink: 0; }
.wf-node.objective { border-color: var(--node-objective); }
.wf-node.objective .ndot { background: var(--node-objective); }
.wf-node.teach { border-color: var(--node-teach); }
.wf-node.teach .ndot { background: var(--node-teach); }
.wf-node.exercise { border-color: var(--node-exercise); }
.wf-node.exercise .ndot { background: var(--node-exercise); }
.wf-node.summary { border-color: var(--node-summary); }
.wf-node.summary .ndot { background: var(--node-summary); }
/* 正文编辑器卡片 */
.wf-textbook {
position: absolute;
background: var(--surface);
border: 2px solid var(--node-textbook);
border-radius: 6px;
box-shadow: var(--shadow-lg);
overflow: hidden;
display: flex;
flex-direction: column;
}
.wf-textbook-head {
background: var(--node-textbook);
color: white;
font-size: 7px;
padding: 2px 5px;
font-weight: 600;
display: flex;
justify-content: space-between;
}
.wf-textbook-body {
padding: 5px 6px;
font-size: 7px;
line-height: 1.5;
flex: 1;
overflow: hidden;
}
.wf-textbook-body .h { font-weight: 700; font-size: 8px; display: block; margin-bottom: 2px; }
.wf-textbook-body .bold { font-weight: 700; }
.wf-textbook-body .anchor {
background: var(--anchor);
color: white;
padding: 0 2px;
border-radius: 2px;
font-size: 6px;
font-weight: 700;
}
.wf-textbook-body .point-anchor {
display: inline-block;
width: 8px;
height: 8px;
line-height: 8px;
text-align: center;
border-radius: 50%;
background: var(--anchor);
color: white;
font-size: 6px;
font-weight: 700;
}
.wf-textbook-toolbar {
display: flex;
gap: 3px;
padding: 2px 5px;
border-top: 1px solid var(--outline);
background: var(--surface-low);
font-size: 6px;
}
.wf-textbook-toolbar .tb {
padding: 1px 3px;
border-radius: 2px;
background: var(--surface-high);
}
/* 连线 */
.wf-edge {
position: absolute;
background: var(--primary);
opacity: 0.4;
transform-origin: 0 0;
height: 1px;
}
/* 文档流样式 */
.wf-docflow {
flex: 1;
overflow: hidden;
padding: 8px 10px;
display: flex;
flex-direction: column;
gap: 6px;
background: var(--surface);
}
.wf-docblock {
border-radius: 4px;
padding: 5px 6px;
font-size: 7px;
line-height: 1.5;
}
.wf-docblock.textbook {
background: rgba(69, 90, 100, 0.06);
border-left: 3px solid var(--node-textbook);
}
.wf-docblock.objective {
background: rgba(76, 175, 80, 0.07);
border-left: 3px solid var(--node-objective);
}
.wf-docblock.teach {
background: rgba(25, 118, 210, 0.07);
border-left: 3px solid var(--node-teach);
}
.wf-docblock.exercise {
background: rgba(156, 39, 176, 0.07);
border-left: 3px solid var(--node-exercise);
}
.wf-docblock.summary {
background: rgba(255, 152, 0, 0.07);
border-left: 3px solid var(--node-summary);
}
.wf-docblock .db-head {
font-weight: 700;
font-size: 7px;
display: flex;
align-items: center;
gap: 3px;
margin-bottom: 2px;
}
.wf-docblock .db-head .ico { width: 6px; height: 6px; border-radius: 1px; }
.wf-docblock.textbook .ico { background: var(--node-textbook); }
.wf-docblock.objective .ico { background: var(--node-objective); }
.wf-docblock.teach .ico { background: var(--node-teach); }
.wf-docblock.exercise .ico { background: var(--node-exercise); }
.wf-docblock.summary .ico { background: var(--node-summary); }
.wf-docblock .anchor { background: var(--anchor); color: white; padding: 0 2px; border-radius: 2px; font-size: 6px; font-weight: 700; }
/* 优劣对比 */
.pros-cons { display: flex; flex-direction: column; gap: 8px; }
.pros-cons .pc {
font-size: 12px;
line-height: 1.5;
}
.pros-cons .pc-label {
font-weight: 700;
font-size: 11px;
margin-bottom: 4px;
display: flex;
align-items: center;
gap: 4px;
}
.pros-cons .pc-label.pro { color: #16a34a; }
.pros-cons .pc-label.con { color: #dc2626; }
.pros-cons ul { margin: 0; padding-left: 14px; }
.pros-cons li { margin-bottom: 2px; color: var(--on-surface-variant); }
.recommend {
margin-top: 8px;
padding: 10px 12px;
background: var(--primary-soft);
border-radius: 8px;
font-size: 12px;
color: var(--primary);
font-weight: 600;
display: flex;
align-items: flex-start;
gap: 6px;
}
footer.page-foot {
margin-top: 40px;
padding-top: 24px;
border-top: 1px solid var(--outline);
color: var(--on-surface-variant);
font-size: 13px;
}
.legend {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 12px;
font-size: 12px;
}
.legend-item { display: flex; align-items: center; gap: 5px; }
.legend-dot { width: 10px; height: 10px; border-radius: 3px; }
</style>
</head>
<body>
<div class="page">
<header class="page-head">
<h1>备课编辑器 · 正文节点布局对比</h1>
<p>三种交互形态对比。共同前提:正文节点变成<strong>真实的富文本编辑器</strong>Tiptap支持加粗/标题/列表/图片真实排版,锚点用 Mark 系统而非字符串偏移。三种方案只差在"正文和教学节点如何排布"。</p>
<div class="legend">
<div class="legend-item"><span class="legend-dot" style="background:var(--node-textbook)"></span>教材正文</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--node-objective)"></span>教学目标</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--node-teach)"></span>新授</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--node-exercise)"></span>练习</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--node-summary)"></span>总结</div>
<div class="legend-item"><span class="legend-dot" style="background:var(--anchor)"></span>锚点标记</div>
</div>
</header>
<div class="layout-grid">
<!-- 方案 1画布 + 真实编辑器 -->
<section class="option">
<div class="option-head">
<span class="option-tag">方案 A</span>
<h2 class="option-title">保留画布 · 正文节点变真实编辑器</h2>
<p class="option-sub">最小改动。React Flow 画布不变,把中央那个 520px 假正文框换成真正的 Tiptap 富文本编辑器卡片,可拖拽缩放到更大。</p>
</div>
<div class="option-body">
<div class="wireframe">
<div class="wf-toolbar">
<span class="dot"></span><span class="dot"></span><span class="dot"></span>
<span class="pill accent"></span><span class="pill"></span><span class="pill"></span>
<span style="margin-left:auto;font-size:6px;">已保存</span>
</div>
<div class="wf-area">
<div class="wf-main">
<!-- 散布的教学节点 -->
<div class="wf-node objective" style="top:8%;left:6%;">
<span class="ndot"></span>教学目标
</div>
<div class="wf-node teach" style="top:14%;right:8%;">
<span class="ndot"></span>新授
</div>
<!-- 中央正文编辑器(变大) -->
<div class="wf-textbook" style="top:26%;left:18%;width:64%;height:52%;">
<div class="wf-textbook-head">
<span>📖 教材正文(可编辑副本)</span>
<span>右键锚定</span>
</div>
<div class="wf-textbook-body">
<span class="h">第一章 · 走进大自然</span>
春天的<span class="anchor"></span>轻轻吹过田野,
带来泥土的芬芳。
<br/>
<span class="bold">观察要点:</span>
<br/>• 花朵的颜色变化
<br/><span class="point-anchor"></span> 叶片的形状
<br/>• 气温的回升
</div>
<div class="wf-textbook-toolbar">
<span class="tb">B</span><span class="tb">I</span>
<span class="tb">H1</span><span class="tb"></span>
<span class="tb">🖼</span><span class="tb"></span>
</div>
</div>
<!-- 下方的教学节点 -->
<div class="wf-node exercise" style="bottom:8%;left:20%;">
<span class="ndot"></span>课堂练习
</div>
<div class="wf-node summary" style="bottom:10%;right:14%;">
<span class="ndot"></span>总结
</div>
<!-- 连线 -->
<div class="wf-edge" style="top:13%;left:14%;width:40px;transform:rotate(35deg);"></div>
<div class="wf-edge" style="top:18%;right:14%;width:38px;transform:rotate(150deg);"></div>
</div>
<div class="wf-right">
<div class="wf-label">选中节点</div>
<div class="field"></div>
<div class="field short"></div>
<div class="field tall"></div>
</div>
</div>
</div>
<div class="pros-cons">
<div class="pc">
<div class="pc-label pro">✓ 优点</div>
<ul>
<li>改动最小,画布交互不变</li>
<li>保留"思维导图"式空间关系</li>
<li>锚点系统改造可独立进行</li>
</ul>
</div>
<div class="pc">
<div class="pc-label con">✗ 缺点</div>
<ul>
<li>长文档在画布上仍受限,需频繁缩放</li>
<li>编辑器卡片和教学节点抢空间</li>
<li>移动端几乎不可用</li>
</ul>
</div>
</div>
</div>
</section>
<!-- 方案 2文档流类 Notion -->
<section class="option">
<div class="option-head">
<span class="option-tag">方案 B</span>
<h2 class="option-title">文档流为主(类 Notion</h2>
<p class="option-sub">正文和教学节点都在同一文档流里,按顺序拼成一篇完整教案。左侧大纲,中间文档,右侧选中节点详情。</p>
</div>
<div class="option-body">
<div class="wireframe">
<div class="wf-toolbar">
<span class="dot"></span><span class="dot"></span><span class="dot"></span>
<span class="pill accent"></span><span class="pill"></span><span class="pill"></span>
<span style="margin-left:auto;font-size:6px;">已保存</span>
</div>
<div class="wf-area">
<div class="wf-sidebar">
<div class="wf-label">大纲</div>
<div class="wf-side-item active"><span class="ico" style="background:var(--node-textbook)"></span>正文</div>
<div class="wf-side-item" style="padding-left:8px;"><span class="ico" style="background:var(--node-objective)"></span>目标</div>
<div class="wf-side-item" style="padding-left:8px;"><span class="ico" style="background:var(--node-teach)"></span>新授</div>
<div class="wf-side-item" style="padding-left:8px;"><span class="ico" style="background:var(--node-exercise)"></span>练习</div>
<div class="wf-side-item" style="padding-left:8px;"><span class="ico" style="background:var(--node-summary)"></span>总结</div>
</div>
<div class="wf-main">
<div class="wf-docflow">
<div class="wf-docblock textbook">
<div class="db-head"><span class="ico"></span>📖 教材正文</div>
<span style="font-weight:700;">第一章 · 走进大自然</span><br/>
春天的<span class="anchor"></span>轻轻吹过田野,带来泥土的芬芳。
<span class="point-anchor" style="display:inline-block;width:8px;height:8px;line-height:8px;text-align:center;border-radius:50%;background:var(--anchor);color:white;font-size:6px;font-weight:700;"></span> 叶片的形状
</div>
<div class="wf-docblock objective">
<div class="db-head"><span class="ico"></span>🎯 教学目标</div>
认识春天的自然现象…
</div>
<div class="wf-docblock teach">
<div class="db-head"><span class="ico"></span>📚 新授</div>
引导学生观察…
</div>
<div class="wf-docblock exercise">
<div class="db-head"><span class="ico"></span>✏ 课堂练习</div>
画一画你看到的春天…
</div>
</div>
</div>
<div class="wf-right">
<div class="wf-label">选中: 新授</div>
<div class="field"></div>
<div class="field short"></div>
<div class="field tall"></div>
</div>
</div>
</div>
<div class="pros-cons">
<div class="pc">
<div class="pc-label pro">✓ 优点</div>
<ul>
<li>编辑体验最好,长文档自然滚动</li>
<li>所见即所得,适合打印导出</li>
<li>移动端友好</li>
<li>教学节点和正文同流,关系清晰</li>
</ul>
</div>
<div class="pc">
<div class="pc-label con">✗ 缺点</div>
<ul>
<li>失去"画布"的空间思维导图感</li>
<li>需要重构数据模型(节点顺序流)</li>
<li>锚点仍需跨"正文块"定位</li>
</ul>
</div>
</div>
</div>
</section>
<!-- 方案 3双栏 -->
<section class="option">
<div class="option-head">
<span class="option-tag">方案 C</span>
<h2 class="option-title">双栏 · 正文编辑器 + 节点面板</h2>
<p class="option-sub">正文富文本编辑器独占主区域(类 A4 文档页),教学节点在右侧面板编辑,左侧是节点树。正文与节点通过锚点关联,互不混排。</p>
</div>
<div class="option-body">
<div class="wireframe">
<div class="wf-toolbar">
<span class="dot"></span><span class="dot"></span><span class="dot"></span>
<span class="pill accent"></span><span class="pill"></span><span class="pill"></span>
<span style="margin-left:auto;font-size:6px;">已保存</span>
</div>
<div class="wf-area">
<div class="wf-sidebar">
<div class="wf-label">节点树</div>
<div class="wf-side-item"><span class="ico" style="background:var(--node-textbook)"></span>📖 正文</div>
<div class="wf-side-item active"><span class="ico" style="background:var(--node-objective)"></span>🎯 目标</div>
<div class="wf-side-item"><span class="ico" style="background:var(--node-teach)"></span>📚 新授</div>
<div class="wf-side-item"><span class="ico" style="background:var(--node-exercise)"></span>✏ 练习</div>
<div class="wf-side-item"><span class="ico" style="background:var(--node-summary)"></span>📝 总结</div>
</div>
<div class="wf-main" style="background:var(--surface-low);display:flex;justify-content:center;padding:8px;">
<div style="background:var(--surface);width:80%;border-radius:4px;box-shadow:var(--shadow);padding:8px;font-size:7px;line-height:1.6;overflow:hidden;">
<div style="font-weight:700;font-size:8px;margin-bottom:3px;">第一章 · 走进大自然</div>
春天的<span class="anchor" style="background:var(--anchor);color:white;padding:0 2px;border-radius:2px;font-size:6px;font-weight:700;"></span>轻轻吹过田野,带来泥土的芬芳。
<br/><br/>
<span style="font-weight:700;">观察要点:</span>
<br/>• 花朵的颜色变化
<br/><span style="display:inline-block;width:8px;height:8px;line-height:8px;text-align:center;border-radius:50%;background:var(--anchor);color:white;font-size:6px;font-weight:700;"></span> 叶片的形状
<br/>• 气温的回升
<div style="margin-top:6px;padding-top:4px;border-top:1px solid var(--outline);display:flex;gap:3px;">
<span style="padding:1px 3px;border-radius:2px;background:var(--surface-high);font-size:6px;">B</span>
<span style="padding:1px 3px;border-radius:2px;background:var(--surface-high);font-size:6px;">I</span>
<span style="padding:1px 3px;border-radius:2px;background:var(--surface-high);font-size:6px;">H1</span>
<span style="padding:1px 3px;border-radius:2px;background:var(--surface-high);font-size:6px;"></span>
<span style="padding:1px 3px;border-radius:2px;background:var(--surface-high);font-size:6px;">🖼</span>
</div>
</div>
</div>
<div class="wf-right">
<div class="wf-label">🎯 教学目标</div>
<div class="field"></div>
<div class="field short"></div>
<div class="field tall"></div>
<div style="margin-top:4px;padding:3px;border:1px dashed var(--primary);border-radius:3px;font-size:6px;color:var(--primary);text-align:center;">+ AI 生成</div>
</div>
</div>
</div>
<div class="pros-cons">
<div class="pc">
<div class="pc-label pro">✓ 优点</div>
<ul>
<li>正文编辑区最大、最专注</li>
<li>正文与节点分离,职责清晰</li>
<li>锚点只在正文里,定位简单</li>
<li>保留节点树导航,不丢结构</li>
</ul>
</div>
<div class="pc">
<div class="pc-label con">✗ 缺点</div>
<ul>
<li>失去画布的连线/空间感</li>
<li>节点间关系靠树而非图表达</li>
<li>需要新增"节点树"组件</li>
</ul>
</div>
</div>
<div class="recommend">
★ 推荐:在"正文必须好编辑"这个核心诉求下C 兼顾了编辑体验和结构清晰,改动量适中。
</div>
</div>
</section>
</div>
<footer class="page-foot">
<p>三种方案的正文节点都是<strong>真正的 Tiptap 富文本编辑器</strong>,区别只在布局。锚点系统统一从"字符串偏移"改为 Tiptap Mark编辑时锚点自动跟随。</p>
</footer>
</div>
</body>
</html>