大屏页面布局
This commit is contained in:
@@ -8,30 +8,52 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, nextTick, watch } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { getItemInfoList } from '@/api/itemInfo'
|
||||
|
||||
const vList = ref([])
|
||||
const chartRef = ref(null)
|
||||
let chartInstance = null
|
||||
|
||||
const initBarLineChart = () => {
|
||||
async function getList() {
|
||||
try {
|
||||
const params = {
|
||||
itemCode: 'ERP_YEARPSAV_M001',
|
||||
reqParam: '2025'
|
||||
}
|
||||
const res = await getItemInfoList(params)
|
||||
vList.value = res || []
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
function initChart() {
|
||||
const el = chartRef.value
|
||||
if (!el) return
|
||||
if (!el || vList.value.length === 0) return
|
||||
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose()
|
||||
}
|
||||
|
||||
chartInstance = echarts.init(el)
|
||||
|
||||
// 收支数据
|
||||
const incomeData = [1200, 2000, 1500, 800, 700, 1100, 1300, 1800, 1600, 900, 1000, 1400]
|
||||
const expenseData = [800, 1500, 1000, 600, 500, 800, 900, 1200, 1100, 700, 800, 950]
|
||||
// 计算支出占收入的比例(保留1位小数)
|
||||
const ratioData = incomeData.map((income, index) => {
|
||||
const expense = expenseData[index]
|
||||
return income === 0 ? 0 : ((expense / income) * 100).toFixed(1)
|
||||
const xData = vList.value.map(item => {
|
||||
const xaxis = item.xaxis || ''
|
||||
return xaxis.includes('月') ? xaxis : `${xaxis}月`
|
||||
})
|
||||
|
||||
const index01Yuan = vList.value.map(item => item.index01 || 0)
|
||||
const index02Yuan = vList.value.map(item => item.index02 || 0)
|
||||
const index03 = vList.value.map(item => item.index03 || 0)
|
||||
|
||||
const index01Wan = index01Yuan.map(val => (val / 10000).toFixed(2))
|
||||
const index02Wan = index02Yuan.map(val => (val / 10000).toFixed(2))
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'cross' },
|
||||
backgroundColor: 'rgba(145, 200, 255, 0.9)',
|
||||
borderColor: '#409EFF',
|
||||
@@ -39,33 +61,48 @@ const initBarLineChart = () => {
|
||||
textStyle: { color: '#0a3b70' },
|
||||
padding: [8, 12],
|
||||
borderRadius: 6,
|
||||
formatter: function(params) {
|
||||
let res = `<b>${params[0].axisValue}</b>`
|
||||
params.forEach(item => {
|
||||
const unit = item.seriesName === '支出占收入比' ? '%' : '万元'
|
||||
res += `<br/>${item.seriesName}:${item.value}${unit}`
|
||||
})
|
||||
return res
|
||||
formatter: function (params) {
|
||||
const title = params[0].axisValue
|
||||
const idx = params[0].dataIndex
|
||||
const incomeVal = index01Yuan[idx]
|
||||
const expenseVal = index02Yuan[idx]
|
||||
const rateVal = index03[idx]
|
||||
|
||||
return `
|
||||
<div style="text-align:center; font-weight:bold; margin-bottom:6px">${title}</div>
|
||||
<table style="width:100%; border-collapse:collapse; text-align:center">
|
||||
<tr>
|
||||
<td style="border:1px solid #409EFF; padding:4px; font-weight:bold">收入(元)</td>
|
||||
<td style="border:1px solid #409EFF; padding:4px; font-weight:bold">支出(元)</td>
|
||||
<td style="border:1px solid #409EFF; padding:4px; font-weight:bold">存储率(%)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border:1px solid #409EFF; padding:4px">${incomeVal}</td>
|
||||
<td style="border:1px solid #409EFF; padding:4px">${expenseVal}</td>
|
||||
<td style="border:1px solid #409EFF; padding:4px">${rateVal}</td>
|
||||
</tr>
|
||||
</table>
|
||||
`
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
legend: {
|
||||
top: '10',
|
||||
left: 'center',
|
||||
left: 'center',
|
||||
textStyle: { fontSize: 12, color: '#e0e6ff' }
|
||||
},
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '10%',
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '10%',
|
||||
top: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
fontSize: 11,
|
||||
interval: 0,
|
||||
color: '#b4c7e7'
|
||||
},
|
||||
@@ -80,10 +117,7 @@ const initBarLineChart = () => {
|
||||
nameTextStyle: { fontSize: 12, color: '#b4c7e7' },
|
||||
axisLabel: { formatter: '{value}', color: '#b4c7e7' },
|
||||
axisLine: { lineStyle: { color: '#1a508b' } },
|
||||
splitLine: { lineStyle: { color: 'rgba(26, 80, 139, 0.3)' } },
|
||||
nameLocation: 'end',
|
||||
nameGap: 10,
|
||||
nameRotate: 0
|
||||
splitLine: { lineStyle: { color: 'rgba(26, 80, 139, 0.3)' } }
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
@@ -91,10 +125,7 @@ const initBarLineChart = () => {
|
||||
nameTextStyle: { fontSize: 12, color: '#b4c7e7' },
|
||||
axisLabel: { formatter: '{value} %', color: '#b4c7e7' },
|
||||
axisLine: { lineStyle: { color: '#1a508b' } },
|
||||
splitLine: { lineStyle: { color: 'rgba(26, 80, 139, 0.3)' } },
|
||||
nameLocation: 'end',
|
||||
nameGap: 10,
|
||||
nameRotate: 0,
|
||||
splitLine: { show: false },
|
||||
min: 0,
|
||||
max: 100
|
||||
}
|
||||
@@ -104,46 +135,47 @@ const initBarLineChart = () => {
|
||||
name: '收入',
|
||||
type: 'bar',
|
||||
yAxisIndex: 0,
|
||||
data: incomeData,
|
||||
itemStyle: { color: '#67C23A' }, // 绿色代表收入
|
||||
barWidth: '12%', // 适配双柱宽度
|
||||
data: index01Wan,
|
||||
itemStyle: { color: '#67C23A' },
|
||||
barWidth: '12%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 10,
|
||||
color: '#fff'
|
||||
color: '#fff',
|
||||
formatter: '{c}' // 移除万元单位,只显示数值
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '支出',
|
||||
type: 'bar',
|
||||
yAxisIndex: 0,
|
||||
data: expenseData,
|
||||
itemStyle: { color: '#F56C6C' }, // 红色代表支出
|
||||
data: index02Wan,
|
||||
itemStyle: { color: '#F56C6C' },
|
||||
barWidth: '12%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 10,
|
||||
color: '#fff'
|
||||
color: '#fff',
|
||||
formatter: '{c}' // 移除万元单位,只显示数值
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '支出占收入比',
|
||||
name: '存储率',
|
||||
type: 'line',
|
||||
yAxisIndex: 1,
|
||||
data: ratioData,
|
||||
data: index03,
|
||||
smooth: true,
|
||||
lineStyle: { width: 1.5, color: '#409EFF' }, // 蓝色代表占比曲线
|
||||
lineStyle: { width: 1.5, color: '#409EFF' },
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
emphasis: { symbolSize: 7 },
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 10,
|
||||
color: '#409EFF',
|
||||
formatter: '{c}%'
|
||||
formatter: '{c}' // 移除%单位,只显示数值
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
@@ -156,10 +188,16 @@ const initBarLineChart = () => {
|
||||
}
|
||||
|
||||
chartInstance.setOption(option)
|
||||
window.addEventListener('resize', () => chartInstance.resize())
|
||||
window.addEventListener('resize', () => chartInstance?.resize())
|
||||
}
|
||||
|
||||
onMounted(() => initBarLineChart())
|
||||
watch(vList, () => {
|
||||
nextTick(() => initChart())
|
||||
}, { deep: true })
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -184,7 +222,7 @@ onMounted(() => initBarLineChart())
|
||||
.chart-card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: '#409EFF';
|
||||
color: #409EFF;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
@@ -192,14 +230,5 @@ onMounted(() => initBarLineChart())
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.echarts-tooltip) {
|
||||
background-color: rgba(145, 200, 255, 0.9) !important;
|
||||
border-color: #409EFF !important;
|
||||
color: #0a3b70 !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user