Files
jjx-wap-sign-only/pages/ai/points.vue
T

243 lines
5.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page-wrap">
<uititle title="积分管理"></uititle>
<!-- 积分概览 -->
<view class="points-header">
<view class="ph-card main">
<view class="ph-label">可用积分</view>
<view class="ph-value">{{ pointsBalance }}</view>
</view>
<view class="ph-card sub">
<view class="ph-label">累计获得</view>
<view class="ph-value">{{ pointsTotalEarned }}</view>
</view>
</view>
<!-- 充值套餐 -->
<view class="section-title">💎 积分充值</view>
<view class="recharge-grid">
<view v-for="(pkg, i) in rechargePackages" :key="i"
:class="['recharge-card', selectedRecharge === i && 'selected']"
@click="selectedRecharge = i">
<view class="rc-points">{{ pkg.points }}</view>
<view class="rc-price">{{ pkg.price }}</view>
<view v-if="pkg.bonus" class="rc-bonus">{{ pkg.bonus }}</view>
</view>
</view>
<view class="p-20">
<u-button type="primary" shape="circle" @click="doRecharge">
立即充值 {{ rechargePackages[selectedRecharge].price }}({{ rechargePackages[selectedRecharge].points }} 积分)
</u-button>
</view>
<!-- 积分明细 -->
<view class="section-title">📊 积分明细</view>
<view v-if="pointsLogList.length === 0" class="empty-tip">暂无积分记录</view>
<view v-for="(item, i) in pointsLogList" :key="i" class="log-item">
<view class="log-left">
<view class="log-reason">{{ item.reason }}</view>
<view class="log-time">{{ item._add_time_str }}</view>
</view>
<view :class="['log-amount', item.type === 'earn' ? 'green' : 'red']">
{{ item.type === 'earn' ? '+' : '-' }}{{ Math.abs(item.amount) }}
</view>
</view>
</view>
</template>
<script>
import uititle from '@/components/common/title'
import dayjs from 'dayjs'
export default {
components: { uititle },
data() {
return {
pointsBalance: 0,
pointsTotalEarned: 0,
pointsLogList: [],
selectedRecharge: 1,
rechargePackages: [
{ points: 10000, price: '20元', bonus: '' },
{ points: 50000, price: '100元', bonus: '' },
{ points: 100000, price: '200元', bonus: '' },
{ points: 450000, price: '900元', bonus: '' },
{ points: 1000000, price: '2000元', bonus: '' },
{ points: 2000000, price: '4000元', bonus: '' },
]
}
},
onShow() {
this.getPointsBalance()
this.getPointsLog()
},
methods: {
async getPointsBalance() {
const res = await vk.callFunction({ url: 'client/points/kh/getBalance' })
if (res.code === 0 && res.data) {
this.pointsBalance = res.data.balance || 0
this.pointsTotalEarned = res.data.total_earned || 0
}
},
async getPointsLog() {
const res = await vk.callFunction({
url: 'client/points/kh/getLog',
data: { pageIndex: 1, pageSize: 50 }
})
if (res.code === 0 && res.data) {
this.pointsLogList = (res.data.rows || []).map(r => ({
...r,
_add_time_str: dayjs(r._add_time && r._add_time['$date'] ? r._add_time['$date'] : r._add_time).format('YYYY-MM-DD HH:mm')
}))
}
},
async doRecharge() {
const pkg = this.rechargePackages[this.selectedRecharge]
const priceMap = {
'20元': 2000, '100元': 10000, '200元': 20000,
'900元': 90000, '2000元': 200000, '4000元': 400000
}
const price = priceMap[pkg.price] || 2000
const res = await vk.callFunction({
url: 'client/points/kh/createOrder',
data: { points: pkg.points, price }
})
if (res.code === 0 && res.data) {
uni.navigateTo({ url: '/pages/shop/pay?id=' + res.data })
} else {
uni.showToast({ title: res.msg || '创建订单失败', icon: 'none' })
}
}
}
}
</script>
<style lang="scss" scoped>
.page-wrap {
min-height: 100vh;
background: #f5f5f5;
}
.points-header {
display: flex;
gap: 20rpx;
padding: 30rpx;
}
.ph-card {
flex: 1;
padding: 30rpx;
border-radius: 16rpx;
color: #fff;
text-align: center;
}
.ph-card.main {
background: linear-gradient(135deg, #a92924, #d4574e);
}
.ph-card.sub {
background: linear-gradient(135deg, #333, #666);
}
.ph-label {
font-size: 24rpx;
opacity: 0.85;
}
.ph-value {
font-size: 48rpx;
font-weight: 700;
margin-top: 8rpx;
}
.section-title {
font-size: 30rpx;
font-weight: 600;
padding: 20rpx 30rpx 10rpx;
}
.recharge-grid {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
padding: 0 30rpx;
}
.recharge-card {
flex: 0 0 calc(33.33% - 12rpx);
padding: 24rpx 0;
text-align: center;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
background: #fff;
position: relative;
}
.recharge-card.selected {
border-color: #a92924;
background: #fdf0f0;
}
.rc-points {
font-size: 32rpx;
font-weight: 700;
color: #333;
}
.rc-price {
font-size: 24rpx;
color: #999;
margin-top: 4rpx;
}
.rc-bonus {
position: absolute;
top: -2rpx;
right: -2rpx;
background: #a92924;
color: #fff;
font-size: 18rpx;
padding: 2rpx 10rpx;
border-radius: 0 10rpx 0 10rpx;
}
.log-item {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #f0f0f0;
}
.log-left {
flex: 1;
}
.log-reason {
font-size: 28rpx;
color: #333;
}
.log-time {
font-size: 22rpx;
color: #999;
margin-top: 4rpx;
}
.log-amount {
font-size: 32rpx;
font-weight: 600;
}
.log-amount.green { color: #67c23a; }
.log-amount.red { color: #f56c6c; }
.empty-tip {
text-align: center;
padding: 60rpx 0;
color: #999;
font-size: 26rpx;
}
</style>