Files
sundynix-pets/pets-fe/pages/record/record.wxml
T
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

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>