You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
9.0 KiB

1 week ago
<template>
<view class="tl" :style="{'--sb': statusBarHeight + 'px'}">
<view class="tl-bg"></view>
<view class="nav" :style="{paddingTop: statusBarHeight + 'px'}">
<view class="nav-back" @tap="goBack"><text class="nav-back-icon"></text></view>
<view class="nav-title">星球券明细</view>
</view>
<scroll-view scroll-y class="tl-scroll" :style="{paddingTop: (statusBarHeight + 44) + 'px'}"
@scrolltolower="loadMore">
<!-- 汇总卡片 -->
<view class="tl-sum">
<view class="tl-sum-glow"></view>
<view class="tl-sum-label">当前持有星球券</view>
<view class="tl-sum-value">
<text class="tl-sum-num">{{balance}}</text>
<text class="tl-sum-unit"></text>
</view>
<view class="tl-sum-tip">星球券永久有效囤越多瓜分越多</view>
</view>
<!-- 骨架屏 -->
<view v-if="loading && list.length===0" class="tl-sk">
<view class="tl-sk-item" v-for="n in 6" :key="n"></view>
</view>
<!-- 明细列表 -->
<view v-else-if="list.length" class="tl-list">
<view class="tl-item" v-for="(item, i) in list" :key="i">
<view class="tl-icon" :class="'t-'+(item.type||'other')">{{typeIcon(item.type)}}</view>
<view class="tl-mid">
<text class="tl-name">{{item.remark || typeName(item.type)}}</text>
<text class="tl-time">{{item.createTime}}</text>
</view>
<view class="tl-right">
<text class="tl-change" :class="item.changeCount >= 0 ? 'up' : 'down'">
{{item.changeCount >= 0 ? '+' : ''}}{{item.changeCount}}
</text>
<text class="tl-balance"> {{item.balance}}</text>
</view>
</view>
<view class="tl-foot">
<text v-if="loading">加载中</text>
<text v-else-if="noMore"> 没有更多了 </text>
<text v-else @tap="loadMore">点击加载更多</text>
</view>
</view>
<!-- 空态 -->
<view v-else class="tl-empty">
<text class="tl-empty-icon">NO LOG</text>
<text class="tl-empty-text">还没有星球券记录</text>
<text class="tl-empty-tip">完成任务下单邀请好友都能获得星球券</text>
</view>
<view style="height:60rpx;"></view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 20,
userId: '',
regionId: '',
balance: 0,
list: [],
pageNumber: 1,
pageSize: 15,
total: 0,
loading: false,
noMore: false
}
},
onLoad() {
const sys = uni.getSystemInfoSync()
this.statusBarHeight = sys.statusBarHeight || 20
this.userId = uni.getStorageSync('id') || ''
try {
const area = uni.getStorageSync('area')
if (area) this.regionId = JSON.parse(area).id || ''
} catch (e) {}
this.loadPage(true)
},
methods: {
loadPage(reset) {
if (this.loading) return
if (!this.userId) {
this.tui.toast('请先登录')
return
}
if (reset) {
this.pageNumber = 1
this.noMore = false
}
this.loading = true
this.tui.request('/app/planet/ticket/log', 'POST', {
userId: this.userId,
regionId: this.regionId,
pageNumber: this.pageNumber,
pageSize: this.pageSize
}, false, false, true).then((res) => {
this.loading = false
if (res.code == 200 && res.result) {
const records = res.result.records || []
this.total = res.result.total || 0
if (reset) {
this.list = records
// 取最新一条余额作为当前持有
if (records.length) this.balance = records[0].balance
} else {
this.list = this.list.concat(records)
}
if (this.list.length >= this.total || records.length < this.pageSize) {
this.noMore = true
}
}
}).catch(() => {
this.loading = false
})
},
loadMore() {
if (this.loading || this.noMore) return
this.pageNumber++
this.loadPage(false)
},
typeIcon(type) {
const map = {
order: '食', group: '团', invite: '邀', sign: '签',
box: '盒', hunt: '追', buff: '能', draw: '奖'
}
return map[type] || '券'
},
typeName(type) {
const map = {
order: '外卖订单', group: '团购订单', invite: '邀请好友', sign: '每日签到',
box: '幸运宝箱', hunt: '星际追捕', buff: '购买增益', draw: '开奖瓜分'
}
return map[type] || '星球券变动'
},
goBack() {
uni.navigateBack({ delta: 1 })
}
}
}
</script>
<style lang="scss" scoped>
.tl {
min-height: 100vh;
background: linear-gradient(155deg, #F3FFF4 0%, #EAF8FF 48%, #F7EEFF 100%);
color: #12342F;
}
.tl-bg {
position: fixed;
top: 0; left: 0; right: 0; height: 520rpx;
background:
radial-gradient(circle at 78% 14%, rgba(53,214,166,0.26), transparent 44%),
radial-gradient(circle at 18% 32%, rgba(143,124,255,0.18), transparent 42%);
pointer-events: none;
}
.nav {
position: fixed;
top: 0; left: 0; right: 0;
height: 44px;
z-index: 20;
display: flex;
align-items: flex-end;
justify-content: center;
background: linear-gradient(180deg, rgba(243,255,244,0.9), rgba(243,255,244,0));
}
.nav-back {
position: absolute;
left: 20rpx;
bottom: 0;
height: 44px;
width: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nav-back-icon { color: #12342F; font-size: 48rpx; font-weight: 300; }
.nav-title {
color: #12342F;
font-size: 34rpx;
font-weight: 800;
letter-spacing: 1rpx;
padding-bottom: 6rpx;
}
.tl-scroll {
height: 100vh;
box-sizing: border-box;
padding: 0 28rpx;
}
/* 汇总卡 */
.tl-sum {
position: relative;
margin-top: 20rpx;
padding: 48rpx 40rpx 40rpx;
border-radius: 44rpx;
background: linear-gradient(150deg, rgba(255,255,255,0.9), rgba(226,255,241,0.7));
border: 2rpx solid rgba(255,255,255,0.92);
overflow: hidden;
box-shadow: 0 24rpx 62rpx rgba(53,214,166,0.14);
}
.tl-sum-glow {
position: absolute;
top: -120rpx; right: -80rpx;
width: 320rpx; height: 320rpx;
background: radial-gradient(circle, rgba(53,214,166,0.28), transparent 65%);
animation: tl-pulse 3s ease-in-out infinite;
}
@keyframes tl-pulse {
0%, 100% { transform: scale(0.85); opacity: 0.55; }
50% { transform: scale(1.1); opacity: 0.95; }
}
.tl-sum-label {
position: relative;
color: #42635E;
font-size: 26rpx;
font-weight: 700;
}
.tl-sum-value {
position: relative;
margin-top: 12rpx;
display: flex;
align-items: baseline;
}
.tl-sum-num {
font-size: 84rpx;
font-weight: 800;
color: #22B889;
font-family: DIN, Arial, sans-serif;
}
.tl-sum-unit {
margin-left: 12rpx;
font-size: 28rpx;
color: #42635E;
}
.tl-sum-tip {
position: relative;
margin-top: 16rpx;
font-size: 24rpx;
color: #7E9691;
}
/* 骨架 */
.tl-sk { margin-top: 28rpx; }
.tl-sk-item {
height: 120rpx;
border-radius: 22rpx;
margin-bottom: 20rpx;
background: linear-gradient(90deg, rgba(255,255,255,0.45) 25%, rgba(255,255,255,0.9) 37%, rgba(255,255,255,0.45) 63%);
background-size: 400% 100%;
animation: tl-shimmer 1.4s ease infinite;
}
@keyframes tl-shimmer {
0% { background-position: 100% 50%; }
100% { background-position: 0 50%; }
}
/* 列表 */
.tl-list { margin-top: 28rpx; }
.tl-item {
display: flex;
align-items: center;
padding: 26rpx 24rpx;
margin-bottom: 18rpx;
border-radius: 30rpx;
background: rgba(255,255,255,0.74);
border: 2rpx solid rgba(255,255,255,0.92);
box-shadow: 0 12rpx 30rpx rgba(53,214,166,0.08);
}
.tl-icon {
width: 76rpx;
height: 76rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
background: rgba(53,214,166,0.12);
flex-shrink: 0;
}
.tl-icon.t-buff, .tl-icon.t-hunt { background: rgba(255,122,89,0.14); }
.tl-icon.t-draw, .tl-icon.t-box { background: rgba(255,184,77,0.16); }
.tl-mid {
flex: 1;
margin-left: 22rpx;
display: flex;
flex-direction: column;
min-width: 0;
}
.tl-name {
color: #12342F;
font-size: 28rpx;
font-weight: 700;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tl-time {
margin-top: 8rpx;
color: #7E9691;
font-size: 22rpx;
}
.tl-right {
display: flex;
flex-direction: column;
align-items: flex-end;
flex-shrink: 0;
}
.tl-change {
font-size: 34rpx;
font-weight: 700;
font-family: DIN, Arial, sans-serif;
}
.tl-change.up { color: #22B889; }
.tl-change.down { color: #FF7A59; }
.tl-balance {
margin-top: 6rpx;
font-size: 22rpx;
color: #7E9691;
}
.tl-foot {
text-align: center;
color: #7E9691;
font-size: 24rpx;
padding: 24rpx 0 8rpx;
}
/* 空态 */
.tl-empty {
margin-top: 140rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.tl-empty-icon {
width: 180rpx;
height: 180rpx;
line-height: 180rpx;
text-align: center;
border-radius: 50%;
background: rgba(255,255,255,0.72);
border: 2rpx solid rgba(255,255,255,0.92);
color: #35D6A6;
font-size: 28rpx;
font-weight: 900;
letter-spacing: 2rpx;
box-shadow: 0 20rpx 44rpx rgba(53,214,166,0.12);
}
.tl-empty-text { margin-top: 24rpx; color: #42635E; font-size: 30rpx; font-weight: 800; }
.tl-empty-tip { margin-top: 12rpx; color: #7E9691; font-size: 24rpx; }
</style>