<template>
|
<div class="screen-page">
|
<el-row :gutter="10" class="kpi-row">
|
<el-col v-for="item in kpis" :key="item.label" :lg="4" :sm="12" :xs="24">
|
<kpi-card v-bind="item" />
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="10" class="mid-row">
|
<el-col :lg="10" :xs="24">
|
<panel-card title="可回收物品类占比" sub="同一时间范围,看结构">
|
<v-chart :option="pieOption" autoresize class="chart" />
|
</panel-card>
|
</el-col>
|
<el-col :lg="14" :xs="24">
|
<panel-card title="各类回收量" sub="横向柱状图更适合长品类名">
|
<v-chart :option="weightOption" autoresize class="chart" />
|
</panel-card>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="10">
|
<el-col :span="24">
|
<panel-card title="回收价值分析" sub="学校最关心:什么垃圾最值钱">
|
<v-chart :option="valueOption" autoresize class="chart chart--value" />
|
</panel-card>
|
</el-col>
|
</el-row>
|
</div>
|
</template>
|
|
<script lang="ts" setup>
|
defineOptions({
|
name: 'report-screen-resource'
|
});
|
|
import { computed } from 'vue';
|
import KpiCard from '../../components/kpi-card.vue';
|
import PanelCard from '../../components/panel-card.vue';
|
import { useChartTheme, useScreenData } from '../../hooks/use-screen';
|
|
const { data } = useScreenData();
|
const { textColor, mutedColor, splitColor, primary, tooltip } = useChartTheme();
|
|
const kpis = computed(() => [
|
{ label: '回收总量', value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2, hint: '全部分类重量合计' },
|
{ label: '可回收物', value: data.value.kpis.recyclableTon, suffix: '吨', fixed: 2, hint: 'SW62' },
|
{ label: '大件垃圾', value: data.value.kpis.bulkTon, suffix: '吨', fixed: 2, hint: 'SW63' },
|
{ label: '电子产品', value: data.value.kpis.elecTon, suffix: '吨', fixed: 2, hint: '可回收子类' },
|
{ label: '废旧织物', value: data.value.kpis.fabricTon, suffix: '吨', fixed: 2, hint: '可回收子类' }
|
]);
|
|
const pieOption = computed(() => ({
|
tooltip: { trigger: 'item', formatter: '{b}<br/>{c} kg ({d}%)', ...tooltip() },
|
legend: { bottom: 0, textStyle: { color: mutedColor.value } },
|
series: [
|
{
|
type: 'pie',
|
radius: ['36%', '60%'],
|
center: ['50%', '46%'],
|
padAngle: 3,
|
itemStyle: { borderRadius: 6 },
|
label: { color: textColor.value, formatter: '{b} {d}%' },
|
data: data.value.recycleItems.map(e => ({
|
name: e.name,
|
value: e.weight,
|
itemStyle: { color: e.color }
|
}))
|
}
|
]
|
}));
|
|
const weightOption = computed(() => ({
|
grid: { containLabel: true, left: 8, right: 28, top: 12, bottom: 8 },
|
tooltip: { trigger: 'axis', ...tooltip() },
|
xAxis: {
|
type: 'value',
|
name: 'kg',
|
splitLine: { lineStyle: { color: splitColor.value, type: 'dashed' } },
|
axisLabel: { color: mutedColor.value },
|
axisLine: { show: false },
|
axisTick: { show: false }
|
},
|
yAxis: {
|
type: 'category',
|
data: data.value.recycleItems.map(e => e.name).reverse(),
|
axisLabel: { color: textColor.value },
|
axisLine: { show: false },
|
axisTick: { show: false }
|
},
|
series: [
|
{
|
type: 'bar',
|
barWidth: 16,
|
data: data.value.recycleItems
|
.map(e => ({ value: e.weight, itemStyle: { color: e.color, borderRadius: [0, 8, 8, 0] } }))
|
.reverse()
|
}
|
]
|
}));
|
|
const valueOption = computed(() => ({
|
grid: { containLabel: true, left: 16, right: 16, top: 28, bottom: 8 },
|
tooltip: { trigger: 'axis', ...tooltip() },
|
xAxis: {
|
type: 'category',
|
data: data.value.recycleItems.map(e => e.name),
|
axisLabel: { color: mutedColor.value },
|
axisLine: { show: false },
|
axisTick: { show: false }
|
},
|
yAxis: {
|
type: 'value',
|
name: '元',
|
nameTextStyle: { color: mutedColor.value },
|
splitLine: { lineStyle: { color: splitColor.value, type: 'dashed' } },
|
axisLabel: { color: mutedColor.value },
|
axisLine: { show: false },
|
axisTick: { show: false }
|
},
|
series: [
|
{
|
type: 'bar',
|
barWidth: 28,
|
data: data.value.recycleItems.map(e => e.value),
|
itemStyle: { color: primary.value, borderRadius: [6, 6, 0, 0] }
|
}
|
]
|
}));
|
</script>
|
|
<style lang="scss" scoped>
|
.screen-page {
|
.kpi-row,
|
.mid-row {
|
margin-bottom: 10px;
|
}
|
|
.kpi-row {
|
:deep(.el-col) {
|
margin-bottom: 10px;
|
}
|
}
|
|
.mid-row {
|
:deep(.panel-card) {
|
min-height: 360px;
|
}
|
}
|
|
.chart {
|
height: 300px;
|
width: 100%;
|
|
&--value {
|
height: 280px;
|
}
|
}
|
}
|
</style>
|