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.
 
 
 

619 lines
17 KiB

<script setup>
import { ref, onMounted, computed ,nextTick} from 'vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'
import moment from 'moment'
import API from '@/util/http'
import { writeFile, utils } from 'xlsx'
// 变量
const adminData = ref({})
const getAdminData = async function () {
try {
const result = await API({
url: '/admin/userinfo',
method: 'post',
data: {}
})
adminData.value = result
// console.log('请求成功', result)
console.log('管理员用户信息', adminData.value)
} catch (error) {
console.log('管理员用户信息请求失败', error)
}
}
// 精网号去空格,处理 goldDetail 中的 jwcode
const trimJwCode = () => {
if (goldDetail.value.jwcode) {
goldDetail.value.jwcode = goldDetail.value.jwcode.replace(/\s/g, '');
}
}
//定义平台信息的加载状态
const isLoadingPlatform = ref(false)
// 平台信息
const platform = ref([])
//获取平台信息的函数
const getPlatform = async () => {
isLoadingPlatform.value = true;
try {
const result = await API({
url: 'http://18.143.76.3:10704/general/platform',
method: 'post',
data: {}// 这里添加参数
})
// 假设后端返回的是字符串数组,转换为 { value, label } 格式
if(Array.isArray(result.data)) {
platform.value = result.data.map(item => ({ value: item, label: item }));
} else {
console.error('平台信息格式错误',result)
ElMessage.error('平台信息格式错误,请联系管理员')
}
} catch (error) {
console.error('获取平台信息失败:', error);
ElMessage.error('获取平台信息失败,请稍后重试');
} finally {
isLoadingPlatform.value = false
}
}
// 数量更新类型选项
const type = [
{
value: '0',
label: '充值'
},
{
value: '1',
label: '消耗'
},
{
value: '2',
label: '退款'
}
]
// 定义加载状态,获取地区数据
const isLoadingArea = ref(false);
const market = ref([])
const getArea = async () => {
isLoadingArea.value = true;
try {
const result = await API({
url: 'http://18.143.76.3:10704/general/market'
});
// 假设后端返回的是字符串数组,转换为 { value, label } 格式
if (Array.isArray(result.data) && typeof result.data[0] === 'string') {
market.value = result.data.map(item => ({ value: item, label: item }));
} else {
market.value = result.data;
}
} catch (error) {
console.error('获取地区数据失败:', error);
ElMessage.error('获取地区数据失败,请稍后重试');
// 可以提供默认数据
market.value = [];
} finally {
isLoadingArea.value = false;
}
};
// 充值明细表格
const tableData = ref([])
// 各金币字段变量
// const sumGoldTotal = ref(0)
const permanentGold = ref(0)
//const freeGold = ref(0)
const taskGold = ref(0)
// 搜索===========================================
//分页总条目
const total = ref(100)
// 搜索对象时间
const getTime = ref([])
// 搜索goldDetail
const goldDetail = ref({})
// 搜索对象
const getObj = ref({
pageNum: 1,
pageSize: 50
})
// 开启条件筛选导出excel
// const getPutEX = ref(false)
// 方法
// 搜索===========================================================================
// 搜索方法
const get = async function (val) {
try {
// 地区赋值,这一期需求用不上
// if (adminData.value.market === '泰国') {
// goldDetail.value.markets = ['泰国', '越南']
// } else if (adminData.value.market !== '总部') {
// goldDetail.value.market = adminData.value.market
// }
// 搜索参数页码赋值
if (typeof val === 'number') {
getObj.value.pageNum = val
}
if (getTime.value.length === 2) {//检查是否同时选择了开始时间和结束时间,如果不是则置空
// 使用 YYYY-MM-DD HH:mm:ss 格式
goldDetail.value.startTime = moment(getTime.value[0]).format('YYYY-MM-DD HH:mm:ss');
goldDetail.value.endTime = moment(getTime.value[1]).format('YYYY-MM-DD HH:mm:ss');
} else {
goldDetail.value.startTime = ''
goldDetail.value.endTime = ''
}
// console.log('moment 库是否正确加载:', moment);能正常加载
// 添加排序字段和排序方式到请求参数
goldDetail.value.sortField = sortField.value
goldDetail.value.sortOrder = sortOrder.value
console.log('搜索参数', getObj.value)
// 发送POST请求
// 打印 jwcode 的类型和值,用于调试
console.log('jwcode 类型:', typeof goldDetail.value.jwcode);
console.log('jwcode 值:', goldDetail.value.jwcode);
const requestData = { ...getObj.value, goldDetail: { ...goldDetail.value } };
console.log('最终请求参数', JSON.stringify(requestData, null, 2)); // 打印格式化后的请求参数
//console.log('请求参数', requestData);
const result = await API({
url: 'http://18.143.76.3:10704/goldDetail/getGoldDetail',
method: 'post',
data: { ...getObj.value, goldDetail: { ...goldDetail.value } }
})
console.log('响应数据', result)
tableData.value = result.data.list
total.value = result.data.total
// 更新永久金币、任务金币
permanentGold.value = tableData.value.reduce((total, row) => {
return total + (Number(row. permanentGold) || 0);
}, 0);
taskGold.value = tableData.value.reduce((total, row) => {
return total + (Number(row.taskGold) || 0);
}, 0);
//由于免费金币的计算方式是6月免费+12月免费,所以需要单独处理,以及计算总的免费金币和总的金币数放在一块
} catch (error) {
console.log('请求失败', error)
}
}
// 重置
const reset = function () {
delete goldDetail.value.jwcode
delete goldDetail.value.type
delete goldDetail.value.startTime
delete goldDetail.value.endTime
delete goldDetail.value.market
delete sortField.value
delete sortOrder.value
getTime.value = []
delete goldDetail.value.payPlatform
}
// 搜索,点击查询按钮后触发
const search = function () {
trimJwCode();
getObj.value.pageNum = 1
get()
}
// 今天
const getToday = function () {
const today = moment()
const startTime = today.startOf('day').toDate()
const endTime = today.add(1, 'days').startOf('day').toDate()
getTime.value = [startTime, endTime]
search()
}
// 昨天
const getYesterday = function () {
const today = moment()
const yesterday = moment().subtract(1, 'day')
const startTime = yesterday.startOf('day').toDate()
const endTime = today.startOf('day').toDate()
getTime.value = [startTime, endTime]
search()
}
// 近7天
const get7Days = function () {
const startTime = moment().subtract(6, 'day').startOf('day').toDate()
const endTime = moment().add(1,'days').startOf('day').toDate()
getTime.value = [startTime, endTime]
search()
}
// 计算所有记录的金币总数
const sumGoldTotal = computed(() => {
return tableData.value.reduce((total, row) => {
return total + (Number(row.sumGold) || 0);
}, 0);
});
// 计算每行免费金币6月+12月的方法
const calculateFreeGold = (row) => {
const freeJune = row.freeJune || 0;
const freeDecember = row.freeDecember || 0;
return (freeJune + freeDecember);
};
// 计算总免费金币的计算属性
const totalFreeGold = computed(() => {
return tableData.value.reduce((total, row) => {
return total + calculateFreeGold(row);
}, 0);
});
// 验证页码跳转输入框的数字是否合法
const checkNumber = function () {
if (typeof parseInt(getObj.value.pageNum) === 'number') {
console.log('总共有多少页' + Math.ceil(total.value / getObj.value.pageSize))
if (
getObj.value.pageNum > 0 &&
getObj.value.pageNum <= Math.ceil(total.value / getObj.value.pageSize)
) {
getObj.value.pageNum = parseInt(getObj.value.pageNum)
console.log('输入的数字合法')
get()
} else {
//提示
ElMessage({
type: 'error',
message: '请检查输入内容'
})
}
} else {
//提示
ElMessage({
type: 'error',
message: '请检查输入内容'
})
}
}
// 新增排序字段和排序方式
const sortField = ref('')
const sortOrder = ref('')
// 处理排序事件
const handleSortChange = (column) => {
if (column.prop === 'sumGold') {//新增金币总数字段排序
sortField.value = 'sum_gold'
} else if(column.prop === ' permanentGold') {
sortField.value = 'permanent_gold'
} else if (column.prop === 'taskGold') {
sortField.value = 'task_gold'
} else if (column.prop === 'freeGold') {
sortField.value = 'free_gold'
} else if (column.prop === 'auditTime') {//删除了更新时间的creatTime
sortField.value = 'audit_time'
} else if (column.prop === 'gold') {
sortField.value = 'gold'
}
sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
//get()要写在handleSortChange方法里面,不然会导致排序失效
get()
}
const handlePageSizeChange = function (val) {
getObj.value.pageSize = val
get()
}
const handleCurrentChange = function (val) {
getObj.value.pageNum = val
get()
}
// 挂载
onMounted(async function () {
await get()
await getArea()
await getAdminData()
await getPlatform() // 调用获取平台信息的函数
})
</script>
<template>
<div>
<el-row>
<el-col>
<el-card style="margin-bottom: 20px;margin-top: 10px;">
<el-row style="margin-bottom: 10px">
<el-col :span="5">
<div class="head-card-element">
<el-text class="mx-1" size="large">精网号</el-text>
<el-input
v-model="goldDetail.jwcode"
style="width: 150px"
placeholder="请输入精网号"
clearable
/>
</div>
</el-col>
<el-col :span="6">
<div class="head-card-element">
<el-text class="mx-1" size="large">平台信息:</el-text>
<el-select
v-model="goldDetail.payPlatform"
placeholder="请选择平台信息"
style="width: 160px"
clearable
:loading="isLoadingPlatform"
>
<el-option
v-for="item in platform"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-col>
<el-col :span="7">
<div class="head-card-element">
<el-text class="mx-1" size="large">数量更新类型:</el-text>
<el-select
v-model="goldDetail.type"
placeholder="请选择更新类型"
style="width: 160px"
clearable
>
<el-option
v-for="item in type"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-col>
<el-col :span="6">
<div class="head-card-element">
<el-text class="mx-1" size="large">所属地区</el-text>
<el-select
v-model="goldDetail.market"
placeholder="请选择所属地区"
style="width: 180px"
clearable
:loading="isLoadingArea"
>
<el-option
v-for="item in market"
:key="item.value || item"
:label="item.label || item"
:value="item.value || item"
/>
</el-select>
</div>
</el-col>
</el-row>
<div class="head-card-element">
<el-text class="mx-1" size="large">更新时间:</el-text>
<el-date-picker
v-model="getTime"
type="datetimerange"
range-separator="至"
start-placeholder="起始时间"
end-placeholder="结束时间"
style="margin-right: 50px"
/>
<el-button @click="getToday()">今</el-button>
<el-button @click="getYesterday()">昨</el-button>
<el-button @click="get7Days()">近7天</el-button>
<el-button type="success" @click="reset()">重置</el-button>
<el-button type="primary" @click="search()">查询</el-button>
<el-button type="primary" @click="exportExcel">导出Excel表格</el-button>
</div>
</el-card>
</el-col>
</el-row>
<el-row>
<el-col>
<el-card>
<div>
金币总数:{{ Math.abs(sumGoldTotal) }}
永久金币:{{ Math.abs( permanentGold) }}
免费金币:{{ Math.abs(totalFreeGold) }}
任务金币:{{ Math.abs(taskGold) }}
</div>
<div style="height: 584px; overflow-y: auto">
<el-table
:data="tableData"
style="width: 100%"
@sort-change="handleSortChange"
height="584px"
>
<el-table-column
type="index"
label="序号"
width="100px"
fixed="left"
>
<template #default="scope">
<span>{{
scope.$index + 1 + (getObj.pageNum - 1) * getObj.pageSize
}}</span>
</template>
</el-table-column>
<el-table-column
fixed="left"
prop="name"
label="姓名"
width="150"
/>
<el-table-column
fixed="left"
prop="jwcode"
label="精网号"
width="120"
/>
<el-table-column prop="market" label="所属地区" width="120" />
<el-table-column
prop="payPlatform"
label="平台信息"
width="140"
>
</el-table-column>
<el-table-column prop="type" label="更新类型" width="110">
<template #default="scope">
<span v-if="scope.row.type === 0">充值</span>
<span v-if="scope.row.type === 1">消耗</span>
<span v-if="scope.row.type === 2">退款</span>
</template>
</el-table-column>
<el-table-column
prop="sumGold"
sortable="custom"
label="金币数量"
width="110"
>
<template #default="scope">
<span>
{{
scope.row.type === 1 // 消费类型
? - scope.row.sumGold
: scope.row.sumGold
}}
</span>
</template>
</el-table-column>
<el-table-column
prop=" permanentGold"
sortable="custom"
label="永久金币"
width="110"
>
<template #default="scope">
<span>{{ scope.row. permanentGold }}</span>
</template>
</el-table-column>
<el-table-column
sortable="custom"
label="免费金币"
width="110"
>
<template #default="scope">
<span>{{ calculateFreeGold(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column
prop="taskGold"
sortable="custom"
label="任务金币"
width="110"
>
<template #default="scope">
<span>{{ scope.row.taskGold }}</span>
</template>
</el-table-column>
<el-table-column prop="adminName" label="提交人" width="110" />
<el-table-column
prop="auditTime"
sortable="custom"
label="更新时间"
width="210"
show-overflow-tooltip
>
<template #default="scope">
<span>{{
moment(scope.row.auditTime).format('YYYY-MM-DD HH:mm:ss')
}}</span>
</template>
</el-table-column>
</el-table>
</div>
<!-- 此处分页 -->
<div class="pagination" style="margin-top: 20px">
<el-pagination
background
:page-size="getObj.pageSize"
:page-sizes="[5, 10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handlePageSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<style scoped>
.pagination {
display: flex;
}
.status {
display: flex;
}
.head-card {
display: flex;
}
.info-panel-header {
font-weight: bold;
margin-bottom: 10px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.export-status {
margin-top: 15px;
text-align: center;
color: #666;
}
.el-progress-bar__inner {
transition: width 0.5s ease;
}
</style>