design: 关系图改为旅程路线——重读参考图核心设计目标
- 重读参考图:连线是点串点的连续自上而下干线(站点圆点悬浮卡间槽内), 便签式错落卡片、无箭头无分叉;线只管顺序、状态在卡上(低视觉音量配角) - P7 重做:indigo 虚线干线 + 六站点 + 两列错落卡(个别微旋转)+ 状态徽回卡; 网状前置/关联明确移交卡片 chips 与 EntryGuide - Args 改 path/stations/status/entryPoints;图例与说明面板同步 - 修复:Chromium 打印空白尾页(合并只取首页);恢复被误删的 EntryGuide 页 及其页码;清除 P7 内混入的重复面板
This commit is contained in:
1 parent
47f1549a0b
commit
c7f17fc323
5 files changed
+44
-33
No files matched your search
@@ -57,7 +57,8 @@ out_dir, stem = sys.argv[1], sys.argv[2]
|
|||||||
pdfs = sorted(glob.glob(f"{out_dir}/page-*.pdf"), key=lambda p: int(re.search(r"(\d+)", os.path.basename(p)).group(1)))
|
pdfs = sorted(glob.glob(f"{out_dir}/page-*.pdf"), key=lambda p: int(re.search(r"(\d+)", os.path.basename(p)).group(1)))
|
||||||
w = PdfWriter()
|
w = PdfWriter()
|
||||||
for p in pdfs:
|
for p in pdfs:
|
||||||
w.append(p)
|
# 只取第 1 页:Chromium 打印偶发产生一个空白尾页(几何已验证无溢出)
|
||||||
|
w.append(p, pages=(0, 1))
|
||||||
w.add_metadata({"/Title": f"课程书架设计稿 · {stem} · stack idealjs", "/Author": "Z.ai", "/Creator": "Z.ai"})
|
w.add_metadata({"/Title": f"课程书架设计稿 · {stem} · stack idealjs", "/Author": "Z.ai", "/Creator": "Z.ai"})
|
||||||
with open(f"{stem}.pdf", "wb") as f:
|
with open(f"{stem}.pdf", "wb") as f:
|
||||||
w.write(f)
|
w.write(f)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 131 KiB |
@@ -181,7 +181,12 @@
|
|||||||
display: flex; align-items: center; gap: 9px; padding: 0 14px;
|
display: flex; align-items: center; gap: 9px; padding: 0 14px;
|
||||||
box-shadow: 0 1px 2px rgba(26,26,26,0.10);
|
box-shadow: 0 1px 2px rgba(26,26,26,0.10);
|
||||||
}
|
}
|
||||||
.gnode .t { font-size: 13px; font-weight: 700; color: #1a1a1a; }
|
.gnode .t { font-size: 13px; font-weight: 700; color: #1a1a1a; flex: 1; }
|
||||||
|
.gnode .st { font-size: 10px; padding: 1px 7px; border-radius: 999px; font-weight: 600; }
|
||||||
|
.gnode .st.done { background: #efe6fb; color: #6d28d9; }
|
||||||
|
.gnode .st.lock { background: #ffffff; color: #6b6b6b; border: 1px solid #d5d5d3; }
|
||||||
|
.gnode.rot-l { transform: rotate(-1.5deg); }
|
||||||
|
.gnode.rot-r { transform: rotate(1.2deg); }
|
||||||
.entry-badge {
|
.entry-badge {
|
||||||
position: absolute; top: -10px; left: -10px;
|
position: absolute; top: -10px; left: -10px;
|
||||||
width: 22px; height: 22px; border-radius: 50%;
|
width: 22px; height: 22px; border-radius: 50%;
|
||||||
@@ -189,9 +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; }
|
.gedges .edge { fill: none; stroke-width: 1.5; stroke-linecap: butt; stroke-dasharray: 9 4; stroke: #6366f1; }
|
||||||
.gedges .edge.pre { stroke: #9a9a98; }
|
.gedges .station { fill: #6366f1; }
|
||||||
.gedges .edge.rel { stroke: #c9c9c7; }
|
|
||||||
.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; }
|
||||||
@@ -236,7 +240,7 @@
|
|||||||
<div class="toc-card"><div class="t"><CourseCard /></div><div class="c">课程白卡</div><div class="d">16:9 预期区(desc ⇄ GIF)· 状态 · 按钮</div></div>
|
<div class="toc-card"><div class="t"><CourseCard /></div><div class="c">课程白卡</div><div class="d">16:9 预期区(desc ⇄ GIF)· 状态 · 按钮</div></div>
|
||||||
<div class="toc-card"><div class="t"><CourseCardMedia /></div><div class="c">播放态</div><div class="d">定时翻转/悬停锁定 + ⏱ GIF 循环</div></div>
|
<div class="toc-card"><div class="t"><CourseCardMedia /></div><div class="c">播放态</div><div class="d">定时翻转/悬停锁定 + ⏱ GIF 循环</div></div>
|
||||||
<div class="toc-card"><div class="t"><EventsPanel /></div><div class="c">事件栏</div><div class="d">彩色条目:类型 · 日期 · 描述 · 时间</div></div>
|
<div class="toc-card"><div class="t"><EventsPanel /></div><div class="c">事件栏</div><div class="d">彩色条目:类型 · 日期 · 描述 · 时间</div></div>
|
||||||
<div class="toc-card"><div class="t"><CourseGraph /></div><div class="c">课程关系图</div><div class="d">前置实线 · 关联虚线 · 入口 ①②③</div></div>
|
<div class="toc-card"><div class="t"><CourseGraph /></div><div class="c">课程路线图</div><div class="d">一条干线六站点 · 入口 ①②③</div></div>
|
||||||
<div class="toc-card"><div class="t"><EntryGuide /></div><div class="c">入口梳理</div><div class="d">读者画像 → 起点与路径</div></div>
|
<div class="toc-card"><div class="t"><EntryGuide /></div><div class="c">入口梳理</div><div class="d">读者画像 → 起点与路径</div></div>
|
||||||
<div class="toc-card"><div class="t">Atoms</div><div class="c">原子组件</div><div class="d">Pill · CircleButton · Chip · IconTile</div></div>
|
<div class="toc-card"><div class="t">Atoms</div><div class="c">原子组件</div><div class="d">Pill · CircleButton · Chip · IconTile</div></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -628,51 +632,57 @@
|
|||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="story-head">
|
<div class="story-head">
|
||||||
<span class="tag"><CourseGraph /></span>
|
<span class="tag"><CourseGraph /></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="canvas" style="top: 146px; left: 40px; width: 1200px; height: 380px;">
|
||||||
<div class="gwrap" style="position:absolute; inset:0;">
|
<div class="gwrap" style="position:absolute; inset:0;">
|
||||||
<svg class="gedges" width="1200" height="380" viewBox="0 0 1200 380">
|
<svg class="gedges" width="1200" height="380" viewBox="0 0 1200 380">
|
||||||
<path d="M 234 186 H 263 Q 271 186 271 178 V 81 Q 271 73 279 73 H 316" class="edge pre"/>
|
<path class="edge" d="M 600 34 V 346"/>
|
||||||
<path d="M 234 200 H 275 Q 283 200 283 208 V 305 Q 283 313 291 313 H 316" class="edge pre"/>
|
<path class="edge" d="M 600 60 H 484"/>
|
||||||
<path d="M 504 73 H 552 Q 560 73 560 81 V 305 Q 560 313 568 313 H 596" class="edge pre"/>
|
<path class="edge" d="M 600 110 H 716"/>
|
||||||
<path d="M 504 73 H 876" class="edge pre"/>
|
<path class="edge" d="M 600 160 H 484"/>
|
||||||
<path d="M 690 286 V 158 Q 690 150 698 150 H 912 Q 920 150 920 142 V 100" class="edge pre"/>
|
<path class="edge" d="M 600 210 H 716"/>
|
||||||
<path d="M 970 100 V 286" class="edge pre"/>
|
<path class="edge" d="M 600 260 H 484"/>
|
||||||
<path d="M 504 313 H 596" class="edge rel"/>
|
<path class="edge" d="M 600 310 H 716"/>
|
||||||
|
<circle class="station" cx="600" cy="60" r="5"/>
|
||||||
|
<circle class="station" cx="600" cy="110" r="5"/>
|
||||||
|
<circle class="station" cx="600" cy="160" r="5"/>
|
||||||
|
<circle class="station" cx="600" cy="210" r="5"/>
|
||||||
|
<circle class="station" cx="600" cy="260" r="5"/>
|
||||||
|
<circle class="station" cx="600" cy="310" r="5"/>
|
||||||
</svg>
|
</svg>
|
||||||
<div class="gnode" style="left:50px; top:170px;"><span class="entry-badge">①</span><span class="icotile" style="background:#e0e7ff;">🌐</span><span class="t">快速开始</span></div>
|
<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>
|
||||||
<div class="gnode" style="left:320px; top:50px;"><span class="entry-badge">②</span><span class="icotile" style="background:#fce7f3;">⚛️</span><span class="t">快速开始 React</span></div>
|
<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="gnode" style="left:320px; top:290px;"><span class="icotile" style="background:#fef3c7;">🧱</span><span class="t">更多示例</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="gnode" style="left:600px; top:290px;"><span class="icotile" style="background:#d1fae5;">📦</span><span class="t">更多</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="gnode" style="left:880px; top:50px;"><span class="icotile" style="background:#e0f2fe;">🔗</span><span class="t">全栈基础</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="gnode" style="left:880px; top:290px;"><span class="entry-badge">③</span><span class="icotile" style="background:#ede9fe;">🧠</span><span class="t">高级教程</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="glegend" style="position:absolute; left:24px; bottom:14px;">
|
<div class="glegend" style="position:absolute; left:24px; bottom:14px;">
|
||||||
<span><span class="sw"></span>前置 prerequisites(深虚线,左→右为学习方向)</span>
|
<span><span class="sw"></span>推荐学习顺序(自上而下,一站一卡)</span>
|
||||||
<span><span class="sw rel"></span>关联 related(浅虚线)</span>
|
|
||||||
<span style="color:#6366f1; font-weight:700;">①②③</span><span>读者入口(见下页)</span>
|
<span style="color:#6366f1; font-weight:700;">①②③</span><span>读者入口(见下页)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="position:absolute; top: 544px; left: 40px; width: 590px;" class="panel">
|
<div style="position:absolute; top: 530px; left: 40px; width: 590px; padding: 10px 14px;" class="panel">
|
||||||
<h3>Args</h3>
|
<h3>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>nodes</code></td><td>Course[]</td><td>直接取 courses.ts,渲染为迷你章节卡</td></tr>
|
<tr><td class="k"><code>path</code></td><td>courseId[]</td><td>推荐学习顺序,站点与干线由此派生</td></tr>
|
||||||
<tr><td class="k"><code>edges.prerequisites</code></td><td>[from,to][]</td><td>深虚线折线,由每章 prerequisites 派生</td></tr>
|
<tr><td class="k"><code>stations</code></td><td>PathNode[]</td><td>站点圆点 + 错落卡片(可微旋转)</td></tr>
|
||||||
<tr><td class="k"><code>edges.related</code></td><td>[from,to][]</td><td>无向浅虚线,由 related 派生</td></tr>
|
<tr><td class="k"><code>status</code></td><td>无 prop</td><td>不在图上编码,由卡片胶囊 / 🔒 表达</td></tr>
|
||||||
<tr><td class="k"><code>entryPoints</code></td><td>Entry[]</td><td>①②③ 入口徽标,数据见 EntryGuide</td></tr>
|
<tr><td class="k"><code>entryPoints</code></td><td>Entry[]</td><td>①②③ 入口徽标,数据见 EntryGuide</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div style="position:absolute; top: 544px; left: 662px; width: 578px;" class="panel">
|
<div style="position:absolute; top: 530px; left: 662px; width: 578px; padding: 10px 14px;" class="panel">
|
||||||
<h3 style="margin-bottom:6px;">为什么要关系图(skill 依据)</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>:错落卡片被干线串成路线,顺序自然可读。</span></div>
|
||||||
<div class="note" style="margin-bottom:4px;"><span class="idx">3</span><span class="txt"><b>入口不锁死</b>:③ 直达是合法路径(skill 死原则)。</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:0;"><span class="idx">4</span><span class="txt">关系现为<b>示例占位</b>;正式关系填 courses.ts 后图自动更新。连线无箭头,方向由布局流向(左→右)表达;卡片 chips 对应:前置实线边框、关联虚线边框。</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.
Reference in new issue
Block a user