Files
maintenance_system/src/views/materialManagement/components/DataAnalysis.vue
re-JZzzz febbcb3241 fix: 修复样式和组件问题并增强数据图表功能
修复多个组件中的::v-deep语法错误和el-row的gutter属性绑定
将el-button的type="text"更新为link类型
在AppMain.vue中添加div包裹keep-alive以解决过渡问题
增强DataAnalysis组件的数据处理能力,添加计算属性和默认值
添加fetchChuRuKuCountBarData调用以完善库存管理功能
2025-10-09 20:22:04 +08:00

307 lines
8.8 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="dashboard-container">
<!-- 第一个图表本月出入库统计 -->
<div class="chart-item">
<div class="title">
本月出入库统计
</div>
<div ref="lineChartRef" class="chart-container"></div>
</div>
<!-- 第二个图表出入库类型分布 -->
<div class="chart-item">
<div class="title">
出入库类型分布
</div>
<div ref="barChartRef" class="chart-container"></div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import * as echarts from 'echarts';
// 定义props
const props = defineProps({
lineData: {
type: Object,
default: () => ({
days: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
rukuCounnts: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
chukuCounnts: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90]
})
},
barData: {
type: Object,
default: () => ({
shebeiTypes: ['光伏组件', '逆变器', '汇流箱', '支架', '电缆'],
rukuCount: [5, 40, 20, 75, 60],
chukuCount: [30, 40, 30, 30, 30]
})
}
});
// 图表容器引用
const lineChartRef = ref(null);
const barChartRef = ref(null);
// 图表实例
let lineChart = null;
let barChart = null;
// 计算属性处理传入的lineData确保数据有效
const processedLineData = computed(() => {
// 检查传入的数据是否有效
if (!props.lineData ||
!props.lineData.days ||
props.lineData.days.length === 0 ||
!Array.isArray(props.lineData.rukuCounnts) ||
!Array.isArray(props.lineData.chukuCounnts)) {
return {
days: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
rukuCounnts: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
chukuCounnts: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90]
};
}
// 检查rukuCounnts和chukuCounnts是否全为0
const isRukuAllZero = props.lineData.rukuCounnts.every(item => item === 0);
const isChukuAllZero = props.lineData.chukuCounnts.every(item => item === 0);
if (isRukuAllZero && isChukuAllZero) {
return {
days: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
rukuCounnts: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
chukuCounnts: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90]
};
}
return props.lineData;
});
// 计算属性处理传入的barData确保数据有效
const processedBarData = computed(() => {
// 检查传入的数据是否有效
if (!props.barData ||
!props.barData.shebeiTypes ||
props.barData.shebeiTypes.length === 0 ||
!Array.isArray(props.barData.rukuCount) ||
!Array.isArray(props.barData.chukuCount)) {
return {
shebeiTypes: ['光伏组件', '逆变器', '汇流箱', '支架', '电缆'],
rukuCount: [5, 40, 20, 75, 60],
chukuCount: [30, 40, 30, 30, 30]
};
}
return props.barData;
});
onMounted(() => {
// 初始化折线图
initLineChart();
// 初始化柱状图
initBarChart();
// 监听窗口大小变化,自适应图表
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
// 销毁图表实例
if (lineChart) {
lineChart.dispose();
}
if (barChart) {
barChart.dispose();
}
// 移除事件监听
window.removeEventListener('resize', handleResize);
});
// 初始化折线图
const initLineChart = () => {
if (lineChartRef.value) {
lineChart = echarts.init(lineChartRef.value);
const option = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['入库数量', '出库数量'],
icon: 'circle',
itemWidth: 10,
itemHeight: 10,
top: 0
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: processedLineData.value.days
},
yAxis: {
type: 'value'
},
series: [
{
name: '入库数量',
type: 'line',
data: processedLineData.value.rukuCounnts,
symbol: 'none',
smooth: true,
lineStyle: {
color: 'rgba(22, 93, 255, 1)'
},
itemStyle: {
color: 'rgba(22, 93, 255, 1)'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(22, 93, 255, 0.2)' },
{ offset: 1, color: 'rgba(22, 93, 255, 0)' }
])
}
},
{
name: '出库数量',
type: 'line',
data: processedLineData.value.chukuCounnts,
symbol: 'none',
smooth: true,
lineStyle: {
color: 'rgba(255, 153, 0, 1)'
},
itemStyle: {
color: 'rgba(255, 153, 0, 1)'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(59, 179, 70, 0.2)' },
{ offset: 1, color: 'rgba(59, 179, 70, 0)' }
])
}
}
]
};
lineChart.setOption(option);
}
};
// 初始化柱状图
const initBarChart = () => {
if (barChartRef.value) {
barChart = echarts.init(barChartRef.value);
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['入库数量', '出库数量'],
icon: 'circle',
itemWidth: 10,
itemHeight: 10,
top: 0
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: processedBarData.value.shebeiTypes,
axisLabel: {
interval: 0, // 强制显示所有标签
rotate: 30, // 标签旋转30度
margin: 15, // 增加与轴线的距离
align: 'right', // 文字右对齐
verticalAlign: 'top' // 垂直方向顶部对齐
}
},
yAxis: {
type: 'value'
},
series: [
{
name: '入库数量',
type: 'bar',
data: processedBarData.value.rukuCount,
itemStyle: {
color: 'rgba(22, 93, 255, 1)' // 入库数量颜色
},
barWidth: '45%',
barGap: '0' // 柱子之间的间距
},
{
name: '出库数量',
type: 'bar',
data: processedBarData.value.chukuCount,
itemStyle: {
color: 'rgba(15, 198, 194, 1)' // 出库数量颜色
},
barWidth: '45%',
barGap: '0' // 柱子之间的间距
}
]
};
barChart.setOption(option);
}
};
// 处理窗口大小变化,让图表自适应
const handleResize = () => {
if (lineChart) {
lineChart.resize();
}
if (barChart) {
barChart.resize();
}
};
// 监听数据变化,更新图表
watch([() => props.lineData, () => props.barData], () => {
initLineChart();
initBarChart();
}, { deep: true });
</script>
<style scoped>
.dashboard-container {
padding: 20px;
}
.chart-item {
background-color: #fff;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.title {
color: rgba(29, 33, 41, 1);
font-weight: bold;
font-size: 16px;
margin-bottom: 16px;
}
.chart-container {
width: 100%;
height: 300px;
}
</style>