feat: 结算页结局演出(彩带+动态标题+鼓励语+场景 emoji)

This commit is contained in:
2026-08-13 15:41:15 +08:00
parent c486a619eb
commit 43a25eaf23
+63 -3
View File
@@ -1,18 +1,31 @@
<template>
<view class="page">
<!-- 彩带通关/完美时 -->
<view v-if="result && stars > 0" class="confetti">
<view
v-for="(p, i) in pieces"
:key="i"
class="confetti-piece"
:style="{ left: p.left + '%', background: p.color, animationDelay: p.delay + 's', animationDuration: p.duration + 's', transform: 'rotate(' + p.rotate + 'deg)' }"
></view>
</view>
<view v-if="result" class="result">
<view class="result-title">闯关完成</view>
<view class="result-emoji">{{ sceneEmoji }}</view>
<view class="result-title" :class="{ great: stars >= 3, ok: stars > 0 && stars < 3, again: stars === 0 }">{{ title }}</view>
<view class="stars-area">
<view
v-for="i in 3"
:key="i"
class="big-star"
:class="{ on: i <= result.final.stars, pop: i <= result.final.stars }"
:class="{ on: i <= stars, pop: i <= stars }"
:style="{ animationDelay: i * 0.35 + 's' }"
></view>
</view>
<view v-if="encourage" class="encourage">💪 {{ encourage }}</view>
<view class="card panel">
<view class="panel-row">
<text class="label">关卡</text>
@@ -44,17 +57,41 @@
</template>
<script>
import { sceneVisual } from '../../utils/visual.js'
import { playSound } from '../../utils/sound.js'
const RESULT_KEY = '36wisdom_result'
export default {
data() {
return { result: null }
return { result: null, pieces: [] }
},
onLoad() {
const saved = uni.getStorageSync(RESULT_KEY)
this.result = saved || null
if (!saved) {
uni.reLaunch({ url: '/pages/map/map' })
return
}
this.pieces = this.makePieces(30)
playSound(this.result.final.stars > 0 ? 'finish' : 'bad')
},
computed: {
stars() {
return this.result.final.stars
},
title() {
if (this.stars >= 3) return '完美通关!'
if (this.stars > 0) return '通关啦!'
return '再试一次!'
},
sceneEmoji() {
return sceneVisual(this.result.scene_name).emoji
},
encourage() {
if (this.stars === 0) return '你已经很棒了,再试一次会更好!'
if (this.stars < 3) return '还差一点点,补完分支就能完美!'
return ''
}
},
methods: {
@@ -63,6 +100,20 @@ export default {
},
backMap() {
uni.reLaunch({ url: '/pages/map/map' })
},
makePieces(n) {
const colors = ['#ff6b35', '#ffb347', '#4ecdc4', '#6c8cff', '#a58cff', '#ff6b9a']
const list = []
for (let i = 0; i < n; i++) {
list.push({
left: Math.random() * 100,
delay: Math.random() * 1.5,
duration: 2 + Math.random() * 2,
color: colors[i % colors.length],
rotate: Math.random() * 360
})
}
return list
}
}
}
@@ -176,4 +227,13 @@ export default {
background: #f5ece0;
color: #7a6248;
}
.result-emoji { font-size: 96rpx; margin-bottom: 8rpx; animation: t-pop 0.6s ease; }
.result-title.great { color: #ffb347; }
.result-title.ok { color: #ff6b35; }
.result-title.again { color: #6c8cff; }
.encourage { font-size: 30rpx; color: #7a6248; background: #fff0e5; border-radius: 30rpx; padding: 16rpx 32rpx; margin-bottom: 32rpx; display: inline-block; }
@keyframes t-pop { 0% { opacity: 0; transform: scale(0.5); } 70% { transform: scale(1.1); } 100% { opacity: 1; transform: scale(1); } }
.confetti { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 5; }
.confetti-piece { position: absolute; top: -40rpx; width: 16rpx; height: 28rpx; border-radius: 4rpx; opacity: 0; animation: confetti-fall linear forwards; }
@keyframes confetti-fall { 0% { opacity: 1; transform: translateY(0) rotate(0); } 100% { opacity: 0.7; transform: translateY(110vh) rotate(720deg); } }
</style>