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>
This commit is contained in:
Blizzard
2026-07-29 10:54:18 +08:00
parent c076968b2c
commit 2fd25e26ef
36 changed files with 305 additions and 291 deletions
+7 -1
View File
@@ -31,6 +31,11 @@ Page({
data: {
pet: {},
planView: 'timeline',
planTabs: [
{ key: 'timeline', label: '路线图' },
{ key: 'calendar', label: '日历' },
{ key: 'aiPlan', label: 'AI 计划' },
],
plan: null,
calCells: [],
calLabel: '',
@@ -117,8 +122,9 @@ Page({
})
.catch(() => {});
},
// 来自 seg-tabs 的 change 事件,key 即 planView
switchPlanView(e) {
const view = e.currentTarget.dataset.view;
const view = e.detail.key;
this.setData({ planView: view });
if (view === 'calendar' && !this.data.calLoaded) this.loadCalendar();
},
+3 -1
View File
@@ -3,6 +3,8 @@
"nav-bar": "/components/nav-bar/nav-bar",
"pet-switch": "/components/pet-switch/pet-switch",
"bottom-sheet": "/components/bottom-sheet/bottom-sheet",
"fab": "/components/fab/fab"
"fab": "/components/fab/fab",
"pt-icon": "/components/pt-icon/index",
"seg-tabs": "/components/seg-tabs/index"
}
}
+4 -13
View File
@@ -2,18 +2,9 @@
<scroll-view class="page-scroll" scroll-y="{{true}}" enhanced="{{true}}" show-scrollbar="{{false}}">
<view class="page-body">
<view class="page-title">
<view class="pt-h2">养宠计划</view>
<view class="pt-p">按宠物查看路线图、日历与 AI 计划。</view>
</view>
<pet-switch bind:add="onAddPet"></pet-switch>
<view class="inline-tabs">
<view class="it-btn {{planView === 'timeline' ? 'active' : ''}}" data-view="timeline" bindtap="switchPlanView">路线图</view>
<view class="it-btn {{planView === 'calendar' ? 'active' : ''}}" data-view="calendar" bindtap="switchPlanView">日历</view>
<view class="it-btn {{planView === 'aiPlan' ? 'active' : ''}}" data-view="aiPlan" bindtap="switchPlanView">AI 计划</view>
</view>
<seg-tabs variant="solid" items="{{planTabs}}" current="{{planView}}" bind:change="switchPlanView"></seg-tabs>
<!-- 路线图 -->
<view wx:if="{{planView === 'timeline'}}">
@@ -29,13 +20,13 @@
<view wx:for="{{plan.tasks}}" wx:key="id" class="time-block">
<view class="time-label">{{item.day_label}}<text wx:if="{{item.dateLabel}}" class="time-date">{{item.dateLabel}}</text></view>
<view class="plan-task {{item.done ? 'done' : ''}}">
<view class="pk-check" catchtap="toggleTimelineTask" data-id="{{item.id}}">{{item.done ? '✓' : ''}}</view>
<view class="pk-check" catchtap="toggleTimelineTask" data-id="{{item.id}}"><pt-icon wx:if="{{item.done}}" name="check" size="{{22}}"></pt-icon></view>
<view class="pk-body" data-type="{{item.sheet_type}}" bindtap="openSheet">
<text class="pk-b">{{item.title}}</text><view class="pk-p">{{item.description}}</view>
</view>
</view>
</view>
<view wx:if="{{!plan}}" class="pt-p" style="padding:20rpx 0">暂无计划</view>
<view wx:if="{{!plan}}" class="empty">暂无计划</view>
</view>
</view>
@@ -64,7 +55,7 @@
<text class="dd-tag rem">提醒</text><text class="dd-b">{{item.title}}</text>
</view>
</block>
<view wx:else class="dd-empty">这天没有安排</view>
<view wx:else class="empty">这天没有安排</view>
</view>
</view>
+36 -39
View File
@@ -1,58 +1,55 @@
.inline-tabs{display:flex;padding:8rpx;gap:8rpx;border-radius:32rpx;background:#EFE8DE;margin-bottom:28rpx}
.it-btn{
flex:1;height:68rpx;line-height:68rpx;text-align:center;border-radius:24rpx;
color:var(--muted);font-weight:900;font-size:26rpx;
}
.it-btn.active{background:#fff;color:var(--primary-dark);box-shadow:0 12rpx 28rpx rgba(0,0,0,.06)}
.timeline{padding-left:36rpx;position:relative}
/* 竖线时间轴 */
.timeline{padding-left:var(--sp-6);position:relative}
.timeline::before{content:"";position:absolute;left:12rpx;top:12rpx;bottom:16rpx;width:4rpx;background:#E8DED0}
.time-block{position:relative;margin-bottom:28rpx}
.time-label{font-weight:900;color:var(--primary-dark);font-size:26rpx;margin-bottom:16rpx;position:relative}
.time-date{margin-left:12rpx;font-weight:600;color:var(--muted);font-size:22rpx}
.time-block{position:relative;margin-bottom:var(--sp-4)}
.time-label{font-weight:var(--fw-b);color:var(--primary-dark);font-size:var(--fs-sm);margin-bottom:var(--sp-3);position:relative}
.time-date{margin-left:var(--sp-2);font-weight:var(--fw);color:var(--muted);font-size:var(--fs-cap)}
.time-label::before{
content:"";position:absolute;left:-34rpx;top:8rpx;width:24rpx;height:24rpx;border-radius:50%;
background:var(--primary);border:6rpx solid #fff;box-shadow:0 0 0 4rpx #F5D5A8;
background:var(--primary);border:6rpx solid #fff;box-shadow:0 0 0 4rpx var(--primary-line);
}
.plan-task{
background:#fff;border-radius:var(--r-md);padding:var(--sp-4);box-shadow:var(--sd-1);
border:1rpx solid transparent;display:flex;gap:var(--sp-3);align-items:flex-start;
}
.plan-task{background:#fff;border-radius:36rpx;padding:26rpx;box-shadow:var(--shadow);border:1rpx solid transparent;display:flex;gap:18rpx;align-items:flex-start}
.plan-task.done{opacity:.55}
.pk-check{
width:44rpx;height:44rpx;border-radius:50%;border:4rpx solid #DED1C4;flex:none;margin-top:2rpx;
display:flex;align-items:center;justify-content:center;color:#fff;font-size:24rpx;font-weight:900;
display:flex;align-items:center;justify-content:center;color:#fff;
}
.plan-task.done .pk-check{background:var(--green);border-color:var(--green)}
.pk-body{flex:1}
.pk-b{font-size:28rpx;font-weight:700}
.pk-p{color:var(--muted);font-size:24rpx;line-height:1.45;margin-top:10rpx}
.ai-plan-tip{color:var(--muted);font-size:26rpx;line-height:1.6;margin-bottom:16rpx}
.pk-b{font-size:var(--fs-md);font-weight:var(--fw-b)}
.pk-p{color:var(--muted);font-size:var(--fs-sm);line-height:1.45;margin-top:var(--sp-1)}
.ai-plan-tip{color:var(--muted);font-size:var(--fs-sm);line-height:1.6;margin-bottom:var(--sp-3)}
.calendar{background:#fff;border-radius:44rpx;padding:28rpx;box-shadow:var(--shadow)}
.cal-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:20rpx;font-weight:900;font-size:30rpx}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:12rpx;text-align:center}
.cal-w{font-size:22rpx;color:var(--muted);padding:8rpx 0}
/* 日历 */
.calendar{background:#fff;border-radius:var(--r-lg);padding:var(--sp-4);box-shadow:var(--sd-1)}
.cal-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--sp-3);font-weight:var(--fw-b);font-size:var(--fs-lg)}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sp-2);text-align:center}
.cal-w{font-size:var(--fs-cap);color:var(--muted);padding:var(--sp-1) 0}
.cal-cell{
height:76rpx;border-radius:24rpx;display:flex;align-items:center;justify-content:center;
font-weight:800;font-size:26rpx;background:#FBFAF8;position:relative;
height:76rpx;border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;
font-weight:var(--fw-b);font-size:var(--fs-sm);background:var(--surface-2);position:relative;
}
.cal-cell.blank{background:transparent}
.cal-cell.today{background:#FFF3DF;color:var(--primary-dark)}
.cal-cell.tasked::after{content:"";position:absolute;bottom:10rpx;width:10rpx;height:10rpx;border-radius:50%;background:var(--green)}
.cal-cell.today{background:var(--primary-soft);color:var(--primary-dark)}
.cal-cell.tasked::after{content:"";position:absolute;bottom:8rpx;width:8rpx;height:8rpx;border-radius:50%;background:var(--green)}
.cal-cell.sel{background:var(--primary);color:#fff}
.cal-cell.sel.tasked::after{background:#fff}
.day-detail{margin-top:24rpx;border-top:1rpx solid var(--line);padding-top:24rpx}
.dd-title{font-weight:900;font-size:28rpx;margin-bottom:16rpx}
.dd-item{display:flex;align-items:center;gap:16rpx;padding:14rpx 0}
.dd-tag{flex:none;font-size:20rpx;font-weight:700;padding:2rpx 12rpx;border-radius:999rpx}
.dd-tag.plan{background:#FFF2DC;color:var(--primary-dark)}
.dd-tag.task{background:#E6F4EA;color:#2E7D5B}
.dd-tag.rem{background:#EAF0FF;color:#3B6BE5}
.dd-b{font-size:27rpx;color:var(--text)}
/* 某天的安排 */
.day-detail{margin-top:var(--sp-4);border-top:1rpx solid var(--line);padding-top:var(--sp-4)}
.dd-title{font-weight:var(--fw-b);font-size:var(--fs-md);margin-bottom:var(--sp-3)}
.dd-item{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) 0}
.dd-tag{flex:none;font-size:var(--fs-cap);font-weight:var(--fw-b);padding:2rpx var(--sp-2);border-radius:var(--r-full)}
.dd-tag.plan{background:var(--primary-soft);color:var(--primary-ink)}
.dd-tag.task{background:var(--green-soft);color:var(--green-ink)}
.dd-tag.rem{background:var(--blue-soft);color:var(--blue-ink)}
.dd-b{font-size:var(--fs-md);color:var(--text)}
.dd-b.done{text-decoration:line-through;color:var(--muted)}
.dd-empty{padding:20rpx 0;color:var(--muted);font-size:26rpx;text-align:center}
.extracted{display:grid;grid-template-columns:1fr 1fr;gap:16rpx;margin:24rpx 0}
.extract{background:#FBFAF8;border-radius:30rpx;padding:20rpx;font-size:24rpx}
.ex-b{display:block;font-size:26rpx;margin-bottom:6rpx;font-weight:700}
/* 页面不自身滚动,改由 page-scroll 承载滚动(隐藏滚动条)*/
/* AI 提取信息 */
.extracted{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3);margin:var(--sp-4) 0}
.extract{background:var(--surface-2);border-radius:var(--r-sm);padding:var(--sp-3);font-size:var(--fs-sm)}
.ex-b{display:block;font-size:var(--fs-sm);margin-bottom:6rpx;font-weight:var(--fw-b);color:var(--muted)}