平台工程

任务系统演进:站内新建、管理台拆分与首页瘦身

一句话:任务书从「写 md 才发」进化到「站内直接发」,代价是表加两列 + 详情页拆成动静两份;管理台一件事一页比一页堆所有内容更清晰;首页是入口不是仓库,362 篇笔记搬去子页后首页从 218 KB 降到 30 KB。

事实记录(不可修改区)

这一轮在哪座地基上加盖

本轮是 静态站接账号系统_内容归git状态归库的双源切分_v1 的续篇。那篇定下了「正文归 git、状态归库、同步只写正文类字段」的基本框架,本轮在上面长出新东西:

也延续了 站内新版块五件套模式_三次复用与起刊两坑_v1 的「数据驱动呈现层」思路——本轮新建的「任务书详情页(/tasks/detail/)」同样是数据驱动,只是数据源从 md 文件换成了数据库。

六条可复用 insight

1. 双源头模型的延伸:source 字段分流同步

静态站接账号系统_内容归git状态归库的双源切分_v1 处理的是「同一个东西一个来源」(md)。现实很快变成同一个 slug 两种来源:md 是真相源,但站内也会创建任务,两者共用一张表、一套流转。

source 列(md / web),同步逻辑全部带 WHERE source = 'md':

同步逻辑必须按来源分流,否则「清单里没有」会被误判为「被删了」。 这条是 静态站接账号系统_内容归git状态归库的双源切分_v1「同步只写正文类字段」的推论,本轮首次实测。

2. 运行时状态再分离:fee_override 独立于真相源

fee 在 md 里写的是任务书原价,但定完人之后临时加钱是常事(报销会员费、加急、追加内容)。改 md 既慢(要等一轮构建)又会被下一轮同步覆盖回去,正好是 静态站接账号系统_内容归git状态归库的双源切分_v1 里「真相源不该承载运行时改动」的又一个实例。

fee_override / fee_note 两列,同步一律不碰:

字段归属谁能改同步覆盖?
fee真相源md
fee_override运行时管理台「调整报酬」
fee_note运行时管理台「事由」

对外接口:fee = COALESCE(fee_override, md.fee) 永远是「现在到底结多少」,页面不用各自判断。导出 md 时只写真相源(fee)——任务书是任务书,这次结多少是这次的事。

区分「真相源字段」和「运行时字段」看一件事:改它要不要等构建、会不会被同步覆盖。 要等构建的就是真相源,即时生效的就是运行时,存在同一张表但要分列。

调价面板交互:填 +40 当场算 100 元 → 140 元(正则找第一个数字,后缀原样留着),也可「直接写新报酬」;「事由」写进流转记录,承接人在任务页看得到;「撤销调整」回到原价。

3. 管理台一件事一页 + 共用壳

管理台原先一页堆了待处理申请、任务列表、账号管理、操作记录。加新内容=在一页里找地方塞,越塞越挤。

改成六页(概览 / 申请 / 任务 / 新建 / 账号 / 记录),共用 AdminLayout.astro 一层壳:

管理台是工具页不是展示页,一件事一页 + 共用壳比一页堆所有内容清晰。 加新页 = 往 NAV 数组加一项 + 新建页面文件,不动其它页。

4. 首页是入口不是仓库

站内新版块五件套模式_三次复用与起刊两坑_v1 的「首页速览版块」原本是露几条 + 入口。但笔记库一直在首页底部完整铺开(7 栏目、35 子栏目、362 张卡、134 KB),占了整页八成篇幅,进站第一眼是卡片墙,看不出这站有什么。

把整个笔记索引搬去 /notes/ 独立成页,首页那一节换成七个栏目入口(篇数 + 一句话定位),点进去带 ?cat= 直接落在对应筛选上(此时不做平滑滚动——人还没看过刊头,把页面拽走反而莫名其妙)。

首页 218 KB → 30 KB,和快讯、任务书两页终于一个量级。分组逻辑抽进 lib/note-groups.mjs,首页与 /notes/ 共用一份,计数不再各算各的。

首页回答「这站有什么」,不回答「这站的所有内容是什么」。 全部内容进子页,首页只给入口。新增板块时先想「进首页还是进子页」,默认进子页。

5. 浏览器侧渲染的安全基线

站内新建的任务书正文存库,构建期看不到,只能在浏览器侧渲染。写了一个轻量 mini-markdown.js(认 ## 标题 / 列表 / 引用 / 粗斜体 / 代码 / 链接 / 图片 / 分隔线,表格脚注不做——写到那份上本来就该落成 md)。

安全基线:内容进过数据库,就不再是「自己写的字符串」——先转义再拼 HTML,链接白名单只放行 /, #, http(s):, mailto:,javascript: 之流当普通文本落地。

这条和 静态站接账号系统_内容归git状态归库的双源切分_v1 的「注水脚本的 catch 里什么都不做」同属一类:给静态站挂后端 / 挂动态内容时,安全边界要设在数据进页面之前,不是写数据的时候。 发布方自己写正文也不能绕过转义。

6. 滚动渐现抽成共用模块

首页 / 快讯 / 任务书 / 笔记四个页面都在用「元素进视口淡入上移、同批错峰」,每个页面各写了一份 IntersectionObserver + rv 类 + keyframes。抽成 scripts/reveal.jsrevealOnScroll(selector),四页共用。rv / rv-in / keyframes 收进 global.css

顺手把刊头 .masthead* 三页重复副本也收进 global.css——快报、任务书、笔记三个板块页共用一套刊头,不该各存一份。

同一份样式 / 同一个 JS 模式出现第三次,就该抽出来。 抽的收益不是少写代码,是改一处能全站生效,避免「改了首页的渐现速度忘了改笔记页」。

关联文档

方法论验证等级

本轮 insight等级
source 字段分流同步⚠️ 首次发现
fee_override 真相源 / 运行时分离⚠️ 首次发现
管理台一件事一页⚠️ 首次发现
首页是入口不是仓库⚠️ 首次发现
浏览器侧渲染安全基线⚠️ 首次发现
滚动渐现抽共用模块⚠️ 首次发现

没有三次验证的方法论,不用于指导下一次决策——只作为「值得继续观察的假设」。本轮六条均首次发现,下次做类似迭代时逐条验证。

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