3fc3cbc7d2
## 通用简易表单
洗护/清洁那 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>
93 lines
5.2 KiB
Plaintext
93 lines
5.2 KiB
Plaintext
<nav-bar title="快速记录"></nav-bar>
|
|
|
|
<view class="top-bar"><pet-switch bind:add="onAddPet"></pet-switch></view>
|
|
|
|
<scroll-view class="page-scroll" scroll-y="{{true}}" enhanced="{{true}}" show-scrollbar="{{false}}">
|
|
<view class="page-body">
|
|
<view wx:if="{{!pet.id}}" class="no-pet">
|
|
<view class="no-pet-ic"><pt-icon name="community" size="{{52}}"></pt-icon></view>
|
|
<view class="no-pet-b">还没有毛孩子的档案</view>
|
|
<view class="no-pet-p">建好档才能记体重、便便、饮食这些,趋势图也是从这些记录里长出来的。</view>
|
|
<view class="btn btn-dark" bindtap="onAddPet"><pt-icon name="plus" size="{{30}}"></pt-icon>建一份档案</view>
|
|
</view>
|
|
|
|
<!-- 记一笔:分组来自后端 record_types,后台加一种不用发版。
|
|
每组一个色系,靠浅色圆底 + 分组配色出彩,图标仍是线性的 -->
|
|
<view class="card">
|
|
<view class="section-head"><view class="sh-title">记一笔</view></view>
|
|
<view wx:for="{{typeGroups}}" wx:key="key" class="tg {{item.tone}}">
|
|
<view class="tg-head"><view class="tg-bar"></view>{{item.label}}<text class="tg-n">{{item.items.length}}</text></view>
|
|
<view class="quick-grid cols-3">
|
|
<view wx:for="{{item.items}}" wx:for-item="t" wx:key="code" class="quick {{item.tone}}"
|
|
data-type="{{t.code}}" bindtap="openSheet">
|
|
<pt-icon name="{{t.icon}}" size="{{44}}" fallback="note"></pt-icon>{{t.label}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view wx:if="{{!typeGroups.length}}" class="empty">还没有配置可记事项</view>
|
|
</view>
|
|
|
|
<view wx:if="{{insights.length}}" class="card">
|
|
<view class="section-head"><view class="sh-title">健康洞察</view><view class="tiny">来自你的记录</view></view>
|
|
<view wx:for="{{insights}}" wx:key="title" class="ins ins-{{item.level}}" data-index="{{index}}" bindtap="onTapInsight">
|
|
<view class="ins-head">
|
|
<view class="ins-ic"><pt-icon name="{{item.icon}}" size="{{30}}"></pt-icon></view>
|
|
<view class="ins-title">{{item.title}}</view>
|
|
</view>
|
|
<view class="ins-detail">{{item.detail}}</view>
|
|
<view class="ins-ev">{{item.evidence}}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="card">
|
|
<view class="section-head"><view class="sh-title">体重趋势</view><view class="link" data-type="weight" bindtap="openSheet">记录</view></view>
|
|
<view wx:if="{{trendStats}}" class="trend-stats">最新 {{trendStats.latest}}kg · 较首次 {{trendStats.delta >= 0 ? '+' : ''}}{{trendStats.delta}}kg · 共 {{trendStats.count}} 次</view>
|
|
<block wx:if="{{trendSvg}}">
|
|
<view class="mini-chart">
|
|
<image class="chart-line" mode="scaleToFill" src="{{trendSvg}}"></image>
|
|
<view class="dot-layer">
|
|
<view wx:for="{{trendDots}}" wx:key="index"
|
|
class="dot {{selIdx === index ? 'on' : ''}}"
|
|
style="left:{{item.xp}}%;top:{{item.yp}}%"
|
|
data-index="{{index}}" bindtap="onTapPoint"></view>
|
|
</view>
|
|
</view>
|
|
<view wx:if="{{selDot}}" class="point-detail">
|
|
<view class="pd-main">
|
|
<text class="pd-date">{{selDot.date}}</text>
|
|
<text class="pd-weight">{{selDot.value}}kg</text>
|
|
<text wx:if="{{selDot.delta !== null}}" class="pd-delta {{selDot.delta > 0 ? 'up' : (selDot.delta < 0 ? 'down' : '')}}">{{selDot.delta > 0 ? '+' : ''}}{{selDot.delta}}kg</text>
|
|
</view>
|
|
<view wx:if="{{selDot.note}}" class="pd-note"><pt-icon name="note" size="{{26}}"></pt-icon> {{selDot.note}}</view>
|
|
<view wx:else class="pd-note muted">这次没有填备注</view>
|
|
</view>
|
|
<view class="chart-hint">点击圆点查看每次记录</view>
|
|
</block>
|
|
<view wx:else class="empty">先记录几次体重,这里会自动画出趋势曲线</view>
|
|
</view>
|
|
|
|
<view class="card">
|
|
<view class="section-head"><view class="sh-title">健康时间轴</view><view class="link" data-type="vetSummary" bindtap="openSheet">摘要</view></view>
|
|
<seg-tabs items="{{recFilters}}" current="{{recFilterIdx}}" bind:change="onFilterTap"></seg-tabs>
|
|
|
|
<view class="health-timeline">
|
|
<view wx:for="{{timeline}}" wx:key="id" class="health-event"
|
|
bindlongpress="onDeleteRecord" data-index="{{index}}">
|
|
<view class="event-dot {{item.tone}}"><pt-icon name="{{item.type}}" size="{{34}}" fallback="note"></pt-icon></view>
|
|
<view class="he-body">
|
|
<text class="he-b">{{item.title}}</text><view class="he-p">{{item.desc}}</view>
|
|
<image wx:if="{{item.image}}" class="he-img" src="{{item.image}}" mode="aspectFill" catchtap="previewImage" data-src="{{item.image}}"></image>
|
|
</view>
|
|
</view>
|
|
<view wx:if="{{timeline.length === 0}}" class="empty">这个分类下还没有记录</view>
|
|
</view>
|
|
<view wx:if="{{timeline.length}}" class="tl-tip">长按任意一条可删除</view>
|
|
<view wx:if="{{recHasMore}}" class="tl-more" bindtap="loadMoreRecords">查看更多(共 {{recTotal}} 条)</view>
|
|
<view wx:elif="{{recPage > 1}}" class="tl-more" bindtap="collapseRecords">收起</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<fab bind:tap="onFab"></fab>
|
|
<bottom-sheet show="{{sheetShow}}" type="{{sheetType}}" bind:close="closeSheet" bind:saved="onSheetSaved"></bottom-sheet>
|