Skip to content

Commit b02a209

Browse files
authored
Merge pull request #1 from lcpu-club/agent/vitepress-ui-port
Port lynn homepage and calendar timeline to VitePress
2 parents 0388498 + acea9eb commit b02a209

27 files changed

Lines changed: 2043 additions & 2344 deletions

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ npm run dev
1313

1414
飞书是动态课程内容的来源:
1515

16-
- Wiki 集合负责整棵讲义目录,Session 映射可继续覆盖单节讲义正文
16+
- Wiki 集合负责整棵讲义目录;网站“课程资料”导航直接显示根节点下的子页面标题
1717
- 课程共享日历中的全部事件直接生成首页和 `/schedule` 活动日历,负责标题、
1818
说明、日期、时间、地点和状态。
1919
- `docs/.vitepress/data/program.ts` 保留 Topic、讲者、提纲等网站策划字段。
@@ -65,18 +65,20 @@ API Scope 之外,应用还必须拥有目标知识空间的资源权限。进
6565
```json
6666
{
6767
"wiki": {
68-
"rootNodeToken": "SURAw8B4riKkhRkUKPYc43k7nHf",
68+
"rootNodeToken": "CWcAw7BUai4MimkMFzEcmV6on7f",
6969
"sourceBaseUrl": "https://lcpu-club.feishu.cn/wiki",
7070
"title": "AI Infra Wiki"
71-
}
71+
},
72+
"sessions": []
7273
}
7374
```
7475

7576
同步器会识别飞书 `<sub-page-list>` 目录块,递归获取所有后代页面,保留层级并
7677
生成 `/wiki/` 导航。页面 URL 使用稳定的 Wiki node token,移动或改名不会
7778
破坏外部链接。
7879

79-
`sessions` 列表用于为单节课程配置:
80+
`sessions` 列表是可选的单节课程映射;不需要独立 Session 页面时保持空数组。
81+
配置单节映射时可使用:
8082

8183
- `wikiNodeToken`:Wiki URL 中 `/wiki/` 后的 token。
8284
- `calendarEventId`:可选。填写后会把共享日历中的该事件链接到对应讲义页;
@@ -102,14 +104,14 @@ npm run sync:feishu
102104

103105
同步器会先在临时目录生成完整结果,所有远端读取和格式校验成功后才替换正式
104106
文件。未知飞书 XML Block、危险 HTML、丢失的日程或下载失败都会中止整批更新。
105-
图片与附件下载到 `docs/public/feishu/<session-id>/`,文件名由内容哈希生成。
107+
图片与附件下载到对应的 `docs/public/feishu/` 子目录,文件名由内容哈希生成。
106108

107109
生成文件包括:
108110

109-
- `docs/sessions/<session-id>.md`
111+
- `docs/sessions/<session-id>.md`(仅在配置独立 Session 映射时生成)
110112
- `docs/wiki/index.md``docs/wiki/<wiki-node-token>.md`
111113
- `docs/.vitepress/data/generated/feishu.json`
112-
- `docs/public/feishu/<session-id>/`
114+
- `docs/public/feishu/<session-id>/`(仅在配置独立 Session 映射时生成)
113115
- `docs/public/feishu/wiki/<wiki-node-token>/`
114116

115117
不要直接修改这些生成文件;请在飞书 Wiki 或日历中修改。

content/feishu/sessions.json

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,9 @@
88
},
99
"publishMeetingUrl": false,
1010
"wiki": {
11-
"rootNodeToken": "SURAw8B4riKkhRkUKPYc43k7nHf",
11+
"rootNodeToken": "CWcAw7BUai4MimkMFzEcmV6on7f",
1212
"sourceBaseUrl": "https://lcpu-club.feishu.cn/wiki",
1313
"title": "AI Infra Wiki"
1414
},
15-
"sessions": [
16-
{
17-
"id": "01",
18-
"wikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
19-
"calendarEventId": "",
20-
"pageTitle": "GPU 与 GPU 编程模型",
21-
"description": "从 SIMD / SIMT 与 CUDA Programming Model,到 Triton / TileLang 的 tile abstraction"
22-
}
23-
]
15+
"sessions": []
2416
}

docs/.vitepress/config.mts

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { defineConfig } from 'vitepress'
2-
import { sessions, topics } from './data/program'
32
import feishuSnapshot from './data/generated/feishu.json'
43

54
interface WikiPage {
@@ -16,18 +15,14 @@ interface WikiSnapshot {
1615
}
1716

1817
const base = '/ai-infra-website/'
19-
const firstPublishedSession = sessions.find(({ href }) => href)
2018
const wiki = (feishuSnapshot as { wiki?: WikiSnapshot }).wiki
21-
const sessionSidebar = topics.map((topic) => ({
22-
text: `Topic ${topic.number} · ${topic.title}`,
23-
collapsed: topic.number !== '01',
24-
items: sessions
25-
.filter((session) => session.topic === topic.key && session.href)
26-
.map((session) => ({
27-
text: `${session.id} · ${session.title}`,
28-
link: session.href!
29-
}))
30-
})).filter(({ items }) => items.length > 0)
19+
const wikiCourseItems = (wiki?.pages ?? [])
20+
.filter((page) => page.parentWikiNodeToken === null)
21+
.sort((left, right) => left.order - right.order)
22+
.map((page) => ({
23+
text: page.title,
24+
link: page.route
25+
}))
3126
const wikiSidebarItems = (parentWikiNodeToken: string | null): any[] =>
3227
(wiki?.pages ?? [])
3328
.filter((page) => page.parentWikiNodeToken === parentWikiNodeToken)
@@ -50,6 +45,11 @@ export default defineConfig({
5045
cleanUrls: true,
5146
appearance: true,
5247
lastUpdated: true,
48+
vite: {
49+
ssr: {
50+
noExternal: ['@schedule-x/vue']
51+
}
52+
},
5353
head: [
5454
[
5555
'meta',
@@ -73,7 +73,7 @@ export default defineConfig({
7373
'meta',
7474
{
7575
property: 'og:description',
76-
content: '从一行 Kernel,到一套大模型系统。七周、四个 Topic,一起把系统跑起来。'
76+
content: '从一行 Kernel,到一套大模型系统。七周、四个主题,一起把系统跑起来。'
7777
}
7878
],
7979
['link', { rel: 'icon', href: `${base}favicon.svg`, type: 'image/svg+xml' }]
@@ -85,30 +85,15 @@ export default defineConfig({
8585
{ text: '课程介绍', link: '/' },
8686
{ text: '活动日历', link: '/schedule' },
8787
...(wiki ? [{ text: wiki.title, link: '/wiki/' }] : []),
88-
...(firstPublishedSession
88+
...(wiki
8989
? [
90-
{
91-
text: `Session ${firstPublishedSession.id}`,
92-
link: firstPublishedSession.href!
93-
}
90+
wikiCourseItems.length > 0
91+
? { text: '课程资料', items: wikiCourseItems }
92+
: { text: '课程资料', link: '/wiki/' }
9493
]
95-
: []),
96-
{
97-
text: '课程资料',
98-
items: [
99-
...(wiki ? [{ text: wiki.title, link: '/wiki/' }] : []),
100-
...sessions
101-
.filter(({ href }) => href)
102-
.map((session) => ({
103-
text: session.title,
104-
link: session.href!
105-
})),
106-
{ text: '完整活动日历', link: '/schedule#full-schedule' }
107-
]
108-
}
94+
: [])
10995
],
11096
sidebar: {
111-
'/sessions/': sessionSidebar,
11297
...(wiki
11398
? {
11499
'/wiki/': [
Lines changed: 6 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
{
22
"version": 1,
3-
"sessions": {
4-
"01": {
5-
"document": {
6-
"wikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
7-
"documentId": "QCpddjfi3oR3LxxRattcszYrnvg",
8-
"objectType": "docx",
9-
"sourceTitle": "Session 1 7.23",
10-
"revisionId": 27
11-
}
12-
}
13-
},
3+
"sessions": {},
144
"calendar": {
155
"timezone": "Asia/Shanghai",
166
"range": {
@@ -49,89 +39,11 @@
4939
},
5040
"wiki": {
5141
"title": "AI Infra Wiki",
52-
"rootNodeToken": "SURAw8B4riKkhRkUKPYc43k7nHf",
53-
"sourceUrl": "https://lcpu-club.feishu.cn/wiki/SURAw8B4riKkhRkUKPYc43k7nHf",
54-
"documentId": "CG7cdsC45ooyVTxorPGcI2Y8nld",
42+
"rootNodeToken": "CWcAw7BUai4MimkMFzEcmV6on7f",
43+
"sourceUrl": "https://lcpu-club.feishu.cn/wiki/CWcAw7BUai4MimkMFzEcmV6on7f",
44+
"documentId": "UFDwdkFbkonl5ExHBFVcJhJOnge",
5545
"objectType": "docx",
56-
"revisionId": 1121,
57-
"pages": [
58-
{
59-
"wikiNodeToken": "E3ltwZcMEiBJy2kusiCcKlk5nzb",
60-
"parentWikiNodeToken": null,
61-
"title": "Topic 1 - Kernel and Compilers",
62-
"route": "/wiki/E3ltwZcMEiBJy2kusiCcKlk5nzb",
63-
"depth": 0,
64-
"order": 0,
65-
"documentId": "LopWdSBvxoi1yJxq5ZYckSwlnJg",
66-
"objectType": "docx",
67-
"revisionId": 14
68-
},
69-
{
70-
"wikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
71-
"parentWikiNodeToken": "E3ltwZcMEiBJy2kusiCcKlk5nzb",
72-
"title": "Session 1 7.23",
73-
"route": "/wiki/VIJPw24sqiPOhXkfEwXcEvVInhg",
74-
"depth": 1,
75-
"order": 1,
76-
"documentId": "QCpddjfi3oR3LxxRattcszYrnvg",
77-
"objectType": "docx",
78-
"revisionId": 27
79-
},
80-
{
81-
"wikiNodeToken": "I6BFwTffUiAKGUk8TgncV6DIn1b",
82-
"parentWikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
83-
"title": "1.1 & 1.2",
84-
"route": "/wiki/I6BFwTffUiAKGUk8TgncV6DIn1b",
85-
"depth": 2,
86-
"order": 2,
87-
"documentId": "GaJGdUDlRowCZSxpOMScacMSncd",
88-
"objectType": "docx",
89-
"revisionId": 148
90-
},
91-
{
92-
"wikiNodeToken": "QmwywJ9UjiysBakT3vychu0PnJe",
93-
"parentWikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
94-
"title": "推送",
95-
"route": "/wiki/QmwywJ9UjiysBakT3vychu0PnJe",
96-
"depth": 2,
97-
"order": 3,
98-
"documentId": "Vr27dsf11ooFf2xhtYzcvFaZnkw",
99-
"objectType": "docx",
100-
"revisionId": 787
101-
},
102-
{
103-
"wikiNodeToken": "YMv1wqrGLiGqDjk8Wv1c08uOnPd",
104-
"parentWikiNodeToken": "VIJPw24sqiPOhXkfEwXcEvVInhg",
105-
"title": "内容打磨",
106-
"route": "/wiki/YMv1wqrGLiGqDjk8Wv1c08uOnPd",
107-
"depth": 2,
108-
"order": 4,
109-
"documentId": "LYZydg4NDo6Y11xUZEEc7wfqnVe",
110-
"objectType": "docx",
111-
"revisionId": 236
112-
},
113-
{
114-
"wikiNodeToken": "UuLEwoEJRiSaBak8gdnc7UfPn9c",
115-
"parentWikiNodeToken": null,
116-
"title": "Weiming HPC Training Camp x LCPU AI Infra Seminars 暑期活动方案",
117-
"route": "/wiki/UuLEwoEJRiSaBak8gdnc7UfPn9c",
118-
"depth": 0,
119-
"order": 5,
120-
"documentId": "Hjbud6tOJotp6YxipiIcP23PnM5",
121-
"objectType": "docx",
122-
"revisionId": 1125
123-
},
124-
{
125-
"wikiNodeToken": "BtqywAZHNiA38KkEwb0cNvTUnNf",
126-
"parentWikiNodeToken": null,
127-
"title": "Weiming HPC Training Camp x LCPU AI Infra Seminars (筹)",
128-
"route": "/wiki/BtqywAZHNiA38KkEwb0cNvTUnNf",
129-
"depth": 0,
130-
"order": 6,
131-
"documentId": "D02XdMhnkoBo6GxdXzacH16KnHb",
132-
"objectType": "docx",
133-
"revisionId": 51
134-
}
135-
]
46+
"revisionId": 24,
47+
"pages": []
13648
}
13749
}

docs/.vitepress/data/program.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ const staticSessions: Session[] = [
105105
'CUDA:grid / block / thread、warp、host / device',
106106
'Triton / TileLang:CTA-level 与 tile abstraction'
107107
],
108-
owners: ['超算队同学'],
109-
href: '/sessions/01'
108+
owners: ['超算队同学']
110109
},
111110
{
112111
id: '02',
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script setup lang="ts">
2+
import { onMounted, ref } from 'vue'
3+
import CalendarTimelineClient from './CalendarTimelineClient.vue'
4+
5+
const mounted = ref(false)
6+
7+
onMounted(() => {
8+
mounted.value = true
9+
})
10+
</script>
11+
12+
<template>
13+
<section
14+
id="calendar-timeline"
15+
class="calendar-timeline-section"
16+
aria-label="交互式课程日历"
17+
>
18+
<div class="calendar-timeline-shell">
19+
<CalendarTimelineClient v-if="mounted" />
20+
<div
21+
v-else
22+
class="calendar-timeline-loading"
23+
role="status"
24+
aria-live="polite"
25+
>
26+
<strong>正在加载交互日历…</strong>
27+
<p>下方日程列表会始终保留。</p>
28+
</div>
29+
</div>
30+
</section>
31+
</template>

0 commit comments

Comments
 (0)