423 lines
10 KiB
Vue
423 lines
10 KiB
Vue
<template>
|
|
<div class="operation-history">
|
|
<!-- 页面标题 -->
|
|
<div class="page-header">
|
|
<div class="header-content">
|
|
<h1>操作历史管理</h1>
|
|
<p>查看和管理系统操作历史记录</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 筛选器 -->
|
|
<el-card class="filter-card">
|
|
<template #header>
|
|
<div class="card-header">
|
|
<el-icon><Filter /></el-icon>
|
|
<span>筛选选项</span>
|
|
</div>
|
|
</template>
|
|
|
|
<el-form :inline="true" :model="filterForm" class="filter-form">
|
|
<el-form-item label="关键词">
|
|
<el-input
|
|
v-model="filterForm.keyword"
|
|
placeholder="搜索详细信息"
|
|
clearable
|
|
@input="handleFilter"
|
|
>
|
|
<template #prefix>
|
|
<el-icon><Search /></el-icon>
|
|
</template>
|
|
</el-input>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="操作模块">
|
|
<div class="custom-select-wrapper">
|
|
<select
|
|
v-model="filterForm.operationModule"
|
|
class="custom-select"
|
|
@change="handleFilter"
|
|
>
|
|
<option value="">全部模块</option>
|
|
<option value="0">会员码管理</option>
|
|
<option value="1">Excel导入</option>
|
|
</select>
|
|
</div>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="操作结果">
|
|
<div class="custom-select-wrapper">
|
|
<select
|
|
v-model="filterForm.operationResult"
|
|
class="custom-select"
|
|
@change="handleFilter"
|
|
>
|
|
<option value="">全部结果</option>
|
|
<option value="成功">成功</option>
|
|
<option value="失败">失败</option>
|
|
</select>
|
|
</div>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleFilter">搜索</el-button>
|
|
<el-button @click="resetFilter">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-card>
|
|
|
|
<!-- 操作历史列表 -->
|
|
<el-card class="history-card">
|
|
<template #header>
|
|
<div class="card-header">
|
|
<el-icon><Clock /></el-icon>
|
|
<span>操作历史列表</span>
|
|
<div class="header-actions">
|
|
<el-button @click="refreshHistory">
|
|
<el-icon><Refresh /></el-icon>
|
|
刷新
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<el-table
|
|
:data="historyList"
|
|
v-loading="loading"
|
|
stripe
|
|
style="width: 100%"
|
|
>
|
|
<el-table-column prop="operationTime" label="操作时间" width="180">
|
|
<template #default="{ row }">
|
|
{{ formatDate(row.operationTime) }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="operationModule" label="操作模块" width="120">
|
|
<template #default="{ row }">
|
|
<el-tag>{{ getModuleText(row.operationModule) }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="operationType" label="操作类型" width="150">
|
|
<template #default="{ row }">
|
|
<el-tag :type="getOperationType(row.operationType)">
|
|
{{ row.operationType }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="userName" label="操作人" width="120">
|
|
<template #default="{ row }">
|
|
{{ row.userName || '-' }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="operationResult" label="操作结果" width="100">
|
|
<template #default="{ row }">
|
|
<el-tag :type="row.operationResult === '成功' ? 'success' : 'danger'">
|
|
{{ row.operationResult }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="operationDetail" label="详细信息" min-width="200">
|
|
<template #default="{ row }">
|
|
{{ row.operationDetail || row.resultMessage || '-' }}
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="pagination-wrapper">
|
|
<el-pagination
|
|
v-model:current-page="pagination.current"
|
|
v-model:page-size="pagination.size"
|
|
:page-sizes="[10, 20, 50]"
|
|
:total="pagination.total"
|
|
layout="total, sizes, prev, pager, next"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handleCurrentChange"
|
|
/>
|
|
</div>
|
|
</el-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import { ElMessage } from 'element-plus'
|
|
import { lotteryApi } from '../../api/index.js'
|
|
import { userStore } from '../../store/user.js'
|
|
|
|
export default {
|
|
name: 'OperationHistory',
|
|
setup() {
|
|
// 筛选表单
|
|
const filterForm = reactive({
|
|
operationModule: '',
|
|
operationResult: '',
|
|
keyword: ''
|
|
})
|
|
|
|
// 操作历史
|
|
const historyList = ref([])
|
|
const loading = ref(false)
|
|
const pagination = reactive({
|
|
current: 1,
|
|
size: 10,
|
|
total: 0
|
|
})
|
|
|
|
// 初始化
|
|
onMounted(() => {
|
|
loadOperationHistory()
|
|
})
|
|
|
|
// 加载操作历史
|
|
const loadOperationHistory = async () => {
|
|
try {
|
|
loading.value = true
|
|
|
|
// 构建查询参数
|
|
const params = {
|
|
operationModule: filterForm.operationModule,
|
|
operationResult: filterForm.operationResult,
|
|
keyword: filterForm.keyword
|
|
}
|
|
|
|
// 调用统一接口获取操作历史
|
|
const response = await lotteryApi.getOperationHistoryList(params)
|
|
console.log('操作历史接口响应:', response)
|
|
|
|
if (response && response.success) {
|
|
// 处理响应数据
|
|
const data = response.data || []
|
|
|
|
// 简单的前端分页
|
|
const startIndex = (pagination.current - 1) * pagination.size
|
|
const endIndex = startIndex + pagination.size
|
|
|
|
historyList.value = data.slice(startIndex, endIndex)
|
|
pagination.total = data.length
|
|
} else {
|
|
ElMessage.error('获取操作历史失败: ' + (response?.message || '未知错误'))
|
|
historyList.value = []
|
|
pagination.total = 0
|
|
}
|
|
} catch (error) {
|
|
console.error('加载操作历史失败:', error)
|
|
ElMessage.error('加载操作历史失败: ' + (error?.message || '未知错误'))
|
|
historyList.value = []
|
|
pagination.total = 0
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 刷新历史
|
|
const refreshHistory = () => {
|
|
pagination.current = 1
|
|
loadOperationHistory()
|
|
}
|
|
|
|
// 筛选处理
|
|
const handleFilter = () => {
|
|
pagination.current = 1
|
|
loadOperationHistory()
|
|
}
|
|
|
|
// 重置筛选
|
|
const resetFilter = () => {
|
|
filterForm.operationModule = ''
|
|
filterForm.operationResult = ''
|
|
filterForm.keyword = ''
|
|
pagination.current = 1
|
|
loadOperationHistory()
|
|
}
|
|
|
|
// 分页处理
|
|
const handleSizeChange = (size) => {
|
|
pagination.size = size
|
|
pagination.current = 1
|
|
loadOperationHistory()
|
|
}
|
|
|
|
const handleCurrentChange = (current) => {
|
|
pagination.current = current
|
|
loadOperationHistory()
|
|
}
|
|
|
|
// 获取操作模块文本
|
|
const getModuleText = (module) => {
|
|
const modules = {
|
|
0: '会员码管理',
|
|
1: 'Excel导入',
|
|
2: '用户管理'
|
|
}
|
|
return modules[module] || '未知模块'
|
|
}
|
|
|
|
// 获取操作类型标签样式
|
|
const getOperationType = (type) => {
|
|
const types = {
|
|
'完整数据导入': 'primary',
|
|
'开奖数据覆盖导入': 'warning',
|
|
'开奖数据追加': 'success',
|
|
'生成会员码': 'info',
|
|
'删除会员码': 'danger'
|
|
}
|
|
return types[type] || 'info'
|
|
}
|
|
|
|
// 格式化日期
|
|
const formatDate = (dateStr) => {
|
|
if (!dateStr) return '-'
|
|
|
|
const date = new Date(dateStr)
|
|
return date.toLocaleString('zh-CN', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
})
|
|
}
|
|
|
|
return {
|
|
filterForm,
|
|
historyList,
|
|
loading,
|
|
pagination,
|
|
handleFilter,
|
|
resetFilter,
|
|
refreshHistory,
|
|
handleSizeChange,
|
|
handleCurrentChange,
|
|
getModuleText,
|
|
getOperationType,
|
|
formatDate
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.operation-history {
|
|
padding: 20px;
|
|
}
|
|
|
|
/* 页面标题 */
|
|
.page-header {
|
|
margin-bottom: 24px;
|
|
background: linear-gradient(135deg, #3a7bd5, #00d2ff);
|
|
padding: 30px;
|
|
border-radius: 8px;
|
|
color: white;
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.header-content h1 {
|
|
font-size: 28px;
|
|
font-weight: 600;
|
|
color: white;
|
|
margin-bottom: 8px;
|
|
text-align: center;
|
|
}
|
|
|
|
.header-content p {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
font-size: 16px;
|
|
margin: 0;
|
|
text-align: center;
|
|
}
|
|
|
|
/* 卡片样式 */
|
|
.filter-card, .history-card {
|
|
margin-bottom: 24px;
|
|
border: none;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.card-header .el-icon {
|
|
font-size: 18px;
|
|
color: #409EFF;
|
|
}
|
|
|
|
.header-actions {
|
|
margin-left: auto;
|
|
}
|
|
|
|
/* 筛选表单 */
|
|
.filter-form {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 16px;
|
|
}
|
|
|
|
/* 自定义下拉框样式 */
|
|
.custom-select-wrapper {
|
|
position: relative;
|
|
width: 100%;
|
|
min-width: 160px;
|
|
}
|
|
|
|
.custom-select {
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
background-color: white;
|
|
font-size: 14px;
|
|
color: #606266;
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23606266'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 8px center;
|
|
background-size: 16px;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.custom-select:hover {
|
|
border-color: #c0c4cc;
|
|
}
|
|
|
|
.custom-select:focus {
|
|
outline: none;
|
|
border-color: #409eff;
|
|
}
|
|
|
|
/* 分页 */
|
|
.pagination-wrapper {
|
|
margin-top: 20px;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 768px) {
|
|
.operation-history {
|
|
padding: 15px;
|
|
}
|
|
|
|
.filter-form {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.filter-form .el-form-item {
|
|
margin-right: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
.header-actions {
|
|
margin-top: 8px;
|
|
margin-left: 0;
|
|
}
|
|
}
|
|
</style> |