跳到主内容
笔记 Article

主题引擎的字段是怎么定下来的

给一套 CMS 做主题系统,最难的不是渲染,而是「哪些东西该暴露给用户改」。这篇记录我把字段从 40 个砍到 20 个的取舍过程。

2 分钟阅读 0 次浏览

起点:什么都想让人改

第一版主题配置我列了 40 多个字段,从「卡片阴影 X 偏移」到「按钮 hover 时长」全都有。

结果是:没人会用。后台面板需要滚动三屏,改一个值不知道影响哪里,最后所有人都只用默认主题。

判断标准:一个字段该不该暴露

我最后用三个问题筛:

  1. 改它会不会让页面变丑? 会 → 不暴露
  2. 它能不能用「三档」表达? 能 → 做成枚举,不做连续滑块
  3. 站长会在什么场景下想改它? 说不出场景 → 删掉

按这三条,40 个字段砍到了 20 个左右。

几个具体的取舍

阴影偏移 → 三档强度

原本有 shadowX / shadowY / shadowBlur / shadowSpread / shadowColor 五个值。合并成一个 shadowIntensity: 'sm' | 'md' | 'lg',每档对应一整套预设好的数值。

理由:站长想要的是「轻一点/重一点」,不是「Y 偏移 2px」。

保留连续值的:模糊半径、透明度

毛玻璃的 cardBlur 和 cardOpacity 保留了 0-20 / 0-100 的滑块。因为这两个值的「手感」必须实时看,而且中间值确实有意义(8px 和 12px 差别明显)。

砍掉的:hover 时长、缓动曲线

没有人会为了「hover 从 200ms 改成 180ms」进后台。这类参数固定写死更专业。

命名踩过的一个坑

我很想把配置类型叫 ThemeConfig——直白、好记。但这个项目里 ThemeConfig 已经被「主页设置·主题与语言」占用了(presetId / mode / radius / fontScale / locale)。

如果硬复用这个名字,TypeScript 会在几十个文件里报错,而且语义完全混了。

最后改叫 ThemeFullConfig,并在类型定义里写了一条显式的警告注释,防止以后有人「顺手合并」这两个类型。

命名冲突不是靠记性避免的,是靠注释里的 🚨 和一句「为什么不能这么做」。

数据契约比 UI 重要

后台面板可以随时重做,但存进数据库的 JSON 结构一旦上线就很难改。

所以这套系统的做法是:

  • 所有字段写入前必须过 validation.ts 的 zod 校验
  • 读取时再过一遍 coerceThemeConfig() 清洗(宽松模式,非法值回落到默认而不是整个报错)
  • 每新增一组字段,同步补 zod schema + 清洗函数 + 默认值 + 单元验证

四件套齐了才算完成,少一件就会在某个边缘情况崩掉。

雄

雄哥

独立开发者 · 长期写作者

关于