feat(ui): 记录页月份联动与多项 UI 美化/修复
- records: 底部列表与月份选择器联动,新增 [本月|最近] 分段控件;标题/空态随模式切换 - leaderboard: 领奖台布局(冠军居中+皇冠)、次数标注于底座且三档水平对齐;头像 cloud:// 批量预解析提速(云函数需重新部署) - index/timer: 主色底图标改白色变体修复隐形;目标数字按微信字体缩放补偿真机遮挡 - settings: 配色方案横滑渐变色卡;头像上传前压缩至 200px - theme: 新增 teal 主题;暗黑背景统一对齐 - 圆形头像双保险(image 自身 border-radius)修复月/年榜方图 注: cloudfunctions/leaderboard 改动须在开发者工具重新部署才生效。
This commit is contained in:
@@ -243,13 +243,13 @@ Page({
|
||||
const nextStreak = (streak.lastDate && streak.count >= 1) ? streak.count + 1 : 1
|
||||
|
||||
if (stats.totalSessions === 0) {
|
||||
return { level: 'first', message: '🎉 第一次训练!坚持就是胜利' }
|
||||
return { level: 'first', message: '第一次训练!坚持就是胜利' }
|
||||
}
|
||||
if ([7, 14, 30, 50, 100, 365].includes(nextStreak)) {
|
||||
return { level: 'milestone', message: `🔥 连续打卡 ${nextStreak} 天!` }
|
||||
return { level: 'milestone', message: `连续打卡 ${nextStreak} 天!` }
|
||||
}
|
||||
if (elapsed > stats.maxDuration) {
|
||||
return { level: 'record', message: `🏆 新纪录!${elapsed}秒` }
|
||||
return { level: 'record', message: `新纪录!${elapsed}秒` }
|
||||
}
|
||||
return { level: 'normal', message: '完成!' }
|
||||
},
|
||||
@@ -454,6 +454,7 @@ Page({
|
||||
this._lastCountdown = 0
|
||||
this._lastTipIndex = -1
|
||||
this._clearVibrateTimers()
|
||||
this._countUpTask = null
|
||||
this.setData({
|
||||
showCompletion: false,
|
||||
isCompleted: false,
|
||||
@@ -462,9 +463,7 @@ Page({
|
||||
isPaused: false,
|
||||
remaining: this.data.duration,
|
||||
overtime: 0,
|
||||
goalReached: false,
|
||||
// Re-init countUp so the big number rolls again on next start
|
||||
_countUpTask: null
|
||||
goalReached: false
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
+12
-12
@@ -29,21 +29,21 @@
|
||||
duration="{{duration}}"
|
||||
remaining="{{isCompleted ? 0 : remaining}}"
|
||||
size="{{360}}"
|
||||
ringWidth="{{16}}"
|
||||
ringWidth="{{22}}"
|
||||
status="{{status}}"
|
||||
primaryColor="{{theme.primary}}"
|
||||
primaryLightColor="{{theme.primaryLight}}"
|
||||
trackColor="{{isDark ? '#2C2C2E' : '#EEEEEE'}}"
|
||||
trackColor="{{isDark ? '#3A3A40' : '#EEEEEE'}}"
|
||||
></progress-ring>
|
||||
|
||||
<!-- 完成庆祝粒子 -->
|
||||
<view class="celebrate-burst" wx:if="{{isCompleted}}">
|
||||
<view class="spark s1">✨</view>
|
||||
<view class="spark s2">⭐</view>
|
||||
<view class="spark s3">💫</view>
|
||||
<view class="spark s4">🌟</view>
|
||||
<view class="spark s5">✨</view>
|
||||
<view class="spark s6">💪</view>
|
||||
<image class="spark s1" src="{{icons.sparkleFill}}" mode="aspectFit"></image>
|
||||
<image class="spark s2" src="{{icons.sparkleFill}}" mode="aspectFit"></image>
|
||||
<image class="spark s3" src="{{icons.crownFill}}" mode="aspectFit"></image>
|
||||
<image class="spark s4" src="{{icons.sparkleFill}}" mode="aspectFit"></image>
|
||||
<image class="spark s5" src="{{icons.sparkleFill}}" mode="aspectFit"></image>
|
||||
<image class="spark s6" src="{{icons.likeFill}}" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
<view class="overtime-badge" wx:if="{{overtime > 0}}">
|
||||
@@ -87,7 +87,7 @@
|
||||
size="xl"
|
||||
block
|
||||
text="开始"
|
||||
icon-src="{{icons.playFill}}"
|
||||
icon-src="{{icons.playWhite}}"
|
||||
bindtap="onStart"
|
||||
></ui-btn>
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
variant="primary"
|
||||
size="xl"
|
||||
text="继续"
|
||||
icon-src="{{icons.playFill}}"
|
||||
icon-src="{{icons.playWhite}}"
|
||||
custom-style="margin-right: 28rpx;"
|
||||
bindtap="onStart"
|
||||
></ui-btn>
|
||||
@@ -137,7 +137,7 @@
|
||||
<view class="completion-mask" wx:if="{{showCompletion}}" catchtouchmove="onNoop">
|
||||
<view class="completion-card">
|
||||
<view class="completion-emoji-wrap">
|
||||
<text class="completion-emoji">{{completionLevel === 'first' ? '🎉' : completionLevel === 'record' ? '🏆' : completionLevel === 'milestone' ? '🔥' : '✨'}}</text>
|
||||
<image class="completion-icon" src="{{completionLevel === 'first' ? icons.partyWhite : completionLevel === 'record' ? icons.trophyWhite : completionLevel === 'milestone' ? icons.hotWhite : icons.sparkleWhite}}" mode="aspectFit"></image>
|
||||
</view>
|
||||
<text class="completion-title">{{completionMessage}}</text>
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
</view>
|
||||
|
||||
<view class="completion-streak" wx:if="{{completionStreak > 0}}">
|
||||
<text class="streak-flame">🔥</text>
|
||||
<image class="streak-flame" src="{{icons.hotFill}}" mode="aspectFit"></image>
|
||||
<text class="streak-text">连续打卡 {{completionStreak}} 天</text>
|
||||
</view>
|
||||
|
||||
|
||||
+17
-14
@@ -17,24 +17,25 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* breathing guide rings — three concentric layers */
|
||||
/* breathing guide rings — soft radial glows instead of hard outline circles,
|
||||
so they read as ambient halo rather than a bullseye */
|
||||
.breathe-ring {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
border: 3rpx solid rgba(var(--primary-rgb), 0.15);
|
||||
background: radial-gradient(circle, rgba(var(--primary-rgb), 0.10) 0%, rgba(var(--primary-rgb), 0) 65%);
|
||||
animation: breathePulse 3.5s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.breathe-ring-1 { width: 480rpx; height: 480rpx; animation-delay: 0s; }
|
||||
.breathe-ring-2 { width: 400rpx; height: 400rpx; animation-delay: 0.5s; border-color: rgba(var(--primary-rgb), 0.25); border-width: 4rpx; }
|
||||
.breathe-ring-3 { width: 320rpx; height: 320rpx; animation-delay: 1s; border-color: rgba(var(--primary-rgb), 0.35); border-width: 5rpx; }
|
||||
.breathe-ring-1 { width: 520rpx; height: 520rpx; animation-delay: 0s; }
|
||||
.breathe-ring-2 { width: 440rpx; height: 440rpx; animation-delay: 0.5s; background: radial-gradient(circle, rgba(var(--primary-rgb), 0.14) 0%, rgba(var(--primary-rgb), 0) 65%); }
|
||||
.breathe-ring-3 { width: 380rpx; height: 380rpx; animation-delay: 1s; background: radial-gradient(circle, rgba(var(--primary-rgb), 0.18) 0%, rgba(var(--primary-rgb), 0) 65%); }
|
||||
|
||||
.breathe-ring.fast { animation: breathePulseFast 1.4s ease-in-out infinite; }
|
||||
.breathe-ring.fast.breathe-ring-1 { animation-delay: 0s; border-color: rgba(var(--primary-rgb), 0.3); }
|
||||
.breathe-ring.fast.breathe-ring-2 { animation-delay: 0.25s; border-color: rgba(var(--primary-rgb), 0.45); }
|
||||
.breathe-ring.fast.breathe-ring-3 { animation-delay: 0.5s; border-color: rgba(var(--primary-rgb), 0.6); }
|
||||
.breathe-ring.fast.breathe-ring-1 { animation-delay: 0s; }
|
||||
.breathe-ring.fast.breathe-ring-2 { animation-delay: 0.25s; }
|
||||
.breathe-ring.fast.breathe-ring-3 { animation-delay: 0.5s; }
|
||||
|
||||
/* celebration burst */
|
||||
.celebrate-burst {
|
||||
@@ -47,11 +48,12 @@
|
||||
|
||||
.spark {
|
||||
position: absolute;
|
||||
font-size: 36rpx;
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
animation: sparkBurst 1s ease-out forwards;
|
||||
}
|
||||
|
||||
.s1 { top: -10rpx; left: 50%; margin-left: -18rpx; animation-delay: 0s; }
|
||||
.s1 { top: -10rpx; left: 50%; margin-left: -22rpx; animation-delay: 0s; }
|
||||
.s2 { top: 30rpx; right: -10rpx; animation-delay: 0.1s; }
|
||||
.s3 { bottom: -10rpx; right: 50rpx; animation-delay: 0.2s; }
|
||||
.s4 { bottom: 20rpx; left: 30rpx; animation-delay: 0.15s; }
|
||||
@@ -264,9 +266,9 @@
|
||||
50% { transform: scale(1.08); }
|
||||
}
|
||||
|
||||
.completion-emoji {
|
||||
font-size: 80rpx;
|
||||
line-height: 1;
|
||||
.completion-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.completion-title {
|
||||
@@ -346,7 +348,8 @@
|
||||
}
|
||||
|
||||
.streak-flame {
|
||||
font-size: 32rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.streak-text {
|
||||
|
||||
Reference in New Issue
Block a user