Skip to content

feat:首页公告卡片区与创建公告表单 - #42

Merged
CapableCCat merged 10 commits into
masterfrom
new_page
Nov 10, 2026
Merged

CapableCCat merged 10 commits into
masterfrom
new_page

Conversation

@Old-cpu

@Old-cpu Old-cpu commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

动机

社团公告目前只能在公告页以纯链接列表展示,首页访客完全看不到社团动态;公告页本身也只是 Markdown 链接堆叠,缺少视觉层次;同时公告条目靠手写 Markdown,新成员容易写错格式。本 PR 一次性解决这三件事。

改动内容

1. 首页公告卡片区

  • 覆写 theme/index.tsx 的 HomeLayout,通过官方 afterFeatures 插槽挂载,仅中文站启用
  • 展示最新 6 条公告:日期 + 来源徽章(微信推文 / Gitee / 外部链接 / 里程碑)+ 标题(两行截断)
  • 有链接的卡片点击新标签页跳转原文;无链接的里程碑渲染为静态卡片(不可点击)
  • 区块头部提供「+ 创建公告」与「查看全部 →」两个入口
  • 滚动进入视口时卡片依次浮入(70ms 交错动画),prefers-reduced-motion 下自动关闭
  • 样式全部使用 Rspress 主题变量(--rp-c-*),浅色 / 深色主题自动适配
file

2. 公告页全量卡片墙(/announcement/)

  • 新增 AnnouncementList 组件:展示 announcements.json 的全部条目,按年份分组(新 → 旧),组头显示年份与条数
  • 每个年份分组滚动进入视口时,卡片依次 blur-fade 浮入(组内 60ms 交错,纯 CSS 实现,无额外依赖)
  • 无链接的里程碑条目同样渲染为静态卡片,与首页卡片样式统一
  • 公告页与创建页的 MDX 入口从 .md 升级为 .mdx,直接挂载组件
file-1

3. 「创建公告」表单页(/announcement/create)

  • 表单字段:原文链接(带格式校验)、卡片标题、发布日期(默认今天、可修改);粘贴链接后自动识别来源(微信 / Gitee / 其他)
  • 右侧实时预览卡片效果与生成的 Markdown 片段
  • 一键复制片段;「去 GitHub 提交」按钮按 Fork 状态自动分流:
    • 填写 GitHub 用户名并「检测我的 Fork」(调用免鉴权 GitHub API,60 次 / 小时 / IP)
    • 已 Fork → 直达本人 Fork 的编辑页
    • 未 Fork / 未检测 → 走上游编辑链接,由 GitHub 自动引导一键创建 Fork
  • 包括仓库管理者在内,所有人统一走 Fork + PR,官方仓库历史保持干净
  • 本地预览(localhost / 127.0.0.1)时提交链接自动指向 new_page 分支,避免 announcements.md 尚未合入 master 导致的 404;正式上线后自动指回 master
file-2

4. 数据自动同步管线

  • 公告源文件由 docs/zh/announcement/index.md 迁移到仓库根目录 announcements.md:位置更醒目,编辑入口固定,贡献者一眼能找到
  • 新增 scripts/gen-announcements.mjs:从 announcements.md 提取标题 / 日期 / 链接 / 来源,生成 docs/components/announcements.json(自动倒序,最新在前)
  • 挂到 predev / prebuild 钩子:维护者只维护公告一个文件,首页卡片与公告页自动同步,无需手工改两处

支持的书写格式:

### [标题:2024.9.27](https://mp.weixin.qq.com/s/…)          <!-- 可跳转公告 -->
### [标题:2024.9.21 - 2024.9.22](https://…)                 <!-- 时间范围 -->
### 标题:2023.6.25                                          <!-- 无链接里程碑,生成静态卡片 -->

数据流

announcements.md ──(predev / prebuild: gen-announcements.mjs)──▶ docs/components/announcements.json
                                                                          │
                        ┌─────────────────────────────────────────────────┴──────────────────┐
                        ▼                                                                    ▼
              首页公告卡片区(最新 6 条)                                       公告页全量卡片墙(按年份分组)
                        ▲
                        │
        创建公告表单(实时预览 → 复制 Markdown 片段 → 自己的 Fork 编辑 → PR 回流到 announcements.md)

提交流程

  1. 在 /announcement/create 填写原文链接与卡片标题,复制生成的 Markdown 片段
  2. 填写 GitHub 用户名 →「检测我的 Fork」→ 直达本人 Fork(未 Fork 时由 GitHub 引导创建)的 announcements.md 编辑页
  3. 把片段粘贴到文件末尾,点击 Commit changes
  4. GitHub 自动跳转 PR 页,确认目标为 TSGU-OSC/website 的 master 后提交

本地验证

npm install
npm run dev   # predev 钩子会自动生成 docs/components/announcements.json
  • 首页:确认 features 下方出现公告卡片区(切到英文站应不显示)
  • /announcement/:确认年份分组与滚动入场动画
  • /announcement/create:填写链接 / 标题,确认实时预览与片段生成

说明与已知限制

  • 公告数据为纯前端静态数据,站点无后端,所有新增公告都要经 PR 回流
  • Fork 检测使用免鉴权 GitHub API(60 次 / 小时 / IP),限流或断网时仅提示「检测失败」,不影响正常提交
  • 请勿直接修改 docs/components/announcements.json:它由脚本生成,下次 predev / prebuild 会被覆盖,请改 announcements.md
  • 首页卡片区仅中文站挂载(公告数据为中文),英文站如需要可后续补充
  • 首页仅取最新 6 条,完整列表见公告页

变更规模

13 个文件,+1504 / -3,5 个 commit。

- 新增 scripts/gen-announcements.mjs:从公告页 md 自动提取数据生成 JSON,predev/prebuild 钩子自动同步
- 新增 AnnouncementCards 组件:首页展示最新 6 条公告卡片,滚动交错浮入动画,点击跳转原文
- theme/index.tsx 覆写 HomeLayout,经 afterFeatures 插槽挂载(仅中文站)
- 新增 /announcement/create 表单页:填写链接+标题实时预览卡片,生成 Markdown 片段,一键复制并跳转 GitHub 编辑页提交 PR
- 首页公告区新增「创建公告」入口按钮
- 全部样式使用 Rspress 主题变量,深浅色自适应,prefers-reduced-motion 下关闭动画
@Old-cpu
Old-cpu requested a review from CapableCCat September 30, 2026 14:59
- 公告数据独立为仓库根目录 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 CapableCCat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

首先感谢这次提交。重新审阅了当前版本后,我认为这次改动不只是简单地增加首页公告卡片,而是尝试建立一套相对完整的公告管理与展示流程,整体设计值得肯定。

尤其是以下几个方面:

  1. 数据源设计合理。 以仓库根目录的 announcements.md 作为单一数据源,通过 scripts/gen-announcements.mjs 生成 announcements.json,再供首页和公告归档页使用,避免了多处维护重复数据的问题。
  2. 工作流设计完整。 从公告表单生成 Markdown、复制内容、引导用户通过 GitHub 提交修改,到构建阶段生成数据,再到首页和公告归档页展示,已经考虑了从投稿到展示的主要环节。
  3. 符合静态站点的技术特点。 采用 GitHub Fork + PR 的方式收集公告,而不是为了这一功能额外引入后端服务,能够控制维护成本,也便于追踪和审核修改记录。
  4. 展示体验考虑较全面。 首页展示最新公告、归档页按年份整理,配合来源标识、里程碑卡片、主题适配以及减少动态效果的处理,整体思路比较完整。
  5. 具备进一步扩展的基础。 这套机制不仅可以服务于社团管理者,也可以让普通成员乃至社团外的开源贡献者参与公告纠错、文案优化和其他细节改进。

建议修改或验证的问题

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 CapableCCat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢继续完善!

不过,我在最新版本中发现一处需要修复的问题:

文件: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 CapableCCat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我对部分细节进行了一些小幅修复和调整,目前整体功能与实现都没有发现其他明显问题。

再次感谢你的贡献和付出!这次新增的公告展示与投稿功能让官网的内容维护更加完善,也很高兴看到项目在大家的共同参与下不断进步。

CapableCCat

This comment was marked as duplicate.

@CapableCCat
CapableCCat self-requested a review November 10, 2026 04:14
CapableCCat

This comment was marked as duplicate.

@Old-cpu
Old-cpu enabled auto-merge November 10, 2026 04:24
@Old-cpu
Old-cpu disabled auto-merge November 10, 2026 04:24
@CapableCCat
CapableCCat merged commit cfd147a into master Nov 10, 2026
2 checks passed
@CapableCCat
CapableCCat deleted the new_page branch November 10, 2026 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants