Files
tamabox/.workbuddy/memory/2026-09-04.md
T
2026-09-08 10:10:44 +08:00

12 KiB
Raw Blame History

2026-09-04

  • 调研并输出 /user/profile 页面(account 面板)UI 优化评审与改造方案(等待用户批准后实施)。
  • 关键结论:
    • 密码强制登出:users.password_version + 会话 pwd_ver 机制已存在(internal/context/auth.go authenticatedUser),改密后旧会话下次请求即失效;但 UpdateProfile 改密后仍重定向 /user/profile,被 Toggle 以「请先登录」错误文案弹回 /login,成功 flash 被吞。改造方向:改密成功 → Session.Flush() + success flash(复用 auth.errPasswordChanged)→ 直接跳 /login。
    • 头像/背景裁剪:项目无任何 crop 库;第三方库全部自托管于 R2(r2.337845818.best/tamabox/cdn)。候选方案:Cropper.js 内嵌 static/(需扩 static/fs.go embed 规则)。当前 avatarPlaceholder 文案自嘲"非1:1会扁"但无强制。
    • 复用点:profile-tabs 面板、Pickr 颜色选择、easy.qrcode 预览、UIkit modal/accordion、imagecheck 像素校验、storage.UploadPictureToS3(自动转 WebP、宽>1920 缩放)。
    • i18n 四语言字典 key 全等校验(i18n_test.go TestDictionaryComplete),新增词条须同步 4 个 dict 文件。

下午:profile account 面板改造已实施(用户已批准方案)

  • 决策:Cropper.js 走自有 R2 CDN(lib/cropperjs/1.6.2/,用户自行上传);改密立即登出跳登录页;卡片分区+折叠(中等重构);前后端双比例校验。
  • 改动清单:
    • route/user/profile.go:avatar→storage.UploadAvatarToS3、background→storage.UploadBackgroundToS3(新增),改密成功(passwordChanged 标志)→ Session.Flush + flash(profile.flash.passwordChanged) → /login;比例不符 flash 提示(profile.err.avatarRatio / backgroundRatio)。
    • internal/imagecheck/imagecheck.go:新增 ErrBadAspectRatio + CheckAspectRatio + DefaultAspectTolerance(0.01);imagecheck_test.go 新增 4 个用例。
    • internal/storage/s3.go:抽 uploadPictureToS3 内部分管线(aspect 可选),UploadAvatarToS3=1:1、UploadBackgroundToS3=16:9,魔数后、像素总量前校验;原有 UploadPictureToS3 兼容签名(其他调用方不变)。
    • internal/i18n/dict_*.go(4 语):新增 15 词条(card.* 4、cropHint 2、cropTitle/cropConfirm、pwdNote、pickAvatar/pickBackground、err.avatarRatio/backgroundRatio/cropLibUnavailable、flash.passwordChanged)。
    • templates/user/profile.html:account 面板重构为 8 张卡片(基础资料/头像与背景[预览+裁剪]/二维码样式折叠/社交折叠/修改密码[随主表单]/标签/页面密码/账号操作);头像 96px 圆、背景 16:9 预览;Cropper 弹窗+写回 file input 逻辑;accordion 展开时重绘二维码预览;新增 .tb-pcard 等样式与暗色适配、移动端单列。
  • 验证:go build ./...(用 dev/webpstub overlay 方式,Windows 无 libwebp)通过;go test internal/i18n + internal/imagecheck 通过;dev/checktpl 全模板语法 OK;HTML 标签开闭平衡校验通过。
  • 待办:R2 上传 cropper.min.{js,css} 到 r2.337845818.best/tamabox/cdn/lib/cropperjs/1.6.2/ 后即可端到端生效;未做浏览器实测(需本地 DB/Redis)。

晚间:修复部署环境 UIkit is not defined(Rocket Loader 时序)

  • 现象:VM234:42 Uncaught ReferenceError: UIkit is not defined;更换头像/背景按钮点击无效果。
  • 根因:裁剪脚本(templates/user/profile.html 末尾)IIFE 解析期即执行 var modalObj = UIkit.modal(modalEl);UIkit 在 base/header.html 是 defer 加载,Cloudflare Rocket Loader 把该内联脚本激活在 UIkit 执行前 → 抛错中断整个脚本 → [data-pick-image] 监听(其后)从未绑定。
  • 修复(templates/user/profile.html,4 处):
    1. modalObj 改为 null 懒创建(startCrop 内、依赖就绪后 UIkit.modal(modalEl));
    2. 新增 notify():UIkit 可用→UIkit.modal.alert,否则回退原生 window.alert;
    3. 新增 whenReady(cb):轮询等待 window.UIkit && window.Cropper,超时 3s → notify(MSG_NO_CROPPER);文件大小校验前置(不依赖库);
    4. 脚本标签加 data-cfasync="false",按钮监听尽早同步绑定。
  • 经验:模板内联脚本禁止在解析期触碰 defer/外部库全局对象(UIkit/Pickr 等),一律在用户事件回调内或依赖就绪后使用——Rocket Loader 会打乱执行序;全站内联脚本仅裁剪脚本踩中此坑。
  • 验证:node --check 通过(模板占位符替换后);R2 上 cropper 文件此前 curl 仍不可达(HTTP 000),用户需先上传,否则选图后 3s 提示「裁剪组件暂不可用」——需提醒用户。

晚间(二):图像保存 UX + 同行居中 + console 噪音排查

  • 用户反馈:图像上传/裁剪已可用;但「保存修改」按钮在「修改密码」卡片里,改图后要去那里点击才生效,不直观;且头像修改显示在左上角别扭。
  • 改动(templates/user/profile.html):
    1. 头像与背景卡片内新增本地保存按钮(type=submit,label 新 i18n key profile.saveMedia,随主表单提交,裁剪写回的文件域一并上传);CSS .tb-media-save(居中条)。
    2. .tb-media-row 改 justify-content:center、子项 flex:0 1 auto + column 居中、tb-frame-bg 固定 320px(max-width:100%);移动端 ≤640 子项 flex-basis:100% 上下堆叠居中、背景图全宽、保存按钮全宽。
    3. 4 语字典新增 profile.saveMedia(zh-CN 保存头像与背景 / zh-TW 儲存頭像與背景 / en Save avatar & background / ja アイコンと背景を保存)。
  • console 噪音排查结论:inspector.js AbortError/Request timeout/responseType arraybuffer 报错非项目代码(全仓库 grep 无 inspector/fetch 包装);是浏览器 XHR 监控类扩展包装 fetch/XHR + Rocket Loader 激进异步调度(arraybuffer 脚本请求被中止)造成的误报。建议无痕窗口验证 + 或 Cloudflare 关闭 Rocket Loader。
  • 验证:gofmt -w 4 个 dict;go test ./internal/i18n/ 通过;go run ./dev/checktpl 全模板语法 OK。

晚间(三):二维码/社交默认展开 + 头像背景组件等宽 + 每卡片独立保存按钮

  • 用户要求:①二维码、社交两块默认展开;②更换头像/更换背景组件大小一致(原头像 96 圆 vs 背景 320 宽预览悬殊);③为 account 面板每块加独立保存按钮(仿头像背景卡样式)。
  • 改动(templates/user/profile.html):
    1. 卡片3/4 的 uk-accordion <li> 加 uk-open 默认展开(仍可折叠,multiple:true)。
    2. .tb-media-item 固定等宽列 320px(flex:0 0 320 + max-width:100%),头像预览 96→120px、背景帧 width:100%(列内满宽 16:9);.tb-media-actions .uk-button min-width:150px 令两个更换按钮同宽。移动端:头像 80→96px、item 全宽堆叠、按钮全宽。
    3. 保存按钮:基础资料(profile.saveBasic)/头像背景(已有 saveMedia)/二维码(profile.saveQR)/社交(profile.saveSocial)/改密(原 admin.saveProfile 改 profile.savePassword「确认修改密码」)——均为同表单 type=submit(提交整表),复用居中类 .tb-card-save(与 .tb-media-save 同规则)。
    4. 二维码预览:默认展开后从其它 tab(?tab=question 等)切回 account 面板时不会再触发 accordion 'shown' → showPanel 里 account 时调 window.__tbRefreshAccountPreview(IIFE 内暴露的 debouncedUpdatePreview)重绘。
  • i18n 4 语新增 saveBasic/savePassword/saveQR/saveSocial;admin.saveProfile key 保留未删(四语仍在,仅模板不再引用)。
  • 验证:go test ./internal/i18n/ 通过;go run ./dev/checktpl OK。

晚间(四):头像/背景框等高 + 按钮统一居中 + 页面纵向压缩

  • 用户反馈:①头像框偏小,希望与背景框显示高度一致;②按钮有的居中有的居左,要求统一并压缩空间。
  • 改动(templates/user/profile.html,纯 CSS/结构):
    1. 预览框等高:头像 120→150px 圆;背景框 267×150(16:9,与头像等高);媒体列 320→280 等宽;行间隙 20/40→14/32;移动端头像 96→120px。
    2. 按钮统一居中:账号操作卡片(登出/导出/停用)text-align:center + 行距 12→9px;卡片6 标签、卡片7 页面密码按钮 div.uk-margin→div.tb-card-save;提问面板 updateHarassment/updateAskPassword、私聊面板 updateChat 三个按钮同改居中。
    3. 压缩:.tb-pcard padding 16/16/10→13/14/8、margin-bottom 16→12、标题 margin 12→10;新增 .profile-panel .uk-margin { margin-bottom: 12px }(全面板字段间距 20→12)。
  • 范围说明:global-blockwords / feature-control-form 两个 partial 模板(三面板共用)内按钮未改(避免影响其它页面),如需统一再单独处理。
  • 验证:go run ./dev/checktpl OK。

晚间(五):账号操作按钮分组同行 + partial 内按钮居中

  • 用户要求:①导出数据/导出全部数据按钮同一行;②退出登录/停用我的账号同一行;③屏蔽词设置、计数设置也居中。
  • 改动:
    1. templates/user/profile.html:账号操作卡重构为 .tb-account-pair(flex 居中,两按钮同行):导出组(默认按钮×2,target=_blank 表单)+ 说明行 .tb-account-note;登出组(danger 按钮+停用链接)+ 说明行。旧的 .tb-account-action 行式堆叠 CSS 删除,暗色规则改 .tb-account-note。
    2. .feat-quota-line 加 text-align:center;.feat-actions 加 justify-content:center(保存/重置计数按钮居中)——覆盖 feature-control-form(提问/私聊/投票共用)。
    3. templates/user/global-blockwords.html:提交按钮行 .uk-margin → .tb-card-save(居中);该 partial 仅 profile.html 引用,无外溢。
    4. 说明文字合并保留:exportHint+exportJSONHint 合并一行小字,deactivateHint(含 )保留在其按钮组下方(deactivate 确认页另有完整警告文案)。
  • 验证:go run ./dev/checktpl OK。

晚间(六):修复导出按钮点击后永久「提交中」转圈

  • 现象:导出数据/导出全部数据(target=_blank 下载表单)文件能下,但按钮永久转圈禁用。
  • 根因:templates/base/footer.html 全局 submit 反馈(P0 防重复提交)把触发按钮置「转圈+提交中」并禁用;复位仅靠整页导航/bfcache pageshow。target="_blank" 下载表单当前页不导航 → 无复位机会 → 永久卡死。
  • 修复(双保险):
    1. templates/user/profile.html:两个导出 form 加 data-tb-skip-submit-feedback="1"(footer 既有跳过通道,每次 submit 读到即跳并移除)。
    2. templates/base/footer.html:submit 监听里对 form.getAttribute('target')==='_blank' 一律 return 跳过反馈——防御未来任何下载/新窗口表单踩同一坑(全站现存 target=_blank 表单仅 profile 这两处,行为从“卡死 bug”变“无反馈”=纯修复)。
  • 经验:全站提交反馈的复位依赖导航,凡不触发本页导航的提交(target=_blank / 下载 / iframe)都必须显式跳过。
  • 验证:go run ./dev/checktpl OK。

晚间(七):私聊面板 chat 专属功能聚合单卡

  • 用户要求:?tab=chat 面板里「私聊块」(功能开关/收集窗口 feature-control-form)与「私聊设置」(update-chat-settings 消息上限)聚合为一张卡;全局屏蔽词为三面板共享、保持独立。
  • 改动(templates/user/profile.html):
    1. chat 面板改两段结构:私聊专属 = <section class="tb-pcard chat-zone"> 内含 FeatureChat partial + <hr> + update-chat-settings 表单(原外层 div.uk-margin 移除);全局屏蔽词维持原 hr + partial 独立区。
    2. CSS .chat-zone:内部 .feat-card 去边框透明(padding:0; border:0; background:transparent),避免卡中卡;hr margin 14px;内部 legend(admin.chat)从 uk-legend 大标题降级为 1.05rem 小节标题。
  • 提问/投票面板未动(结构同前)。
  • 验证:go run ./dev/checktpl OK。

晚间(八):功能控制卡按钮尺寸统一为常规按钮

  • 用户要求:「保存该功能设置」按钮样式/大小改成与「更新私聊设置」一致;「重置计数」同调。
  • 改动(templates/user/feature-control-form.html,三面板共享 partial):feat-actions 内两按钮去掉 uk-button-small —— 保存改 uk-button uk-button-primary、重置改 uk-button uk-button-default(常规尺寸,与全站其它表单主按钮一致)。提问/私聊/投票同步生效。
  • 验证:go run ./dev/checktpl OK。