发布于 更新于 约 6 分钟读完 · 2,385 字

本文目录 11 节
  1. 事实记录(不可修改区)
  2. 五件套模式(第三次复用,已收敛)
  3. 两坑(均首次实测)
  4. ⚠️ YAML 裸日期坑:frontmatter 的 2026-07-20 不是字符串
  5. ⚠️ 机器人仓库 push 竞争:人工 push 前默认 rebase
  6. 状态机演进:新增一态 ≠ 改一个字段(2026-07-24 补,任务书首次状态更新)
  7. ⚠️ 头号坑:取反式过滤会静默吞掉新状态
  8. 新增一态要穿线的所有渲染点(清单)
  9. 附:两个小陷阱
  10. 结果分析
  11. 关联文档

站内新版块五件套模式:三次复用与起刊两坑

一句话:蛛网之上加一个内容版块 = 固定五件套(数据源/内容集合/列表详情页/首页速览/全站导航),第三次复用已收敛成套路;数据驱动让「起刊/撤稿」的成本压到增删一个数据文件。

事实记录(不可修改区)

  • 项目:蛛网之上「任务书 · Commissions」版块(/tasks/),2026-07-20 单次会话内从零到双域名上线
  • 前两个同构版块:「AIGC 快讯」(2026-07-02,见 每日定时任务自动更新内容板块_首次自动化生产落地_v1)、「成为 Prompt 大师」画廊
  • 交付链路当天演进:本地任务书 md → Claude artifact 嵌入版(一次性转发)→ 站内常设版块(正式发布渠道)
  • 起刊裁决:作者裁定旧任务(赛博废土武侠)不入站,版块从「当代年轻人精神状态检测」正式起刊;撤下动作 = git rm 一个数据文件,一次 push 双域名生效
  • 两次构建失败均在本地被拦截:① 内容集合 schema 日期类型不匹配;② push 被云端 cron 的自动提交抢先(non-fast-forward)
  • 验证状态:✅ 五件套模式第三次复用;两坑均实测复现并修复,线上 tiaozhuxiansheng.com/tasks/ 已 200 验证
  • 数据来源:会话执行记录 + git log(above-the-web 65808c3→9ddc34c)

五件套模式(第三次复用,已收敛)

给数据驱动的静态站(Astro/同类 SSG)新增一个内容版块,固定做五件事,缺一件就是「孤岛页面」:

  1. 数据源:src/data/<版块>/ 下一条内容一个文件(md+frontmatter 或 JSON),schema 注释写在读取代码旁;
  2. 内容集合/加载器:构建期统一读取、校验、排序,坏文件跳过并告警不阻断构建;
  3. 列表页 + 详情页:/<版块>/ 与 /<版块>/[slug]/,排印复用主站 design token(本站是杂志刊头式),零新增依赖;
  4. 首页速览版块:最新几条 + 入口,版块索引(toc)与刊眉编号用条件插入自动顺延,不硬编码编号;
  5. 全站导航入口:页头 + 页脚各补一个链接。

五件套做完,发布/撤稿/收官全部退化为数据文件操作:新内容 = 加一个文件;撤稿 = 删一个文件;状态在已有取值间流转 = 改一个 frontmatter 字段(如 status: open → closed)。这是 每日定时任务自动更新内容板块_首次自动化生产落地_v1「自动化只碰数据律」的前提结构——呈现层先数据驱动,内容操作才可能收缩为纯数据操作。

注意边界:上句只对已有状态之间的流转成立。给状态机新增一个取值不是改数据、是改代码,另有坑,见下「状态机演进」。

两坑(均首次实测)

⚠️ YAML 裸日期坑:frontmatter 的 2026-07-20 不是字符串

现象:内容集合 schema 写 date: z.string(),构建报 Expected type "string", received "date"。

根因:YAML 规范把裸写的 2026-07-20 解析成 Date 对象,不是字符串;js-yaml/Astro 均遵循此行为。

修法(任选,推荐前者做在 schema 层一劳永逸):

// schema 层收敛:两种类型都接受,统一转 YYYY-MM-DD 字符串
const dateStr = z
  .union([z.string(), z.date()])
  .transform((v) => (v instanceof Date ? v.toISOString().slice(0, 10) : v));

或 frontmatter 里给日期加引号 date: "2026-07-20"(依赖每个写入者自觉,不如 schema 层收敛可靠)。

⚠️ 机器人仓库 push 竞争:人工 push 前默认 rebase

现象:功能开发完 git push 被拒(non-fast-forward),远端多出一个陌生提交。

根因:仓库挂着云端定时任务(每日快讯 cron)会自动 commit + push,人工开发窗口越长,撞车概率越高。

规则:凡是有机器人自动提交的仓库,人工 push 失败不是异常是常态,git pull --rebase 后重推即可;心智上把「push 前先 rebase」设为默认动作,不要看到 rejected 才处理。

状态机演进:新增一态 ≠ 改一个字段(2026-07-24 补,任务书首次状态更新)

任务书板从「二态式」(招募中 / 已收官)演进到四态状态机(招募中 open → 进行中 taken → 完工待打款 done → 已收官 closed),起因是三份测评任务被接取、要标注「进行中 · 接取人」。落地暴露:「状态流转=改一个字段」只对已有取值成立;新增一个取值是一次跨多处的代码改动,且藏着一个静默坑。

⚠️ 头号坑:取反式过滤会静默吞掉新状态

现象:列表页原本二分——open 进「招募中」,其余 进「已收官」归档。新增 taken 后,若不改过滤,taken 任务会被那句 status !== 'open' 静默归进「已收官」,显示成早已完成——错得离谱且构建不报错。

根因:取反 / 兜底式过滤(!== 'open'、else、default)默认「除了我关心的,其余都算同一类」。枚举一旦扩容,新值就从这个「其余」缺口漏进错误的桶,而类型系统和构建都不会拦——它语法完全合法。

规则:状态分桶一律正向枚举,不写取反。把 closed = status !== 'open' 改成 closed = status === 'done' || status === 'closed',新增状态时这句自然不接纳它,逼你显式决定它进哪个桶。一句话律:enum 扩容时,先审所有「取反 / else / default」分支——那里是新值静默泄漏的必经之地。

新增一态要穿线的所有渲染点(清单)

一个状态值不是加进 schema 就完事,得挨个渲染点补齐,漏一处就是显示错误:

  1. schema enum:加取值(+ 本次配套加 taker 字段);
  2. 列表页过滤:正向枚举分桶(见上),并为新态开一个展示区(本次「进行中」独立成区,中性色卡片,不和招募中/已收官混);
  3. 列表页 / 详情页 / 首页速览的状态标签:三处各有一份 label 映射,全要认识新值(漏一处就 fallback 成错标签)。

教训:label 映射散落在多个页面是重复源,新增状态时最易漏。可考虑抽成单一 statusLabel(status) 共享函数收敛——本次三处仍是各写各的,记为下次重构点。

附:两个小陷阱

  • text-transform: uppercase 会吃掉专名大小写:状态胶囊统一大写,对「招募中」这类关键词无碍,但一旦往徽章里注入人名(接取人 Jane),会被顶成刺眼的 JANE。给注入专名的徽章单独 text-transform: none。规律:统一大写的样式令牌只对「标签词」安全,注入用户数据 / 专有名词的位置要豁免。
  • 公开看板上标注他人身份是外向决策,先问再显示:把接取人姓名显示在公开页,属可被索引、难撤回的对外动作。落地前显式问作者「公开显示接取人名 / 只标已接取不露名 / 直接归档」,不替他默认(本次作者选公开显示「进行中 · 南山」)。参见 任务书制作与学员协作需求收口方法论_v1 的公域红线同源判断。

结果分析

  • 从「摸清站点结构」到「双域名上线验证」单会话完成,五件套没有一步需要重新设计——模式收敛的直接收益;
  • 部署零新增工作:push main 自动触发双目标(GitHub Pages 子路径 + rsync 香港服务器根路径),复用 双部署目标的base路径陷阱_根路径拼出双斜杠_v1 踩通的既有管线,import.meta.env.BASE_URL 归一化写法让同一套页面在两种 base 下都不用改;
  • 版块内容侧(任务书怎么写、交付载体怎么选)的方法论在 任务书制作与学员协作需求收口方法论_v1,与本档是「内容规范 × 承载工程」的分工。

关联文档

类型/平台工程主题/版块工程