Files
intc-vue3/src/views/invest/accountsBalance/index.vue

595 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<div class="search-con">
<div class="title">查询条件</div>
<el-form :model="queryParams" ref="queryRef" :inline="true" :rules="rules" label-width="100px">
<el-form-item label="账户类型" prop="type">
<el-select v-model="queryParams.dataType" placeholder="请选择账户类型" @change="handleChange" clearable>
<el-option v-for="dict in account_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="" prop="time" v-if="queryParams.type === 1">
<el-date-picker
v-model="queryParams.time"
type="daterange"
disabled="true"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
format="YYYY-MM-DD"
@calendar-change="calendarChange"
/>
</el-form-item>
</el-form>
<div class="search-btn-con">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="info" icon="Refresh" @click="resetQuery">重置</el-button>
</div>
</div>
<div class="main-con">
<div class="summary-con">
<div class="center-con" v-hasPermi="['invest:debitCard']">
<div class="icon-box">
<el-icon :size="40" color="#409EFF"><WalletFilled /></el-icon>
</div>
<div class="item-wrap">
<div class="title">储蓄账户余额</div>
<div class="num">{{ accountsBalance.debitAllBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:debitCard']">
<div class="icon-box">
<el-icon :size="40" color="#67C23A"><CreditCard /></el-icon>
</div>
<div class="item-wrap">
<div class="title">储蓄卡余额</div>
<div class="num">{{ accountsBalance.debitBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:debitCard']">
<div class="icon-box">
<el-icon :size="40" color="#E6A23C"><Money /></el-icon>
</div>
<div class="item-wrap">
<div class="title">I类储蓄卡余额</div>
<div class="num">{{ accountsBalance.idebitBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:debitCard']">
<div class="icon-box">
<el-icon :size="40" color="#F56C6C"><Coin /></el-icon>
</div>
<div class="item-wrap">
<div class="title">II类储蓄卡余额</div>
<div class="num">{{ accountsBalance.iidebitBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:creditCard']">
<div class="icon-box">
<el-icon :size="40" color="#909399"><CreditCard /></el-icon>
</div>
<div class="item-wrap">
<div class="title">信用卡可用额度</div>
<div class="num">{{ accountsBalance.creditAvailableLimit }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:creditCard']">
<div class="icon-box">
<el-icon :size="40" color="#00D0FF"><Money /></el-icon>
</div>
<div class="item-wrap">
<div class="title">信用卡余额</div>
<div class="num">{{ accountsBalance.creditBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:onlineLend']">
<div class="icon-box">
<el-icon :size="40" color="#FF6B9D"><Coin /></el-icon>
</div>
<div class="item-wrap">
<div class="title">借贷账户余额</div>
<div class="num">{{ accountsBalance.lendAccountBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:futureStocks:list']">
<div class="icon-box">
<el-icon :size="40" color="#409EFF"><TrendCharts /></el-icon>
</div>
<div class="item-wrap">
<div class="title">投资账户余额</div>
<div class="num">{{ accountsBalance.investBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:futureStocks:list']">
<div class="icon-box">
<el-icon :size="40" color="#67C23A"><Histogram /></el-icon>
</div>
<div class="item-wrap">
<div class="title">期货投资账户余额</div>
<div class="num">{{ accountsBalance.futuresBalance }}</div>
</div>
</div>
<div class="center-con" v-hasPermi="['invest:futureStocks:list']">
<div class="icon-box">
<el-icon :size="40" color="#E6A23C"><Odometer /></el-icon>
</div>
<div class="item-wrap">
<div class="title">股票投资账户余额</div>
<div class="num">{{ accountsBalance.stocksBalance }}</div>
</div>
</div>
</div>
<div class="title-con">
<div class="title">记账账户统计</div>
<div class="operate-btn-con">
<el-radio-group v-model="radioVal" @change="handleRadioChange">
<el-radio-button label="柱状图" />
<el-radio-button label="折线图" />
<el-radio-button label="账户余额" />
<el-radio-button label="信用卡可用余额" />
</el-radio-group>
</div>
</div>
<div class="content-con">
<div v-show="radioVal === '柱状图'" class="chart" id="chartBar"></div>
<div v-show="radioVal === '折线图'" class="chart" id="chartLine"></div>
<el-table v-show="radioVal === '账户余额'" v-loading="loading" :data="accountsBalance.accountsBalancesList">
<el-table-column label="序号" width="50" type="index" align="center">
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="记账账户" align="center" prop="account" />
<el-table-column label="可用余额" align="center" prop="availableLimit" />
</el-table>
<el-table v-show="radioVal === '信用卡可用余额'" v-loading="loading" :data="accountsBalance.creditBalancesList">
<el-table-column label="序号" width="50" type="index" align="center">
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="信用卡名称" align="center" prop="account" />
<el-table-column label="可用余额" align="center" prop="availableLimit" />
</el-table>
</div>
</div>
</div>
</template>
<script setup name="CreditAnalysis">
import dayjs from 'dayjs'
import * as echarts from 'echarts'
import { ElMessage } from 'element-plus'
import { WalletFilled, CreditCard, Money, Coin, TrendCharts, PieChart, Histogram, Odometer } from '@element-plus/icons-vue'
import { getAccountsAnalysis } from '@/api/invest/statisticAnalysis'
const { proxy } = getCurrentInstance()
const { account_type } = proxy.useDict('account_type')
const loading = ref(true)
const total = ref(0)
const radioVal = ref('柱状图')
const dateValidate = (rules, value, callback) => {
const dateType = rules.dateType || 'days'
const num = rules.num || 31
const dateString = rules.dateString || '天'
const message = rules.message || `时间跨度不能超过${num}${dateString}`
if (value && value.length === 2) {
const start = value[0]
const end = value[1]
if (dayjs(end).diff(dayjs(start), dateType) > num) {
queryParams.value.time = [start, dayjs(start).add(59, 'months')]
ElMessage.warning(message)
}
}
}
const data = reactive({
queryParams: {
type: 1,
time: null,
dataType: null,
id: null
},
rules: {
time: [{ validator: dateValidate, dateType: 'months', num: 59, dateRange: '月', message: '时间跨度不能大于60个月默认选择开始日期的24个月' }]
}
})
const { queryParams, rules } = toRefs(data)
const handleChange = (id) => {
queryParams.value.dataType = id
getList()
}
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
const start = end
queryParams.value.time = [start, end]
const firstChooseDate = ref('')
const calendarChange = (val) => {
firstChooseDate.value = val[0].getTime()
if (val[1]) firstChooseDate.value = ''
}
const accountsBalance = ref({
debetBalance: '',
creditAvailableLimit: '',
creditBalance: '',
investBalance: '',
debitBalance: '',
accountsBalancesList: []
})
const chartData = ref({
name: [],
value1: []
})
function getList() {
loading.value = true
chartData.value = { name: [], value1: [] }
const { type, time, id, dataType } = queryParams.value
let formatValue = 'YYYY-MM-DD'
if (type === 1) {
formatValue = 'YYYY-MM-DD'
} else if (type === 2) {
formatValue = 'YYYY-MM'
} else {
formatValue = 'YYYY'
}
const params = {
type,
startTime: time && time.length > 0 ? dayjs(time[0]).format(formatValue) : '',
endTime: time && time.length > 0 ? dayjs(time[1]).format(formatValue) : '',
id,
dataType
}
getAccountsAnalysis(params).then((response) => {
loading.value = false
accountsBalance.value = { ...response.data }
accountsBalance.value.accountsBalancesList.map((item) => {
return {
name: item.account,
value: item.availableLimit
}
})
response.data.accountsBalancesList.map((item) => {
chartData.value.name.push(item.account)
chartData.value.value1.push(item.availableLimit)
})
handleRadioChange(currentType.value)
})
}
function handleQuery() {
getList()
}
function resetQuery() {
proxy.resetForm('queryRef')
queryParams.value.id = null
queryParams.value.dataType = null
total.value = 0
handleQuery()
}
const drawBar = (data) => {
if (document.getElementById('chartBar') === null) {
return
}
echarts.dispose(document.getElementById('chartBar'))
const myChart = echarts.init(document.getElementById('chartBar'))
const option = {
legend: {
// 图示例样式
show: true,
top: 50,
right: 50,
itemGap: 20
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
return params[0].name + '<br>' + '可用余额:' + params[0].value + '元'
}
},
grid: {
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: data.name,
axisTick: {
alignWithLabel: true // 刻度线是否与标签对齐默认false
},
// 设置 X 轴线条粗细
axisLine: {
lineStyle: {
width: 1, // 根据需求调整数值大小,单位是像素
color: '#999'
}
}
}
],
yAxis: [
{
type: 'value',
axisTick: {
show: false // 默认为true如果要隐藏则改为 false
},
axisLine: {
show: true,
lineStyle: {
width: 1,
color: '#999'
}
}
}
],
series: [
{
data: data.value1,
type: 'bar',
barMaxWidth: 40,
itemStyle: {
color: function (params) {
// 根据数值大小设置颜色
if (params.data < 0) {
return '#f56c6c' // 红色表示负数(欠款)
} else if (params.data === 0) {
return '#909399' // 灰色表示零
} else {
return '#67c23a' // 绿色表示正数(有余额)
}
}
}
}
],
// 添加点击事件的处理函数
emphasis: {
// itemStyle: {
// color: '#2283cf',
// barWidth: 20 // 根据需求调整数值大小,单位是像素
// },
// barWidth: 24 // 根据需求调整数值大小,单位是像素
}
}
myChart.setOption(option)
setTimeout(() => {
myChart.resize()
}, 100)
}
const drawLine = (data) => {
if (document.getElementById('chartLine') === null) {
return
}
echarts.dispose(document.getElementById('chartLine'))
const myChart = echarts.init(document.getElementById('chartLine'))
const option = {
grid: {
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
return params[0].name + '<br>' + '可用余额:' + params[0].value + '元'
}
},
xAxis: {
type: 'category',
data: data.name,
axisTick: {
alignWithLabel: true
},
axisLine: {
lineStyle: {
width: 1,
color: '#999'
}
}
},
yAxis: {
type: 'value',
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
width: 1,
color: '#999'
}
}
},
series: [
{
data: data.value1,
type: 'line',
lineStyle: {
color: '#4181c9',
width: 2
},
itemStyle: {
color: function (params) {
// 根据数值大小设置颜色
if (params.data < 0) {
return '#f56c6c' // 红色表示负数(欠款)
} else if (params.data === 0) {
return '#909399' // 灰色表示零
} else {
return '#67c23a' // 绿色表示正数(有余额)
}
}
},
smooth: true,
symbol: 'emptyCircle',
areaStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(65,129,201, 0.70)'
},
{
offset: 1,
color: 'rgba(65,129,201, 0.10)'
}
],
false
),
shadowColor: 'rgba(65,129,201, 0.10)',
shadowBlur: 10
}
}
]
}
myChart.setOption(option)
setTimeout(() => {
myChart.resize()
}, 100)
}
const currentType = ref('柱状图')
const handleRadioChange = (type) => {
currentType.value = type
nextTick(() => {
switch (type) {
case '柱状图':
drawBar(chartData.value)
break
case '折线图':
drawLine(chartData.value)
break
default:
break
}
})
}
getList()
</script>
<style lang="scss" scoped>
.main-con {
height: calc(100vh - 200px);
display: flex;
flex-direction: column;
overflow: hidden;
}
.summary-con {
gap: 0.14rem !important;
justify-content: flex-start !important;
flex-wrap: wrap;
margin-bottom: 0.08rem !important;
flex-shrink: 0;
.center-con {
flex: 1 1 calc(20% - 0.112rem);
min-width: 2.4rem;
max-width: calc(20% - 0.112rem);
list-style: none !important;
&::before,
&::after {
display: none !important;
content: none !important;
}
}
.item-wrap {
list-style: none !important;
&::before,
&::after {
display: none !important;
content: none !important;
}
.num,
.title {
&::before,
&::after {
display: none !important;
content: none !important;
}
}
}
.icon-box {
&::before,
&::after {
display: none !important;
content: none !important;
}
}
}
.title-con {
flex-shrink: 0;
margin-top: 0 !important;
padding-top: 0.08rem !important;
}
.content-con {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
.chart {
flex: 1;
min-height: 0;
width: 100%;
}
.el-table {
flex: 1;
min-height: 0;
}
}
@media (max-width: 1600px) {
.summary-con .center-con {
flex: 1 1 calc(25% - 0.105rem);
max-width: calc(25% - 0.105rem);
}
}
@media (max-width: 1200px) {
.summary-con .center-con {
flex: 1 1 calc(33.333% - 0.093rem);
max-width: calc(33.333% - 0.093rem);
}
}
@media (max-width: 768px) {
.summary-con .center-con {
flex: 1 1 calc(50% - 0.07rem);
max-width: calc(50% - 0.07rem);
}
}
</style>