wangfukang 1 day ago
parent
commit
db5824a7ee
  1. 127
      package1/components/planet/planet-header.vue
  2. 123
      package1/planet/rank.vue
  3. 2
      package1/planet/ticketLog.vue

127
package1/components/planet/planet-header.vue

@ -56,7 +56,7 @@
</view> </view>
</view> </view>
<view class="ph-core-label">得现金奖励</view> <view class="ph-core-label">得现金奖励</view>
<view class="ph-pool"> <view class="ph-pool" :class="{bong: poolBong}">
<text class="ph-pool-symbol"></text> <text class="ph-pool-symbol"></text>
<text class="ph-pool-num">{{poolText}}</text> <text class="ph-pool-num">{{poolText}}</text>
</view> </view>
@ -92,12 +92,17 @@
data() { data() {
return { return {
remain: 0, remain: 0,
timer: null timer: null,
poolTimer: null,
poolBongTimer: null,
displayPoolAmount: 0,
lastPoolAmount: 0,
poolBong: false
} }
}, },
computed: { computed: {
poolText() { poolText() {
const v = Number(this.data.poolAmount || 0) const v = Number(this.displayPoolAmount || 0)
return v.toFixed(2) return v.toFixed(2)
}, },
rankText() { rankText() {
@ -121,14 +126,19 @@
'data.countdownMillis'(val) { 'data.countdownMillis'(val) {
this.remain = val || 0 this.remain = val || 0
this.startTimer() this.startTimer()
},
'data.poolAmount'(val) {
this.animatePool(Number(val || 0))
} }
}, },
mounted() { mounted() {
this.remain = this.data.countdownMillis || 0 this.remain = this.data.countdownMillis || 0
this.animatePool(Number(this.data.poolAmount || 0), true)
this.startTimer() this.startTimer()
}, },
beforeDestroy() { beforeDestroy() {
if (this.timer) clearInterval(this.timer) if (this.timer) clearInterval(this.timer)
this.clearPoolTimers()
}, },
methods: { methods: {
goTicketLog() { goTicketLog() {
@ -156,6 +166,47 @@
} }
this.remain -= 1000 this.remain -= 1000
}, 1000) }, 1000)
},
clearPoolTimers() {
if (this.poolTimer) clearInterval(this.poolTimer)
if (this.poolBongTimer) clearTimeout(this.poolBongTimer)
this.poolTimer = null
this.poolBongTimer = null
},
animatePool(target, initial) {
target = Number(target || 0)
this.clearPoolTimers()
this.poolBong = false
const start = initial ? 0 : Number(this.displayPoolAmount || 0)
const diff = target - start
this.lastPoolAmount = target
if (Math.abs(diff) < 0.01) {
this.displayPoolAmount = target
this.playPoolBong()
return
}
const duration = initial ? 1500 : 900
const startTime = Date.now()
this.displayPoolAmount = start
this.poolTimer = setInterval(() => {
const progress = Math.min(1, (Date.now() - startTime) / duration)
const eased = 1 - Math.pow(1 - progress, 3)
this.displayPoolAmount = start + diff * eased
if (progress >= 1) {
clearInterval(this.poolTimer)
this.poolTimer = null
this.displayPoolAmount = target
this.playPoolBong()
}
}, 30)
},
playPoolBong() {
this.poolBong = true
if (this.poolBongTimer) clearTimeout(this.poolBongTimer)
this.poolBongTimer = setTimeout(() => {
this.poolBong = false
this.poolBongTimer = null
}, 520)
} }
} }
} }
@ -548,20 +599,82 @@
.ph-pool { .ph-pool {
position: relative; position: relative;
text-align: center; text-align: center;
margin-top: 8rpx; margin-top: 10rpx;
color: #16A779; padding: 4rpx 22rpx 10rpx;
color: #FFF7B8;
border-radius: 999rpx;
background:
radial-gradient(circle at 50% 0%, rgba(255,255,255,0.68), transparent 34%),
linear-gradient(135deg, rgba(255,214,92,0.28), rgba(255,122,89,0.1));
text-shadow:
0 2rpx 0 #8A4A00,
0 8rpx 20rpx rgba(255,145,35,0.48),
0 0 34rpx rgba(255,224,138,0.8);
filter: drop-shadow(0 12rpx 24rpx rgba(255,145,35,0.26));
overflow: hidden;
transform-origin: center center;
}
.ph-pool::before {
content: '';
position: absolute;
left: -80rpx;
top: 0;
width: 56rpx;
height: 100%;
background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,0.92), rgba(255,255,255,0));
transform: skewX(-18deg);
animation: poolShine 1.8s ease-in-out infinite;
}
.ph-pool::after {
content: '';
position: absolute;
left: 24rpx;
right: 24rpx;
bottom: 6rpx;
height: 10rpx;
border-radius: 999rpx;
background: radial-gradient(circle, rgba(255,184,77,0.78), rgba(255,184,77,0));
filter: blur(4rpx);
}
.ph-pool.bong {
animation: poolBong .52s cubic-bezier(.2, 1.65, .32, 1);
}
@keyframes poolShine {
0% { transform: translateX(0) skewX(-18deg); opacity: 0; }
24% { opacity: .95; }
58% { opacity: .78; }
100% { transform: translateX(410rpx) skewX(-18deg); opacity: 0; }
}
@keyframes poolBong {
0% { transform: scale(1); }
42% { transform: scale(1.22) rotate(-2deg); }
68% { transform: scale(.95) rotate(1deg); }
100% { transform: scale(1) rotate(0); }
} }
.ph-pool-symbol { .ph-pool-symbol {
font-size: 38rpx; position: relative;
z-index: 1;
font-size: 42rpx;
font-weight: 900; font-weight: 900;
color: #FFE08A;
} }
.ph-pool-num { .ph-pool-num {
font-size: 92rpx; position: relative;
z-index: 1;
font-size: 98rpx;
font-weight: 900; font-weight: 900;
font-family: DIN, sans-serif; font-family: DIN, sans-serif;
letter-spacing: -2rpx; letter-spacing: -2rpx;
background: linear-gradient(180deg, #FFFFFF 0%, #FFF4A8 34%, #FFB52F 76%, #F77719 100%);
-webkit-background-clip: text;
color: transparent;
} }
.ph-pool-label { .ph-pool-label {

123
package1/planet/rank.vue

@ -31,13 +31,67 @@
<view class="rank-kicker">WEALTH COORDINATES</view> <view class="rank-kicker">WEALTH COORDINATES</view>
<view class="rank-title">财富坐标榜</view> <view class="rank-title">财富坐标榜</view>
</view> </view>
<view class="rank-page-no">已加载 {{pageNum}} / {{totalPages}} </view>
</view> </view>
<view v-if="pagedList.length" class="rank-list"> <view v-if="podiumList.length" class="podium-card">
<view class="podium-bg-glow"></view>
<view class="podium-head">
<view>
<view class="podium-kicker">TOP HUNTERS ARE WATCHING</view>
<view class="podium-title">前三领奖台</view>
</view>
<view class="podium-prize">抢榜越高 · 越容易被盯上</view>
</view>
<view class="reward-rule">
<view class="reward-main">每日 21:30 按校区分别结算有券前 5 名瓜分星球券</view>
<view class="reward-chips">
<text>第1名 +5</text>
<text>第2名 +4</text>
<text>第3名 +3</text>
<text>第4名 +2</text>
<text>第5名 +1</text>
</view>
</view>
<view class="podium-stage">
<view
class="podium-player second"
v-if="podiumSecond"
@tap="onHunt(podiumSecond)">
<view class="crown silver">2</view>
<image class="podium-avatar" :class="{stealth: podiumSecond.stealth}" :src="podiumSecond.stealth ? defaultAvatar : (podiumSecond.avatar || defaultAvatar)" mode="aspectFill"></image>
<view class="podium-name">{{podiumName(podiumSecond)}}</view>
<view class="podium-ticket">{{podiumSecond.ticketCount || 0}}</view>
<view class="podium-base">第二名</view>
</view>
<view
class="podium-player first"
v-if="podiumFirst"
@tap="onHunt(podiumFirst)">
<view class="crown gold">1</view>
<view class="king-aura"></view>
<image class="podium-avatar champion" :class="{stealth: podiumFirst.stealth}" :src="podiumFirst.stealth ? defaultAvatar : (podiumFirst.avatar || defaultAvatar)" mode="aspectFill"></image>
<view class="podium-name champion-name">{{podiumName(podiumFirst)}}</view>
<view class="podium-ticket hot">{{podiumFirst.ticketCount || 0}}</view>
<view class="podium-base king">第一名</view>
</view>
<view
class="podium-player third"
v-if="podiumThird"
@tap="onHunt(podiumThird)">
<view class="crown bronze">3</view>
<image class="podium-avatar" :class="{stealth: podiumThird.stealth}" :src="podiumThird.stealth ? defaultAvatar : (podiumThird.avatar || defaultAvatar)" mode="aspectFill"></image>
<view class="podium-name">{{podiumName(podiumThird)}}</view>
<view class="podium-ticket">{{podiumThird.ticketCount || 0}}</view>
<view class="podium-base">第三名</view>
</view>
</view>
<view class="podium-tip">点领奖台头像即可发起追查今天还剩 {{home.remainHunt || 0}} 次机会</view>
</view>
<view v-if="normalList.length" class="rank-list">
<view <view
class="rank-row" class="rank-row"
v-for="(item, index) in pagedList" v-for="(item, index) in normalList"
:key="item._rankKey"> :key="item._rankKey">
<view class="rank-no">#{{item._displayRankNo}}</view> <view class="rank-no">#{{item._displayRankNo}}</view>
<image class="avatar" :class="{stealth: item.stealth}" :src="item.stealth ? defaultAvatar : (item.avatar || defaultAvatar)" mode="aspectFill"></image> <image class="avatar" :class="{stealth: item.stealth}" :src="item.stealth ? defaultAvatar : (item.avatar || defaultAvatar)" mode="aspectFill"></image>
@ -60,7 +114,7 @@
</view> </view>
</view> </view>
</view> </view>
<view v-else class="empty-card">暂无上榜居民攒券登顶成为今日主角</view> <view v-else-if="!podiumList.length" class="empty-card">暂无上榜居民攒券登顶成为今日主角</view>
<view v-if="rankList.length" class="load-more">{{loadMoreText}}</view> <view v-if="rankList.length" class="load-more">{{loadMoreText}}</view>
@ -128,6 +182,28 @@
pagedList() { pagedList() {
return this.rankList return this.rankList
}, },
podiumList() {
return this.rankList.filter((item) => item._displayRankNo >= 1 && item._displayRankNo <= 3)
},
podiumMap() {
const map = {}
this.podiumList.forEach((item) => {
map[item._displayRankNo] = item
})
return map
},
podiumFirst() {
return this.podiumMap[1]
},
podiumSecond() {
return this.podiumMap[2]
},
podiumThird() {
return this.podiumMap[3]
},
normalList() {
return this.rankList.filter((item) => item._displayRankNo > 3)
},
loadMoreText() { loadMoreText() {
if (this.listLoading) return '正在加载更多坐标...' if (this.listLoading) return '正在加载更多坐标...'
if (this.noMore) return '没有更多财富坐标了' if (this.noMore) return '没有更多财富坐标了'
@ -210,6 +286,11 @@
if ((this.home.remainHunt || 0) <= 0) return '次数用完' if ((this.home.remainHunt || 0) <= 0) return '次数用完'
return '发起追查' return '发起追查'
}, },
podiumName(item) {
if (!item) return '神秘同学'
if (item.stealth) return '隐身侠'
return item.nickname || '神秘同学'
},
onHunt(item) { onHunt(item) {
if (item.self) { if (item.self) {
this.tui.toast('不能追捕自己') this.tui.toast('不能追捕自己')
@ -299,6 +380,40 @@
.rank-head { margin-top: 30rpx; display: flex; align-items: flex-end; justify-content: space-between; } .rank-head { margin-top: 30rpx; display: flex; align-items: flex-end; justify-content: space-between; }
.rank-title { margin-top: 6rpx; color: #12342F; font-size: 40rpx; font-weight: 900; } .rank-title { margin-top: 6rpx; color: #12342F; font-size: 40rpx; font-weight: 900; }
.rank-page-no { color: #6B817D; font-size: 23rpx; font-weight: 800; } .rank-page-no { color: #6B817D; font-size: 23rpx; font-weight: 800; }
.podium-card { position: relative; margin-top: 22rpx; padding: 30rpx 24rpx 26rpx; border-radius: 46rpx; background: radial-gradient(circle at 50% 8%, rgba(255,184,77,0.42), transparent 36%), linear-gradient(155deg, rgba(30,27,75,0.94), rgba(36,58,84,0.9) 48%, rgba(18,52,47,0.88)); border: 2rpx solid rgba(255,255,255,0.24); box-shadow: 0 30rpx 72rpx rgba(30,27,75,0.24); overflow: hidden; }
.podium-bg-glow { position: absolute; left: 50%; top: -170rpx; width: 620rpx; height: 620rpx; transform: translateX(-50%); border-radius: 50%; background: radial-gradient(circle, rgba(255,214,92,0.38), rgba(255,122,89,0.12) 42%, transparent 68%); animation: podiumPulse 2.4s ease-in-out infinite; }
@keyframes podiumPulse { 0%,100%{ opacity:.58; transform: translateX(-50%) scale(.92); } 50%{ opacity:1; transform: translateX(-50%) scale(1.06); } }
.podium-head { position: relative; z-index: 1; display: flex; justify-content: space-between; gap: 16rpx; align-items: flex-start; }
.podium-kicker { color: rgba(255,214,92,0.86); font-size: 17rpx; font-weight: 900; letter-spacing: 2rpx; }
.podium-title { margin-top: 6rpx; color: #FFFFFF; font-size: 40rpx; font-weight: 900; text-shadow: 0 8rpx 20rpx rgba(0,0,0,0.18); }
.podium-prize { max-width: 210rpx; padding: 10rpx 16rpx; border-radius: 999rpx; background: rgba(255,255,255,0.12); color: #FFE08A; font-size: 19rpx; font-weight: 900; line-height: 1.25; text-align: center; border: 1rpx solid rgba(255,255,255,0.18); }
.reward-rule { position: relative; z-index: 1; margin-top: 20rpx; padding: 18rpx; border-radius: 28rpx; background: linear-gradient(135deg, rgba(255,224,138,0.18), rgba(255,255,255,0.1)); border: 1rpx solid rgba(255,255,255,0.18); box-shadow: inset 0 1rpx 0 rgba(255,255,255,0.18); }
.reward-main { color: #FFF4B8; font-size: 23rpx; font-weight: 900; line-height: 1.35; }
.reward-chips { margin-top: 12rpx; display: flex; flex-wrap: wrap; gap: 10rpx; }
.reward-chips text { padding: 7rpx 12rpx; border-radius: 999rpx; background: rgba(255,255,255,0.16); color: rgba(255,255,255,0.92); font-size: 19rpx; font-weight: 900; }
.podium-stage { position: relative; z-index: 1; margin-top: 28rpx; height: 430rpx; display: flex; align-items: flex-end; justify-content: center; gap: 14rpx; }
.podium-player { position: relative; width: 200rpx; display: flex; flex-direction: column; align-items: center; transition: transform .18s ease; }
.podium-player:active { transform: scale(.96); }
.podium-player.first { width: 222rpx; margin-bottom: 28rpx; }
.podium-player.second { margin-bottom: 0; }
.podium-player.third { margin-bottom: -18rpx; }
.king-aura { position: absolute; top: 22rpx; width: 190rpx; height: 190rpx; border-radius: 50%; background: radial-gradient(circle, rgba(255,214,92,0.48), transparent 68%); animation: kingAura 1.8s ease-in-out infinite; }
@keyframes kingAura { 0%,100%{ transform: scale(.88); opacity:.66; } 50%{ transform: scale(1.08); opacity:1; } }
.crown { position: relative; z-index: 3; width: 62rpx; height: 50rpx; line-height: 50rpx; border-radius: 18rpx 18rpx 10rpx 10rpx; text-align: center; color: #4A2A00; font-size: 28rpx; font-weight: 900; box-shadow: 0 12rpx 24rpx rgba(0,0,0,0.2); transform: translateY(16rpx); }
.crown.gold { background: linear-gradient(145deg, #FFF7B8, #FFB84D); }
.crown.silver { background: linear-gradient(145deg, #FFFFFF, #BFD7FF); color: #28415F; }
.crown.bronze { background: linear-gradient(145deg, #FFE0B8, #C87A35); color: #4A2500; }
.podium-avatar { position: relative; z-index: 2; width: 112rpx; height: 112rpx; border-radius: 38rpx; border: 6rpx solid rgba(255,255,255,0.88); box-shadow: 0 18rpx 36rpx rgba(0,0,0,0.22); background: rgba(255,255,255,0.22); }
.podium-avatar.champion { width: 136rpx; height: 136rpx; border-radius: 46rpx; border-color: #FFE08A; box-shadow: 0 20rpx 46rpx rgba(255,184,77,0.36); animation: championFloat 2.1s ease-in-out infinite; }
@keyframes championFloat { 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-8rpx); } }
.podium-avatar.stealth { opacity: .62; filter: grayscale(100%); }
.podium-name { margin-top: 14rpx; max-width: 178rpx; color: #FFFFFF; font-size: 24rpx; font-weight: 900; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.champion-name { font-size: 28rpx; color: #FFF4B8; }
.podium-ticket { margin-top: 8rpx; padding: 6rpx 14rpx; border-radius: 999rpx; background: rgba(255,255,255,0.14); color: rgba(255,255,255,0.88); font-size: 20rpx; font-weight: 900; }
.podium-ticket.hot { background: linear-gradient(135deg, #FF7A59, #FFB84D); color: #FFFFFF; box-shadow: 0 10rpx 24rpx rgba(255,122,89,0.3); }
.podium-base { margin-top: 16rpx; width: 170rpx; height: 92rpx; line-height: 92rpx; border-radius: 28rpx 28rpx 12rpx 12rpx; text-align: center; color: rgba(255,255,255,0.92); font-size: 24rpx; font-weight: 900; background: linear-gradient(180deg, rgba(255,255,255,0.18), rgba(255,255,255,0.07)); border: 1rpx solid rgba(255,255,255,0.16); }
.podium-base.king { width: 198rpx; height: 126rpx; line-height: 126rpx; color: #4A2A00; font-size: 28rpx; background: linear-gradient(180deg, #FFE08A, #FFB84D); border: 0; box-shadow: inset 0 10rpx 22rpx rgba(255,255,255,0.26), 0 18rpx 36rpx rgba(255,184,77,0.22); }
.podium-tip { position: relative; z-index: 1; margin-top: 16rpx; height: 58rpx; line-height: 58rpx; border-radius: 999rpx; background: rgba(255,255,255,0.12); color: #FFE08A; font-size: 22rpx; font-weight: 900; text-align: center; border: 1rpx solid rgba(255,255,255,0.16); }
.rank-list { margin-top: 18rpx; } .rank-list { margin-top: 18rpx; }
.rank-row { margin-top: 16rpx; padding: 22rpx; border-radius: 34rpx; background: rgba(255,255,255,0.82); border: 2rpx solid rgba(255,255,255,0.94); box-shadow: 0 16rpx 36rpx rgba(53,214,166,0.1); display: flex; align-items: center; } .rank-row { margin-top: 16rpx; padding: 22rpx; border-radius: 34rpx; background: rgba(255,255,255,0.82); border: 2rpx solid rgba(255,255,255,0.94); box-shadow: 0 16rpx 36rpx rgba(53,214,166,0.1); display: flex; align-items: center; }
.rank-no { min-width: 70rpx; color: #22B889; font-size: 28rpx; font-weight: 900; } .rank-no { min-width: 70rpx; color: #22B889; font-size: 28rpx; font-weight: 900; }

2
package1/planet/ticketLog.vue

@ -125,7 +125,7 @@
noMore: false, noMore: false,
raiders: [], raiders: [],
raiderPageNumber: 1, raiderPageNumber: 1,
raiderPageSize: 5, raiderPageSize: 10,
raiderTotal: 0, raiderTotal: 0,
raiderLoading: false, raiderLoading: false,
raiderNoMore: false, raiderNoMore: false,

Loading…
Cancel
Save