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
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>
|