金币系统前端
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.
 
 
 

1680 lines
50 KiB

<script setup>
import * as echarts from 'echarts'
import { ref, onMounted, reactive, computed } from 'vue'
import { VscInfo } from 'vue-icons-plus/vsc'
import * as bs from 'vue-icons-plus/bs'
import axios, { all } from 'axios'
import API from '@/util/http'
import moment from 'moment'
import * as math from 'mathjs'
import { getTime } from 'element-plus/es/components/countdown/src/utils.mjs'
// 变量
// 加载对象
const loading = ref(true)
const areaRankLoading = ref(true)
// 总览对象
const getSumCoin = ref({})
const statistics = ref({})
// const getYearConsumeCoin = ref({});
// const getDayConsumeCoin = ref({});
// 中间统计图搜索参数
const changeTimeRatio = ref('allDays')
const searchTime = ref([])
// 月份柱状图
const getMiddleBarObj = ref({
updateType: 0
})
const getMiddleBarData = ref({})
const middleTotalRecharge = ref(0)
const middleTotalFree = ref(0)
const middleTotalTask = ref(0)
const middleCategory = ref([])
const middleRecharge = ref([])
const middleFree = ref([])
const middleTask = ref([])
// 地区排名
const getAreaRankObj = ref({
updateType: 0
})
const getMediumArea = ref([])
const areaRank = ref([])
// 金币概览
const option3Data = ref([])
const option4Data = ref([])
const option5Data = ref([])
// 四大学科类别占比
const platformData = ref([])
const allData = ref([])
const ERPData = ref([])
const HCData = ref([])
const LinkData = ref([])
const goldData = ref([])
// 重构工作台,第一个方框类别
const oneData = ref([])
const twoData = ref([])
const threeData = ref([])
// 搜索对象
const goldType = ref('全部类型')
const platform = ref('全部平台')
//默认高亮标签页
const activeName = ref('recharge')
// 金币分类选项
const gold = [
{
value: '全部类型',
label: '全部类型'
},
{
value: '充值金币',
label: '永久金币'
},
{
value: '免费金币',
label: '免费金币'
},
{
value: '任务金币',
label: '任务金币'
}
]
const list = ref([])
const token = localStorage.getItem('token')
let rechargeBar = null
// 方法
// 搜索方法
const get = async function () {
try {
getAreaRank()
getMiddleBar()
// 发送POST请求
// const result1 = await API.post(
// "http://54.251.137.151:10702/statistics/getSumCoin",
// {}
// );
const result2 = await API({ url: '/statistics/a', data: {} })
// const result3 = await API.post(
// "http://54.251.137.151:10702/statistics/getYearConsumeCoin",
// {}
// );
// const result4 = await API.post(
// "http://54.251.137.151:10702/statistics/getDayConsumeCoin",
// {}
// );
// const result5 = await API.post(
// "http://192.168.8.93:10010/statistics/getMediumAreaPay",
// {}
// );
// const result6 = await API.post(
// "http://192.168.8.93:10010/statistics/getMediumAreaConsume",
// {}
// );
// const result7 = await API.post(
// "http://192.168.8.93:10010/statistics/getMediuPayCoin",
// {}
// );
// const result8 = await API.post(
// "http://192.168.8.93:10010/statistics/getMediuConsumeCoin",
// {}
// );
const result9 = await API({ url: '/statistics/b', data: {} })
// 重构的工作台
const result10 = await API({
url: '/One/getOne',
data: {
token: token
}
})
const result11 = await API({
url: '/One/getTwo',
data: {
token: token
}
})
const result12 = await API({
url: '/One/getThree',
data: { token: token }
})
oneData.value = result10
twoData.value = result11
threeData.value = result12
console.log('oneData', oneData.value)
// 将响应结果存储到响应式数据中
// getSumCoin.value = result1.data;
statistics.value = result2.data
// getYearConsumeCoin.value = result3.data;
// getDayConsumeCoin.value = result4.data;
platformData.value = result9.data
// console.log("getSumCoin", getSumCoin.value);
console.log('statistics', statistics.value)
// console.log("getYearConsumeCoin", getYearConsumeCoin.value);
// console.log("getDayConsumeCoin", getDayConsumeCoin.value);
console.log('platformData', platformData.value)
option3Data.value = [
{
value: Math.abs(twoData.value.rechargegold),
name: '永久金币' + ' | ' + formatNum(twoData.value.rechargegold / 100)
},
{
value: Math.abs(twoData.value.freegold),
name: '免费金币' + ' | ' + formatNum(twoData.value.freegold / 100)
},
{
value: Math.abs(twoData.value.taskgold),
name: '任务金币' + ' | ' + formatNum(twoData.value.taskgold / 100)
}
]
option4Data.value = [
{
value: Math.abs(threeData.value.rechargegold),
name:
'永久金币' +
' | ' +
formatNum(Math.abs(threeData.value.rechargegold / 100))
},
{
value: Math.abs(threeData.value.freegold),
name:
'免费金币' +
' | ' +
formatNum(Math.abs(threeData.value.freegold / 100))
},
{
value: Math.abs(threeData.value.taskgold),
name:
'任务金币' +
' | ' +
formatNum(Math.abs(threeData.value.taskgold / 100))
}
]
console.log('option4Data', option4Data.value)
option5Data.value = [
{
value: Math.abs(oneData.value.rechargegold),
name: '永久金币' + ' | ' + formatNum(oneData.value.rechargegold / 100)
},
{
value: Math.abs(oneData.value.freegold),
name: '免费金币' + ' | ' + formatNum(oneData.value.freegold / 100)
},
{
value: Math.abs(oneData.value.taskgold),
name: '任务金币' + ' | ' + formatNum(oneData.value.taskgold / 100)
}
]
console.log('option5Data', option5Data.value)
// 平台数据处理
ERPData.value = [
platformData.value.erpsum
.filter((item) => item.subject == '第一学科')
.map((item) => Math.abs(item.totalERPSum)),
platformData.value.erpsum
.filter((item) => item.subject == '第二学科')
.map((item) => Math.abs(item.totalERPSum)),
platformData.value.erpsum
.filter((item) => item.subject == '第三学科')
.map((item) => Math.abs(item.totalERPSum)),
platformData.value.erpsum
.filter((item) => item.subject == '第四学科')
.map((item) => Math.abs(item.totalERPSum))
]
ERPData.value.forEach((item, index) =>
item == ''
? (ERPData.value[index] = {
value: 0,
name: '第' + (index + 1) + '学科' + 0
})
: (ERPData.value[index] = {
value: item[0],
name: '第' + (index + 1) + '学科' + item[0]
})
)
console.log('ERPData', ERPData.value)
HCData.value = [
platformData.value.homilyChartSum
.filter((item) => item.subject == '第一学科')
.map((item) => Math.abs(item.totalHomilyChartSum)),
platformData.value.homilyChartSum
.filter((item) => item.subject == '第二学科')
.map((item) => Math.abs(item.totalHomilyChartSum)),
platformData.value.homilyChartSum
.filter((item) => item.subject == '第三学科')
.map((item) => Math.abs(item.totalHomilyChartSum)),
platformData.value.homilyChartSum
.filter((item) => item.subject == '第四学科')
.map((item) => Math.abs(item.totalHomilyChartSum))
]
HCData.value.forEach((item, index) =>
item == ''
? (HCData.value[index] = {
value: 0,
name: '第' + (index + 1) + '学科' + 0
})
: (HCData.value[index] = {
value: item[0],
name: '第' + (index + 1) + '学科' + item[0]
})
)
console.log('HCData', HCData.value)
LinkData.value = [
platformData.value.homilyLinkSum
.filter((item) => item.subject == '第一学科')
.map((item) => Math.abs(item.totalHomilyLinkSum)),
platformData.value.homilyLinkSum
.filter((item) => item.subject == '第二学科')
.map((item) => Math.abs(item.totalHomilyLinkSum)),
platformData.value.homilyLinkSum
.filter((item) => item.subject == '第三学科')
.map((item) => Math.abs(item.totalHomilyLinkSum)),
platformData.value.homilyLinkSum
.filter((item) => item.subject == '第四学科')
.map((item) => Math.abs(item.totalHomilyLinkSum))
]
LinkData.value.forEach((item, index) =>
item == ''
? (LinkData.value[index] = {
value: 0,
name: '第' + (index + 1) + '学科' + 0
})
: (LinkData.value[index] = {
value: item[0],
name: '第' + (index + 1) + '学科' + item[0]
})
)
console.log('LinkData', LinkData.value)
goldData.value = [
platformData.value.coinSystemSum
.filter((item) => item.subject == '第一学科')
.map((item) => Math.abs(item.totalCoinSystemSum)),
platformData.value.coinSystemSum
.filter((item) => item.subject == '第二学科')
.map((item) => Math.abs(item.totalCoinSystemSum)),
platformData.value.coinSystemSum
.filter((item) => item.subject == '第三学科')
.map((item) => Math.abs(item.totalCoinSystemSum)),
platformData.value.coinSystemSum
.filter((item) => item.subject == '第四学科')
.map((item) => Math.abs(item.totalCoinSystemSum))
]
goldData.value.forEach((item, index) =>
item == ''
? (goldData.value[index] = {
value: 0,
name: '第' + (index + 1) + '学科' + 0
})
: (goldData.value[index] = {
value: item[0],
name: '第' + (index + 1) + '学科' + item[0]
})
)
console.log('goldData', goldData.value)
allData.value = [
{
value:
Number(ERPData.value[0].value) +
Number(HCData.value[0].value) +
Number(LinkData.value[0].value) +
Number(goldData.value[0].value),
name:
'第一学科' +
(Number(ERPData.value[0].value) +
Number(HCData.value[0].value) +
Number(LinkData.value[0].value) +
Number(goldData.value[0].value))
},
{
value:
Number(ERPData.value[1].value) +
Number(HCData.value[1].value) +
Number(LinkData.value[1].value) +
Number(goldData.value[1].value),
name:
'第二学科' +
(Number(ERPData.value[1].value) +
Number(HCData.value[1].value) +
Number(LinkData.value[1].value) +
Number(goldData.value[1].value))
},
{
value:
Number(ERPData.value[2].value) +
Number(HCData.value[2].value) +
Number(LinkData.value[2].value) +
Number(goldData.value[2].value),
name:
'第三学科' +
(Number(ERPData.value[2].value) +
Number(HCData.value[2].value) +
Number(LinkData.value[2].value) +
Number(goldData.value[2].value))
},
{
value:
Number(ERPData.value[3].value) +
Number(HCData.value[3].value) +
Number(LinkData.value[3].value) +
Number(goldData.value[3].value),
name:
'第四学科' +
(Number(ERPData.value[3].value) +
Number(HCData.value[3].value) +
Number(LinkData.value[3].value) +
Number(goldData.value[3].value))
}
]
loading.value = false
console.log('allData', allData.value)
} catch (error) {
console.log('请求失败', error)
loading.value = false
// 在这里可以处理错误逻辑,比如显示错误提示等
}
}
// 获取中间柱状图数据
const getMiddleBar = async function () {
const result = await API({
url: '/statistics/getCoinTime',
data: getMiddleBarObj.value
})
getMiddleBarData.value = result.data
console.log('getMiddleBarData', getMiddleBarData.value)
// 柱状图数据处理
middleCategory.value = getMiddleBarData.value.map((item) =>
item.day == null ? item.month : item.day.substring(5, 10)
)
middleRecharge.value = getMiddleBarData.value.map((item) =>
Math.abs(item.rechargeSumCoin)
)
middleFree.value = getMiddleBarData.value.map((item) =>
Math.abs(item.freeSumCoin)
)
middleTask.value = getMiddleBarData.value.map((item) =>
Math.abs(item.taskSumCoin)
)
middleTotalRecharge.value = 0
middleTotalFree.value = 0
middleTotalTask.value = 0
middleRecharge.value.forEach((number) => {
middleTotalRecharge.value = math.add(
math.bignumber(middleTotalRecharge.value),
math.bignumber(number)
)
})
middleFree.value.forEach((number) => {
middleTotalFree.value = math.add(
math.bignumber(middleTotalFree.value),
math.bignumber(number)
)
})
middleTask.value.forEach((number) => {
middleTotalTask.value = math.add(
math.bignumber(middleTotalTask.value),
math.bignumber(number)
)
})
console.log('middleCategory', middleCategory.value)
console.log('middleRecharge', middleRecharge.value)
console.log('middleFree', middleFree.value)
console.log('middleTask', middleTask.value)
console.log('middleTotalRecharge', middleTotalRecharge.value)
console.log('middleTotalFree', middleTotalFree.value)
console.log('middleTotalTask', middleTotalTask.value)
if (getMiddleBarObj.value.updateType == 0) {
// 基于准备好的dom,初始化echarts实例
updateChart()
// var recharge = echarts.init(document.getElementById('recharge'))
// const option = {
// tooltip: {
// trigger: 'axis',
// axisPointer: {
// type: 'shadow'
// },
// formatter: function (params) {
// let total = 0
// let content = `${params[0].name}<br/>`
// params.forEach((param) => {
// content += `${param.seriesName}: ${param.value}<br/>`
// total += param.value
// })
// content += `总和: ${total}`
// return content
// }
// },
// legend: {
// right: '-5%',
// orient: 'vertical'
// },
// grid: {
// left: '3%',
// right: '4%',
// bottom: '3%',
// containLabel: true
// },
// xAxis: {
// type: 'category',
// data: middleCategory.value
// },
// yAxis: {
// type: 'value'
// },
// series: [
// {
// name: '永久金币',
// color: '#35e383',
// type: 'bar',
// stack: 'total',
// label: {
// show: false
// },
// emphasis: {
// focus: 'series'
// },
// data: middleRecharge.value
// },
// {
// name: '免费金币',
// color: '#5f8ff5',
// type: 'bar',
// stack: 'total',
// label: {
// show: false
// },
// emphasis: {
// focus: 'series'
// },
// data: middleFree.value
// },
// {
// name: '任务金币',
// color: '#ffe733',
// type: 'bar',
// stack: 'total',
// label: {
// show: false
// },
// emphasis: {
// focus: 'series'
// },
// data: middleTask.value
// }
// ]
// }
// // 使用刚指定的配置项和数据显示图表。
// recharge.setOption(option)
} else {
// 基于准备好的dom,初始化echarts实例
var consume = echarts.init(document.getElementById('consume'))
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
let total = 0
let content = `${params[0].name}<br/>`
params.forEach((param) => {
content += `${param.seriesName}: ${param.value}<br/>`
total += param.value
})
content += `总和: ${total}`
return content
}
},
legend: {
right: '-5%',
orient: 'vertical'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: middleCategory.value
},
yAxis: {
type: 'value'
},
series: [
{
name: '永久金币',
color: '#35e383',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleRecharge.value
},
{
name: '免费金币',
color: '#5f8ff5',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleFree.value
},
{
name: '任务金币',
color: '#ffe733',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleTask.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
consume.setOption(option)
}
}
// 获取门店排名
const getAreaRank = async function () {
const result = await API({
url: '/statistics/getMee',
data: getAreaRankObj.value
})
getMediumArea.value = result.data
console.log('getMediumArea', getMediumArea.value)
if (getAreaRankObj.value.type == '充值金币') {
areaRank.value = getMediumArea.value.map((item) => ({
value: Math.abs(item.rechargeSumCoin).toFixed(2),
name: item.area
}))
} else if (getAreaRankObj.value.type == '免费金币') {
areaRank.value = getMediumArea.value.map((item) => ({
value: Math.abs(item.freeSumCoin).toFixed(2),
name: item.area
}))
} else if (getAreaRankObj.value.type == '任务金币') {
areaRank.value = getMediumArea.value.map((item) => ({
value: Math.abs(item.taskSumCoin).toFixed(2),
name: item.area
}))
} else {
areaRank.value = getMediumArea.value.map((item) => ({
value: Math.abs(item.totalRechargeSum).toFixed(2),
name: item.area
}))
}
areaRank.value.sort((a, b) => b.value - a.value)
areaRankLoading.value = false
console.log('areaRank', areaRank.value)
}
// 金币类型
const findBsComponent = function (index) {
let iconName
if (index < 3) {
iconName = `bs.Bs${index + 1}CircleFill` // 根据index拼接图标名称
} else {
iconName = `bs.Bs${index + 1}Circle` // 根据index拼接图标名称
}
return eval(iconName) // 动态执行图标名称,返回图标组件
}
// 门店排名下拉框
const changeGoldType = function () {
console.log('changeGoldType', goldType.value)
if (goldType.value == '全部类型') {
getAreaRankObj.value.type = ''
} else if (goldType.value == '充值金币') {
getAreaRankObj.value.type = '充值金币'
} else if (goldType.value == '免费金币') {
getAreaRankObj.value.type = '免费金币'
} else if (goldType.value == '任务金币') {
getAreaRankObj.value.type = '任务金币'
}
areaRankLoading.value = true
getAreaRank()
}
// 点击标签页初始化
const handleChange = function () {
if (activeName.value == 'recharge') {
getMiddleBarObj.value.updateType = 0
getAreaRankObj.value.updateType = 0
} else {
getMiddleBarObj.value.updateType = 1
getAreaRankObj.value.updateType = 1
}
getAreaRankObj.value.type = ''
goldType.value = '全部类型'
getMiddleBar()
areaRankLoading.value = true
getAreaRank()
}
// 时间范围控制
const disabledDate = function (date) {
const currentDate = new Date()
const startDate = new Date(
currentDate.getFullYear(),
currentDate.getMonth() - 1,
1
)
const endDate = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0
)
if (date >= startDate && date <= endDate) {
return false
}
return true
}
// 本日
const today = function () {
const current = new Date()
const startDate = new Date(
current.getFullYear(),
current.getMonth(),
current.getDate()
)
const endDate = new Date(
current.getFullYear(),
current.getMonth(),
current.getDate()
)
searchTime.value = [startDate, endDate]
search()
// console.log("searchTime", moment(searchTime.value[0]).format("YYYY-MM-DD") + "至" + moment(searchTime.value[1]).format("YYYY-MM-DD"))
}
// 本周
const thisWeek = function () {
const current = new Date()
const dayOfWeek = current.getDay() // 获取今天是星期几(0 表示周日,1 表示周一,以此类推)
const diff = current.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1) // 计算本周第一天的日期差值
const startDate = new Date(current.getFullYear(), current.getMonth(), diff)
const endDate = new Date()
searchTime.value = [startDate, endDate]
search()
// console.log("searchTime", moment(searchTime.value[0]).format("YYYY-MM-DD") + "至" + moment(searchTime.value[1]).format("YYYY-MM-DD"))
}
// 本月
const thisMonth = function () {
const current = new Date()
const startDate = new Date(current.getFullYear(), current.getMonth(), 1)
const endDate = new Date()
searchTime.value = [startDate, endDate]
search()
// console.log("searchTime", moment(searchTime.value[0]).format("YYYY-MM-DD") + "至" + moment(searchTime.value[1]).format("YYYY-MM-DD"))
}
// 本年
const thisYear = function () {
const current = new Date()
const startDate = new Date(current.getFullYear(), 0, 1)
const endDate = new Date(current.getFullYear(), current.getMonth() + 1, 0)
const year = 1
searchTime.value = [startDate, endDate, year]
search()
// console.log("searchTime", moment(searchTime.value[0]).format("YYYY-MM-DD") + "至" + moment(searchTime.value[1]).format("YYYY-MM-DD"))
}
// 全部
const allTime = function () {
searchTime.value = ['', '']
search()
}
// 时间选择器
const changeTime = function () {
console.log('changeTimeRatio', changeTimeRatio.value)
if (changeTimeRatio.value == 'allDays') {
allTime()
} else if (changeTimeRatio.value == 'week') {
thisWeek()
} else if (changeTimeRatio.value == 'month') {
thisMonth()
} else if (changeTimeRatio.value == 'year') {
thisYear()
} else if (changeTimeRatio.value == 'day') {
today()
}
}
// 根据时间搜索
const search = function () {
console.log(
'searchTime',
moment(searchTime.value[0]).format('YYYY-MM-DD') +
'至' +
moment(searchTime.value[1]).format('YYYY-MM-DD')
)
getMiddleBarObj.value.searchStartTime = moment(searchTime.value[0]).format(
'YYYY-MM-DD'
)
getMiddleBarObj.value.searchEndTime = moment(searchTime.value[1]).format(
'YYYY-MM-DD'
)
if (getMiddleBarObj.value.searchStartTime == 'Invalid date') {
delete getMiddleBarObj.value.searchStartTime
}
if (getMiddleBarObj.value.searchEndTime == 'Invalid date') {
delete getMiddleBarObj.value.searchEndTime
}
console.log('getMiddleBarObj', getMiddleBarObj.value)
getAreaRankObj.value.searchStartTime = moment(searchTime.value[0]).format(
'YYYY-MM-DD'
)
getAreaRankObj.value.searchEndTime = moment(searchTime.value[1]).format(
'YYYY-MM-DD'
)
if (getAreaRankObj.value.searchStartTime == 'Invalid date') {
delete getAreaRankObj.value.searchStartTime
}
if (getAreaRankObj.value.searchEndTime == 'Invalid date') {
delete getAreaRankObj.value.searchEndTime
}
console.log('getAreaRankObj', getAreaRankObj.value)
if (searchTime.value[2] == 1) {
getMiddleBarObj.value.year = searchTime.value[2]
} else {
delete getMiddleBarObj.value.year
}
getMiddleBar()
areaRankLoading.value = true
getAreaRank()
}
// 切换平台
const changePlatform = function () {
console.log('changePlatform', platform.value)
if (platform.value == '全部平台') {
// 基于准备好的dom,初始化echarts实例
var all = echarts.init(document.getElementById('all'))
const option6 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: allData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
all.setOption(option6)
} else if (platform.value == 'ERP') {
// 基于准备好的dom,初始化echarts实例
var ERP = echarts.init(document.getElementById('ERP'))
const option7 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: ERPData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
ERP.setOption(option7)
} else if (platform.value == 'HC') {
// 第4-3个饼状图 基于准备好的dom,初始化echarts实例
var HC = echarts.init(document.getElementById('HC'))
const option8 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: HCData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
HC.setOption(option8)
} else if (platform.value == 'Link') {
// 第4-4个饼状图 基于准备好的dom,初始化echarts实例
var Link = echarts.init(document.getElementById('Link'))
const option9 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: LinkData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
Link.setOption(option9)
} else if (platform.value == '金币系统') {
// 第4-5个饼状图 基于准备好的dom,初始化echarts实例
var gold = echarts.init(document.getElementById('gold'))
const option10 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: goldData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
gold.setOption(option10)
}
}
// 计算属性
// 格式化数字 这是一个方法
const formatNum = function (val) {
if (val === undefined) {
return ''
}
const num = parseFloat(val)
// 判断是否为整数
if (Number.isInteger(num)) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
} else {
// 四舍五入保留两位小数
const roundedVal = num.toFixed(2)
return roundedVal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
}
function updateChart() {
// 第一个柱状图 基于准备好的dom,初始化echarts实例
rechargeBar = echarts.init(document.getElementById('recharge'))
const option1 = {
tooltip: {
trigger: 'axis',
axisPointer: {
// Use axis to trigger tooltip
type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow'
}
},
legend: {
right: 0,
orient: 'vertical'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: middleCategory.value
},
yAxis: {
type: 'value'
},
series: [
{
name: '永久金币',
color: '#35e383',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleRecharge.value
},
{
name: '免费金币',
color: '#5f8ff5',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleFree.value
},
{
name: '任务金币',
color: '#ffe733',
type: 'bar',
stack: 'total',
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: middleTask.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
rechargeBar.setOption(option1)
}
onMounted(async function () {
await get()
updateChart()
// 第一个饼状图 基于准备好的dom,初始化echarts实例
var yearRechargePie = echarts.init(document.getElementById('yearRecharge'))
const option3 = {
tooltip: {
trigger: 'item',
position: ['15%', '-3%'],
formatter: function (params) {
return params.seriesName + '<br/>' + params.name
}
},
legend: {
bottom: '-1%',
left: 'center',
orient: 'vertical'
},
series: [
{
name:
'全年累计金币数(个)\n' +
formatNum(Math.abs(twoData.value.totalgold / 100)),
type: 'pie',
radius: ['60%', '80%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'center',
formatter: '{a}',
fontSize: 15,
fontWeight: 'bold'
},
labelLine: {
show: false
},
data: option3Data.value,
color: ['#57a5ff', '#7f29ff', '#f2d113']
}
]
}
// 使用刚指定的配置项和数据显示图表。
yearRechargePie.setOption(option3)
// 第二个饼状图 基于准备好的dom,初始化echarts实例
var yearConsumePie = echarts.init(document.getElementById('yearConsume'))
const option4 = {
tooltip: {
trigger: 'item',
position: ['15%', '-3%'],
formatter: function (params) {
return params.seriesName + '<br/>' + params.name
}
},
legend: {
bottom: '-1%',
left: 'center',
orient: 'vertical'
},
grid: {
top: '0%' // 设置图表距离容器顶部的距离为10%,使饼图上移
},
series: [
{
name:
'全年累计消耗金币数(个)\n' +
formatNum(Math.abs(threeData.value.consumeGold / 100)),
type: 'pie',
radius: ['60%', '80%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'center',
formatter: '{a}',
fontSize: 15,
fontWeight: 'bold'
},
labelLine: {
show: false
},
data: option4Data.value,
color: ['#57a5ff', '#7f29ff', '#f2d113']
}
]
}
// 使用刚指定的配置项和数据显示图表。
yearConsumePie.setOption(option4)
// 第三个饼状图 基于准备好的dom,初始化echarts实例
var nowGoldPie = echarts.init(document.getElementById('nowGold'))
const option5 = {
tooltip: {
trigger: 'item',
position: ['15%', '-3%'],
formatter: function (params) {
return (
params.seriesName +
'<br/>' +
params.name +
(params.value == oneData.value.freegold
? '</br>6月到期 | ' +
oneData.value.sfreegold / 100 +
' ; 12月到期 | ' +
oneData.value.dfreegold / 100
: '')
)
}
},
legend: {
bottom: '-1%',
left: 'center',
orient: 'vertical'
},
grid: {
top: '10%' // 设置图表距离容器顶部的距离为10%,使饼图上移
},
series: [
{
name:
'当前金币余量(个)\n' +
formatNum(Math.abs(oneData.value.sumgold / 100)),
type: 'pie',
radius: ['60%', '80%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'center',
formatter: '{a}',
fontSize: 15,
fontWeight: 'bold'
},
labelLine: {
show: false
},
data: option5Data.value,
color: ['#57a5ff', '#7f29ff', '#f2d113']
}
]
}
// 使用刚指定的配置项和数据显示图表。
nowGoldPie.setOption(option5)
// 第4-1个饼状图 基于准备好的dom,初始化echarts实例
var all = echarts.init(document.getElementById('all'))
const option6 = {
tooltip: {
trigger: 'item'
},
series: [
{
name: '四大学科类别占比',
type: 'pie',
radius: ['40%', '60%'],
avoidLabelOverlap: false,
data: allData.value
}
]
}
// 使用刚指定的配置项和数据显示图表。
all.setOption(option6)
})
</script>
<template>
<div v-loading="loading">
<el-row :gutter="20">
<el-col :span="6">
<el-card style="height: 260px">
<p>当前金币余量</p>
<p class="head-mid-font">
{{ formatNum(oneData.sumgold / 100) }}
</p>
<p>
<span v-if="oneData.differr > 0">
<div class="comparedWithYesterday">
<span>较前一天 {{ formatNum(oneData.differr / 100) }}</span>
<span
class="red-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="oneData.differr < 0">
<div class="comparedWithYesterday">
<span>较前一天 {{ formatNum(oneData.differr / 100) }}</span>
<span
class="green-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="oneData.differr == 0">
<div class="comparedWithYesterday">
<span>较前一天 {{ formatNum(oneData.differr / 100) }}</span>
<span
class="grey-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
</p>
<template #footer>
<span style="font-size: 15px"
>永久{{ formatNum(oneData.rechargegold / 100) }} 免费{{
formatNum(oneData.freegold / 100)
}}
任务{{ formatNum(oneData.taskgold / 100) }}
</span>
<p style="font-size: 12px">
免费金币:6月到期 |
{{ formatNum(oneData.sfreegold / 100) }} ; 12月到期 |
{{ formatNum(oneData.dfreegold / 100) }}
</p>
</template>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 260px">
<p>全年累计金币数</p>
<p class="head-mid-font">
{{ formatNum(Math.abs(twoData.totalgold / 100)) }}
</p>
<p>
折合新币累计金额
{{ formatNum(Math.abs(twoData.totalcoin / 100)) }}
</p>
<template #footer
>昨日新增
{{ formatNum(Math.abs(twoData.yesterdaytotal / 100)) }}
,其中充值{{
formatNum(Math.abs(twoData.yesterdayrecharge / 100))
}}</template
>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 260px">
<p>全年累计消耗金币数</p>
<p class="head-mid-font">
{{
formatNum(
Math.abs((threeData.consumeGold + threeData.refundCoin) / 100)
)
}}
</p>
<p>
消费
{{ formatNum(Math.abs(threeData.consumeGold / 100)) }}; 退款
{{ formatNum(Math.abs(threeData.refundCoin / 100)) }}
</p>
<template #footer
>昨日新增消耗{{
formatNum(
Math.abs(
threeData.yesterdayGold + threeData.yesterdayrefund !==
undefined &&
threeData.yesterdayGold + threeData.yesterdayrefund !== null
? (threeData.yesterdayGold + threeData.yesterdayrefund) /
100
: 0
)
)
}}
; 消费{{
formatNum(
Math.abs(
threeData.yesterdayGold !== undefined &&
threeData.yesterdayGold !== null
? threeData.yesterdayGold / 100
: 0
)
)
}}
; 退款{{
formatNum(
Math.abs(
threeData.yesterdayrefund !== undefined &&
threeData.yesterdayrefund !== null
? threeData.yesterdayrefund / 100
: 0
)
)
}}</template
>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 260px">
<p>全年累计充值人数</p>
<p class="head-mid-font">
{{ formatNum(Math.abs(statistics.rechargeCount)) }}
</p>
<p style="display: flex">
<span v-if="statistics.weekOverWeekRate > 0">
<div class="comparedWithYesterday">
<span>周同比 {{ statistics.weekOverWeekRate }}%</span>
<span
class="red-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="statistics.weekOverWeekRate < 0">
<div class="comparedWithYesterday">
<span>周同比 {{ statistics.weekOverWeekRate }}%</span>
<span
class="green-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="statistics.weekOverWeekRate == 0">
<div class="comparedWithYesterday">
<span>周同比 {{ statistics.weekOverWeekRate }}%</span>
<span
class="grey-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span v-if="statistics.dayOverDayRate > 0">
<div class="comparedWithYesterday">
<span> 日环比{{ statistics.dayOverDayRate }}%</span>
<span
class="red-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="statistics.dayOverDayRate < 0">
<div class="comparedWithYesterday">
<span> 日环比{{ statistics.dayOverDayRate }}%</span>
<span
class="green-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
<span v-if="statistics.dayOverDayRate == 0">
<div class="comparedWithYesterday">
<span> 日环比{{ statistics.dayOverDayRate }}%</span>
<span
class="grey-triangle"
style="margin: 6px 0px 0px 7px"
></span>
</div>
</span>
</p>
<template #footer
>昨日充值人数{{
formatNum(Math.abs(statistics.rechargeCountYesterday))
}}
,其中首充{{
formatNum(Math.abs(statistics.firstRechargeCountYesterday))
}}人</template
>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-card>
<div style="margin-right: auto; text-align: right">
<el-radio-group
v-model="changeTimeRatio"
style="margin-right: 10px"
@change="changeTime()"
>
<el-radio-button
label="全部"
value="allDays"
style="border-color: white"
/>
<el-radio-button
label="本日"
value="day"
style="border-color: white"
/>
<el-radio-button
label="本周"
value="week"
style="border-color: white"
/>
<el-radio-button
label="本月"
value="month"
style="border-color: white"
/>
<el-radio-button
label="本年"
value="year"
style="border-color: white"
/>
</el-radio-group>
<!-- <el-button text @click="allTime()" dark=true>全部</el-button>
<el-button text @click="today()">今日</el-button>
<el-button text @click="thisWeek()">本周</el-button>
<el-button text @click="thisMonth()">本月</el-button>
<el-button text @click="thisYear()">本年</el-button> -->
<el-date-picker
v-model="searchTime"
type="daterange"
range-separator="→"
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 200px"
:disabled-date="disabledDate"
@change="search"
/>
</div>
<el-tabs
v-model="activeName"
class="demo-tabs"
@tab-change="handleChange"
>
<el-tab-pane label="金币充值" name="recharge">
<div>
合计:永久金币:
<span class="mid-head-font">{{
formatNum(middleTotalRecharge)
}}</span>
,免费金币:
<span class="mid-head-font">{{
formatNum(middleTotalFree)
}}</span>
,任务金币:
<span class="mid-head-font">{{
formatNum(middleTotalTask)
}}</span>
</div>
<div class="bar">
<div id="recharge" style="width: 100%; height: 400px"></div>
<div style="width: 140px">
<div class="goldCategory">
<span>永久金币</span>
</div>
<div class="goldCategory">
<span>免费金币</span>
</div>
<div class="goldCategory">
<span>任务金币</span>
</div>
</div>
<div style="width: 30%">
<div class="ranking-header">
<span style="width: 150px">地区金币充值排名</span>
<el-select
v-model="goldType"
placeholder="请选择金币类型"
size="small"
style="margin-left: auto; width: 25%"
@change="changeGoldType"
>
<el-option
v-for="item in gold"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-loading="areaRankLoading">
<el-scrollbar height="360px">
<div
v-for="(item, index) in areaRank"
:key="item"
class="ranking-item"
>
<!-- <component :is="findBsComponent(index)" /> -->
<span style="width: 15px; text-align: center">{{
index + 1
}}</span>
<span style="margin-left: 10px">{{ item.name }}</span>
<span style="margin-left: auto; margin-right: 10px">{{
formatNum(item.value)
}}</span>
</div>
</el-scrollbar>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="金币消费" name="consume">
<div>
合计:永久金币:
<span class="mid-head-font">{{
formatNum(middleTotalRecharge)
}}</span>
,免费金币:
<span class="mid-head-font">{{
formatNum(middleTotalFree)
}}</span>
,任务金币:
<span class="mid-head-font">{{
formatNum(middleTotalTask)
}}</span>
</div>
<div class="bar">
<div id="consume" style="width: 100%; height: 400px"></div>
<div style="width: 140px">
<div class="goldCategory">
<span>永久金币</span>
</div>
<div class="goldCategory">
<span>免费金币</span>
</div>
<div class="goldCategory">
<span>任务金币</span>
</div>
</div>
<div style="width: 310px">
<div class="ranking-header">
<span style="margin-right: 90px; width: 150px"
>地区金币消费排名</span
>
<el-select
v-model="goldType"
placeholder="请选择金币类型"
size="small"
style="width: 90px"
@change="changeGoldType"
>
<el-option
v-for="item in gold"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-loading="areaRankLoading">
<el-scrollbar height="360px">
<div
v-for="(item, index) in areaRank"
:key="item"
class="ranking-item"
>
<!-- <component :is="findBsComponent(index)" /> -->
<span style="width: 15px; text-align: center">{{
index + 1
}}</span>
<span style="margin-left: 10px">{{ item.name }}</span>
<span style="margin-left: auto; margin-right: 10px">{{
formatNum(item.value)
}}</span>
</div>
</el-scrollbar>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="16">
<el-card>
<template #header>
<div class="card-header">
<span class="tail-head">金币概览</span>
</div>
</template>
<div class="pie">
<div id="yearRecharge" style="width: 400px; height: 450px"></div>
<div id="yearConsume" style="width: 400px; height: 450px"></div>
<div id="nowGold" style="width: 400px; height: 450px"></div>
</div>
</el-card>
</el-col>
<!-- <el-col :span="8">
<el-card>
<template #header>
<div class="card-header" style="display: flex">
<span class="tail-head">四大学科类别占比</span>
<el-radio-group
v-model="platform"
fill="#ffffff"
text-color="#409eff"
size="small"
@change="changePlatform"
style="margin-left: auto"
>
<el-radio-button label="全部平台" value="全部平台" />
<el-radio-button label="ERP" value="ERP" />
<el-radio-button label="HC" value="HC" />
<el-radio-button label="Link" value="Link" />
<el-radio-button label="金币系统" value="金币系统" />
</el-radio-group>
</div>
</template>
<span v-if="platform == '全部平台'">
<div id="all" style="width: 500px; height: 450px"></div>
</span>
<span v-if="platform == 'ERP'">
<div id="ERP" style="width: 500px; height: 450px"></div>
</span>
<span v-if="platform == 'HC'">
<div id="HC" style="width: 500px; height: 450px"></div>
</span>
<span v-if="platform == 'Link'">
<div id="Link" style="width: 500px; height: 450px"></div>
</span>
<span v-if="platform == '金币系统'">
<div id="gold" style="width: 500px; height: 400px"></div>
</span>
</el-card>
</el-col> -->
</el-row>
</div>
</template>
<style scoped>
.medium-button {
display: flex;
}
.head-mid-font {
font-size: 20px;
font-weight: bold;
}
.mid-head-font {
font-weight: bold;
color: #5eb7ff;
}
.tail-head {
font-weight: bold;
}
.comparedWithYesterday {
display: flex;
}
.ranking-item {
margin-bottom: 10px;
display: flex;
}
.ranking-header {
margin-bottom: 10px;
display: flex;
}
.goldCategory {
margin-bottom: 4px;
margin-right: 20px;
display: flex;
}
.bar {
display: flex;
}
.pie {
display: flex;
}
.el-row {
margin-bottom: 20px;
}
.el-radio-button {
border: 1px solid grey;
}
</style>