design: 路线图重构为线条构件版——六原语 + 曲线分流并线

- 新增 <RouteLine/> 线条组件展区:segment/elbow/curve/fork/merge/station 六原语逐一展示
- 组合总图改贝塞尔曲线:快速开始 → 分流岔口(React 线/示例线)→ 「更多」曲线并线 → 全栈基础 → 高级教程
- 网状关系在路线内以岔口/并线表达(原则2:岔口即分支)
- Args 改 path/forks/merges/stations;修复 linecard SVG fill 选择器与右列面板叠压
This commit is contained in:
cqh963852 committed 2026-10-02 18:20:40 +08:00
1 parent c7f17fc323
commit ce6f6b05dd
3 files changed
+89 -44

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 139 KiB

+89 -44
View File
@@ -194,8 +194,8 @@
display: flex; align-items: center; justify-content: center; display: flex; align-items: center; justify-content: center;
} }
.gedges { position: absolute; inset: 0; pointer-events: none; } .gedges { position: absolute; inset: 0; pointer-events: none; }
.gedges .edge { fill: none; stroke-width: 1.5; stroke-linecap: butt; stroke-dasharray: 9 4; stroke: #6366f1; } .edge { fill: none; stroke-width: 1.5; stroke-linecap: butt; stroke-dasharray: 9 4; stroke: #6366f1; }
.gedges .station { fill: #6366f1; } .station { fill: #6366f1; }
.glegend { display: flex; gap: 22px; font-size: 12px; color: #555; align-items: center; } .glegend { display: flex; gap: 22px; font-size: 12px; color: #555; align-items: center; }
.glegend .sw { display: inline-block; width: 30px; border-top: 1.5px dashed #9a9a98; margin-right: 6px; vertical-align: middle; } .glegend .sw { display: inline-block; width: 30px; border-top: 1.5px dashed #9a9a98; margin-right: 6px; vertical-align: middle; }
.glegend .sw.rel { border-top-color: #c9c9c7; } .glegend .sw.rel { border-top-color: #c9c9c7; }
@@ -215,6 +215,23 @@
table.spec.tight th { padding: 4px 10px 4px 0; } table.spec.tight th { padding: 4px 10px 4px 0; }
table.spec.tight td { padding: 3px 10px 3px 0; } table.spec.tight td { padding: 3px 10px 3px 0; }
/* P7 路线图(线条构件版) */
.rnode {
position: absolute; width: 160px; height: 44px;
background: #ffffff; border-radius: 12px;
display: flex; align-items: center; gap: 7px; padding: 0 12px;
box-shadow: 0 1px 2px rgba(26,26,26,0.10);
}
.rnode .t { font-size: 12px; font-weight: 700; color: #1a1a1a; flex: 1; }
.rnode .st { font-size: 9.5px; padding: 1px 6px; border-radius: 999px; font-weight: 600; }
.rnode .st.done { background: #efe6fb; color: #6d28d9; }
.rnode .st.lock { background: #ffffff; color: #6b6b6b; border: 1px solid #d5d5d3; }
.rnode .icotile { width: 22px; height: 22px; border-radius: 7px; font-size: 12px; }
.linecard {
background: #ffffff; border-radius: 14px; padding: 12px 14px 10px;
display: flex; flex-direction: column; gap: 6px;
box-shadow: 0 1px 2px rgba(26,26,26,0.06);
}
</style> </style>
</head> </head>
<body> <body>
@@ -628,61 +645,89 @@
<div class="pagenum">06 / 09</div> <div class="pagenum">06 / 09</div>
</div> </div>
<!-- ================= P7 CourseGraph 课程关系图 ================= --> <!-- ================= P7 CourseGraph 课程路线图(线条构件版) ================= -->
<div class="page"> <div class="page">
<div class="story-head"> <div class="story-head">
<span class="tag">&lt;CourseGraph /&gt;</span> <span class="tag">&lt;CourseGraph /&gt;</span>
<h2>课程路线图 · 一条主线的学习旅程</h2> <h2>课程路线图 · 线条是构件</h2>
<div class="desc">复刻参考稿的路线语言:一条自上而下的虚线干线串起六个站点,卡片如便签错落两侧;线只管顺序,状态在卡上;①②③ = 读者入口。</div> <div class="desc">路线的最小构件是线条:直段 / 圆角转角 / 曲线 / 分流岔口 / 汇合 / 站点。主线在岔口分流出两条车道,曲线并线后继续前进——网状关系在路线内可读。</div>
</div> </div>
<div class="canvas" style="top: 146px; left: 40px; width: 1200px; height: 380px;"> <!-- 组合:路线总图(曲线 + 分流 + 并线) -->
<div class="gwrap" style="position:absolute; inset:0;"> <div class="canvas" style="top: 138px; left: 40px; width: 880px; height: 306px; padding: 0;">
<svg class="gedges" width="1200" height="380" viewBox="0 0 1200 380"> <svg class="gedges" width="880" height="306" viewBox="0 0 880 306">
<path class="edge" d="M 600 34 V 346"/> <path class="edge" d="M 12 132 H 22"/>
<path class="edge" d="M 600 60 H 484"/> <path class="edge" d="M 182 132 C 207 132, 207 52, 232 52"/>
<path class="edge" d="M 600 110 H 716"/> <path class="edge" d="M 182 132 C 207 132, 207 212, 232 212"/>
<path class="edge" d="M 600 160 H 484"/> <path class="edge" d="M 392 52 C 417 52, 407 120, 432 120"/>
<path class="edge" d="M 600 210 H 716"/> <path class="edge" d="M 392 212 C 417 212, 407 144, 432 144"/>
<path class="edge" d="M 600 260 H 484"/> <path class="edge" d="M 592 132 H 632"/>
<path class="edge" d="M 600 310 H 716"/> <path class="edge" d="M 712 154 V 232"/>
<circle class="station" cx="600" cy="60" r="5"/> <circle class="station" cx="12" cy="132" r="5"/>
<circle class="station" cx="600" cy="110" r="5"/> <circle class="station" cx="207" cy="132" r="5"/>
<circle class="station" cx="600" cy="160" r="5"/> <circle class="station" cx="224" cy="52" r="4.5"/>
<circle class="station" cx="600" cy="210" r="5"/> <circle class="station" cx="224" cy="212" r="4.5"/>
<circle class="station" cx="600" cy="260" r="5"/> <circle class="station" cx="420" cy="132" r="5"/>
<circle class="station" cx="600" cy="310" r="5"/> <circle class="station" cx="624" cy="132" r="4.5"/>
</svg> <circle class="station" cx="712" cy="224" r="4.5"/>
<div class="gnode" style="left:300px; top:37px;"><span class="entry-badge">①</span><span class="icotile" style="background:#e0e7ff;">🌐</span><span class="t">快速开始</span><span class="st done">✓</span></div> </svg>
<div class="gnode rot-l" style="left:720px; top:87px;"><span class="entry-badge">②</span><span class="icotile" style="background:#fce7f3;">⚛️</span><span class="t">快速开始 React</span><span class="st done">✓</span></div> <div class="rnode" style="left:22px; top:110px;"><span class="entry-badge" style="width:20px;height:20px;font-size:11px;">①</span><span class="icotile" style="background:#e0e7ff;">🌐</span><span class="t">快速开始</span><span class="st done">✓</span></div>
<div class="gnode" style="left:300px; top:137px;"><span class="icotile" style="background:#fef3c7;">🧱</span><span class="t">更多示例</span><span class="st done">✓</span></div> <div class="rnode" style="left:232px; top:30px;"><span class="entry-badge" style="width:20px;height:20px;font-size:11px;">②</span><span class="icotile" style="background:#fce7f3;">⚛️</span><span class="t">React</span><span class="st done">✓</span></div>
<div class="gnode" style="left:720px; top:187px;"><span class="icotile" style="background:#d1fae5;">📦</span><span class="t">更多</span><span class="st done">✓</span></div> <div class="rnode" style="left:232px; top:190px;"><span class="icotile" style="background:#fef3c7;">🧱</span><span class="t">更多示例</span><span class="st done">✓</span></div>
<div class="gnode rot-r" style="left:300px; top:237px;"><span class="icotile" style="background:#e0f2fe;">🔗</span><span class="t">全栈基础</span><span class="st lock">🔒</span></div> <div class="rnode" style="left:432px; top:110px;"><span class="icotile" style="background:#d1fae5;">📦</span><span class="t">更多</span><span class="st done">✓</span></div>
<div class="gnode" style="left:720px; top:287px;"><span class="entry-badge">③</span><span class="icotile" style="background:#ede9fe;">🧠</span><span class="t">高级教程</span><span class="st done">✓</span></div> <div class="rnode" style="left:632px; top:110px;"><span class="icotile" style="background:#e0f2fe;">🔗</span><span class="t">全栈基础</span><span class="st lock">🔒</span></div>
<div class="glegend" style="position:absolute; left:24px; bottom:14px;"> <div class="rnode" style="left:632px; top:232px;"><span class="entry-badge" style="width:20px;height:20px;font-size:11px;">③</span><span class="icotile" style="background:#ede9fe;">🧠</span><span class="t">高级教程</span><span class="st done">✓</span></div>
<span><span class="sw"></span>推荐学习顺序(自上而下,一站一卡)</span> <div style="position:absolute; right:12px; top:10px; font-size:11px; color:#6b6b6b;">分流岔口 ×1 · 曲线并线 ×2 · 站点 ×7</div>
<span style="color:#6366f1; font-weight:700;">①②③</span><span>读者入口(见下页)</span> </div>
<!-- 构件:线条组件六原语 -->
<div class="canvas" style="top: 462px; left: 40px; width: 880px; height: 258px;">
<div style="font-size:14px; font-weight:700; color:#1a1a1a; margin-bottom:10px;">&lt;RouteLine /&gt; 线条组件 · 六原语</div>
<div style="display:grid; grid-template-columns:repeat(3, 1fr); gap:12px;">
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 20 28 H 220"/><circle class="station" cx="20" cy="28" r="4.5"/><circle class="station" cx="220" cy="28" r="4.5"/></svg>
<div class="vlabel"><b>segment</b> · 直段</div>
</div>
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 20 44 H 105 Q 125 44 125 24 V 10"/><circle class="station" cx="20" cy="44" r="4.5"/></svg>
<div class="vlabel"><b>elbow</b> · 圆角转角</div>
</div>
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 15 42 C 60 4, 180 58, 225 16"/><circle class="station" cx="15" cy="42" r="4.5"/><circle class="station" cx="225" cy="16" r="4.5"/></svg>
<div class="vlabel"><b>curve</b> · 曲线</div>
</div>
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 20 28 H 80 C 100 28, 100 10, 118 10 H 200"/><path class="edge" d="M 80 28 C 100 28, 100 46, 118 46 H 200"/><circle class="station" cx="80" cy="28" r="4.5"/></svg>
<div class="vlabel"><b>fork</b> · 分流岔口</div>
</div>
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 20 10 H 95 C 113 10, 113 28, 130 28 H 220"/><path class="edge" d="M 20 46 H 95 C 113 46, 113 28, 130 28"/><circle class="station" cx="130" cy="28" r="4.5"/></svg>
<div class="vlabel"><b>merge</b> · 汇合并线</div>
</div>
<div class="linecard">
<svg width="240" height="56" viewBox="0 0 240 56"><path class="edge" d="M 20 28 H 220"/><circle class="station" cx="90" cy="28" r="6"/><circle class="station" cx="170" cy="28" r="6"/></svg>
<div class="vlabel"><b>station</b> · 站点(悬浮于卡间槽内)</div>
</div> </div>
</div> </div>
</div> </div>
<div style="position:absolute; top: 530px; left: 40px; width: 590px; padding: 10px 14px;" class="panel"> <div style="position:absolute; top: 138px; left: 948px; width: 292px;" class="panel">
<h3>Args</h3> <h3 style="margin-bottom:8px;">Args</h3>
<table class="spec tight"> <table class="spec tight">
<tr><th>Prop</th><th>类型</th><th>说明</th></tr> <tr><th>Prop</th><th>类型</th><th>说明</th></tr>
<tr><td class="k"><code>path</code></td><td>courseId[]</td><td>推荐学习顺序,站点与干线由此派生</td></tr> <tr><td class="k"><code>path</code></td><td>Segment[]</td><td>直段/转角/曲线序列</td></tr>
<tr><td class="k"><code>stations</code></td><td>PathNode[]</td><td>站点圆点 + 错落卡片(可微旋转)</td></tr> <tr><td class="k"><code>forks</code></td><td>Fork[]</td><td>分流岔口(分出车道)</td></tr>
<tr><td class="k"><code>status</code></td><td>无 prop</td><td>不在图上编码,由卡片胶囊 / 🔒 表达</td></tr> <tr><td class="k"><code>merges</code></td><td>Merge[]</td><td>曲线并线点</td></tr>
<tr><td class="k"><code>entryPoints</code></td><td>Entry[]</td><td>①②③ 入口徽标,数据见 EntryGuide</td></tr> <tr><td class="k"><code>stations</code></td><td>Node[]</td><td>站点圆点,锚定卡间槽</td></tr>
<tr><td class="k"><code>status</code></td><td>无 prop</td><td>不在图上编码</td></tr>
</table> </table>
</div> </div>
<div style="position:absolute; top: 530px; left: 662px; width: 578px; padding: 10px 14px;" class="panel"> <div style="position:absolute; top: 420px; left: 948px; width: 292px;" class="panel">
<h3 style="margin-bottom:6px;">为什么是路线,不是图(参考稿原则)</h3> <h3 style="margin-bottom:6px;">设计原则</h3>
<div class="note" style="margin-bottom:4px;"><span class="idx">1</span><span class="txt"><b>线只管顺序</b>:状态交给卡片(✓ / 🔒),线保持最低音量。</span></div> <div class="note" style="margin-bottom:4px;"><span class="idx">1</span><span class="txt"><b>线只管顺序</b>:状态交给卡片(✓ / 🔒)。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">2</span><span class="txt"><b>单线无叉的旅程</b>:错落卡片被干线串成路线,顺序自然可读。</span></div> <div class="note" style="margin-bottom:4px;"><span class="idx">2</span><span class="txt"><b>岔口即分支</b>:快速开始分流出 React 线与示例线,在「更多」并线。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">3</span><span class="txt"><b>网状关系放别处</b>:前置/关联看卡片 chips,多入口见 EntryGuide。</span></div> <div class="note" style="margin-bottom:4px;"><span class="idx">3</span><span class="txt"><b>线条是构件</b>:六原语可拼任意路线。</span></div>
<div class="note" style="margin-bottom:0;"><span class="idx">4</span><span class="txt">推荐顺序为<b>示例占位</b>,正式顺序填 courses.ts 后自动更新。</span></div> <div class="note" style="margin-bottom:0;"><span class="idx">4</span><span class="txt">顺序为<b>示例占位</b>,填 courses.ts 自动更新。</span></div>
</div>
</div> </div>
<div class="footline">组件设计稿 · Storybook 拆分 · stack idealjs</div> <div class="footline">组件设计稿 · Storybook 拆分 · stack idealjs</div>
Binary file not shown.