75765b3ee8
之前用户记几十条数据只换回一条折线,数据没有回到他身上,所以不记也不亏。 新增 GET /api/pets/:id/insights,只看最近 90 天(更早的对「现在怎么样」 没参考价值,还会让关联分析找出一堆巧合),产出最多 6 条按严重度排序的结论: 1. 体重趋势 —— 单次数字没意义,跨度 ≥14 天的连续同向变化才算。 跌 10% 报警建议血检,涨 15% 提醒控制,跌 5% 持续观察 2. 换粮 → 软便的时间关联 —— 找异常排便前 72 小时内的饮食记录。 这是用户最看不出来的一类:两条记录隔两三天、分属不同类型,翻时间轴翻不出来 3. 异常扎堆 —— 两周内 ≥2 次异常。偶发一次和反复出现完全不是一回事 4. 逾期提醒 —— 设了不看等于没设 5. 同龄体重对比 —— 同物种、月龄差 2 个月内其它宠物的中位数。 样本 <8 只直接不显示:拿 3 只算出来的「中位数」比不给还糟 6. 记录习惯 —— 数据不足时negative空手而归,给一句「再记几条就能看出规律」 每条都带 evidence(支撑它的具体数据)和 action(点击直接跳到对应记录入口), 结论不能只是断言。文案沿用 AI 助手同一套护栏:不做诊断,异常一律写清 什么时候必须就医。 前端落在记录页体重趋势卡上方,三档配色区分严重度。 实测(造 4 条体重下滑 + 换粮 + 软便 + 两次异常): 🔴 体重掉了 13%,建议就医检查(39 天内 4.50→3.90kg) 🔴 两周内记了 2 次异常 🟠 这次「软便」之前 2 天有过饮食变化(7月20日换粮 → 7月22日软便) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
60 lines
3.3 KiB
Plaintext
60 lines
3.3 KiB
Plaintext
.mini-chart{
|
|
height:256rpx;border-radius:var(--r-md);margin-top:var(--sp-4);position:relative;overflow:hidden;
|
|
background:
|
|
linear-gradient(180deg,rgba(115,190,157,.16),rgba(115,190,157,0)),
|
|
repeating-linear-gradient(0deg,#fff,#fff 60rpx,#EFE8DE 62rpx);
|
|
}
|
|
.chart-line{position:absolute;left:36rpx;right:36rpx;top:44rpx;bottom:44rpx;width:auto;height:auto}
|
|
.dot-layer{position:absolute;left:36rpx;right:36rpx;top:44rpx;bottom:44rpx}
|
|
.dot{position:absolute;width:40rpx;height:40rpx;margin:-20rpx 0 0 -20rpx;border-radius:50%;}
|
|
.dot::after{content:'';position:absolute;left:50%;top:50%;width:18rpx;height:18rpx;margin:-9rpx 0 0 -9rpx;border-radius:50%;background:#fff;border:4rpx solid var(--green);box-sizing:border-box}
|
|
.dot.on::after{width:26rpx;height:26rpx;margin:-13rpx 0 0 -13rpx;background:var(--green);box-shadow:0 0 0 6rpx rgba(115,190,157,.25)}
|
|
.trend-stats{margin-top:var(--sp-3);font-size:var(--fs-sm);color:var(--muted)}
|
|
|
|
.point-detail{
|
|
margin-top:var(--sp-3);padding:var(--sp-4);border-radius:var(--r-md);
|
|
background:var(--green-soft);border:1rpx solid #DCEFE4;
|
|
}
|
|
.pd-main{display:flex;align-items:baseline;gap:var(--sp-3)}
|
|
.pd-date{font-size:var(--fs-sm);color:var(--muted)}
|
|
.pd-weight{font-size:var(--fs-xl);font-weight:var(--fw-b);color:var(--green-ink)}
|
|
.pd-delta{font-size:var(--fs-sm);font-weight:var(--fw-b)}
|
|
.pd-delta.up{color:var(--red-ink)}
|
|
.pd-delta.down{color:var(--green-ink)}
|
|
.pd-note{margin-top:var(--sp-2);font-size:var(--fs-md);color:var(--text-2);line-height:1.5}
|
|
.pd-note.muted{color:var(--muted)}
|
|
.chart-hint{margin-top:var(--sp-2);font-size:var(--fs-cap);color:var(--muted);text-align:center}
|
|
|
|
.health-timeline{display:flex;flex-direction:column;gap:var(--sp-2)}
|
|
.health-event{display:flex;gap:var(--sp-3);background:var(--surface-2);border-radius:var(--r-md);padding:var(--sp-4)}
|
|
/* 底色和文字色由 .tone-N 提供(记录类型决定),这里只管形状 */
|
|
.event-dot{
|
|
width:64rpx;height:64rpx;border-radius:var(--r-sm);flex:none;
|
|
display:flex;align-items:center;justify-content:center;
|
|
}
|
|
.he-b{font-size:var(--fs-md);font-weight:var(--fw-b)}
|
|
.he-p{color:var(--muted);font-size:var(--fs-sm);line-height:1.45;margin-top:6rpx}
|
|
.he-body{flex:1;min-width:0}
|
|
.he-img{margin-top:var(--sp-2);width:220rpx;height:220rpx;border-radius:var(--r-sm)}
|
|
|
|
.tl-tip{margin-top:var(--sp-3);text-align:center;color:var(--muted);font-size:var(--fs-cap)}
|
|
.tl-more{
|
|
margin-top:var(--sp-3);padding:var(--sp-3);text-align:center;color:var(--primary-dark);
|
|
background:var(--surface-2);border-radius:var(--r-md);font-size:var(--fs-sm);font-weight:var(--fw-b);
|
|
}
|
|
|
|
/* 健康洞察 */
|
|
.ins{border-radius:var(--r-md);padding:var(--sp-4);margin-bottom:var(--sp-2)}
|
|
.ins:last-child{margin-bottom:0}
|
|
.ins-info{background:var(--surface-2)}
|
|
.ins-warn{background:var(--primary-soft)}
|
|
.ins-alert{background:var(--red-soft)}
|
|
.ins-head{display:flex;align-items:flex-start;gap:var(--sp-2)}
|
|
.ins-ic{flex:none;margin-top:2rpx}
|
|
.ins-info .ins-ic{color:var(--green-ink)}
|
|
.ins-warn .ins-ic{color:var(--primary-ink)}
|
|
.ins-alert .ins-ic{color:var(--red-ink)}
|
|
.ins-title{flex:1;font-size:var(--fs-md);font-weight:var(--fw-b);line-height:1.4}
|
|
.ins-detail{color:var(--text-2);font-size:var(--fs-sm);line-height:1.6;margin-top:var(--sp-2)}
|
|
.ins-ev{color:var(--muted);font-size:var(--fs-cap);margin-top:var(--sp-2)}
|