Commit Graph

63 Commits

Author SHA1 Message Date
Blizzard d9d7e128ff feat: 引导页阶段按生日推断 + 8 套养护模板按临床共识重配
## 引导页三个逻辑漏洞

1. **阶段和生日脱节**:用户填了 3 个月的生日,却能手选「成年期」,
   而阶段决定疫苗针次、驱虫周期和每天要做的事,选错整套计划都是偏的。
   现在按生日自动推断(猫狗同:12 月龄成年、7 岁进老年),仍可手改,
   但改成矛盾值时会弹框说明代价;服务端 NormalizeStage 兜底。

2. **`goals` 是假选择**:6 个勾选框收上来只存进 pets.goals,一处没用过。
   现在真正生效:体重提醒、月度报告按勾选生成,勾了「想控制养宠开销」
   会多一条记账任务。疫苗和驱虫不给关——狂犬是法定要求,漏驱虫真会出事。

3. **「刚到家 0-30 天」和年龄阶段互斥**:挤在一个四选一里,刚接回家的
   成年猫只能二选一。现在拆开:stage 只存年龄阶段,新增 pets.arrived_at,
   到家不满 30 天时把安置期那套任务和计划叠加上去(同标题去重)。

顺带:生日/到家日期不能选未来(前后端各拦一道)、体重范围校验。

## 疫苗提醒改为按月龄算

原来不管多大都排「14 天后首针」,一只 8 月龄才接回家的猫会被安排去打首免。
现在 dueDaysFor 按真实月龄推:<2 月龄等到 8 周龄、2-5 月龄间隔 21 天、
5-12 月龄两周内补齐、成年走年度加强。标题也跟着改写,否则用户照着
「年度疫苗加强」去打错针。

年度疫苗不再编一个假的到期日(原来写 30 天后),改用频率描述。

## 8 套模板按临床共识重配

依据 WSAVA 疫苗指南、ESCCAP/CAPC 驱虫建议、AAHA 生命阶段指南整理:
猫三联 3 针间隔 3-4 周末针不早于 16 周龄、犬联苗 2-3 针 + 3 月龄狂犬、
体内驱虫 6 月龄前每月一次之后每 3 个月、幼崽 3-6 月龄每天 3-4 餐、
成年犬每天 2 次共 30-60 分钟遛狗、老年建议半年一次体检。
每套从 11 条扩到 10-14 条,描述写成能直接照做的具体动作。

后台新增「恢复默认」:启动 seed 改为只补缺失、不覆盖已有(管理员可能
改过),内置模板更新后必须从后台显式推一次。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 11:58:00 +08:00
Blizzard 35fc57e8de feat(fe): AI 独立成页(打字机)+ 修快速记录 6 处问题 + 导航栏去接缝
AI 从底部弹层改成独立页面 pages/ai/ai:
- 整屏聊天,输入框固定在底部,不再是「问题都打不完」的小格子
- 回复逐字吐出(30ms/2 字),点一下可跳过
- 会话 session 从 sheet 改为 chat,历史拉 50 条
- 组件里对应的 ai 分支和 aiMessages/aiInput/sendAI 一并删掉,
  避免两套实现并存

快速记录九个入口逐个排查,修掉 6 处:
1. 疫苗/驱虫的默认日期写死成 2026-07-21 / 2026-07-15,早已是过去的
   日期 —— 改成打开时按今天 +30 / +90 天算
2. 异常观察没选症状时,optIdx 返回 0 会被当成选了「呕吐」,等于替
   用户瞎填 —— 加 optPicked 判断,没选就提示
3. 体重为空时会静默存成「上次的体重」,凭空造一条假数据 —— 改为必填校验
4. 消费金额为空会存成 ¥0 —— 必填校验
5. 用药药品名为空 —— 必填校验
6. 照片弹层里「模拟上传预览」是没删掉的假文案

顺带清理:保存按钮上的 data-text / data-icon 从来没被读过(onSave 只用
buildRecord 的返回值),是纯误导的死属性,删掉。我上一条 commit 把它们
说成「写库值」是说错了 —— 真正写库的是 buildRecord 里的 icon 字段,那部分
仍然没动。

导航栏原来是一整条半透明色块,底边和页面渐变硬碰硬,屏幕上横着一道接缝。
改成上实下虚的渐变,并用同一条 mask 把毛玻璃一起淡出(只淡背景不淡 blur
的话,接缝会从色差变成糊边)。返回键做成圆形,和右上角胶囊视觉对称。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 11:10:41 +08:00
Blizzard 2fd25e26ef feat(fe): 其余 8 页 + 三个薄组件套用新设计语言
页面:
- record:3×3 emoji 九宫格(184rpx 高、全站最大的点击块)换成图标 + 4 色分类,
  和首页的 8 宫格合并成同一套 .quick-grid,此前它俩是同一个东西的两个副本
- record/plan/community:三套横向切换全部换成 seg-tabs
- record/plan/community/report/learn:砍掉与 nav-bar 重复的 46rpx 大标题,
  每页白赚约 130rpx 首屏
- 时间轴图标改按 HealthRecord.Type 取(9 值枚举,可靠),老数据里的 emoji
  只作兜底;写库的 icon 字段一个字符没动
- profile:设置行加分类图标 + 右侧箭头换图标
- community/report:主操作改深色 CTA,btn-primary 继续留给弹层的「保存」
- 6 套空态写法统一成 .empty

组件:
- nav-bar 的 ‹ 和 fab 的 "AI" 文字换成图标;fab 从蓝渐变改深色,
  和全站唯一主 CTA 的语义对齐
- pet-switch 的「+」换图标;宠物自己的 emoji 是用户数据,保留

pt-icon 开了 virtualHost,组件标签上的 class 不生效,需要定位的地方
(profile 行图标、箭头)都用外层 view 包了一层。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:54:18 +08:00
Blizzard c076968b2c feat(fe): 首页改成品牌活泼版(本次设计语言的样板页)
- 门面换成完成度环 + 状态 chip:一眼能看到「今天还剩几件事」,
  原来的 hero 卡只是把宠物信息平铺,占了 340rpx 却没给出任何判断
- 快速记录 8 宫格从 emoji 换成图标 + 4 色分类(体重/疫苗=橙、
  便便/饮食=绿、异常/用药=蓝、消费/照片=紫),靠颜色分组而不是靠认 emoji
- AI 建议卡底部加深色 CTA,全页唯一的深色块,指明主操作
- 顶部 🔔⚙ 换成图标;日期条、任务卡、空态全部走 token
- 任务列表落地时顺手算未完成数,门面文案由它驱动

后 8 页按这套语言套用,不再重新发明。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:40:09 +08:00
Blizzard b99099759f refactor(fe): 结构去重 + 修 FAB 遮挡内容(视觉等价,不含设计调整)
app.wxss 是从 preview.html 迁移来的,带来一批小程序里根本不生效的
标签选择器(wxml 没有 h2/p/b/span):.page-title h2、.task-text b、
.stat b、.article-card p、.record-row span、.poster h3。各页当初都
自建了替身 class,于是 .pt-h2 在 5 个文件里逐字重复、.ac-b 3 处、
.tt-b 2 处、page{height:100vh} 更是 9 个文件一模一样抄了 9 遍。

- 删掉 6 组死规则,替身 class 收进 app.wxss
- 页面骨架 page{} / .page-scroll / .page-body 统一到 app.wxss
- learn.wxss 清空后删除(该页已无私有样式)
- 左右留白统一 40rpx(home/article 原本是 36rpx)

顺带修一个真 bug:FAB 固定在 bottom:190rpx、高 116rpx,上沿距底
306rpx,但 7 个挂 FAB 的页面只留了 210rpx(learn/profile 更只有
60rpx)底部留白,最后一张卡片一直被它压住。改为 --pad-b-fab 330rpx。

本次不含任何色值/字号/圆角改动,设计调整在下一步。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 10:28:48 +08:00
Blizzard 7093e6517d perf(fe): 修复 token 过期白屏、请求翻倍与失败伪装成空态
token 过期后小程序静默白屏(影响所有用户)
- JWT 有效期 7 天,过期后 40100 只 clearToken 不重新登录,而
  store.ready 的 promise 已缓存不会重跑,加上 23 处静默 catch,
  用户看到的是「什么都没有、也没有任何提示」,只能重启小程序
- request 层加 token 失效钩子:自动重新登录并重试一次(只重试一次,
  防止登录接口本身故障时死循环);store 注册钩子重置引导缓存
- 补 15s 请求超时、60s 上传超时,超时给明确文案(原先默认 60s 卡住无反馈)

请求翻倍
- 每个 tab 页同时用 store.subscribe 和 onShow→ready().then() 加载,
  而 ready() 内部 loadPets 会 notify 触发 subscriber,首次进入请求翻倍
- subscriber 改为只处理「切换宠物 / 数据变更」,首次加载交给 onShow
- 首页 bind:save 与组件实际触发的 saved 事件名不一致,onSheetSave
  从未生效;一并修正,并去掉关闭弹层时的全量重载

失败伪装成空态
- 社区请求失败时显示「还没有帖子,来发第一条吧」,把故障说成没数据。
  改为区分「加载失败(可点击重试)」「关注 tab 为空」「确实没有帖子」
- 新增 utils/ui.js 统一错误提示(同文案 3 秒内去重,避免并发失败刷屏),
  首页与记录页主数据加载失败不再静默

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 17:56:35 +08:00
Blizzard 2e3345cdfc feat: 记录删除与筛选、用户侧内容删除、AI 聊天历史
修复雪花 ID 精度丢失(真 bug)
- bottom-sheet 的 postId 声明为 Number,而 ID 是 18 位雪花字符串,
  超出 JS 安全整数范围:339346584095428608 会被转成 ...600,
  评论弹层实际查的是不存在的帖子。改为 String

记录
- 后端 DELETE /records/:id 早已就绪但前端从未调用,记错了删不掉。
  时间轴支持长按删除
- 时间轴加类型筛选(体重/便便/饮食/异常/用药/疫苗/消费/照片),
  后端 ?type= 本就支持

用户侧内容删除(UGC 合规:用户应能删除自己发布的内容)
- 新增 DELETE /posts/:id 与 DELETE /comments/:id,仅限本人,
  越权返回 40300;帖子软删除,评论删除同步递减 comment_count
- 评论列表返回 is_self;社区长按自己的帖子、长按自己的评论可删

AI 聊天历史
- ai_messages 一直在写但没有查询接口,每次打开弹层都是空白。
  新增 GET /api/ai/messages,弹层打开时接在开场白后加载

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 17:42:14 +08:00
Blizzard 77beb9ca96 fix(pro): 会员改为「即将开放」,堵住点一下白拿会员的漏洞
原先 /api/pro/activate 直接写库开通一年会员,没有任何支付校验,
任何人调一次接口就是会员。支付暂不接入,这里必须在服务端拒绝,
只改 UI 挡不住直接调接口。

- ActivatePro 一律返回 ErrPayNotReady;真正写库的逻辑保留为
  activateProAfterPaid,等接微信支付时在校验支付单据后调用
- handler 对该错误返回参数错而非 500,前端直接展示提示文案
- 小程序 Pro 弹层按钮置灰为「即将开放」,我的页入口改为
  「Pro 会员(即将开放)」

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 18:15:38 +08:00
Blizzard 3fde90e97b feat: 补齐五块缺失功能(记录丢数据/文章正文/提醒管理/我的页入口/分享/关注)
P0 修数据问题
- 记录弹层有 5 个输入框从未绑定,用户填的便便备注、饮食内容、药品名称、
  剂量、消费备注全部丢弃;用药记录因此只存下「用药记录」四个字。已全部绑定并入库
- 异常观察保存时写死「风险中」,AI 实际判定的等级被丢掉。改为使用 riskData
  的真实 risk_level,并把成因与建议存进备注

文章正文
- 早期 seed 的 4 篇文章 Content 全空,点开只是打开关联记录弹层,内容运营等于白做
- 补写 4 篇真实正文(疫苗驱虫/软便判断/换粮方案/养宠花销),遵循不诊断、
  异常必提就医的护栏;对已存在的空正文做幂等回填
- 新增文章详情页,学习页与首页卡片改为打开正文

提醒管理
- 后端 CRUD 早已具备但小程序只读,用户改不了疫苗驱虫日期。提醒弹层支持增删改
- 修复后端 UpdateReminder 漏掉 type 字段导致改类型不生效

「我的」页 7 个死入口接活
- 提醒设置、健康记录、多宠物管理、会员权益分别落到对应功能
- 数据导出:汇总档案与记录为文本,可复制发给医生
- 意见反馈:新增 feedback 表与提交接口,后台加「意见反馈」管理页
- 关于我们:应用说明与免责声明

分享
- 各页面补 onShareAppMessage/onShareTimeline
- 帖子分享按钮改用微信原生 open-type="share",删除原来点了没反应的空壳弹层

社区关注
- 新增 follows 表与关注/取关接口,「关注」tab 此前等同「推荐」,
  现只显示已关注用户的帖子;帖子头部可直接关注,标记 followed / is_self

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 18:11:08 +08:00
Blizzard 3816cd1b02 chore: 小程序更名为「肉垫计划」
- 原名「毛孩子计划」在微信已被占用,全项目 24 处替换(导航标题、
  AI 提示词身份、社区官方号、后台登录页、logo 横版文案)
- logo 英文副标同步改为 PAW PAD · CARE PLAN
- 新增 小程序资料.md:后台要填的简介(多长度版本)、关键词、
  服务类目建议与审核避雷要点

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 16:46:21 +08:00
Blizzard 28b95a6468 feat: 每日任务顺延与增删改 + 计划到期续期 + 靠谱养护模板 + 图片URL修复
后端
- 每日任务惰性生成:某天为空则从最近一天顺延复制(done 重置),首天用模板
- 任务增删改 API(POST /pets/:id/tasks、PUT/DELETE /tasks/:id),改动自动顺延
- 30 天计划到期自动归档并按当前阶段生成新一轮
- 内置养护模板重写为兽医常识向:狗每阶段含遛狗/牵引/狂犬,猫含猫砂/梳毛/饮水
- 文件 URL 改为按 object_name + 当前配置动态拼接,换 IP/域名不再有旧地址

小程序
- 首页今日任务加「管理」入口:增删改任务弹层
- 记录时间轴显示照片缩略图(可全屏预览)+ 拍照成功提示
- 社区发布条精简为单个「发布图文」按钮,去掉头像/输入框误触

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 10:06:13 +08:00
Blizzard 2f5dd6eefc feat: 养护模板/社区运营/体重趋势/计划日历 + 雪花ID重构 + 文件表与图片上传
后端
- 主键改雪花字符串 ID(pkg/idgen + Base.BeforeCreate),全表外键/JWT/中间件随之调整
- 新增 files 表:/api/upload 按 MD5 去重,返回 {id,url,md5},服务端只收图片
- 头像/记录附图/帖子图改 file_id 关联,读取解析为 URL
- 养护模板(物种×阶段)后台可配 + AI 生成草稿;建档按模板生成任务/计划/提醒
- 社区 AI 运营:虚拟账号池 + 每日定时/手动生成,帖子带 AI 标
- 计划路线图节点带真实日期;首页周历与计划日历同源;新增 day-plan 当日安排
- 体重趋势接口带备注;记录列表分页

小程序
- 公共图片上传 utils/upload.js(仅图片);记录拍照/我的头像/社区发图三处接入
- 首页日历点选查当日任务;记录页体重趋势可点看备注 + 时间轴分页折叠
- 计划页日历点选查当日计划;自定义 tabBar 高度调整

后台(React)
- 新增「养护模板」「社区运营」页;用户管理加机器人筛选

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:48:15 +08:00
Blizzard 609f7d06cf init: 毛孩子计划 小程序 + Go 后端 + 内嵌后台
- pets-fe: 微信原生小程序(首页/计划/记录/报告/社区/引导),
  服务端驱动、无假数据;弹层改用 scroll-view,打开时隐藏自定义 tabBar
- pets-be: Gin + GORM(MySQL, sundynix_ 前缀) + MinIO,统一响应/分页,
  微信 code2session 登录,provider-neutral AI(DeepSeek),go:embed React 后台
- 修复:分段选择类型不匹配(字符串 vs 数字)导致选不中

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:36:55 +08:00