| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- <template>
- <div class="points-log admin-page">
- <el-card>
- <div slot="header" class="admin-page-header">
- <span class="admin-page-title">积分记录</span>
- <div class="admin-page-actions">
- <el-select v-model="filter.type" placeholder="类型筛选" size="mini" clearable @change="loadData">
- <el-option label="全部" value="" />
- <el-option label="任务奖励" value="task" />
- <el-option label="系统调整" value="adjust" />
- <el-option label="兑换扣除" value="exchange" />
- <el-option label="退款返还" value="refund" />
- <el-option label="超时扣分" value="timeout" />
- </el-select>
- <el-select v-model="filter.category" placeholder="分类筛选" size="mini" clearable @change="loadData">
- <el-option label="全部" value="" />
- <el-option label="任务积分" value="task" />
- <el-option label="系统积分" value="system" />
- </el-select>
- <el-input v-model="filter.childKeyword" placeholder="搜索孩子 ID..." prefix-icon="el-icon-search" size="mini" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
- </div>
- </div>
- <div class="table-scroll-wrap-sm">
- <el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
- <el-table-column prop="createdAt" label="时间" width="160">
- <template slot-scope="{ row }">{{ formatTime(row.createdAt) }}</template>
- </el-table-column>
- <el-table-column prop="childId" label="孩子ID" width="80" />
- <el-table-column label="类型" width="100">
- <template slot-scope="{ row }">{{ typeLabel(row.type) }}</template>
- </el-table-column>
- <el-table-column label="分类" width="100">
- <template slot-scope="{ row }">
- <el-tag :type="row.category === 'task' ? 'success' : 'warning'" size="mini">
- {{ row.category === 'task' ? '任务积分' : '系统积分' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="变动" width="100">
- <template slot-scope="{ row }">
- <span :style="{ color: row.amount > 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
- {{ row.amount > 0 ? '+' : '' }}{{ row.amount }}
- </span>
- </template>
- </el-table-column>
- <el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
- <el-table-column prop="expireAt" label="过期时间" width="160">
- <template slot-scope="{ row }">
- <span v-if="row.expireAt" :style="{ color: row.expired ? '#999' : '#E6A23C' }">
- {{ formatTime(row.expireAt) }}
- </span>
- <span v-else style="color:#999">永久有效</span>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="200" fixed="right">
- <template slot-scope="{ row }">
- <el-button size="mini" type="primary" @click="handleDetail(row)">详情</el-button>
- <el-dropdown trigger="hover" @command="(cmd) => handleMoreCmd(row, cmd)">
- <el-button size="mini">
- 更多<i class="el-icon-arrow-down el-icon--right"></i>
- </el-button>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="adjust" icon="el-icon-edit">手动调整</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <el-pagination
- v-if="total > 0"
- @size-change="handleSizeChange"
- @current-change="handlePageChange"
- :current-page="filter.page"
- :page-sizes="[10, 20, 50]"
- :page-size="filter.size"
- layout="total, sizes, prev, pager, next, jumper"
- :total="total"
- class="pagination-wrap"
- />
- </el-card>
- <!-- 详情对话框 -->
- <el-dialog title="积分记录详情" :visible.sync="detailVisible" width="500px">
- <div v-if="currentRow" class="detail-content">
- <el-descriptions :column="2" border>
- <el-descriptions-item label="记录ID">{{ currentRow.id }}</el-descriptions-item>
- <el-descriptions-item label="孩子ID">{{ currentRow.childId }}</el-descriptions-item>
- <el-descriptions-item label="类型">{{ typeLabel(currentRow.type) }}</el-descriptions-item>
- <el-descriptions-item label="分类">
- <el-tag :type="currentRow.category === 'task' ? 'success' : 'warning'" size="mini">
- {{ currentRow.category === 'task' ? '任务积分' : '系统积分' }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="变动">
- <span :style="{ color: currentRow.amount > 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
- {{ currentRow.amount > 0 ? '+' : '' }}{{ currentRow.amount }}
- </span>
- </el-descriptions-item>
- <el-descriptions-item label="过期时间">
- {{ currentRow.expireAt ? formatTime(currentRow.expireAt) : '永久有效' }}
- </el-descriptions-item>
- <el-descriptions-item label="描述" :span="2">{{ currentRow.description || '—' }}</el-descriptions-item>
- <el-descriptions-item label="创建时间" :span="2">{{ formatTime(currentRow.createdAt) }}</el-descriptions-item>
- </el-descriptions>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- import { getPointsLogs } from '@/api/admin'
- const TYPE_MAP = {
- task: { label: '任务奖励', type: 'success' },
- adjust: { label: '系统调整', type: 'warning' },
- exchange: { label: '兑换扣除', type: 'danger' },
- refund: { label: '退款返还', type: 'info' },
- timeout: { label: '超时扣分', type: 'danger' }
- }
- export default {
- name: 'PointsLog',
- computed: {
- tableHeight() {
- return window.innerHeight - 300
- }
- },
- data() {
- return {
- loading: false,
- list: [],
- total: 0,
- filter: {
- type: '',
- category: '',
- childKeyword: '',
- page: 1,
- size: 10
- },
- detailVisible: false,
- currentRow: null
- }
- },
- created() {
- this.loadData()
- },
- methods: {
- typeLabel(type) {
- return (TYPE_MAP[type] && TYPE_MAP[type].label) || type || '—'
- },
- formatTime(t) {
- if (!t) return '-'
- return t.replace ? t.replace('T', ' ').substring(0, 19) : t
- },
- async loadData() {
- this.loading = true
- try {
- const params = {
- page: this.filter.page,
- size: this.filter.size
- }
- if (this.filter.type) params.type = this.filter.type
- if (this.filter.category) params.category = this.filter.category
- if (this.filter.childKeyword) {
- const childId = parseInt(this.filter.childKeyword)
- if (!isNaN(childId)) params.memberId = childId
- }
- const res = await getPointsLogs(params)
- this.list = (res.data && res.data.records) || []
- this.total = (res.data && res.data.total) || 0
- } catch (e) {
- this.$message && this.$message.error && this.$message.error('加载积分记录失败')
- } finally {
- this.loading = false
- }
- },
- handleSizeChange(size) {
- this.filter.size = size
- this.filter.page = 1
- this.loadData()
- },
- handlePageChange(page) {
- this.filter.page = page
- this.loadData()
- },
- handleSearch() {
- this.filter.page = 1
- this.loadData()
- },
- handleDetail(row) {
- this.currentRow = row
- this.detailVisible = true
- },
- handleMoreCmd(row, cmd) {
- switch (cmd) {
- case 'adjust':
- this.$message.info('请在 "积分管理" 页面中对指定孩子进行积分调整')
- break
- }
- }
- }
- }
- </script>
- <style scoped>
- .points-log { padding: 20px; }
- .detail-content { padding: 10px 0; }
- </style>
|