Files
MrleeAdmin/app/pages/member/components/points/index.vue
T

200 lines
5.1 KiB
Vue
Raw Normal View History

2026-04-07 11:01:11 +08:00
<template>
<div class="member-points">
<h2 class="page-title">{{ t('member.points.page_title') }}</h2>
<el-card class="points-card">
<div class="points-summary">
<el-row :gutter="20">
<el-col :span="8">
<div class="points-item">
<div class="points-label">{{ t('member.points.current_points') }}</div>
<div class="points-value">{{ pointsTotal.current_points }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="points-item">
<div class="points-label">{{ t('member.points.monthly_points') }}</div>
<div class="points-value">{{ pointsTotal.monthly_points }}</div>
</div>
</el-col>
<el-col :span="8">
<div class="points-item">
<div class="points-label">{{ t('member.points.total_points') }}</div>
<div class="points-value">{{ pointsTotal.total_points }}</div>
</div>
</el-col>
</el-row>
</div>
<div class="points-list">
<el-table :data="pointsRecords" style="width: 100%" v-loading="loading">
<el-table-column prop="id" :label="t('member.points.record_id')" width="200" />
<el-table-column prop="type" :label="t('member.points.type')" width="120">
<template #default="scope">
<el-tag :type="scope.row.type === 1 ? 'success' : 'danger'">
{{ scope.row.type === 1 ? t('member.points.type_earn') : t('member.points.type_deduct') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="points" :label="t('member.points.points')" width="100">
<template #default="scope">
<span :class="scope.row.type === 1 ? 'text-success' : 'text-danger'">
{{ scope.row.type === 1 ? '+' : '-' }}{{ scope.row.points }}
</span>
</template>
</el-table-column>
<el-table-column prop="remark" :label="t('member.points.reason')" />
<el-table-column prop="created_at" :label="t('member.points.time')" width="180">
<template #default="scope">
{{ timeFormat(scope.row.created_at, 'yyyy-mm-dd hh:MM:ss') }}
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { getPointTransactions, getMemberPointsTotal } from '~/api/member'
import { timeFormat } from '~/utils/common'
// 积分概览数据
const pointsTotal = reactive({
current_points: 0,
monthly_points: 0,
total_points: 0
})
// 分页数据
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const loading = ref(false)
// 积分记录数据
const pointsRecords = ref([])
// 获取积分总额
const fetchPointsTotal = async () => {
try {
const res: any = await getMemberPointsTotal()
if (res) {
pointsTotal.current_points = res.current_points || 0
pointsTotal.monthly_points = res.monthly_points || 0
pointsTotal.total_points = res.total_points || 0
}
} catch (error) {
console.error('获取积分总额失败', error)
}
}
// 获取积分记录
const fetchPointsRecords = async () => {
loading.value = true
try {
const res: any = await getPointTransactions({
page: currentPage.value,
limit: pageSize.value
})
if (res) {
pointsRecords.value = res.items || []
total.value = res.total || 0
}
} catch (error) {
console.error('获取积分记录失败', error)
} finally {
loading.value = false
}
}
// 分页方法
const handleSizeChange = (size: number) => {
pageSize.value = size
fetchPointsRecords()
}
const handleCurrentChange = (current: number) => {
currentPage.value = current
fetchPointsRecords()
}
// 初始化
onMounted(() => {
fetchPointsTotal()
fetchPointsRecords()
})
</script>
<style scoped>
.member-points {
padding: 20px;
}
.page-title {
font-size: 20px;
font-weight: 600;
margin-bottom: 20px;
color: #333;
}
.points-card {
margin-bottom: 20px;
border: none !important;
box-shadow: none !important;
padding: 30px;
border-radius: 4px;
/* background-color: #ffffff; */
}
.points-summary {
margin-bottom: 30px;
padding: 20px;
background-color: #f5f7fa;
border-radius: 8px;
}
.points-item {
text-align: center;
}
.points-label {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.points-value {
font-size: 24px;
font-weight: 600;
color: #333;
}
.points-list {
margin-top: 20px;
}
.pagination {
margin-top: 20px;
text-align: right;
}
.text-success {
color: #67c23a;
}
.text-danger {
color: #f56c6c;
}
</style>