今天这轮改造基本围绕两件事:头像系统从「能用」变成「好用」,分类模板从各写一套变成「统一底座 + 各自独立文件」。

一、头像上传:看得见、拖得动、裁得准

原来的裁剪弹窗只有一块画布,图片只能缩放,没有取景框。现在改成标准的取景式裁剪:

  • 白色裁剪框 + 三分构图线,框外压暗,边界一眼可见;
  • 四角手柄可拖拽,正方形取景框随之放大缩小,对角 / 对边固定;
  • 滚轮与滑杆缩放,以裁剪框中心为锚点,框不居中时画面不会跑偏;
  • 导出只截取框内区域,按原图坐标反算,不带进暗边,也没有二次放大损失。

一个容易踩的坑:主题有一条全局收口 * { border-radius: 0 !important; box-shadow: none !important },裁剪框的「框外压暗」被它直接吃掉,必须给 .ua-crop 的 box-shadow 加 !important(类选择器优先级高于 *)才压得住。

二、预设头像:素材丢进目录就能用

素材放在 usr/uploads/user_avatar,插件扫描目录而不是写死文件名,新增图片刷新即出现(jpg / png / webp)。

  • 注册页和个人中心都能选,另有「随机一个」;
  • 预设头像只记录路径、不复制文件,之后换自定义头像也不会误删素材;
  • 提交的路径必须命中扫描结果白名单,不能把任意路径写进 avatar 字段。

三、评论区也有了头像

  • 注册用户用站内头像(自定义 / 预设 / 默认都算),游客用昵称首字母 SVG,零外部请求;
  • 头像统一圆形,这条要加进主题的「圆角例外」白名单,否则会被全局直角规则压成方块;
  • AJAX 发表后列表局部替换,头像是服务端渲染的,发完立刻出现,不用刷新页面。

四、右栏标题前的首字母圆标

右侧栏「本分类最新」每条标题前加了一个圆形字母标:

  • 英文标题取首字母大写,中文标题按 GB2312 一级汉字区(该区按拼音排序)反查拼音首字母——「站点改造 → Z」「从零实现 → C」;
  • 序号奇偶换底色:1、3、5… 黑底白字,2、4、6… 浅灰底黑字;
  • 标题折行时,图标相对整块标题垂直居中,不再贴在第一行。

五、导航二级菜单补上缩略名

一级菜单早就有 教程 tutorials 这样的弱化缩略名,二级下拉之前没有,现在补齐:深色浮层用更弱一档的白,移动端白色浮层换成浅灰。

六、分类模板统一:一套底座,各自独立

以博客分类为基准,把其余分类的模板全部对齐,但每个分类都保留自己的文件名(category/{slug}.php、post-{slug}.php、tag-{slug}.php、css/{slug}.css、sidebar-*-{slug}.php),后期单独改哪一栏都不会波及其它分类。

  • 子分类(随笔、开发、编程工具、WX 原创)不再各写一套,统一继承父级一级分类;
  • 卡片标题字号统一到 16px,与管理栏标题同一档。

日志单独一套模板

日志是流水,不需要封面和摘要,所以 category/logs.php 不再复用卡片网格,自己输出「时间 + 标题」的单行列表:时间定宽在左(13px 灰字、等宽数字),标题在右,一条一行,窄屏自动换行。

日志不再混进博客一级列表

Typecho 的分类归档默认包含所有子孙分类,日志文章会同时出现在「博客」列表和右栏。现在用查询钩子把指定子分类摘掉,并同步过滤分页总数用的 countSql,末页不会多出一页空白。

七、顺手修掉的几个老问题

  • 个人中心「恢复默认头像」点了没反应:插件配置在页脚才注入,页面脚本却提前读了 apiUrl,取值永远是 undefined;
  • 分类翻页后每页条数会退回全站默认(插件只在 Router::$current === 'category' 时套用「文章数」规则,翻页时路由名变成了 category_page),问题已定位,待处理。

备份

服务器上没有 git,改动前把会被覆盖的文件都备份到了 .codebuddy/backup/ 下(2026-10-22-category-unify、2026-10-22-logs-template、2026-10-22-card-title-size),需要回滚直接拷回去即可。