design: RouteLine 并行线设计——三线并行不合并、单线圆点/多线扁点自适应、新增全栈基础卡

This commit is contained in:
cqh963852 committed 2026-10-02 22:58:19 +08:00
1 parent baa23ee55f
commit 8eca17586e
2 files changed
+78 -61

No files matched your search

+78 -61
View File
@@ -217,30 +217,30 @@
/* P7 路线图(线条构件版 · 大卡 CourseCard 实例) */
.rcard {
position: absolute; width: 190px;
background: #ffffff; border-radius: 14px; padding: 10px;
position: absolute; width: 136px;
background: #ffffff; border-radius: 12px; padding: 10px;
box-shadow: 0 1px 3px rgba(26,26,26,0.08);
}
.rcard .rzone {
height: 95px; border-radius: 8px;
height: 65px; border-radius: 7px;
display: flex; align-items: center; justify-content: center;
position: relative;
}
.rcard .rzone span { font-size: 30px; }
.rcard .rzone span { font-size: 24px; }
.rcard .rzone i {
position: absolute; right: 7px; bottom: 7px; font-style: normal;
font-size: 9px; color: #6b6b6b; background: rgba(255,255,255,0.9);
padding: 1px 6px; border-radius: 999px; font-weight: 600;
position: absolute; right: 6px; bottom: 6px; font-style: normal;
font-size: 8.5px; color: #6b6b6b; background: rgba(255,255,255,0.9);
padding: 1px 5px; border-radius: 999px; font-weight: 600;
}
.rcard .rt { display: flex; align-items: center; gap: 7px; margin-top: 9px; }
.rcard .rt .icotile { width: 22px; height: 22px; border-radius: 7px; font-size: 12px; flex: none; }
.rcard .rt b { font-size: 13px; color: #1a1a1a; flex: 1; }
.rcard .st { font-size: 9.5px; padding: 1px 6px; border-radius: 999px; font-weight: 600; flex: none; }
.rcard .rt { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.rcard .rt .icotile { width: 18px; height: 18px; border-radius: 6px; font-size: 10px; flex: none; }
.rcard .rt b { font-size: 12px; color: #1a1a1a; flex: 1; }
.rcard .st { font-size: 9px; padding: 1px 5px; border-radius: 999px; font-weight: 600; flex: none; }
.rcard .st.done { background: #efe6fb; color: #6d28d9; }
.rcard .st.lock { background: #ffffff; color: #6b6b6b; border: 1px solid #d5d5d3; }
.linecard {
background: #ffffff; border-radius: 14px; padding: 10px 12px 8px;
display: flex; flex-direction: column; gap: 6px;
background: #ffffff; border-radius: 12px; padding: 8px 10px 6px;
display: flex; flex-direction: column; gap: 4px;
box-shadow: 0 1px 2px rgba(26,26,26,0.06);
}
</style>
@@ -661,81 +661,97 @@
<div class="story-head">
<span class="tag">&lt;CourseGraph /&gt;</span>
<h2>课程路线图 · 线条是构件</h2>
<div class="desc">路线的最小构件是线条:直段 / 圆角转角 / 直角步进 / 分流岔口 / 汇合 / 站点,横平竖直。CourseCard 由路线串联:岔口分流、并线前进——网状关系在路线内可读。</div>
<div class="desc">线条构件:直段 / 转角 / 步进 / 分流 / 并线 / 并行 / 站点,横平竖直。并行线逐条不合并;单线圆点、多线扁点。CourseCard 由路线串联成网。</div>
</div>
<!-- 构件:RouteLine 六原语(横平竖直 · 小圆角) -->
<div class="canvas" style="top: 138px; left: 40px; width: 880px; height: 258px; padding: 16px 22px;">
<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;">
<!-- 构件:RouteLine 八原语(横平竖直 · 小圆角 · 并行不合并) -->
<div class="canvas" style="top: 138px; left: 40px; width: 880px; height: 210px; padding: 12px 20px;">
<div style="font-size:14px; font-weight:700; color:#1a1a1a; margin-bottom:8px;">&lt;RouteLine /&gt; 线条组件 · 八原语</div>
<div style="display:grid; grid-template-columns:repeat(4, 1fr); gap:10px;">
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><path class="edge" d="M 20 26 H 220"/><circle class="station" cx="20" cy="26" r="2.8"/><circle class="station" cx="220" cy="26" r="2.8"/></svg>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 22 H 160"/><circle class="station" cx="16" cy="22" r="2.8"/><circle class="station" cx="160" cy="22" r="2.8"/></svg>
<div class="vlabel"><b>segment</b> · 直段</div>
</div>
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><path class="edge" d="M 20 42 H 90 A 8 8 0 0 0 98 34 V 8"/><circle class="station" cx="20" cy="42" r="2.8"/><circle class="station" cx="98" cy="8" r="2.8"/></svg>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 36 H 66 A 8 8 0 0 0 74 28 V 8"/><circle class="station" cx="16" cy="36" r="2.8"/><circle class="station" cx="74" cy="8" r="2.8"/></svg>
<div class="vlabel"><b>elbow</b> · 圆角转角</div>
</div>
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><path class="edge" d="M 30 42 H 60 A 8 8 0 0 0 68 34 V 18 A 8 8 0 0 1 76 10 H 220"/><circle class="station" cx="30" cy="42" r="2.8"/><circle class="station" cx="220" cy="10" r="2.8"/></svg>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 36 H 40 A 8 8 0 0 0 48 28 V 16 A 8 8 0 0 1 56 8 H 160"/><circle class="station" cx="16" cy="36" r="2.8"/><circle class="station" cx="160" cy="8" r="2.8"/></svg>
<div class="vlabel"><b>step</b> · 直角步进</div>
</div>
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><path class="edge" d="M 20 26 H 54"/><path class="edge" d="M 54 26 A 6 6 0 0 0 60 20 V 14 A 6 6 0 0 1 66 8 H 220"/><path class="edge" d="M 54 26 A 6 6 0 0 1 60 32 V 38 A 6 6 0 0 0 66 44 H 220"/><circle class="station" cx="20" cy="26" r="2.8"/><circle class="station" cx="220" cy="8" r="2.8"/><circle class="station" cx="220" cy="44" r="2.8"/></svg>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 22 H 40"/><path class="edge" d="M 40 22 A 6 6 0 0 0 46 16 V 12 A 6 6 0 0 1 52 6 H 160"/><path class="edge" d="M 40 22 A 6 6 0 0 1 46 28 V 32 A 6 6 0 0 0 52 38 H 160"/><circle class="station" cx="16" cy="22" r="2.8"/><circle class="station" cx="160" cy="6" r="2.8"/><circle class="station" cx="160" cy="38" r="2.8"/></svg>
<div class="vlabel"><b>fork</b> · 分流岔口</div>
</div>
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><path class="edge" d="M 20 8 H 144 A 6 6 0 0 1 150 14 V 20 A 6 6 0 0 0 156 26 H 220"/><path class="edge" d="M 20 44 H 144 A 6 6 0 0 0 150 38 V 32 A 6 6 0 0 1 156 26 H 220"/><circle class="station" cx="20" cy="8" r="2.8"/><circle class="station" cx="20" cy="44" r="2.8"/><circle class="station" cx="220" cy="26" r="2.8"/></svg>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 6 H 106 A 6 6 0 0 1 112 12 V 16 A 6 6 0 0 0 118 22 H 160"/><path class="edge" d="M 16 38 H 106 A 6 6 0 0 0 112 32 V 28 A 6 6 0 0 1 118 22 H 160"/><circle class="station" cx="16" cy="6" r="2.8"/><circle class="station" cx="16" cy="38" r="2.8"/><circle class="station" cx="160" cy="22" r="2.8"/></svg>
<div class="vlabel"><b>merge</b> · 汇合并线</div>
</div>
<div class="linecard">
<svg width="240" height="52" viewBox="0 0 240 52"><rect x="8" y="12" width="30" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><rect x="202" y="12" width="30" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><path class="edge" d="M 38 26 H 202"/><circle class="station" cx="38" cy="26" r="3"/><circle class="station" cx="202" cy="26" r="3"/></svg>
<div class="vlabel"><b>station</b> · 站点(半嵌卡边)</div>
<svg width="176" height="44" viewBox="0 0 176 44"><path class="edge" d="M 16 18 H 160"/><path class="edge" d="M 16 22 H 160"/><path class="edge" d="M 16 26 H 160"/></svg>
<div class="vlabel"><b>parallel</b> · 并行线(不合并)</div>
</div>
<div class="linecard">
<svg width="176" height="44" viewBox="0 0 176 44"><rect x="6" y="8" width="26" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><rect x="144" y="8" width="26" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><path class="edge" d="M 32 22 H 144"/><circle class="station" cx="32" cy="22" r="3"/><circle class="station" cx="144" cy="22" r="3"/></svg>
<div class="vlabel"><b>dot</b> · 单线圆点(半嵌卡边)</div>
</div>
<div class="linecard">
<svg width="176" height="44" viewBox="0 0 176 44"><rect x="6" y="8" width="26" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><rect x="144" y="8" width="26" height="28" rx="6" fill="#f4f4f2" stroke="#e2e2e0"/><path class="edge" d="M 32 18 H 144"/><path class="edge" d="M 32 22 H 144"/><path class="edge" d="M 32 26 H 144"/><ellipse class="station" cx="144" cy="22" rx="7" ry="4"/></svg>
<div class="vlabel"><b>flat</b> · 多线扁点(半嵌卡边)</div>
</div>
</div>
</div>
<!-- 实例:CourseCard 之间的路线(正交走线 + R8 小圆角,站点贴卡边) -->
<div class="canvas" style="top: 406px; left: 40px; width: 880px; height: 330px; padding: 0;">
<svg class="gedges" width="880" height="330" viewBox="0 0 880 330">
<path class="edge" d="M 6 165 H 20"/>
<path class="edge" d="M 210 165 H 232"/>
<path class="edge" d="M 232 165 A 8 8 0 0 0 240 157 V 92 A 8 8 0 0 1 248 84 H 345"/>
<path class="edge" d="M 232 165 A 8 8 0 0 1 240 173 V 238 A 8 8 0 0 0 248 246 H 345"/>
<path class="edge" d="M 535 84 H 557 A 8 8 0 0 1 565 92 V 157 A 8 8 0 0 0 573 165 H 670"/>
<path class="edge" d="M 535 246 H 557 A 8 8 0 0 0 565 238 V 173 A 8 8 0 0 1 573 165 H 670"/>
<path class="edge" d="M 860 165 H 872"/>
<!-- 实例:CourseCard 之间的路线(三线并行不合并 · 单线圆点 / 多线扁点) -->
<div class="canvas" style="top: 356px; left: 40px; width: 880px; height: 388px; padding: 0;">
<svg class="gedges" width="880" height="388" viewBox="0 0 880 388">
<path class="edge" d="M 6 194 H 20"/>
<path class="edge" d="M 156 194 H 372"/>
<path class="edge" d="M 168 194 H 236 A 8 8 0 0 0 244 186 V 74 A 8 8 0 0 1 252 66 H 372"/>
<path class="edge" d="M 440 252 V 265"/>
<path class="edge" d="M 508 66 H 596 A 8 8 0 0 1 604 74 V 182 A 8 8 0 0 0 612 190 H 724"/>
<path class="edge" d="M 508 194 H 724"/>
<path class="edge" d="M 508 322 H 596 A 8 8 0 0 0 604 314 V 206 A 8 8 0 0 1 612 198 H 724"/>
<path class="edge" d="M 860 194 H 872"/>
</svg>
<div class="rcard" style="left:20px; top:92px;">
<span class="entry-badge" style="width:20px;height:20px;font-size:11px;">①</span>
<div class="rzone" style="background:#e0e7ff;"><span>🌐</span><i>16:9 · GIF</i></div>
<div class="rcard" style="left:20px; top:137px;">
<span class="entry-badge" style="width:18px;height:18px;font-size:10px;">①</span>
<div class="rzone" style="background:#e0e7ff;"><span>🌐</span><i>16:9</i></div>
<div class="rt"><span class="icotile" style="background:#e0e7ff;">🌐</span><b>快速开始</b><span class="st done">✓</span></div>
</div>
<div class="rcard" style="left:345px; top:11px;">
<span class="entry-badge" style="width:20px;height:20px;font-size:11px;">②</span>
<div class="rzone" style="background:#fce7f3;"><span>⚛️</span><i>16:9 · GIF</i></div>
<div class="rcard" style="left:372px; top:9px;">
<span class="entry-badge" style="width:18px;height:18px;font-size:10px;">②</span>
<div class="rzone" style="background:#fce7f3;"><span>⚛️</span><i>16:9</i></div>
<div class="rt"><span class="icotile" style="background:#fce7f3;">⚛️</span><b>React</b><span class="st done">✓</span></div>
</div>
<div class="rcard" style="left:345px; top:173px;">
<div class="rzone" style="background:#fef3c7;"><span>🧱</span><i>16:9 · GIF</i></div>
<div class="rcard" style="left:372px; top:137px;">
<div class="rzone" style="background:#fef3c7;"><span>🧱</span><i>16:9</i></div>
<div class="rt"><span class="icotile" style="background:#fef3c7;">🧱</span><b>更多示例</b><span class="st done">✓</span></div>
</div>
<div class="rcard" style="left:670px; top:92px;">
<div class="rzone" style="background:#d1fae5;"><span>📦</span><i>16:9 · GIF</i></div>
<div class="rcard" style="left:372px; top:265px;">
<div class="rzone" style="background:#e0f2fe;"><span>🔗</span><i>16:9</i></div>
<div class="rt"><span class="icotile" style="background:#e0f2fe;">🔗</span><b>全栈基础</b><span class="st lock">🔒</span></div>
</div>
<div class="rcard" style="left:724px; top:137px;">
<div class="rzone" style="background:#d1fae5;"><span>📦</span><i>16:9</i></div>
<div class="rt"><span class="icotile" style="background:#d1fae5;">📦</span><b>更多</b><span class="st done">✓</span></div>
</div>
<svg class="gedges" width="880" height="330" viewBox="0 0 880 330">
<circle class="station" cx="20" cy="165" r="2.8"/>
<circle class="station" cx="210" cy="165" r="2.8"/>
<circle class="station" cx="345" cy="84" r="2.8"/>
<circle class="station" cx="345" cy="246" r="2.8"/>
<circle class="station" cx="535" cy="84" r="2.8"/>
<circle class="station" cx="535" cy="246" r="2.8"/>
<circle class="station" cx="670" cy="165" r="2.8"/>
<circle class="station" cx="860" cy="165" r="2.8"/>
<svg class="gedges" width="880" height="388" viewBox="0 0 880 388">
<circle class="station" cx="20" cy="194" r="2.8"/>
<circle class="station" cx="156" cy="194" r="2.8"/>
<circle class="station" cx="372" cy="66" r="2.8"/>
<circle class="station" cx="372" cy="194" r="2.8"/>
<circle class="station" cx="508" cy="66" r="2.8"/>
<circle class="station" cx="508" cy="194" r="2.8"/>
<circle class="station" cx="440" cy="252" r="2.8"/>
<circle class="station" cx="440" cy="265" r="2.8"/>
<circle class="station" cx="508" cy="322" r="2.8"/>
<ellipse class="station" cx="724" cy="194" rx="8" ry="4"/>
<circle class="station" cx="860" cy="194" r="2.8"/>
</svg>
<div style="position:absolute; right:14px; top:250px; font-size:11px; color:#6b6b6b;">→ 下一程:全栈基础 🔒 · ③ 高级教程</div>
<div style="position:absolute; right:12px; top:10px; font-size:11px; color:#6b6b6b;">分流 ×1 · 并线 ×2 · 站点 ×8</div>
<div style="position:absolute; right:14px; top:262px; font-size:11px; color:#6b6b6b;">→ 下一程:③ 高级教程</div>
<div style="position:absolute; right:12px; top:10px; font-size:11px; color:#6b6b6b;">分流 ×1 · 三线并行 ×1 · 圆点 ×10 · 扁点 ×1</div>
</div>
<div style="position:absolute; top: 138px; left: 948px; width: 292px;" class="panel">
@@ -745,17 +761,18 @@
<tr><td class="k"><code>path</code></td><td>Segment[]</td><td>直段/转角/步进序列</td></tr>
<tr><td class="k"><code>forks</code></td><td>Fork[]</td><td>分流岔口(分出车道)</td></tr>
<tr><td class="k"><code>merges</code></td><td>Merge[]</td><td>直角并线点</td></tr>
<tr><td class="k"><code>stations</code></td><td>Node[]</td><td>站点圆点,半嵌卡边</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>
</div>
<div style="position:absolute; top: 420px; left: 948px; width: 292px;" class="panel">
<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">2</span><span class="txt"><b>背景级线条</b>:鼠尾草绿 <code>#A2B49B</code> · 1.4px · 划隙 4:2;站点 <code>#758C72</code> 半嵌卡边(圆点中心落在卡边上),直径 ≈ 4× 线宽。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">3</span><span class="txt"><b>横平竖直</b>:走向只有水平与垂直,转折用小圆角 R8,全图无斜线。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">4</span><span class="txt"><b>岔口即分支</b>:快速开始分流出 React 线与示例线,在「更多」并线。</span></div>
<div class="note" style="margin-bottom:0;"><span class="idx">5</span><span class="txt">顺序为<b>示例占位</b>,填 courses.ts 自动更新。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">2</span><span class="txt"><b>背景级线条</b>:鼠尾草绿 <code>#A2B49B</code> · 1.4px · 划隙 4:2;站点 <code>#758C72</code> 半嵌卡边。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">3</span><span class="txt"><b>横平竖直</b>:走向只有水平与垂直,转折用小圆角 R8。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">4</span><span class="txt"><b>并行不合并</b>:多线并行逐条渲染,间距 4px,不合成一条。</span></div>
<div class="note" style="margin-bottom:4px;"><span class="idx">5</span><span class="txt"><b>站点随线变形</b>:单线 → 圆点 r2.8;多线入同一卡口 → 扁点 rx8×ry4。</span></div>
<div class="note" style="margin-bottom:0;"><span class="idx">6</span><span class="txt">顺序为<b>示例占位</b>,填 courses.ts 自动更新。</span></div>
</div>
<div class="footline">组件设计稿 · Storybook 拆分 · stack idealjs</div>