Blizzard
bbc34c5bd6
feat(fe): Step4 门面品牌色带(方案A)+ nav-bar tone
...
- nav-bar 加 tone="brand":透明底 + 深棕字,压在色带上;默认分支不动
- 首页/记录页顶部加 252rpx 品牌橘色带(下沿大圆角,z-index:-1 垫背后),
盖住 nav + 切换条,门面卡在色带下方
- 切换条压在色带上:chip 半透明白 + 深棕字,选中实白
- page 加 position:relative 供色带绝对定位锚定
- 新增 --band-a/--band-b/--band-ink token(取自 preview-v3 定稿)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 13:42:11 +08:00
Blizzard
bb7db78763
feat(fe+be): 身份卡头像不再压扁 + 内容丰富
...
- 头像用九参数 drawImage 居中裁剪(cover),竖图/横图都不变形,加白边圈
- 后端 IDCard 增 zodiac(按生日算星座) + weight,卡面加「星座/体重」行
- 加淡淡的肉垫水印 + 旋转的「肉垫计划·官方认证」印章
- 画布加高容纳新增内容
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 11:50:04 +08:00
Blizzard
96c92f2cfb
feat(fe): 今日任务完成走记录表单,去掉「全部完成」
...
- 去掉首页「全部完成」按钮,避免一键刷完不留记录
- 勾选带记录类型的任务 → 跳记录表单,保存成功后才回填任务完成,
返回首页 onShow 自动刷新任务勾选 + 最近记录(带 taskId 传参)
- 只对未完成任务传 taskId,避免重复完成把已完成任务 toggle 回去
- 无记录类型的任务(如遛狗)仍直接勾选完成
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 09:03:27 +08:00
Blizzard
603bd5773e
feat: 用户可见自己帖子的审核状态
...
- 发帖后若未直接过审,弹窗明确「审核中,通过后才出现在社区」,
不再让用户以为发失败/是 bug
- 后端 ListUserPosts:看自己主页时返回待审核/未通过的帖子(带状态),
看别人仍只返回已发布
- 个人主页帖子加「审核中/未通过」状态标 + 说明
- 我的页加「我的帖子」入口,进自己主页看审核状态
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 08:49:20 +08:00
Blizzard
b01effaf5e
style(fe): 社区帖子图片改固定小缩略图(210rpx 正方形)
...
aspect-ratio 在微信渲染不生效导致竖图被撑长。改成 flex-wrap +
显式 210rpx 见方的缩略图,小而统一,点击 previewImage 放大。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 08:40:06 +08:00
Blizzard
f0ea05696c
feat(fe): 社区帖子图片点击放大预览
...
缩略图保持网格展示,点击走 wx.previewImage 全屏预览,
可左右切换同帖多图(emoji 占位不参与)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 08:33:55 +08:00
Blizzard
c852817363
fix(fe): 修社区图片撑破网格;发帖限 3 张;上传偶发失败自动重试
...
- .photo-tile 补 width:100%+min-width:0:微信 image 默认 320x240,
不给宽高会冲破 photo-grid(社区帖子图片"爆炸")
- 发帖图片上限从 9 张改成 3 张
- uploadFile 三重兜底:冷启动没 token 先续期、40100 续期重试、
网络/网关瞬时错误自动重试一次(后端 MD5 去重,重传安全)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-31 08:32:22 +08:00
Blizzard
a010629ac1
chore(deploy): 部署注入 WECHAT_MSG_TOKEN(内容安全回调校验)
...
deploy/docker-compose.yml 把 .env 的 WECHAT_MSG_TOKEN 映射成
PETS_WECHAT_MSG_TOKEN 注入容器(可选,留空则回调不校验签名);
.env.example 补上说明。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 19:08:11 +08:00
Blizzard
6bb327e62e
fix(be): 登记 wechat.msg_token 默认值,让 PETS_WECHAT_MSG_TOKEN 能覆盖
...
viper AutomaticEnv 只对已登记的 key 生效,纯 .env 部署下未登记的
key 绑不上,会静默取空值。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 19:04:38 +08:00
Blizzard
67b97e4b38
feat(be+admin): 后台看板扩展 + 社区内容安全审核
...
看板(Recharts):
- 概览页加 DAU/WAU/MAU、今日/本月新增 KPI,新增趋势/活跃趋势/月活/留存曲线
- GET /admin/analytics 内存计算,活跃口径=当天有记录/发帖/评论,排除 bot
内容安全(微信官方 UGC):
- 文本 msg_sec_check 同步判、图片 media_check_async 异步查
- 帖子/评论加 pending/rejected 审核态,feed 只放 published
- 图片结果回调 /api/wx/sec-callback,JSON/XML + 明文模式,签名校验
- 检测不了/未发布时一律转待审核,走后台手动审核
- 后台帖子/评论审核页:修好看不到图(补 attachPostImages)、
加状态筛选 + 通过/打回;新增评论审核状态接口
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 19:01:48 +08:00
Blizzard
c48e241fe1
feat(fe): 评论改小红书式展开输入面板;FAB 统一暖橘;顶部去冗余入口
...
- 评论:底部平时一条细「说点什么」,点开才展开大写评论面板
(大输入框+工具栏+发送,浮在键盘上方)。失焦时有草稿保持展开,
避免点发送因面板收起而丢点击
- FAB 主题色统一:社区发帖 FAB 从深色改成和首页肉垫一致的暖橘圆钮
- 报告页顶部筛选去掉「添加」(报告页不需要建档入口)
- 社区去掉顶部「发布」按钮,发帖统一走右下角悬浮按钮
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 18:13:41 +08:00
Blizzard
4f52a7d3a1
style(fe): 评论弹窗重做——空态加图标、输入区合成圆角输入栏
...
- 空态从一行飘字改成 图标+两行文案 居中
- 相机/输入框/发送合成一条聊天式圆角输入栏,字数只在输入时显示
- 头部标题加粗
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 18:05:25 +08:00
Blizzard
396f531023
feat(fe): 肉垫 FAB + 冷启动闪屏;顶部筛选改纯文字对齐
...
- FAB 重设计成肉垫造型(呼应「肉垫计划」),修 fab.js 漏声明
icon 属性导致的兜底文档图标;社区发帖 FAB 保持图标
- onboarding 加冷启动闪屏,登录+拉宠物在闪屏期完成再进首页,
不再闪一下建档向导;欢迎屏 logo 换肉垫、去掉过时 AI 文案
- 顶部宠物筛选去掉头像改纯文字(带图/emoji 时高度对不齐),
固定高度 + vertical-align:middle 彻底对齐,添加用「+」文字
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 17:57:06 +08:00
Blizzard
de2b72221c
fix(be): 编辑档案补写到家日期/生日;关迁移期外键修复重复索引
...
- UpdatePet 的 fields map 之前漏了 birthday 和 arrived_at,
导致编辑档案改到家日期不落库(首页天数一直显示「-」)
- DisableForeignKeyConstraintWhenMigrating:外键列自动索引和字段
index tag 撞成同名索引,父子表同迁时报 1061,关掉库级外键约束创建
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 17:57:05 +08:00
Blizzard
e2ce56680a
fix(fe): 修切换条头像撑大 chip;我的页菜单只留设置
...
- pet-switch 头像 flex:none 锁死 52rpx,真机上图片固有尺寸不再撑大 chip
- 我的毛孩子去掉「+添加」(首页切换条可加)
- 菜单区只留「设置」,档案/计划/多宠都从首页和宠物卡进
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 17:20:02 +08:00
Blizzard
11c4d490e6
feat(fe): 宠物照片替代默认头像,身份卡移到首页门面卡
...
- 首页/我的/切换条:上传过照片就用照片,没有才退回 emoji
- 报告页分享海报:先异步加载头像再开画,画成圆形头像
- 一起生活的天数改成从到家日期算,没填就显示「-」并可点去补
- 身份卡入口从「我的」页移到首页门面卡右上角
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 17:08:32 +08:00
Blizzard
cbfcaada55
feat: 宠物身份卡(canvas 绘制 + 小程序码 + 存相册/分享)
...
竞品那张「居民身份卡」,完整做了。
## 后端
service/wxacode.go —— 小程序码。两步:先拿 access_token(2h 有效,进程内缓存、
提前 5 分钟过期),再调 getwxacodeunlimit 换一张 PNG 存到 MinIO 返回 URL。
同一只宠物的码 object 名按 pet id 定死,存在就直接返回不重新生成 ——
微信侧有日调用配额,不能每次点都烧一次。
⚠️ getwxacodeunlimit 要求 page 在**已发布**的小程序版本里。开发/未发布时返回
errcode 41030,实测确认。这时身份卡照常出、只是没码(qr_ready=false),
发布后自动就有,不用改代码。best-effort,取不到不算错。
service/idcard.go —— 组装卡片内容。身份 ID 用「宠物雪花 id 的数字 + 生日」
拼成 18 位、每 4 位空一下,纯装饰不入库不校验,同一只每次都一样。
介绍按物种给默认(汪星人/喵星人来地球啦~)。有效期用生日起算。
GET /api/pets/:id/id-card
storage 加了 Exists(StatObject),生成前先查。
## 前端 pages/idcard
离屏 canvas 2d 画卡,导出成图展示 + 存相册 + 分享(open-type=share,
imageUrl 用画好的卡当封面)。
两张远程图(头像 + 小程序码)都用 node.createImage() 异步加载,
**Promise.all 等两张都就绪再开画** —— 否则小程序码会画不上或画一半
(规划里专门点过名的坑)。任一张加载失败 resolve(null),缺图也照画:
头像缺→画物种 emoji,码缺→画「小程序码 待发布」占位框。
存相册的权限被拒过一次后 wx.authorize 不再弹,走 openSetting 引导(同海报那套)。
绘制复用了 bottom-sheet 里 poster 的 canvas 模式(dpr 放大、roundRect、
canvasToTempFilePath),但 poster 只画文字不画远程图,这里的双图加载是新写的。
入口:「我的」→ 身份卡,用当前选中的宠物。
## 验证(预生产库实跑)
id-card 接口返回:姓名/性别/品种/生日/介绍/身份ID/有效期 全对
身份 ID = 3410 4333 1420 2503 17(宠物id数字+生日,稳定)
qr_ready = false,日志确认 41030 invalid page(小程序未发布,预期)
canvas 版式用 HTML 复刻确认过:未发布=占位、发布后=真码
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 16:48:16 +08:00
Blizzard
048408b0e9
fix(fe): 报告页/我的 底部被 tabBar 遮住
...
no-fab 的底部留白是 60rpx,那是给二级页(无 tabBar)用的。报告页和「我的」
是 tab 页,底下有原生 tabBar(高 108rpx),60rpx 让不开,最后一张卡/入口
被 tabBar 压住 —— 报告页的「全部记录」就点不到。
加 --pad-b-tab(150rpx + 安全区)和 .tab-nofab 类,报告页和我的改用它。
no-fab(60rpx)留给真正的二级页(record/plan/expense/history/settings…)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 16:05:14 +08:00
Blizzard
7abcc0dd2d
refactor(fe): 报告页重构成数据看板,历史页降级成「全部记录」
...
## 之前报告页的问题
它是个顶级 tab,却只有四张薄卡,而真正的分析全被埋起来:
- 养宠账单里「记一笔」开 cost 弹层 —— 那分支上一轮随记录表单搬走了,
点了开空弹层,是个断按钮
- 养宠账单是我新建花销页的一个残缺子集,重复
- 后端有 6 条洞察 + 体重曲线,全在「历史页」,报告页只用一行链过去
- 健康摘要四行手拼字符串,很薄
## 报告 = 数据看板
把埋在历史页的分析提上来,报告页成为真正「看数据」的地方:
本周概览 周报小结 + 完成/体重变化/高风险三个数 + 生成分享卡片
健康洞察 6 条洞察直接铺在报告页(按 alert>warn>info 上色),
点一条跳去记那一类。这是看板的主角
体重趋势 把那张 SVG 曲线图提上来(点圆点看每次记录)
健康摘要 疫苗/驱虫/体重/异常四行 + 导出就医摘要
养宠花销 只给「本月 ¥X + top 类别 + 分类条」概要,点整卡进花销页,
不再内嵌半套花销 UI,断掉的「记一笔」删了
全部记录 一行入口进历史页
## 历史页降级成「全部记录」
洞察和体重曲线搬走了,历史页只留「时间轴流水 + 类型筛选」——
分工清晰:报告=看分析,全部记录=翻流水。nav 标题改成「全部记录」,
去掉不再用的 bottom-sheet / fab / seg-tabs 之外的东西。
体重曲线的「记一笔」原来开 weight 弹层(已删),改成跳
addrecord?type=weight;洞察点击也从开弹层改成跳 addrecord。
## 顺手
报告页去掉了 Pro 会员占位卡(支付未接入,就是个营销占位),
接入支付时再加回来。
## 验证(预生产库实跑)
周报 需要关注 / 完成0 / 高风险1,小结文案对
洞察 1 条(食便相关),带 level=warn + action=food + 依据
体重趋势 字段验证只有 1 个点 → 曲线走空态「先记录几次」
健康摘要 疫苗 0/3 即将到期、驱虫下次日期、体重稳定增长、异常 1 次
账单 本月 ¥188、top 医疗、2 个类别
5 个接口全部返回真数据
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 15:03:47 +08:00
Blizzard
6a132d13bd
style(fe): 记录页从「肥色块」改成白卡收纳
...
截图那个真的丑:.quick 是 128rpx 的大方块,整格铺 tone-N 的浅色底,
四个排一行就是一片肥色块,还直接浮在页面渐变上、没有卡片收纳,
不完整的行还留大缺口,整体像一张配色测试表。
改成 preview-v3(你当时认可的那版)的做法:
每组一张白卡收纳(.card)
颜色只集中在图标那个 96rpx 小圆角块上(.rec-ic + tone-N)
标签用纯深色,不跟 tone 变 —— 四组底下的字统一深灰,才不花
组标题一根同色系竖条 + 组名
.quick / .quick-grid / .tg 现在只有记录页用,直接换成 record 页私有的
.rec-* 类,不动全局。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 14:26:00 +08:00
Blizzard
6fd4977f46
feat(fe): 建档挑方案、计划页套方案、阶段漂移提示
...
后端上一轮做完了但小程序上看不到,这次接上。
## 建档第四步:挑方案
方案按阶段取,所以必须排在「资料」之后(阶段是第三步定的)。卡片上按重复方式
分开报数(每天 3 项 / 每周 2 项 / 一次性 2 项),不报一个总数——4 条「每天」
套一整月就是 120 多条,只给总数用户会以为出 bug。
「先空着,我自己排」是个平等的选项,和方案卡长一样、就在下面一眼能看到,
不是藏起来的退路:已经养熟的宠物主人有自己的节奏,硬塞一套只会被删掉。
默认选第一套——多数用户是新手,给一个合理默认比让他面对空白好。
编辑档案时不出现第四步:改档案不该顺手改计划。
套方案失败不算建档失败:档案已经建好了,方案之后在计划页还能套,
不该把用户退回表单。
## 计划页:空月份和平时都能套
空月份的提示条带「套一套方案」按钮 —— 空着让用户从零排,多数人会直接退出去。
但「+ 加一件」始终在,不能只给套用。
浮层里写明「套用是往里加,不会覆盖你已经排好的」,因为服务端就是按
「日期+标题」去重的,这句话是真的。套完 toast 报排了几件;一件都没排
(全都已存在)时说「这个月已经有这些安排了」,不说「成功」。
## 阶段漂移提示
首页门面卡下面一张卡:「钞票已经 17个月,从幼年期进入成年期了」,
带上新阶段的划分依据、养护重点和体型说明,点进去到建档页改。
用主色不用红色 —— 这是「可以做一下」不是「出问题了」。
改完回首页 onShow 重拉一次,卡片自然消失。
不在首页直接改阶段:改完要不要套新方案是同一件事,放在建档页一起做才连贯。
## 顺手把合并的尾巴清了
manageTasks 那一支删了:它管的是 DailyTask,而今日任务已经并进计划节点,
增删改都在计划页。留着会出现「这里加的任务」和「计划页加的节点」进不同的表。
连带清掉 7 个死方法 + taskSheets + 一个死 require(简易表单那套早随记录表单
搬到 pages/addrecord 了)。首页现在一个弹层都不开,bottom-sheet 组件也去掉了。
弹层累计:js 1110 → 689 行,wxml 485 → 278 行。
## 验证(预生产库实跑)
建档四步 6 个月柯基 → 幼年期 → 拉到「幼犬标准照护」→ 套用本月 7 条
→ 首页今日任务 4 条
先空着 今日任务 0 条,疫苗驱虫提醒仍然建
计划页套用 0 → 7 条;重复套用 0 条(去重生效)
漂移检测 17 个月柯基存着幼年期 → drifted=true,给出依据/重点/体型
改成成年期 → drifted=false
没生日 → 不提示(算不出就不猜)
「刚到家」→ 不提示(叠加层不是年龄段)
第一版验证脚本把阶段改成了和算出来一样的值,drifted=False 是对的,
但我的 print 无条件打了提示文案,看着像 bug。重测才验到真的。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 12:59:27 +08:00
Blizzard
cff6982613
chore(admin): 删掉停用的老方案,养护方案页按猫狗分 tab
...
## 停用的 8 套直接删了
上一个提交把老方案(按 3 段配的)改名停用没删,理由是「万一新内容有问题
还能翻回去看」。你要求删掉,删了。
走 service 的 DeleteTemplate 而不是直接删主表:明细要跟着一起清。
复查孤儿明细 0 条。剩 10 套(5 阶段 × 2 物种,各一套)。
已套用出去的计划节点不受影响 —— 套用时就展开成实体行、和模板断开了。
## 按猫狗分 tab
混在一起 10 套要上下找,而且阶段名两边一样(幼年期/青年期…),扫一眼分不清
哪套是猫的。tab 上带条数,「阶段」列不再重复物种。
顺带两处:
行按阶段顺序排 —— 数据库按 sort 排,但 sort 是全局的,分物种看时会跳号
新建时默认跟当前 tab 的物种,省一步点击
品种管理页本来就有猫狗 tab;记录事项页不分物种(记录类型猫狗共用)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 12:53:22 +08:00
Blizzard
c4c0c2b7cd
feat: 生命阶段按猫狗真实生理规律细分,划分标准和判定用同一份数据
...
## 你问的「养了半年会不会自动切换」
原来的答案是「都不会,而且比这更糟」:
age「2个月」 建档时算好存进库,养半年后首页还显示 2个月
stage「幼年期」同上,一年后还是幼年期
养护方案 按 stage 挑的,所以永远给幼猫那套
NormalizeStage 只在建档那一次调用(handler/pet.go:51),之后就是两个死字符串。
现在:
age 改成计算字段(gorm:"-"),读取时现算。它没有手改需求,存下来只会过期。
填在 ownedPet 这个收口里,不是逐个函数补——那样漏一个就返回空年龄。
stage 保留存储(有正当的手改需求:领养的猫生日是估的,主人按体型判断更准),
但加了漂移检测 GET /pets/:id/stage-drift。
**系统负责发现,用户负责决定。** 不自动改的三个理由:
1. 用户可能手改过
2. 已经排好的这个月计划不该被推翻(套用是「往里加」不是「替换」)
3. 偷偷换会让用户莫名发现计划变了,找不到原因
## 猫狗不能共用阈值 —— 这是这次最实质的发现
原来一刀切「<12月幼年,>=7岁老年」,对猫勉强,对狗两头都错:
吉娃娃 8 个月已性成熟、可换成犬粮;大丹犬 8 个月还在长骨头,
这时喂成犬粮(钙磷比和热量密度都不同)会加重关节负担。
吉娃娃 7 岁还在成年期(8 岁才进中年,能活 13-16 年);
大丹犬 7 岁已是老年(平均寿命 7-10 年)。
所以狗的阶段判定要看体型。体型不能靠当前体重(幼犬体重说明不了成年后多大),
只能靠品种 —— breeds 表加 size_class,45 个犬种逐个标了。
实测:同样 10 个月大 → 吉娃娃青年期、柴犬幼年期、金毛幼年期、大丹犬幼年期;
同样 7 岁 → 吉娃娃成年期、大丹犬老年期。
## 阶段 3 段 → 5 段
幼年期 / 青年期 / 成年期 / 中年期 / 老年期。
标签做成物种中立(不分幼猫期/幼犬期)——物种本来是另一个字段,
分开会让 (species,stage) 的组合和方案配置都翻倍。
「刚到家 0-30 天」不进这五段:它和年龄正交(刚接回家的成年猫两套都需要),
代码里本来就是叠加处理的。
猫按 AAFP/AAHA 猫生命阶段指南那套,在成年里细分出中年。
狗五段的阈值按体型走四组,越大的犬种生长期越长、老得越早。
## 划分标准和判定用同一张表
StageRules 那张表既驱动判定,也直接吐给前端当依据展示
(GET /api/life-stages?species=dog&size=giant)。
不是「代码里判定 + 文档里写标准」——后者一定会漂:改了阈值忘了改文档,
用户看到的说明和实际行为对不上,比没有说明更糟。
建档第三步的阶段选择器现在会显示「0-18 月 · 巨型犬生长期最长,18 个月还在长;
这阶段最忌过度补钙」,还会标出「巨型犬(成年 >40kg)——阶段阈值按体型算」。
前端和后台的 STAGES 硬编码列表都删了,改成读后端。
## 10 套方案,内容按各阶段真实重点配
不是把同一份换个名字:
幼年期 疫苗序列 + 驱虫 + 社会化,大型犬还要控制生长速度
青年期 绝育窗口 + 换成年粮
成年期 维持期,把基线数据记下来
中年期 年度血检开始有意义,体重和牙结石重点看
老年期 体检半年一次;猫记饮水量(多饮多尿是慢性肾病最典型的早期表现)、
狗记精神食欲,都设成「重要」
老的 8 套(按 3 段配的)改名停用不删:万一新内容有问题还能翻回去看;
而且已套用出去的计划早就和模板断开了,停用不影响任何用户。
## 验证(预生产库实跑)
体型判定 10 个月 / 7 岁两组对照,四个体型都落在预期阶段
age '13个月' 现算,不入库
漂移检测 手改成幼年期后 drifted=true,连带给出新阶段的依据和重点
划分标准 猫 5 段、狗 4 个体型各 5 段,老年起点 7/8/10/11 岁
全链路 3 个月大丹犬建档 → 幼年期 → 0 任务 + 4 条必要提醒 →
挑「幼犬标准照护」→ 套用下月 104 条节点,
周四那天正确出现每周项(检查爪垫和耳朵)
迁移 45 个犬种体型回填;现有 5 只宠物阶段重算后无变化(原本都对)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 12:51:10 +08:00
Blizzard
afdbf94450
feat(admin): 养护方案页重写 —— 多套、重复规则、"弹层"改成真实的记录事项
...
## 你问的那个「弹层」是什么
sheet_type = 用户在小程序点这条计划时,直接跳到哪个记录表单。
「体重记录」这条关联 weight,点了就是体重表单,不用自己去记录页找。
叫「弹层」是因为那时候记录表单是底部弹出的浮层。三件事让这个名字烂掉了:
1. 记录表单上一批已经搬成 pages/addrecord 独立页面了
2. 可选值写死 6 个,而记录事项现在有 24 种且后台可配 —— 新加的一个都选不到
3. 里头的 report / taskDetail 早就不存在,选了等于点了没反应
现在改成「关联记录事项」,下拉读 record_types 表。后台加一种事项,
这里立刻能选到。
## 这一页原来和后端已经对不上了
它的结构(今日任务 / 30 天计划 / 提醒 三段、第 N 天偏移)就是上一个提交在后端
推翻掉的那套。你在上面配的东西一部分已经不会生效——所以先改它,不等前端。
三段 → 两段(计划事项 / 到期提醒)
「第 N 天 + 标签」 → 重复规则:每天 / 每周(勾星期几)/ 每月(几号)/ 一次性
一个 (物种,阶段) 一套 → 多套,列表页展示,每套有名字和摘要
## 后端跟着改成按 id 存取
原来是「按 species+stage 覆盖」:GET/PUT /admin/care-templates?species=&stage=。
那个模型下「让用户选方案」无从选起。改成
GET /admin/care-templates 列全部
GET /admin/care-templates/:id
POST /admin/care-templates 新增或更新
DELETE /admin/care-templates/:id
## 唯一索引是真拦路石
从模型 tag 里去掉 uniqueIndex:idx_species_stage 之后,新增第二套仍然报
Duplicate entry —— **AutoMigrate 会加索引但不会删已有的**。写了个一次性程序
DropIndex 才通。这个坑值得记:改索引不能只改 tag。
## 校验放服务端
一条配错(「每周」没勾星期几)会让套用时静默少排几条,用户看不出是配错了。
所以保存时就拦,并且报出是哪一条:「梳毛」选了每周,但没勾星期几。
## 列表里报「展开后大概多少条」
只报明细条数会骗人:4 条「每天」套一整月就是 120 多条。
列表和小程序端的方案卡都按重复方式分开报数。
## 验证(预生产库实跑 service 层)
8 套现有方案迁移后都有名字
没名字 / 每周没勾星期几 / 每月几号填 0 → 三条校验都拦住并指名道姓
(猫,成年期) 成功配出第二套「成年猫省心版」,小程序端能看到 2 套可选
tsc --noEmit 通过;npm run build 后重启,/admin/ 资源哈希与新构建一致
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:59:52 +08:00
Blizzard
8b1b4cde02
refactor(be): 今日任务并进计划节点,养护方案改成可选、按重复规则配
...
## 三个问题,一起解决
你问「模版要不要做成可选」,摸下来发现底下有三个更硬的:
**① 根本没有多套模版可选。** 模板表唯一索引是 (species, stage) ——
同一个「猫 × 幼年期」只能有一套。「让用户选模版」在数据模型上做不到。
去掉唯一索引,加 Name / Summary / Sort / Enabled。
**② 今日任务和计划节点是两套,而且是我上一轮改出来的。**
DailyTask 模板 kind=task 生成,ensureDayTasks 每天把昨天那份复制到今天
PlanTask 模板 kind=plan 生成,Day 偏移
计划改成月度管理 + 加了「应用到每天」之后,两者做的是同一件事,
但首页读 DailyTask、计划页管 PlanTask —— 用户在计划页加一条「每天喂药」,
首页今日任务里看不到。
DailyTask 退役。task.go 重写成 PlanTask 的一层「按日期取」的门面,
/pets/:id/tasks 路径不变,小程序端不用为这次合并改调用。
PlanTask 加 Priority(首页那份要能标出哪条重要)。
顺手删掉重复的 CreateTask/UpdateTask/DeleteTask —— /plan-tasks 那套已经
覆盖了,留着两套会出现「首页管理弹层加的任务」和「计划页加的节点」进不同的表。
**③ 模板的 Day 偏移和月度计划对不上。** 月底建档的话 day=14/21/30 全落到
下个月,用户建完档打开计划页发现本月是空的。
改成重复规则:once(偏移 N 天,疫苗序列要用)/ daily / weekly(星期几)
/ monthly(几号)。套用 = 展开成目标月份的具体日期。
「每月 31 号」在 2 月按月末算,不然那个月直接没有。
列名用 repeat_rule 不用 repeat —— repeat 是 MySQL 保留字(和 group_key 同理)。
## 展开成实体行,不是「存规则读时展开」
勾选状态是按天的。存规则得再开一张表记「哪天打过勾」,而且用户把
「每周二梳毛」这周挪到周三就要引入例外记录。一次展开成行,增删改和打勾全免费。
代价是套用后模板和计划断开:后台改模板不影响已套用的宠物。这是有意的——
用户已经在自己的计划上勾了几十个勾,后台一改就被覆盖才是灾难。
## 建档不再自动铺
seedPetDefaults 只建必要提醒(疫苗、驱虫)。漏针是真会出事的,而且它们是
「到期提醒」不占计划页的格子。其余交给用户挑方案。
自动铺的问题是:用户还没看懂这个 App 是干什么的,首页已经躺着十几条他没
答应过的任务,第一反应是「这些是什么」而不是「我该做什么」。
**改完发现还有第二条自动铺的路径**:newStagePlan 在建计划壳子时顺手把模板
铺成节点。所以我改完 seedPetDefaults 之后,建档后首页仍然躺着 5 条任务。
惰性生成尤其难查——不是建档时发生的,是第一次读计划才发生的。
## 方案摘要按重复方式分开报数
一开始只报一个总数,「10 条」套用一整月展开成 130 条,用户会以为出 bug。
现在分成 每天 4 · 每周 0 · 每月 0 · 一次性 6 · 提醒 4。
## 数据迁移(预生产库,已执行)
模板明细 kind=task → plan + repeat=daily 28 条
模板明细 kind=plan 补 repeat=once 44 条
8 套方案补名字和摘要
DailyTask → PlanTask 34 条,跳过 0
DailyTask 表的行**没删**,先留着当备份。
迁移第一版又踩了「列还没 AutoMigrate 出来就跑」那个坑:Count 静默返回 0,
我以为「没有需要补的」。第二版加了 HasColumn 前置检查才发现 44 条没转。
和上次 record_types.fields 回填是同一个错。
## 验证(预生产库实跑)
今日任务/计划页今天 4 条 vs 4 条,一致
建档后 0 任务 / 0 计划节点 / 4 条必要提醒
套用本月 从今天到月末,4 条(7/30-7/31 两天)
重复套用 0 条新增(按「日期+标题」去重)
套用下月 130 条覆盖 31 天,每天 4.2 条
全部完成 5 → 0 未做
## 还没做(下一步)
前端:建档第 4 步选方案、计划页空月份的套用入口、首页「管理」改跳计划页、
弹层删 manageTasks;后台模板页要支持多套 + 重复规则编辑。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:50:54 +08:00
Blizzard
69bd56671c
feat(admin): 补品种管理和记录事项两个后台页
...
## 这两个页面是漏的,不是新需求
Step 2 我说了「记录类型后台可配」,接口加了(GET/POST/DELETE
/api/admin/record-types)但 React 页面根本没建;品种那次同样只加了接口。
也就是说「可配」这件事在后台上一直是点不到的。补上。
## 品种管理
猫/狗切换,按首字母分段列出(和小程序端的 A-Z 索引对得上)。
首字母是手填的输入框,配了一句说明:多音字自己定(藏獒 Z、柴犬 C)。
不做自动转拼音——Go 没有标准拼音库,而且多音字自动转常出错,
错了以后用户在小程序里按字母索引就找不到那个品种。
## 记录事项
按分组列出 24 种,「表单字段」那列把 DSL 渲染成人话
(体重·数值kg / 状态·单选★),★ 表示这个单选落 category。
字段配置的写法说明直接放在编辑弹窗里,不是写进文档:这东西一年用两次,
去翻文档的成本比它本身还高。
内置那 9 种打了「内置」标签、隐藏删除按钮、code 输入框禁用 —— 但真正的
拦截在 service 层,前端只是别让人白点。
## 报错原样透出
两个页面的保存失败都把后端消息显示出来,不写成「保存失败」。
后端那些消息是特意写具体的(第几行、错在哪、几个档案在用),
包成一句「失败」等于把它们扔了。
## 验证(预生产库实跑 service 层)
品种 首字母两位/中文 → 拒;物种 bird → 拒;同物种重名「布偶猫」→ 拒
有 1 个档案在用时删 → 拒并报出数量;没人用 → 删成功
事项 两个字段都落 category → 「第 2 行」;options 没选项 → 「第 1 行」;
类型写成 num → 「第 1 行类型 num 不认识」;缺名称 → 「第 1 行缺名称」;
第二个加 :- → 通过
tsc --noEmit 通过;npm run build 后重启,/admin/ 返回的资源哈希
和新构建一致(go:embed 是编译期打包的,不重启看不到新页面)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:32:50 +08:00
Blizzard
aefb1bc103
feat: 建档改成三步向导页,品种改成后台可配的选择器
...
## pages/petform 三步向导
① 名字 + 传头像
② 猫还是狗 → 选品种
③ 性别 / 生日 / 到家日期 / 体重 / 毛色 / 阶段
**编辑时不分步**,一屏全放开:用户是来改某一项的,不该被按顺序走一遍。
同一个页面两种形态,靠 ?id= 区分。
每一步只校验这一步的东西。三步全填完才校验的话,用户在第三步才被告知
第一步没填名字,还得翻回去。
进度条没用 seg-tabs:那是「可以随意切」的语义,这里有顺序,
点第三步跳过前两步会拿到一份没名字的档案。
## 生日和到家日期分开
原来是一个「生日 / 到家时间」字段。领养的成年猫狗生日常常是不知道的,
而「一起生活了多少天」要按到家日算——合成一个字段两件事都说不准。
验过:到家 4 个月前 → 第 121 天;按生日算会是 801 天。
模型里 Birthday 和 ArrivedAt 本来就是两个字段,只是表单没露出来。
## 品种:自由文本 → 后台可配的选择器
原来品种是个输入框,用户手打「柯基」「柯基犬」「威尔士柯基」算三个品种,
以后想按品种做体重基准、常见病提示这类事就没法做。
新增 breeds 表,预置 34 种猫 + 45 种狗,按首字母分组、右侧 A-Z 索引跳转、
首字母吸顶。留了「不确定」——领养的串串确实说不出品种,逼着选一个只会
得到假数据。换物种会清掉已选品种(原来那个一定不对了)。
**首字母存字段不运行时算**:Go 没有标准拼音库,而多音字自动转常出错——
「藏獒」按 cang 还是 zang 分组、「柴犬」的柴,人来定比库来猜靠谱。
后台新增品种时手填这一位,服务端校验必须是单个 A-Z。
已有档案在用的品种不许删(删了那些档案的品种就变成查不到的字符串),
想隐藏用 enabled=false。同物种下不许重名——品种是统计口径,重名会把
同一种猫劈成两半。
预置数据自己填错了两条,实跑时看出来的:「苏格兰柯利犬」我按「柯利」
填了 K,应该按「苏格兰」算 S;「双血统边牧」根本不是品种,是血统描述。
seed 源和库里都改了。
## 弹层继续瘦
addPet/editPet 两支删掉,连带 10 个方法、ageFromBirthday/GENDERS/STAGES
和 5 个 add* 字段。累计(从记录表单搬走那次算起):
js 1110 → 734 行
wxml 485 → 307 行
多宠管理里「点某只去编辑」原来是 setType('editPet'),那支没了会开一个
空白弹层——改成关弹层再跳页。8 个页面的入口全换完,grep 无残留。
## 验证(预生产库实跑)
品种接口 猫 34 种 16 个首字母、狗 45 种 17 个首字母;非法 species 返回 []
建档 生日 / 到家日期 分别落库,品种毛色阶段都对
编辑 只改名字,到家日期没被冲掉
修正 柯利犬 K→S、双血统边牧已删
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:26:51 +08:00
Blizzard
2aaae2b917
style(fe): 计划页只留日历和当天安排
...
去掉完成度卡和完整路线图。这页的用途是「排/看某一天要做什么」,
完成度是个统计(报告页的活),完整路线图和日历在说同一件事、
只是换了个排法——两张卡加起来把日历挤到了第二屏。
跟着清掉 doneCount / allOpen / toggleAll / dateLabel 和一个没人绑的 openSheet
(路线图里的 pk-body 原来绑它,现在那块没了)。
一个前提确认过:删掉路线图不会让节点变孤儿。模板从计划开始日生成 day 0-30,
正好落在本月和下月,两个月都能从日历翻到。只有很旧的计划(开始日在上个月之前)
会有节点翻不到,那些已经是过去的事。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:12:46 +08:00
Blizzard
9b30bfaaff
feat: 计划按自然月管理,加「应用到每天」和下月未排提醒
...
## 为什么不是「从计划开始日起 30 天」
上一版是那样做的,截图一看就不对:计划是月中建的,日历显示
「7月26日 — 8月25日」,既不像本月也不像下月,用户想问「这个月还剩什么」
根本对不上。改成自然月,日历就是一眼能认的月历。
能翻到下月 —— 否则「做下月计划」这件事本身做不了。
## 校验从「Day 上限」改成「日期」
PlanTask.Day 是相对计划开始日的,月份边界是相对今天的,两者会错开。
原来卡 Day<=30,计划建了几天之后下月末就换算成 Day=40 多,
用户在日历上明明看得到那格、点进去却存不了。
现在的规则:不早于计划开始日(下界放到开始日而不是本月 1 号——模板生成的
历史节点可能在上个月,那些要允许原地改),不晚于下月月底。
## 应用到每天
一天建一条,不做「一条 + repeat 字段读时展开」:勾选状态是按天的,
展开方案还得再开一张表记「哪天打过勾」,而直接建 N 条天然就有这个能力。
范围止于**这一天所在那个月**的月底,不跨月——「应用到每天」说的是这个月每天,
跨过去就变成用户没要求的事了。只有新增能选,已有的那条改成每天等于凭空
复制 N 份(用户想要的是「以后每天」,不是「把这条撒开」)。
## 首页那个提醒
GET /pets/:id/plan/month-status 返回本月件数/剩余、下月件数、need_next。
need_next 只在**月末最后 7 天**且下月为空时为真:月初就催「排下个月」太早,
用户会当成噪音。角标做在图标上而不是弹 toast——每次进首页弹一下很烦,
而这件事不紧急、看见就行。
副标题有优先级:「8 月计划还没排」压过「本月都做完了」,因为前者有时效。
四种状态实跑验过,包括让位关系。
## 顺手
pet-switch 加 show-add 属性。计划页只需要在既有宠物之间切,建档入口在首页
和「我的」就够了,到处摆一个「添加」会让这条 chip 变得很长。
本月/下月的切换用新的 .link-tabs 而不是挂在 .head-links 上:首页的
「管理 / 全部完成」也用 head-links,那是两个并列动作,不该有一个是灰的。
## 验证(预生产库实跑)
月边界 本月末通过、下月末通过、下下月拒(报出具体日期)
应用到每天 今天→本月末 2 条,没跨月
month-status 下月清空 → need_next 翻 true;补一条 → 翻回 false
四种副标题 下月未排 / 本月还有 N 件 / 本月都做完了 / 还没有安排,含优先级
测试数据全部还原
上一条 cd 打错目录,导致「日期窗口」那次改动没写进文件、只有批量那半截进去了,
所以中间出现过一次 planWindow undefined。这次一并改对。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 11:09:06 +08:00
Blizzard
bbc9706576
style(fe): 记录页按 preview-v3 收拾干净
...
## 分组那片色块是个 bug,不是设计
我把 tone-{{item.tone}} 加在分组外层是为了给组标题上色,但 .tone-N 在
app.wxss 里本身就带 background(`.tone-1{background:var(--primary-soft)}`),
于是整组被涂成一片色块——和视觉稿完全不是一回事。
分组着色单独走 g-1..g-4,只管 .tg-head 的文字色。格子的浅色底仍然是
.quick + .tone-N,那是它本来的用途。
## 另外三处
三列 → 四列(视觉稿是四列,三列一行只放三个,洗护/清洁要多滚一屏)
去掉组右侧的数量(6/7/6/5 —— 用户不关心一个组里有几项)
组名去掉「记录」后缀(「日常记录」在标题位置念着啰嗦,「日常」就够)
## 去掉顶部的宠物切换和添加
这页只是个事项目录,点进去才是表单。记哪只宠物在添加页里选(那页第一行
就是「记录宠物」,多宠家庭最容易记错到别的宠物身上,放在表单里才对)。
record.json 跟着去掉 pet-switch 注册。
## .tg 挪回页面级
历史页那份宫格上一批已经删了,现在只有记录页在用,全局层只放真正共用的。
哪天别的页面要用,检查器会报「跨页借用」提醒再挪上去。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 10:53:31 +08:00
Blizzard
30b190363e
fix(fe): 修弹层编译不过(链首被删),检查器补上 wx:if 链校验
...
## Bug
上一批把 9 个记录分支从弹层整体搬到 addrecord 页时,连带删掉了带 wx:if 的
第一支(weight),整条链从 wx:elif 开头。小程序直接报
Bad attr `wx:elif` with message: `wx:if not found, then something must be wrong`
整个组件编译不过 —— 不是少个样式,是弹层完全打不开。把现在的链首
(就医前摘要)改成 wx:if。
## 检查器补这一条
这种错「删对了 9 支、漏改 1 个属性」就会发生,而且是编译期爆炸,
检查器原来完全看不见。
判断必须靠真正的标签栈。中间走错两次,都值得写下来:
**① 按缩进深度分链 —— 不行。** 这个项目里 scroll-view 和它的子节点缩进
是一样深的,「同层」判断会把父节点当兄弟节点。而且更糟的是它不报错:
前一条链的 wx:if 被当成这一条的链首,注入错误也查不出来,是个假绿。
**② 给 void 标签列白名单 —— 不行。** wxml 里 <image></image> 是显式闭合的,
把它当 void 就变成「开标签不入栈、闭标签却弹栈」,一路把父级弹光,8 个误报。
只认 /> 就够。
**③ 自闭合不能用单独的捕获组。** 属性那段是贪婪的,会把 /> 里的 / 一起吃掉,
(\/?) 永远匹配空。多行写的 <input ... /> 因此被当成非自闭合入了栈,
把整份栈层级带偏,7 个误报。改成从 attrs 尾部 /\/\s*$/ 判断。
## 自测
把链首改回 wx:elif → 精确报第 96 行那一处,其余 24 个 wxml 零误报;
还原 → 恢复绿。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 10:49:23 +08:00
Blizzard
15b52eebd0
feat: 首页改成记录时间轴,计划可自己管,花销独立成页
...
## 首页
原来是任务卡 + 日期带/日历 + 接下来 + AI建议 + 快速记录 + 新手内容的堆叠,
六张聚合卡,唯独看不到「我记了什么」。改成:
宠物名片(品种·年龄·星座 + 性别徽章叠头像 + 一起生活的第 N 天)
两个入口(管理计划 / 记花销)
今日任务(有才显示)
记录时间轴 —— 竖线 + 圆点 + 卡片,往下翻,长按删
日历挪回计划页了:它本来就属于那儿。Phase B 当时把它并进首页是因为计划还是
个 tab;现在计划是二级页,日历跟着回去更合理。
情绪点那几样字段后端早就返回了,只是没人用。抽了 utils/petmeta.js:
星座七个边界(含 12/22 跨年那个)+ 天数(到家日优先于建档日,
「一起生活」说的是它到你家之后的日子)+ 性别徽章,都在 node 里跑过。
顺带 stat-ring 组件和 homeSummary 接口现在没人用了,先留着没删。
## 两个入口取代竞品那一排
竞品是买商品/上豪车/记花销/领猫砂盆——除了记花销全是电商和广告位。
副标题给了真信息:「还有 5 件没做」「本月 ¥128」,不然就是两个没信息量的图标。
## 计划页:用户自己能管了
后端原来只有 toggle,节点全靠内置模板生成,用户加不了自己的事。补了
POST /api/pets/:id/plan-tasks
PUT /api/plan-tasks/:id
DELETE /api/plan-tasks/:id
三件事值得说:
**30 天边界硬拦在服务端**(dayOffset)。只在前端拦的话,改个请求就能塞一条
第 200 天的节点,日历上没有那格、它就永远不显示也删不掉。
**归属校验单独抽了 ownedPlanTask**。PUT/DELETE /plan-tasks/:id 这种按资源 id
的路由最容易漏——不校验的话拿到别人的 task id 就能改删别人的计划。验过:
别人的 token 改和删都返回「无权操作」。
**边界差一天,是验证时撞出来的**:内置模板生成到 day=30(第 31 天),
我一开始按 0-29 卡,结果模板自己的最后一个节点(生成月度报告)落在窗口外——
日历上没有那一格,用户看得到却改不动也删不掉。前后端都改成 [0,30],
两边各留了一句注释指向对方,别再单方面改。
日历只画计划覆盖的 31 天,不画整月:整月会多出一堆空白格子、跨月还要翻页。
## 花销独立成页
写的是同一张表(type='cost',金额进 num_value、类别进 category),
报告页的账单聚合照样认——独立页的价值在专门的录入体验和当页就有月度汇总,
不是另存一份数据。
类别预置读 record_types 里 cost 的字段配置,后台改一处这页和 addrecord
同时生效,不会出现两套类别把账单切开。另外允许自定义类别,验过「寄养」
(不在预置里)能落库、账单也认。
## 检查器又抓到一次跨页借用
我在计划页复用了花销页的 ex-ph(placeholder 类),检查器直接报了位置。
顺手把三个页面的私有 placeholder 类统一到 app.wxss 已有的 .placeholder。
cal-* 现在首页没有了、计划页在用,也提到了 app.wxss。
## 验证(预生产库实跑)
计划 CRUD 加/改/删 全过;空标题拒;越权改删拒
30 天边界 day=30 通过、day=31 拒、day=-1 拒
模板 day=30 现在能原地改了(修边界前会被自己的规则拒掉)
首页时间轴 8 条记录按 occurred_at 倒序,type/tone/图标都取到
两个入口副标题 「还有 5 件没做」「本月 ¥128」
花销自定义类别 「寄养」落库,账单分类变成 [(医疗,128),(寄养,60)]
petmeta 星座 7 个边界 + 天数 3 种情况,node 单测全过
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 10:43:08 +08:00
Blizzard
3ea50efb7d
feat: 添加记录独立成页,表单字段由后端配置驱动
...
## 弹层里塞 24 个表单是走不通的
弹层高度受 .sheet-scroll 的 78vh 限制,字段一多就变成内滚;24 项的选择器
挤在弹层里更难看(用户原话「很丑」)。整体搬成页面。
## pages/addrecord —— 一个页面吃掉全部 24 种
形态:记录宠物 / 记录时间 / 类型专属字段 / 描述 + 照片 / 底部固定保存键。
关键在「类型专属字段」整段是后端驱动的:前端不认识「体重」「金额」这些业务词,
只认识 number / options / text 三种渲染方式,以及每个字段的值该落到哪儿。
record_types 加了 fields 列,后台用紧凑写法配(一行一个):
number:体重:kg 数值 → num_value
options:状态:正常|软便|拉稀 单选 → category
options:症状:呕吐|拉稀|精神差:- 末尾 - 表示不落 category,只进标题
text:吃了什么 文本 → 只进标题
(空) 只要 时间+描述+照片
解析放服务端不放前端:配错了要在后台保存时就报出来(第几行、错在哪),
不能等用户点开表单才发现渲染不出东西。读取时解析失败只让这一种事项没有额外
字段并打 warn,不让一条烂配置把整个记录页打空。
## 那个 - 开关不是过度设计
异常观察有两个单选(症状 + 严重程度),而 category 只有一个坑,
周报的高风险数按 category='高' 统计(report.go:46)——必须能指定谁占这个坑。
同理账单按 cost 的 category 分组聚合(report.go:134),
食便相关性排除 poop 的 category='正常'。这三处口径都得严丝合缝对上。
## 记录页瘦成纯列表
只留分组宫格。健康洞察 / 体重趋势 / 健康时间轴整页搬到 pages/history,
从报告页「记录与趋势」进——报告页才是看数据的地方,而一个「我要记一笔」的
页面上摆三块只读图表,用户每次都得先滚过去才能找到要点的东西。
**没有直接删掉那三块**:时间轴是唯一能看和删历史记录的地方,报告页只有
周报/账单这些聚合。删了用户就再也看不到自己记过什么。搬页面用的是 git 里
改动前的完整版复制,比往 report.js 里合并代码安全。
## 弹层瘦了一圈
9 个记录分支删掉,连带 17 个方法、SIMPLE_HINT、buildRecord 的 7 个 case
和一批只有它们在用的 data 字段。
js 1089 → 857 行
wxml 480 → 335 行
弹层现在只管「不是记一笔」的事:提醒、海报、档案、发帖、评论、导出、反馈。
buildRecord 只剩 vetSummary 一个分支(它写一条 note 留痕,不是用户填的表单)。
## 验证(预生产库实跑)
24 种的字段配置逐个核对解析结果,然后照 addrecord 的 buildBody 组装落库:
体重 title='体重:4.6kg' num=4.6 → 宠物档案回写成 4.6kg ✓
记账 title='记账:128元 医疗' num=128 cat=医疗 → 账单 total=128 分类[(医疗,128)] ✓
异常 title='异常:呕吐 高' cat=高 → 周报 high_risk_count=1 ✓
排便 cat=软便 食便相关性口径保住
饮食 title='饮食:幼猫粮 45g 偏少' cat=偏少
喝水 num=180(新类型带数值,老代码没有它的分支也不影响)
洗澡 title='洗澡'(无额外字段)
看病 num=320(两个字段:文本+数值)
体重趋势 1 个点、值 4.6,没被其他 7 条污染。
回填踩过一次坑:fields 列是服务启动时 AutoMigrate 才建的,我在启动前就跑了
回填,Update 报错被忽略、13 行静默没写进去。第二版加了 HasColumn 前置检查
和逐行错误统计才发现。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 10:25:42 +08:00
Blizzard
29d2cd3faf
refactor(fe): 记录从 tab 降级成页面,tabBar 减到 4 个
...
## tabBar
首页 / 报告 / 社区 / 我的。记录不再是 tab。
因为高亮是 tabBar 组件按当前路由自己算的(Phase A 那次改的),删一个 tab
只需要动 LIST 一处,四个页面一行都没改。
## 快速记录独立成页 —— 但没有新建页面
弹层里塞 24 项确实挤(用户原话「很丑」)。撤掉上一版加的 quickRecord 分支。
**pages/record/record 本身就是那个页面**:它顶部已经是 24 项 4 组宫格,
下面接着健康洞察、体重趋势、健康时间轴。再单独建一个只放宫格的页面,等于同一个
宫格维护两份,而且那页除了宫格什么都没有,进去点一下就得退出来。
所以把它从 tab 降级成二级页:nav 标题从「快速记录」改成「记录」+ 返回键,
移除 tabBar 同步。首页右下角悬浮键直接跳它,落地就是宫格。
pet-switch 保留 —— 时间轴/趋势/洞察都是按宠物看的,而且计划页作为二级页
也是这么处理的,一致。
## 入口
首页悬浮键 → 记录页(全部 24 项)
首页「快速记录」卡 → 8 个高频项直接开表单,「更多」→ 记录页
文章页 / 设置页 → 记录页
三处 switchTab 改成 navigateTo(记录页已经不是 tab,switchTab 会静默失败)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 09:55:52 +08:00
Blizzard
7636454650
feat: 下掉用户端 AI,首页悬浮键改成快速记录
...
## 只砍入口,后端一行不动
10 个 AI 路由、service/ai_*.go、后台配额配置页、ai_usages / ai_messages
两张表全部保留。api.js 里那 5 个方法注释掉而不是删——想开回来解注释、
把入口接上就行,不用重写。
## 5 处露出
pages/ai 聊天页 删页面 + 从 app.json 移除
首页「AI 今日建议」卡 整张删(含「问问 AI 养宠助手」按钮)
计划页「AI 计划」tab 删 tab + wxml 分支 + ?tab 深链;只剩「路线图」一项后
整条 seg-tabs 也藏了——单选的 tab 条是个没用的控件
异常观察的 AI 风险评估 见下
引导页「AI 日历」文案 改成「养护日历」
## 异常观察这一处差点做错
原链路是:symptom 只收集表单 → AI 风险评估 → 用户在 risk 页再点保存 →
buildRecord 的 case 'risk' 才真正落库。**symptom 自己从来不落库。**
拆掉中间环节如果只删 risk,结果就是「记了异常但没存下来」,而且不报错。
补了 case 'symptom' 让它自己存。连带发现第二个问题:category 存的是 AI 给的
风险等级,而 report.go:46 按 category='高' 统计周报的高风险数——不写这个字段
周报会永远是 0。改成让用户自己选严重程度(轻微/需留意/严重 → 低/中/高):
谁看着它谁最清楚,比规则化猜一个准,还顺手保住了周报。
## FAB
首页 → 打开 24 项分组选择器(弹层新增 quickRecord 分支,
点某一项在同一个弹层内 setType 切过去,不关不跳)
社区 → 改成发帖(它本来就不该是记录入口)
记录/报告/我的/计划/学习 → 直接去掉,底部留白从 pad-b-fab 换成 pad-b-plain,
不然白留 330rpx
fab 组件原来图标写死成 ai,加了 icon 属性——按钮干什么事图标就得是什么。
顺手删了 settings.js 里一个死的 onFab(Phase A 拆页时漏的,页面上根本没有 fab)。
.tg 分组样式从 record.wxss 提到 app.wxss:记录页和快速记录弹层都在用,
页面级 wxss 跨不了页(这个项目已经栽过三次)。
## 顺手修了周报两个先前就有的 bug
验证时撞上的,和 AI 无关,但 AI 建议卡拆掉后周报权重变高了:
1. 摘要把「无高风险异常记录」写死,和它自己刚算出来的 highRisk 自相矛盾——
记了 2 条高风险,摘要还说没有
2. next_week_focus 是一整句静态文案「第 2 针疫苗提醒、继续观察体重趋势、
避免频繁更换食物」,不管谁的宠物多大年纪都是这句,而「第 2 针疫苗」
对成年猫狗根本不适用。改成按真实数据拼:未来 7 天到期的提醒 +
有高风险就提就医 + 一周没称体重就提醒补记
## 验证(预生产库实跑)
异常观察三档 低/中/高 各存一条,category 正确落库
周报 summary「有 2 条高风险异常记录」,不再自相矛盾
next_week_focus 有高风险的宠物 → 「继续观察上周记录的异常,必要时就医」
新建幼犬(提醒都在 7 天外、没称过体重)→ 「本周还没称体重,补记一次」
症状聚类洞察 仍然工作(insight.go 按 symptom 过滤,没受影响)
全站 grep 无 pages/ai / onFab / riskData / onGenRisk 残留
FAB 只剩首页(plus)和社区(edit)两处
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 09:50:33 +08:00
Blizzard
3fc3cbc7d2
feat(fe): 记录页 24 种 4 组,弹层加通用简易表单
...
## 通用简易表单
洗护/清洁那 15 种只需要「什么时候 + 备注 + 可选照片」。弹层现在是 28 个
wx:elif 手写分支(402 行),各写一个会推到 700 行,而且每加一种类型都要发版。
加一个 wx:elif="{{isSimple}}",isSimple 由 JS 按后端返回的 form 字段算,
和上面那 9 种永不重叠。插在 photo 之后、提醒中心之前,没动任何现有分支的顺序。
备注给了逐类型的具体占位提示(「用了什么沐浴露、有没有吹干」),
比「请输入备注」有用得多——用户看到提示才知道这栏该写什么。
## 一个不写就会静默出错的地方
dayToISO():后端用 time.Parse(time.RFC3339) 解 occurred_at,只给日期
("2026-07-30")它解不出来会**静默回退成 time.Now()**——用户选「昨天洗澡」
会存成今天,而且不报错。
时区必须带真实偏移:转成 UTC 的 Z 形式,落库再转回本地时会把边界日期挪一天
(首页任务重复生成那个 bug 就是这么来的)。取正午同样是为了远离日界。
## 四处写死的类型列表全删
RECORD_ITEMS record.js 记录页 9 宫格
QUICK_ITEMS home.js 首页 8 宫格
TYPE_TONE record.js 时间轴色调(9 种写死,新类型会全掉到橙色一片分不清)
TASK_SHEETS 弹层 任务关联记录类型的下拉(只有 6 种,加了类型选不到)
全部改成读 utils/recordTypes.js 这份共用缓存。缓存 load() 只真正请求一次,
并发调用共用同一个 promise;isSimple/label/groups 是同步的,弹层打开时
不该再等一次网络。
首页 8 宫格改成取后端前 8 个(按分组顺序再按 sort),后台调 sort 就能换首屏
露出哪几个;全部 24 种在记录页。
分组色系(daily橙/health绿/care紫/clean蓝)留在前端,后端只存 group key——
改配色不用动数据。
## 联调(预生产库实跑)
15 种新类型 全部落库,且选「昨天」没被存成今天(15/15)
原有 9 种 逐一回归,写库 emoji 原样;weight 回写宠物档案 → 4.5kg ✓
时间轴 24 条混排,色调分布 6/7/5/6,没有一条查不到类型
体重趋势 仍只有 1 个点(没被 24 条记录污染)
周报/首页汇总 正常
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 09:44:07 +08:00
Blizzard
a0f00b086e
chore(fe): 移除误提交的 token 文件,preview-v3 加进包体忽略
...
adm.txt 是联调时写 access token 的临时文件,我 cwd 弄错写进了 pets-fe 并跟着
上一个提交进了仓库。撤掉并在 .gitignore 里堵住(连 at.txt 一起)。
preview-v3.html 加进 packOptions.ignore,和 preview.html / preview-v2.html 一样
不进小程序包体。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 09:24:43 +08:00
Blizzard
60ee9d4bbc
feat(be): 记录类型挪进数据库,后台可配 + 15 种新类型
...
## 为什么
9 种记录类型全是低频医疗和记账(疫苗一年一次、驱虫一季一次、体检更少),
用户今天打开 App 大概率没什么可记,时间轴是空的。竞品 35 种里有 26 种是
高频日常(洗澡/剪指甲/换猫砂/喝水/洗食盆),那才是每天打开的理由。
## 一个比预想好得多的发现
本来担心加类型会踩到分析逻辑。把那 9 个常量的引用全捞了一遍,结论是不会:
weight record.go:83 回写宠物体重;home/insight/report 的体重趋势与基准
food + poop insight.go:130 食便相关性
symptom insight.go:160 症状聚类;report 高风险计数
cost report.go:99 消费统计
vaccine report.go:137 疫苗完成度
deworm/medicine/photo 没有任何特殊分支
这些分支全都是「按某个具体常量过滤」,没有一处是 switch 全枚举、也没有
default 兜底。CreateRecord 更是完全没有 type 白名单校验。所以新增类型
不可能碰到任何现存逻辑——一行分析代码都不用改。
于是分工是:
record_types 表 负责「展示什么、能记什么」
那 9 个常量 负责「哪几种参与分析」
两者各管一段,常量一个都没删。
## 表设计
code / label / icon / group_key / sort / enabled / form / locked。
group_key 而不是 group:group 是 MySQL 保留字,GORM 会加反引号所以能跑,
但手写 SQL 排查时很容易踩。
form 区分 full(弹层里有专用 wx:elif 分支)和 simple(时间+备注+照片)。
15 种新类型全是 simple——下一步在弹层加一个通用分支吃掉它们,不然 28 个
分支再加 15 个会把 bottom-sheet 写到 1800 行。
locked 给那 9 种:有代码分支依赖、且被 care_template_items.sheet_type 引用。
## 两条硬拦在 service 层的规则
1. locked 的删不掉
2. 已经有记录的删不掉(删了历史记录会变孤儿)
想让它从记录页消失应该用 enabled=false,历史记录仍能正常显示。
都在 service 层拦,不是靠前端隐藏按钮。改 code 同样受 2 的约束——
code 是落库值,改了历史记录会对不上任何类型。
## bootstrap 的取舍
文章和养护模板当初按你的要求从代码里挪走了,这次 24 种类型仍然放在 seed 里,
因为它不是内容而是结构:表空着记录页一个可记事项都没有,App 直接不能用。
和管理员账号一样,只在表**完全为空**时铺一次,之后一切以数据库为准。
表非空就完全不碰,否则后台删掉的类型会每次重启自己长回来。
ListRecordTypes 在表为空时返回空数组 + 打 warn,不硬编码兜底一份——
那等于把「可配置」又变回代码常量,下次改配置的人会发现改了没用。
## 图标
新增 15 个(iconfont.wxss 40 → 55),全部取自本地那份 tabler-icons-3.46.0
真源,不是凭记忆画路径。已解码抽检确认路径非空。
## 验证(生产库实跑)
建表 + 24 条 bootstrap 一次到位,分组 daily6/health7/care6/clean5
locked 9 个、simple 表单 15 个
规则 1 删 weight → 「有统计和分析逻辑依赖它,不能删」
规则 2 新增 nose 成功 → 重复 code 报错 → 删除成功
规则 3 造 1 条 tmptest 记录 → 删类型被拦;删掉记录后再删 → 成功;残留 0
规则 4 停用「美容」→ 小程序端洗护组只剩 5 项;恢复后回到 6 项
规则 3 一开始没真验到:库里唯一的记录类型是 weight,locked 先拦住了,
「已有记录」那个分支根本没走到。补了个造真记录的测试才算验过。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 09:24:24 +08:00
Blizzard
09322ecbec
chore(fe): 静态自查按作用域算 class,当场抓出第三例跨页裸奔
...
## 原来的检查是错的
它把所有 wxss 并成一个全局集合再看「这个 class 有没有人定义过」。
可这个项目连着栽的两次都是「有人定义过,但定义在别的页面里」:
.post-card 留在 community.wxss,用户主页用它 → 帖子完全没样式
.profile-row 留在 settings.wxss,「我的」用它 → 四个入口整个散架
两次它都报「✓ 全部对得上」。全局并一起看,恰好检查不出这一类问题。
## 改成按作用域
app.wxss 全局;页面 wxss 只对自己那页生效;组件 wxss 只对组件自己的节点
生效,且要开了 addGlobalClass 才看得到全局。@import 跟着递归收
(pt-icon 的图标就是这么来的)。
class 不在作用域内时分两种报法——「没有任何定义」是拼错了,
「只定义在 xxx.wxss」是跨页借用,后者直接把定义位置指出来。
## 跑起来当场又抓到一个
pages/relations 的关注按钮 .follow-btn / .follow-btn.on 只定义在
community.wxss —— 关注/粉丝列表里那个按钮一直是裸的。已提到 app.wxss。
## 自测过
往 learn.wxml 塞一个只在 decorate.wxss 里定义的 class,确认报错并指对了
位置,再还原确认恢复绿。不然这检查本身就是个装饰。
脚本从临时目录挪进 pets-fe/scripts/check.js(原来只活在会话的临时目录里,
会话一结束就没了),路径改成相对自己。scripts/ 加进 packOptions.ignore,
不进小程序包体。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 08:30:59 +08:00
Blizzard
6d49d28e1a
fix(fe): 修 Phase D 三个渲染问题
...
## 1. tabBar 高亮不跟着切(进「我的」还亮在「首页」)
Phase A 我把高亮改成 custom-tab-bar 自己在 pageLifetimes.show 里按路由算,
想省掉五个页面的硬编码。实测不行:自定义 tabBar 不在页面节点树里,
pageLifetimes 拿不到可靠时机,selected 一直停在默认的 0。
回到官方那套「页面 onShow 推一把」,但索引仍然由 tabBar 按当前路由自己算
(utils/tabbar.js → syncSelected),页面这边不写死 0/1/2/3/4。
调 tab 顺序还是只改一个 LIST,五个页面一行都不用动——原来想要的收益保住了,
只是多了五行 syncTabBar(this)。
## 2. 头像被头图盖住,只露出下半个
.pf-bg 带了 position:relative,定位元素会盖过静态的兄弟节点,DOM 顺序在后
也没用。给 .pf-av 加 position:relative + z-index,同时把 .pf-bg 上那个没人
用的 position 去掉。头图高度 220 → 180rpx,纯渐变时不至于占掉半屏。
## 3.「我的」页四个入口整个散架,图标文字箭头各占一行
.profile-list / .profile-row / .pr-ic / .pr-label / .pr-val 全在
settings.wxss 里——Phase A 从 profile 拆页时留在了设置页,mine 用同一批
class 但样式跨不了页,于是完全裸奔。提到 app.wxss。
这是这个项目第二次踩「页面级 wxss 跨页用」了(上次是 .post-card 在用户
主页裸奔)。两个页面共用的 class 就不该留在任一页的 wxss 里。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-30 08:22:17 +08:00
Blizzard
1584aabcc5
feat(fe): Phase D —— 主页装扮,「我的」和「宠友主页」共用一套渲染
...
## profile-head 组件
头图 / 头像 / 昵称 / 签名 / 帖子关注粉丝 / 养宠数据 / 宠物名片墙,
pages/mine 和 pages/user 用的是同一个组件、同一个接口
(GET /users/:id/profile)。
这件事必须一开始就做对:自己看和别人看要是两套渲染,会慢慢长歪,
装扮功能也就失去意义了——你调半天颜色,结果只有自己那页变了。
两边唯一的差别是底部按钮:自己看是「装扮我的主页」,别人看是「关注 TA」。
顺带把 mine 的头部从 /user/summary 切到了 /users/:id/profile。原来两边
字段对不上,装扮效果在「我的」页根本预览不到。
主题只在组件 wxss 里定义 --pf-a/--pf-b/--pf-ink 三个变量,下面所有着色
都走变量。后端存 key 不存色值,就是为了这套配色随时能在前端改。
## pages/decorate 装扮页
头图上传 / 五套主题色 / 个性签名 60 字 / 宠物墙开关,顶部实时预览。
预览用的就是 profile-head 本身,不是仿一个——仿的迟早会和真的长得不一样。
喂给它一份改过的 card 就行,组件那边不需要知道自己在被预览。
头图有个坑单独处理了:bg_file_id 只在真动过的时候才传。新上传带新 id,
点「恢复默认渐变」带空串,都没动就不传字段。否则「只改个主题色」会把
已有头图冲掉。上传时先用本地临时路径顶上,不让用户对着转圈等。
联调验证(本地 9090,真上传了一张图走完存储链路):
上传 → file id + MinIO url
保存装扮 → bg_url 落库,主题 violet,签名落库
主页读回 → bio/theme/show_pets/bg_url/宠物墙/养宠数据 全对
只改主题 → theme 变 sky,头图还在(没被冲掉)
恢复默认渐变 → bg_url 清空,theme 和 bio 都没被动
别人视角 → is_self=false、followed=false,装扮和宠物墙都能看到
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 18:02:07 +08:00
Blizzard
8606c1dfc8
feat(be): Phase C —— 个人主页装扮 + 养宠数据
...
## User 加四个装扮字段
bio / bg_file_id / theme / hide_pets。
hide_pets 存的是「隐藏」而不是「展示」,为的是零值即默认:AutoMigrate
给存量行填 0,正好等于「展示宠物墙」,不用给老用户跑一次刷值。对外
API 仍然用 show_pets(UI 上是个「展示我的宠物」开关,正着说更自然),
只在 handler 边界取一次反。
theme 存 key 不存色值。色值属于前端表现层,存进库以后想调色就得改数据;
存 key 还能保证前端只渲染已知的那几种。非法 key 走 40000,老用户的空
theme 在读取时兜底成 warm,前端不会拿空 key 去查表。
## GET /users/:id/profile 扩展
原来只有昵称头像和三个计数,现在带上 bio / bg_url / theme / show_pets
+ 宠物名片墙 + 养宠数据。自己看和别人看走同一个接口,省得两套渲染慢慢长歪。
## 养宠数据
days 养宠天数,按最早那只的建档日算——这里要表达的是「你在这照顾它
多久了」,不是宠物活了多久
records 累计记录条数
act_days 有记录的天数
streak 连续打卡
streak 有个必须处理的边界:今天还没记录不能算断签,否则用户每天早上打开
都会看到连续天数归零。实现是先看今天有没有记,没有就从昨天起往回数。
## PUT /api/user/decoration
四个字段全用指针,区分「没传」和「传了空串」——清空个性签名和不改个性
签名是两件事。bio 服务端截到 60 字。
联调验证(本地 9090):
老用户读取 theme 兜底 warm、bio ''、hide_pets false
改装扮 theme=mint、bio 落库
theme=rainbow 40000 参数不合法
bio 100 字 截断到 60
show_pets false → pets 字段消失,stats.pet_count 仍为 1
别人视角 is_self=false、followed=false、装扮和宠物墙都能看到
streak 1/2/3/5 天前各记一条:act_days=4 streak=3(第 4 天空档正确断开)
今天再补一条:act_days=5 streak=4
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:54:16 +08:00
Blizzard
cecc7f4cbb
feat(fe): Phase B —— 计划并进首页,日期条能展开成整月
...
## 日期条 → 可展开日历
首页那条七天日期带下面加了「展开整月」。展开后是整月网格(有安排的
日子带绿点),点任意一天,任务卡跟着切到那天。收起来还是七天,默认
不拉日历接口。
这块原来是计划页的「日历」tab,现在从计划页整个摘掉了——「哪天要做
什么」和「今天要做什么」本来就是一件事,分在两个 tab 里只是让人多点
两下。日历样式(.cal-* / .day-detail / .dd-*)跟着从 plan.wxss 搬到
home.wxss,plan.wxss 里没留死规则。
## 任务卡下面挂当天的计划节点和提醒
day-plan 接口本来就返回 plan_nodes / reminders / tasks 三份。这里只取
前两份,任务列表仍然走 /tasks——因为 /tasks 会补生成当天任务而
day-plan 不会,拿它的 tasks 覆盖列表会让今天的任务凭空少掉。
## 「接下来」卡
30 天计划里最近 3 个还没做的节点,日期显示成「今天/明天/3 天后」而不是
7月31日。带完成度进度条,右上角「完整计划」进计划页。
计划页降级成二级页之后,这张卡是它在首页的唯一露出;没有它,计划这个
功能对用户来说就等于消失了。
## AI 计划入口
AI 页快捷区加了「生成养护计划」,直达 /pages/plan/plan?tab=aiPlan。
没有把这个表单搬进 AI 聊天页:它要渲染 extracted 四宫格和可勾选的任务
节点,塞进聊天流意味着同一个页面维护两套完全不同的渲染,收益只是少跳
一次。原本要解决的是「计划页降级后 AI 计划找不到了」,一个入口就够了。
顺带:iconfont 补了 up / down 两个 chevron(展开收起用)。
联调验证(本地 9090,新建幼犬档案):
day-plan 今天 → plan_nodes=['确认免疫与驱虫计划']
plan → completion_pct=0,4 个节点,date 字段齐全
接下来筛出 → 07-29 确认免疫与驱虫计划 / 08-01 观察饮水与排便 / 08-05 体重趋势检查
calendar → 2026-7,today=29,tasked_days=[29]
day-plan 未来日 → 08-01、08-05 各自返回对应节点
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:48:12 +08:00
Blizzard
60baff8a2b
refactor(fe): Phase A —— tab 换成「我的」,计划降级,设置拆出来
...
## tab 结构
首页 / 记录 / 报告 / 社区 / 我的。计划从 tab 移出变二级页(导航栏补了
返回键),从「我的 → 养护计划」进。
## 消灭 5 处硬编码
tabBar 高亮原来靠每个 tab 页在 onShow 里写死 selected: 0/1/2/3/4,
调一次顺序就得同时改五个文件,漏一个就高亮错位——这次把计划换成我的
正好会踩到。改成 tabBar 组件在 pageLifetimes.show 里按当前 route 自己
匹配,五处硬编码全删。
## profile 拆成两页
原来的 profile 混了两类东西:「我是谁」和「怎么设置」。拆开:
pages/mine(tab) 个人名片(头像/昵称/签名/关注粉丝记录三个数)
+ 我的毛孩子列表 + 常用入口 + 齿轮进设置
pages/settings 提醒设置、会员权益、数据导出、意见反馈、关于我们
「我的」上放了个「看看别人眼里的我」,点进去就是 pages/user 那个公开
主页——自己看和别人看必须是同一个页面同一套渲染,否则两边会慢慢长歪。
这也是 Phase D 装扮功能的落点。
首页齿轮从「进 profile」改成「进设置」(个人页已经在 tab 上了)。
旧的 pages/profile 整个删掉,没留兼容层。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:33:32 +08:00
Blizzard
3ad1516aa4
fix(fe): 按钮长文案撑爆 + 用户主页帖子没样式 + 首字头像空白
...
三个都是我上一轮引入或没顾上的。
## 「Pro 会员(即将开放)」把按钮撑爆
.btn 同时用了 flex 垂直居中和 line-height:96rpx。flex 已经负责居中了,
line-height 纯属多余,而且文案一换行就被这个固定行高顶到按钮外面——
「我的」页底部那颗按钮正好触发。改成 min-height + line-height:1.3,
按钮能随文案长高,短文案的高度不变。
## 用户主页的帖子没有任何样式
.post-card 那一整套只写在 pages/community/community.wxss 里,而页面级
wxss 不跨页生效,所以用户主页上的帖子退化成裸文本。整块提到 app.wxss。
顺带给主页的帖子补上作者行和标签,和社区保持一致。
## 头像圈里空白
WXML 表达式不支持字符串下标,{{nickname[0]}} 求值为空。改成在 js 里
slice 好再传给模板。
另外确认一下:粉丝列表本来就能点进主页——关注和粉丝共用 pages/relations
一个页面,每行都绑了 goUser,和关注列表走同一个 pages/user 主页。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:19:18 +08:00
Blizzard
25f655a6fc
feat: 补齐关注的入口——用户主页 + 关注/粉丝列表
...
关注之前只做了一半:能从帖子上点「+关注」,也有「关注」信息流,但
关注完就石沉大海——没有用户主页、看不到自己关注了谁、也不知道谁关注
了自己。功能是通的,路是断的。
后端新增:
- GET /api/users/:id/profile 公开资料 + 帖子/关注/粉丝三个计数 + 我是否已关注
- GET /api/users/:id/posts TA 发布的帖子
- GET /api/users/:id/relations?kind=following|followers
- /api/user/summary 补 following / followers,否则「我的」页那两行永远是 0
关系列表里「我是否关注了这批人」用一次 IN 查询查完,不是每行一次。
小程序端新增两个页面:
- pages/user/user 用户主页:头像/昵称/三项计数/关注按钮 + TA 的帖子
- pages/relations 关注列表与粉丝列表(同一页,kind 区分)
入口:
- 社区点头像或昵称 → TA 的主页
- 主页点「关注/粉丝」数字 → 对应列表
- 「我的」页新增「我的关注」「我的粉丝」两行
关注按钮先本地翻转再发请求,失败回滚——等接口返回按钮才变会显得很迟钝。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:13:04 +08:00
Blizzard
b8b3ba99b4
fix(fe): 顶部固定条去掉补丁感 + 社区分类吸顶 + 切分类回顶部
...
## 那条 banner 为什么丑
我给它加了不透明底色 + 分隔线,而页面本身是渐变背景——等于在渐变上
贴了块补丁,屏幕上出现三条颜色不搭的横带。
但它根本不需要背景:它在文档流里而不是浮层,内容永远不会滚到它下面。
去掉 background / backdrop-filter / border 之后自然融进页面渐变。
顺手把 .pet-bar 改名 .top-bar,因为社区也要用它。
## 社区
- 分类标签移出滚动区吸顶。原来一滚就没了,想换分类还得先滚回顶部
- 「发布图文」那个大黑按钮独占 124rpx,而发帖是低频操作,不该在每屏
都占着首屏。压成右侧的小胶囊,收进同一条,始终可点
- 切分类回到顶部:不然从「推荐」滚到一半切到「关注」,看到的是新列表
的中间,会以为内容错乱了
回顶用 scroll-into-view + 锚点,并在 bindscroll 里清掉锚点值——
不清的话下次再设同一个值不会触发,第二次切分类就不动了。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 17:05:17 +08:00
Blizzard
fe420ba47c
feat(fe): 评论改成小红书那套交互——点评论直接唤起输入
...
上一版做成了居中弹窗,参考图给的是另一种范式:输入栏常驻底部,点任意
一条评论就把它激活并填上「回复 @xxx」。按参考图重做,居中那套一并删掉,
不留死代码。
结构从「一个滚动容器装所有东西」改成三段式:
固定头(共 N 条评论)+ 滚动列表 + 常驻输入栏
输入栏必须在滚动区外——放进去的话列表一滚它就跟着走,点完评论还得再
把输入框找回来,正是这次要解决的问题。
交互:
- 点评论或回复的任意位置 → 输入框获得焦点,placeholder 变「回复 @xxx」,
上方出现可取消的橙色提示条。不用再单独点一个「回复」按钮
- 删除从长按改成显式的「删除」文字,只在自己的评论上出现——长按是
隐藏交互,没人会发现
- 回复带首字头像并缩进一层,「甲 回复 乙」的指向关系显示在昵称行
键盘处理用 adjust-position=false + bindfocus 拿键盘高度自己顶:弹层是
fixed 定位,交给系统调整会把整块推出屏幕。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 16:39:36 +08:00
Blizzard
9fc61e878e
feat: 评论支持回复(两级 + @某人)
...
不做无限层级——手机屏幕撑不住层层缩进,读到第四层就没法看了。
微信、小红书、B站清一色是两级:一级评论 + 其下的回复列表,回复里
用「回复 @某人」表达指向谁。
数据结构:comments 加 parent_id + reply_to_name。回复的回复会被
压平到同一条一级评论下(parent_id 取爷爷的),同时把被回复人的名字
记进 reply_to_name —— 这样既保住两级,又不丢「在跟谁说话」的信息。
几个容易做错的地方:
- 一次查完这一页所有一级评论的回复,不是每条一次查询(N+1)
- 一级评论默认只带 3 条回复,其余点「展开全部 N 条」再拉,避免热门
评论一次返回几百条
- 删一级评论要连它下面的回复一起删,否则回复变成挂在空处的孤儿;
帖子的 comment_count 也要按实际删除条数减,不是减 1
- total 统计含回复,和帖子上显示的数字对得上
- replies 为空时返回 [],不是 null
实测四条评论(含一条回复的回复):
▸ 甲:一级评论 (2 条回复)
└ 乙:多久了?
└ 甲 回复 乙:三天了
▸ 乙:另一条一级评论 (0 条回复)
删掉第一条一级评论后 total 4→1,comment_count 同步。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 16:33:50 +08:00
Blizzard
535ef08da7
fix: 评论配图整条链路补全 + 宠物切换条吸顶
...
## 评论图片传了等于没传
上次只做了一半:model 加了 Images 字段、前端做了上传 UI,但
handler 的 commentReq 没有 images、service 的 CreateComment 连
参数都没有,图片上传完就丢了;评论列表也从没渲染过图片。
补齐:请求体 → service 落库(JSON 数组) → 列表回显 → 点击大图预览。
实测带两张图的评论和纯文字评论各存各的,互不影响。
## 宠物切换条吸顶
首页/计划/记录/报告四页的 pet-switch 原本在 scroll-view 里,滚下去
就找不到了。而切宠物是随时要用的动作——多宠用户看着 A 的数据想切到
B,还得先滚回顶部。
移出滚动区,放在导航栏下方做成固定的一条,带毛玻璃和分隔线。首页的
问候语留在滚动区里,滚走就滚走,反正它只在刚进页面时有意义。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-07-29 16:19:32 +08:00