Repository navigation
feat:首页公告卡片区与创建公告表单 - #42
Conversation
- 新增 scripts/gen-announcements.mjs:从公告页 md 自动提取数据生成 JSON,predev/prebuild 钩子自动同步 - 新增 AnnouncementCards 组件:首页展示最新 6 条公告卡片,滚动交错浮入动画,点击跳转原文 - theme/index.tsx 覆写 HomeLayout,经 afterFeatures 插槽挂载(仅中文站) - 新增 /announcement/create 表单页:填写链接+标题实时预览卡片,生成 Markdown 片段,一键复制并跳转 GitHub 编辑页提交 PR - 首页公告区新增「创建公告」入口按钮 - 全部样式使用 Rspress 主题变量,深浅色自适应,prefers-reduced-motion 下关闭动画
- 公告数据独立为仓库根目录 announcements.md(从 docs/zh/announcement/index.md 迁出) - 公告页改为全量卡片墙:39 条全展示、按年份分组、blur-fade 滚动入场动画(纯 CSS,无新依赖) - 提取脚本支持无链接里程碑条目,渲染为不可点击的静态卡片 - 创建公告表单改走 Fork 流程:主按钮变为「Fork 仓库并编辑」,步骤说明更新;社团成员保留直链编辑入口 - GitHub 编辑链接指向新的 announcements.md
- 撤销「Fork 仓库并编辑」按钮:已 Fork 的提交者点 /fork 会碰壁 - 改为编辑直链:未 Fork 自动引导创建,已 Fork 自动在自己的 Fork 中编辑,仓库成员提示新建分支 - 步骤文案按三种身份说明,成员提示并入步骤
announcements.md 随本 PR 才合入 master,合并前本地预览点击 「去 GitHub 提交」会因 master 上无此文件而 404。 现检测 localhost 自动切换到 new_page 分支链接,并显示提示; 生产环境(非 localhost)仍指向 master,行为不变。
- 新增 GitHub 用户名字段与「检测我的 Fork」按钮:
调用免鉴权 API GET /repos/{user}/website 判断 Fork 是否存在
- 已 Fork(含仓库管理者)→ 提交按钮直达本人 Fork 编辑页;
未 Fork → 上游编辑链接,GitHub 自动引导创建
- 提示 Sync fork 同步要求;步骤与说明文案同步更新
CapableCCat
left a comment
There was a problem hiding this comment.
首先感谢这次提交。重新审阅了当前版本后,我认为这次改动不只是简单地增加首页公告卡片,而是尝试建立一套相对完整的公告管理与展示流程,整体设计值得肯定。
尤其是以下几个方面:
- 数据源设计合理。 以仓库根目录的
announcements.md作为单一数据源,通过scripts/gen-announcements.mjs生成announcements.json,再供首页和公告归档页使用,避免了多处维护重复数据的问题。 - 工作流设计完整。 从公告表单生成 Markdown、复制内容、引导用户通过 GitHub 提交修改,到构建阶段生成数据,再到首页和公告归档页展示,已经考虑了从投稿到展示的主要环节。
- 符合静态站点的技术特点。 采用 GitHub Fork + PR 的方式收集公告,而不是为了这一功能额外引入后端服务,能够控制维护成本,也便于追踪和审核修改记录。
- 展示体验考虑较全面。 首页展示最新公告、归档页按年份整理,配合来源标识、里程碑卡片、主题适配以及减少动态效果的处理,整体思路比较完整。
- 具备进一步扩展的基础。 这套机制不仅可以服务于社团管理者,也可以让普通成员乃至社团外的开源贡献者参与公告纠错、文案优化和其他细节改进。
建议修改或验证的问题
1. Fork 检测需要更准确
目前 CreateAnnouncement.tsx 中的 checkFork 主要通过 GitHub API 返回的 data.fork 判断仓库是否为 Fork。
建议进一步确认 Fork 的来源仓库是否确实为 TSGU-OSC/website,而不只是判断它是否为某个仓库的 Fork。同时,可以校验用户名格式,并确认目标分支和 announcements.md 文件确实存在。
这样可以避免用户填写了一个同名、但与本项目无关的仓库时,页面仍然给出错误的投稿引导。
2. 需要验证实际的 GitHub 投稿流程
目前页面会引导用户进入自己的 Fork 编辑 announcements.md,并提示提交修改后可以继续创建 PR。
这里建议进行实际测试:在 Fork 中点击 Commit changes,并不意味着所有情况下 GitHub 都一定会自动进入创建上游 PR 的流程。具体行为还可能受到分支状态和 GitHub 页面交互的影响。
建议至少验证以下场景:
- 从未 Fork 过仓库的普通访客;
- 已经 Fork 过仓库的用户;
- Fork 尚未同步上游更新,或者缺少目标文件的用户;
- 社团成员和外部贡献者分别进行投稿的情况。
如果不能保证提交后能够顺利创建 PR,建议在页面中明确提供下一步指引,例如引导用户进入 Compare & pull request,或者手动创建指向 TSGU-OSC/website 的 PR,避免用户完成编辑后不知道如何继续。
3. 公告生成脚本应避免依赖文件排列顺序
目前 scripts/gen-announcements.mjs 使用 items.reverse() 反转公告列表,这隐含了一个前提:源 Markdown 中的公告始终按照日期从旧到新排列。
当前数据符合这一约定,因此这不一定是现存的功能错误。但未来如果有人补录较早的公告,或者编辑时没有遵循既定顺序,首页的“最新公告”就可能出现排序错误。
建议优先根据解析出的日期进行排序,并对无法识别或不合法的日期给出明确提示。对于关键字段缺失、日期格式错误等情况,也可以考虑在构建阶段报错,避免问题静默进入正式网站。
4. 可以适当加强公告表单的输入校验
目前 URL 校验主要依赖简单的正则表达式,日期字段也缺少严格的日期语义校验。
建议使用标准 URL 解析方式验证链接,并明确限制为 http 或 https 协议;同时校验日期格式,针对无效输入提供清晰的错误提示。
这不需要把表单做得过于复杂,重点是减少普通贡献者因为输入格式不正确而反复修改 PR 的情况。
5. 合并前需要完成构建和页面验证
目前还需要进一步确认以下事项:
- 完整执行项目构建,确认
prebuild自动生成公告 JSON 后,整个构建流程能够正常完成; - 确认开发环境和生产构建都能正确生成并读取公告数据;
- 检查中文站与英文站的公告入口、页面内容和导航是否符合预期;
- 检查键盘导航、动画降级及减少动态效果的处理;
- 确认生产环境的路由和部署方式能够正确访问新增页面。
需要说明的是,以上属于待验证事项,并不代表这些功能目前一定存在缺陷。
总结
总体而言,我认可这次 PR 的主要设计方向,尤其是单一 Markdown 数据源、自动生成公告数据、首页与归档页联动,以及通过 GitHub PR 实现开源协作的思路。
我建议保留现有的整体架构,优先完善 Fork 来源校验、实际投稿流程引导和公告日期解析排序,再完成构建及页面验证。
这些问题处理完毕并完成必要验证后,我认为这套方案就具备了比较好的合并基础。感谢提交者为公告管理流程和用户体验所做的工作。
审查意见 #3:脚本原先用 items.reverse() 反转列表,隐含「源文件必须 按时间升序书写」的前提。补录较早公告或编辑时不遵守顺序,首页「最新」 就会排序错误。 改动: - 按解析出的起始日期降序排序,区间公告取起始日,同日起始按结束日, 无日期条目沉底并告警,不再依赖文件中的书写顺序 - 日期解析支持 2024.9.27 / 2024-9-27 / 2024/9/27 / 2023年6月25日 及区间(- ~ 至 到 /),并做真实日历校验(2026.2.30、2026.13.45 均拒绝) - 关键字段缺失或格式非法时收集全部错误后以退出码 1 中止,不再静默上线 - 支持行尾 HTML 注释、剥离代码围栏示例、跳过重复条目 - 标题从右往左匹配冒号,标题自身含冒号不会被错误切断 - 源文件缺失时给出可读提示而非原始 ENOENT 堆栈 对现有 39 条公告输出与原版逐字节一致,零内容变化。
审查意见 #1、#2、#4: #1 Fork 检测不准确 - 用户名按 GitHub 规则校验,不合法直接提示且不发请求 - 校验 parent/source 的 full_name 是否为 TSGU-OSC/website, 同名但无关的仓库不再被误判为有效 Fork - 用 API 返回的 default_branch 拼编辑链接,不再硬编码 master - 额外确认 Fork 中 announcements.md 是否存在,缺失时进入 stale 状态并给出 Sync fork 链接(本 PR 上线时所有存量 Fork 都会遇到) - 403 且 x-ratelimit-remaining 为 0 时单独提示限流,不再笼统报失败 #2 投稿流程兜底 - 步骤说明补充「若 Commit 后未自动跳转 PR 页面」的处理方式 - 新增 Compare & pull request 与手动创建 PR 直达链接 #4 输入校验 - 链接改用 new URL() 解析,限定 http/https 协议且 hostname 有效, 正则预检带 i 标志,大写 HTTPS:// 不再被误拒 - 日期改用真实日历校验,与 gen-announcements.mjs 规则完全一致, 非法日期禁用提交并给出明确提示
站点未开启 route.cleanUrls,静态托管下 /announcement/create 返回 404 (实测 osc.tsguas.cn 同样如此,只有 .html 可访问)。首页组件用的是裸 <a>,不会被 Rspress 改写链接;改用 rspress/theme 的 Link 后,构建产物 自动变成 /announcement/create.html。 审查意见 #5 的页面验证项。
- Fork 落后时改为打开 Fork 仓库主页,提示用户点击 Sync fork → Update branch, 不再依赖未经确认的 /sync 路由 - 文件检查只有返回成功时才标记为 exists;404 仍为 stale,其余异常状态 提示检测失败,允许重试或继续手动提交 - gen-announcements 增加 http(s) 链接校验,构建阶段拦截无效公告链接
CapableCCat
left a comment
There was a problem hiding this comment.
感谢继续完善!
不过,我在最新版本中发现一处需要修复的问题:
文件:docs/components/CreateAnnouncement.tsx
当前代码中,submitUrl 的计算逻辑引用了 userForkSyncUrl:
const submitUrl =
forkState === 'exists'
? userForkEditUrl
: forkState === 'stale'
? userForkSyncUrl
: editUrl;
但我检查了当前文件,发现并没有定义这个变量。
但是前面实际上已经对 userForkHomeUrl 定义了正确的链接:
const userForkHomeUrl = `https://github.com/${user}/website`;
这会导致一个具体问题:当用户的 Fork 缺少 announcements.md、检测状态变为 stale 时,组件渲染会因为引用未定义变量而报错。 这不是单纯的链接失效,而是可能导致整个创建公告页面无法正常显示。
建议直接将 userForkSyncUrl 改为 userForkHomeUrl,让用户进入自己的 Fork 仓库主页,再按页面提示点击 Sync fork。
另外,虽然当前 GitHub Actions 在 Node.js 18 和 20 下均构建成功,但这次问题仍然存在,说明现有构建流程没有捕获这个错误。后续可以考虑增加 TypeScript 类型检查。
辛苦再继续完善一下代码,再次感谢你的贡献!
- submitUrl 的三元表达式仍引用 9b04846 中已改名的 userForkSyncUrl, Fork 内缺少 announcements.md(stale)时渲染抛 ReferenceError, 导致创建公告页整页白屏;同时 submitLabel 是同条件的第二个三元, 两处各自演化容易改一处漏一处 - 改用 userForkHomeUrl,指向用户自己的 Fork 仓库主页,由页面提示 点击 Sync fork → Update branch - 将链接与文案合并为单个 submitAction 对象,由同一条件派生, 避免同类漂移 - 验证:stale 状态 SSR 渲染探针由 ReferenceError 变为正常渲染; tsc --strict 无报错;npm run build 通过
CapableCCat
left a comment
There was a problem hiding this comment.
我对部分细节进行了一些小幅修复和调整,目前整体功能与实现都没有发现其他明显问题。
再次感谢你的贡献和付出!这次新增的公告展示与投稿功能让官网的内容维护更加完善,也很高兴看到项目在大家的共同参与下不断进步。
动机
社团公告目前只能在公告页以纯链接列表展示,首页访客完全看不到社团动态;公告页本身也只是 Markdown 链接堆叠,缺少视觉层次;同时公告条目靠手写 Markdown,新成员容易写错格式。本 PR 一次性解决这三件事。
改动内容
1. 首页公告卡片区
theme/index.tsx的HomeLayout,通过官方afterFeatures插槽挂载,仅中文站启用prefers-reduced-motion下自动关闭--rp-c-*),浅色 / 深色主题自动适配2. 公告页全量卡片墙(
/announcement/)AnnouncementList组件:展示announcements.json的全部条目,按年份分组(新 → 旧),组头显示年份与条数.md升级为.mdx,直接挂载组件3. 「创建公告」表单页(
/announcement/create)localhost/127.0.0.1)时提交链接自动指向new_page分支,避免announcements.md尚未合入master导致的 404;正式上线后自动指回master4. 数据自动同步管线
docs/zh/announcement/index.md迁移到仓库根目录announcements.md:位置更醒目,编辑入口固定,贡献者一眼能找到scripts/gen-announcements.mjs:从announcements.md提取标题 / 日期 / 链接 / 来源,生成docs/components/announcements.json(自动倒序,最新在前)predev/prebuild钩子:维护者只维护公告一个文件,首页卡片与公告页自动同步,无需手工改两处支持的书写格式:
数据流
提交流程
/announcement/create填写原文链接与卡片标题,复制生成的 Markdown 片段announcements.md编辑页TSGU-OSC/website的master后提交本地验证
npm install npm run dev # predev 钩子会自动生成 docs/components/announcements.json/announcement/:确认年份分组与滚动入场动画/announcement/create:填写链接 / 标题,确认实时预览与片段生成说明与已知限制
docs/components/announcements.json:它由脚本生成,下次predev/prebuild会被覆盖,请改announcements.md变更规模
13 个文件,+1504 / -3,5 个 commit。