feat: multi-frame squash->overshoot->settle Q-bounce (inline transform) + rotating fun/balance bubble presets

This commit is contained in:
2026-09-01 20:28:15 +08:00
parent 6343b9499e
commit d54e361e81
+26 -63
View File
@@ -17,17 +17,13 @@
<!-- 中页:主页 / 吉祥物(无按钮,点击互动) --> <!-- 中页:主页 / 吉祥物(无按钮,点击互动) -->
<div class="page-item center-page"> <div class="page-item center-page">
<!-- 气泡区:始终占位,让气泡在头像正上方居中 --> <!-- 气泡区:始终占位,让气泡在头像正上方居中;只显示趣味/上轮消耗信息 -->
<div class="bubble-zone"> <div class="bubble-zone">
<div class="bubble" if="{{bubbleVisible}}"> <div class="bubble" if="{{bubbleVisible}}">
<text class="bubble-title">DeepSeek 余额</text> <text class="bubble-text">{{bubbleText}}</text>
<text class="bubble-balance">¥{{bubbleBalance}}</text>
<text class="bubble-usage">今日已用 ¥{{bubbleUsage}}</text>
<text class="bubble-mode {{isPeak ? 'bubble-mode-peak' : 'bubble-mode-off'}}">{{peakLabel}}</text>
<text class="bubble-fun">{{bubbleText}}</text>
</div> </div>
</div> </div>
<image class="mascot {{tapAnim ? 'mascot-tap' : ''}}" src="/common/dsniang.png" onclick="onTap" /> <image class="mascot" style="transform: scale({{mascotSX}}, {{mascotSY}})" src="/common/dsniang.png" onclick="onTap" />
<text class="peak {{isPeak ? 'peak-red' : 'peak-green'}}">{{peakLabel}}</text> <text class="peak {{isPeak ? 'peak-red' : 'peak-green'}}">{{peakLabel}}</text>
<text class="stats">余额 {{balance}}</text> <text class="stats">余额 {{balance}}</text>
<text class="stats">今日 {{todayTokens}} tokens · 预估 ¥{{todayCost}}</text> <text class="stats">今日 {{todayTokens}} tokens · 预估 ¥{{todayCost}}</text>
@@ -94,22 +90,24 @@ export default {
todayCost: '--', todayCost: '--',
bubbleVisible: false, bubbleVisible: false,
bubbleText: '', bubbleText: '',
bubbleBalance: '--', bubbleIndex: 0,
bubbleUsage: '--', mascotSX: 1,
tapAnim: false, mascotSY: 1,
settings: { settings: {
serverUrl: 'ws://127.0.0.1:8787', serverUrl: 'ws://127.0.0.1:8787',
userId: '', userId: '',
token: '' token: ''
}, },
connText: '手机/手表未连接', connText: '手机/手表未连接',
lines: [ bubblePresets: [
'我算得比你快,但没你可爱。', '我算得比你快,但没你可爱。',
'余额在跳,我也在跳,别慌。', '上轮消耗 ¥0.08,钱包还撑得住。',
'峰时了,省着点用哦~', '峰时了,省着点用哦~',
'谷时来了,冲就完事!', '谷时来了,冲就完事!',
'今天也要一起聪明地偷懒。', '今天也要一起聪明地偷懒。',
'点我一下,解压一下。' '点我一下,解压一下。',
'上轮余额 ¥12.34,别浪~',
'思考中…其实是发呆。'
] ]
}, },
@@ -152,18 +150,21 @@ export default {
}, },
onTap() { onTap() {
// Q 弹:先上下压缩,再平滑回弹;回弹时放音效 // Q 弹:压扁 -> 回弹过冲 -> 回正(多帧驱动,不依赖 CSS transition)
this.tapAnim = true
const self = this const self = this
setTimeout(() => { self.tapAnim = false }, 150) this.mascotSX = 1.00
setTimeout(() => { playDuckSound() }, 150) this.mascotSY = 1.00
setTimeout(() => { self.mascotSX = 1.06; self.mascotSY = 0.84 }, 0)
setTimeout(() => { self.mascotSX = 0.98; self.mascotSY = 1.06 }, 60)
setTimeout(() => { self.mascotSX = 1.00; self.mascotSY = 1.00 }, 120)
// 回弹时播鸭叫
setTimeout(() => { playDuckSound() }, 120)
const idx = Math.floor(Math.random() * this.lines.length) // 轮播趣味/上轮消耗信息
const mode = this.isPeak ? '当前是峰时,钱包瑟瑟发抖' : '当前是谷时,薅羊毛好时机' const idx = this.bubbleIndex % this.bubblePresets.length
this.bubbleText = this.lines[idx] + ' | ' + mode this.bubbleIndex += 1
this.bubbleBalance = this.balance this.bubbleText = this.bubblePresets[idx]
this.bubbleUsage = this.todayCost this.bubbleVisible = true
this.bubbleVisible = !this.bubbleVisible
}, },
selectSession(index) { selectSession(index) {
@@ -267,10 +268,6 @@ export default {
transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1); transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1);
} }
.mascot-tap {
transform: scale(1.05, 0.86);
}
.peak { .peak {
font-size: 22px; font-size: 22px;
font-weight: bold; font-weight: bold;
@@ -300,46 +297,12 @@ export default {
background-color: #ffffff; background-color: #ffffff;
} }
.bubble-title { .bubble-text {
color: #5b6b8c;
font-size: 13px;
text-align: center;
}
.bubble-balance {
color: #1c2c47; color: #1c2c47;
font-size: 28px; font-size: 15px;
font-weight: bold;
text-align: center; text-align: center;
} }
.bubble-usage {
color: #5b6b8c;
font-size: 12px;
text-align: center;
}
.bubble-mode {
font-size: 13px;
font-weight: bold;
text-align: center;
}
.bubble-mode-peak {
color: #ff5b5b;
}
.bubble-mode-off {
color: #1f9e5a;
}
.bubble-fun {
color: #1c2c47;
font-size: 12px;
text-align: center;
margin-top: 4px;
}
.setting-label { .setting-label {
color: #8fa4c9; color: #8fa4c9;
font-size: 14px; font-size: 14px;