kakapay后台管理系统
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.
 
 
 
 

375 lines
12 KiB

<template>
<data-view-layout
title="卡卡数据可视化"
identifier="KK- MANAGE"
:icon="icon"
@leave="handleLeave"
@audioStatus="toggleMute"
:isMute="isMute"
ref="layout"
>
<template #charts>
<data-view-echart :config="chart1"/>
<data-view-echart :config="chart2"/>
<data-view-echart :config="chart3"/>
<data-view-echart :config="chart4"/>
</template>
<template #left-table>
<data-view-table
title="商户数据"
:columnSizes="[20, 20, 20, 20, 20]"
:columns="[
{label: '商户名称', key: 'username'},
{label: '余额', key: 'balance'},
{label: '剩余额度', key: 'residueBalance'},
{label: '成功金额', key: 'collectionSuccessPrice'},
{label: '成功率', key: 'percentage'},
]"
:data="data1"
size="middle"
ref="table1"
/>
</template>
<template #middle-table>
<data-view-table
title="在线卡商数据"
:columnSizes="[25, 25, 25, 25]"
:columns="[
{label: '卡商名称', key: 'username'},
{label: '剩余押金/固定押金', key: 'dayMargin'},
{label: '冻结', key: 'frozenAmount'},
{label: '日总跑量', key: 'toDayTotal'},
]"
:data="data3"
size="middle"
ref="table3"
>
<template #dayMargin="{row}">
<div class="day-margin-row">
<span>{{ row.margin }}</span>
<span>{{ row.dayMargin }}</span>
</div>
</template>
</data-view-table>
</template>
<template #right-table>
<data-view-table
title="在线卡数据"
:columnSizes="[14.2,14.2,14.2,14.2,14.2,14.2,14.2,]"
:columns="[
{label: '银行名称', key: 'bankName'},
{label: '姓名', key: 'cardHolder'},
{label: '卡商名称', key: 'username'},
{label: '已收款', key: 'todayIncomeReceived'},
{label: '剩余额度', key: 'todayRemainingAmount'},
{label: '余额', key: 'remainingAmount'},
{label: '通道', key: 'channels'},
]"
:data="data2"
size="large"
ref="table2"
>
<template #channels="{row}">
<horizontal-scroll-pane>
<span v-for="channelName of row.channels" :key="channelName">
{{ channelName }}
</span>
</horizontal-scroll-pane>
</template>
</data-view-table>
</template>
</data-view-layout>
</template>
<script>
import DataViewBG from '@/assets/images/data-view-bg.png'
import DataViewEchart from './components/data-view-echart.vue'
import DataViewLayout from './components/data-view-layout.vue'
import icon from '@/assets/logo/plain.png'
import DataViewTable from './components/data-view-table.vue'
import { amountFormat, amountFriendlyFormat, sortBy } from '@/utils/ruoyi'
import screenfull from 'screenfull'
import HorizontalScrollPane from './components/horizontal-scroll-pane.vue'
import Constants from '@/utils/constants'
export default {
components: { HorizontalScrollPane, DataViewTable, DataViewLayout, DataViewEchart },
data() {
return {
DataViewBG,
icon,
// 商户数据
data1: [],
// 在线卡数据
data2: [],
// 在线卡商数据
data3: [],
// 图表-代收成功单数/代收总单数
chart1: {
value: 0,
total: 0,
unit: '单',
// 进度条主色(渐变色), 由左到右
progressBar: ['#4494FF', '#B04BFF'],
// 进度条背景色
progressBarBG: '#091560',
// 两边透明的圆边颜色, 第一个浅色, 第二个深色
circle2Color: ['#168FFF00', '#168FFF'],
// 内圆的渐变, 由内到外
innerCircle: ['#082863', '#082863', '#8000FF68'],
// 透明边框的颜色, 数组第一个为浅色, 第二个为深色
opacityBorder: ['rgba(0, 0, 0, 0)', 'rgba(45, 103, 252, 1)'],
// 投影颜色
shadowColor: '#2d68ffc4',
// 刻度颜色
scaleColor: '#6DCBFF',
// 数值文字
valueLabel: '代收成功单数',
// 总数值文字
totalLabel: '总订单:0'
},
chart2: {
value: 0,
total: 0,
unit: '元',
progressBar: ['#4494FF', '#B04BFF'],
progressBarBG: '#091560',
circle2Color: ['#168FFF00', '#168FFF'],
innerCircle: ['#082863', '#082863', '#8000FF68'],
opacityBorder: ['rgba(0, 0, 0, 0)', 'rgba(45, 103, 252, 1)'],
shadowColor: '#2d68ffc4',
scaleColor: '#6DCBFF',
valueLabel: '代收成功金额',
totalLabel: '总金额:0'
},
chart3: {
value: 0,
total: 0,
unit: '单',
progressBar: ['#42EA9A', '#EFA83E'],
progressBarBG: '#0A2F28',
circle2Color: ['#30BE7900', '#30BE79'],
innerCircle: ['#2EB87642', '#2EB87642', '#2AA56C'],
opacityBorder: ['rgba(0, 0, 0, 0)', '#30C17B'],
shadowColor: '#30C17Bc4',
scaleColor: '#6DCBFF',
valueLabel: '代付成功单数',
totalLabel: '总金额:0'
},
chart4: {
value: 0,
total: 0,
unit: '元',
progressBar: ['#42EA9A', '#EFA83E'],
progressBarBG: '#0A2F28',
circle2Color: ['#30BE7900', '#30BE79'],
innerCircle: ['#2EB87642', '#2EB87642', '#2AA56C'],
opacityBorder: ['rgba(0, 0, 0, 0)', '#30C17B'],
shadowColor: '#30C17Bc4',
scaleColor: '#6DCBFF',
valueLabel: '代付成功金额',
totalLabel: '总金额:0'
},
ws: null,
isScreenFull: false,
// 是否静音
isMute: localStorage.getItem('isMute') === 'true'
}
},
mounted() {
if (this.$route.query.fullscreen) {
this.isScreenFull = true
setTimeout(() => {
this.$nextTick(() => {
screenfull.request()
})
})
}
this.connectWS()
},
methods: {
// 切换静音状态
toggleMute() {
this.isMute = !this.isMute
localStorage.setItem('isMute', this.isMute)
},
connectWS() {
this.ws = new WebSocket(Constants.wsHost)
// `ws://kaka-qws.weirui0755.com/websocket` : "wss://wss.bodabay.com/websocket"
// this.ws = new WebSocket("wss://wss.bodabay.com/websocket")
this.ws.onopen = () => {
this.ws.send(JSON.stringify({ 'type': 'add_push' }))
}
this.ws.onmessage = (event) => {
if (!event.data) {
return
}
let data
try {
data = JSON.parse(event.data)
} catch (e) {
return
}
if (!data || data.type !== 'push') {
return
}
const card = JSON.parse(data.value.card)
const carddealer = JSON.parse(data.value.carddealer)
const statisticsPush = JSON.parse(data.value.statisticsPush)
// payTotalQty 代收总订单数
// paySuccessQty 代收成功订单数
// paySuccessAmount 代收成功金额
// payTotalAmount 代收总金额
// transferTotalQty 代付总订单数
// transferSuccessQty 代付成功订单数
// transferSuccessAmount 代付成功金额
// transferTotalAmount 代付总金额
const chart1Total = amountFriendlyFormat(statisticsPush.payTotalQty)
const chart1Value = amountFriendlyFormat(statisticsPush.paySuccessQty, chart1Total.unit)
this.chart1.value = chart1Value.amount
this.chart1.unit = chart1Value.unit + '单'
this.chart1.total = chart1Total.amount
this.chart1.totalLabel = '总订单:' + chart1Total.display
const payTotalAmount = this.NumberDiv(statisticsPush.payTotalAmount, 100)
const paySuccessAmount = this.NumberDiv(statisticsPush.paySuccessAmount, 100)
const chart2Total = amountFriendlyFormat(payTotalAmount)
const chart2Value = amountFriendlyFormat(paySuccessAmount, chart2Total.unit)
this.chart2.value = chart2Value.amount
this.chart2.unit = chart2Value.unit + '元'
this.chart2.total = chart2Total.amount
this.chart2.totalLabel = '总金额:' + chart2Total.display
const chart3Total = amountFriendlyFormat(statisticsPush.transferTotalQty)
const chart3Value = amountFriendlyFormat(statisticsPush.transferSuccessQty, chart3Total.unit)
this.chart3.value = chart3Value.amount
this.chart3.unit = chart3Value.unit + '单'
this.chart3.total = chart3Total.amount
this.chart3.totalLabel = '总订单:' + chart3Total.display
const transferSuccessAmount = this.NumberDiv(statisticsPush.transferSuccessAmount, 100)
const transferTotalAmount = this.NumberDiv(statisticsPush.transferTotalAmount, 100)
const chart4Total = amountFriendlyFormat(transferTotalAmount)
const chart4Value = amountFriendlyFormat(transferSuccessAmount, chart4Total.unit)
this.chart4.value = chart4Value.amount
this.chart4.unit = chart4Value.unit + '元'
this.chart4.total = chart4Total.amount
this.chart4.totalLabel = '总金额:' + chart4Total.display
const pushMerchant = JSON.parse(data.value.pushMerchant)
const f = (v) => amountFormat({ amount: v, decimal: false, decimalLength: 0 })
// 商户数据
this.data1 = pushMerchant.map(i => {
return {
username: i.username,
balance: f(i.balance) || '0',
residueBalance: f(i.residueBalance) || '0',
collectionSuccessPrice: f(i.collectionSuccessPrice) || '0',
percentage: Number.parseInt(i.percentage * 100) + '%',
balanceWarning: i.balanceWarning
}
})
this.data1 = sortBy(this.data1, 'balanceWarning')
// this.data1 = this.data1.slice(0, 10)
// 在线卡数据
this.data2 = card.map(i => {
return {
bankName: i.bankName,
cardHolder: i.cardHolder,
username: i.username,
todayIncomeReceived: f(i.todayIncomeReceived) || '0',
todayRemainingAmount: f(i.todayRemainingAmount) || '0',
todayOutNumber: i.todayOutNumber + '/' + f(i.todayOutReceived) || '0',
remainingAmount: f(i.remainingAmount) || '0',
balanceWarning: 0,
channels: i.channelNames
}
})
this.data2 = sortBy(this.data2, 'balanceWarning')
this.data2 = this.data2.slice(0, 10)
// 在线卡商数据
this.data3 = carddealer.map(i => {
return {
username: i.username,
dayMargin: f(i.dayMargin) || '0',
margin: f(i.margin) || '0',
toDayTotal: f(i.toDayTotal) || '0',
turnoverRate: (i.turnoverRate * 100).toFixed(2) + '%',
balanceWarning: i.marginWarning,
frozenAmount: f(i.frozenAmount) || '0',
}
})
this.data3 = sortBy(this.data3, 'balanceWarning')
this.data3 = this.data3.slice(0, 10)
this.$refs.table1.scrollReset()
this.$refs.table2.scrollReset()
this.$refs.table3.scrollReset()
if (this.isMute) {
const audio = new Audio('/alarm.mp3')
const hasBalanceWarning = this.data1.some(i => i.balanceWarning) || this.data2.some(i => i.balanceWarning) || this.data3.some(i => i.balanceWarning)
if (hasBalanceWarning) {
audio.play()
}
}
}
},
/**
* 退出全屏
*/
handleLeave() {
if (this.isScreenFull) {
screenfull.exit()
} else {
screenfull.request(this.$refs.layout.$el)
}
this.isScreenFull = !this.isScreenFull
},
disconnect() {
this.ws?.send({ 'type': 'del_push' })
}
},
beforeDestroy() {
this.disconnect()
}
}
</script>
<style lang="scss">
@font-face {
font-family: "YouSheBiaoTiHei";
src: url('../../assets/fonts/YouSheBiaoTiHei.ttf');
font-weight: normal;
font-style: normal;
}
.YouSheBiaoTiHei {
font-family: "YouSheBiaoTiHei", serif;
font-style: normal;
font-weight: 400;
}
.day-margin-row {
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
span {
// white-space: normal;
width: 100%;
}
}
</style>