146 lines
4.0 KiB
Vue
146 lines
4.0 KiB
Vue
|
|
<template>
|
|||
|
|
<div ref="chart" class="chart" style="width: 100%; height: 300px"></div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import * as echarts from 'echarts';
|
|||
|
|
export default {
|
|||
|
|
name: 'StatusChart',
|
|||
|
|
data () {
|
|||
|
|
return {
|
|||
|
|
chart: null,
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
computed: {
|
|||
|
|
// 从vuex获取项目列表
|
|||
|
|
projects () {
|
|||
|
|
return this.$store.getters.projectList || [];
|
|||
|
|
},
|
|||
|
|
// 按规则统计各状态的项目数量
|
|||
|
|
chartData () {
|
|||
|
|
// 初始化各状态计数
|
|||
|
|
const statusCount = {
|
|||
|
|
'已完成': 0,
|
|||
|
|
'已逾期': 0,
|
|||
|
|
'即将到期': 0,
|
|||
|
|
'进行中': 0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 获取当前日期(仅保留年月日,消除时分秒影响)
|
|||
|
|
const today = new Date();
|
|||
|
|
today.setHours(0, 0, 0, 0);
|
|||
|
|
|
|||
|
|
this.projects.forEach(project => {
|
|||
|
|
// 优先判断已完成状态
|
|||
|
|
if (project.projectStatus == 1) {
|
|||
|
|
statusCount['已完成']++;
|
|||
|
|
} else {
|
|||
|
|
// 处理未完成项目的时间判断
|
|||
|
|
if (project.finishTime) {
|
|||
|
|
try {
|
|||
|
|
// 将finishTime转换为日期对象(兼容YYYY-MM-dd hh:mm:ss格式)
|
|||
|
|
const finishDate = new Date(project.finishTime);
|
|||
|
|
finishDate.setHours(0, 0, 0, 0); // 统一时间维度
|
|||
|
|
|
|||
|
|
// 计算间隔天数(毫秒转天)
|
|||
|
|
const timeDiff = finishDate - today;
|
|||
|
|
const dayDiff = timeDiff / (1000 * 60 * 60 * 24);
|
|||
|
|
|
|||
|
|
if (dayDiff < 0) {
|
|||
|
|
// 已逾期:截止日期已过
|
|||
|
|
statusCount['已逾期']++;
|
|||
|
|
} else if (dayDiff < 10) {
|
|||
|
|
// 即将到期:截止日期在3天内
|
|||
|
|
statusCount['即将到期']++;
|
|||
|
|
} else {
|
|||
|
|
// 其他情况:进行中
|
|||
|
|
statusCount['进行中']++;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
// 日期格式错误时默认归为进行中
|
|||
|
|
console.error('日期格式错误:', project.finishTime, e);
|
|||
|
|
statusCount['进行中']++;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 无截止日期的未完成项目归为进行中
|
|||
|
|
statusCount['进行中']++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 转换为ECharts所需的数据格式(过滤数量为0的状态)
|
|||
|
|
return Object.entries(statusCount)
|
|||
|
|
.filter(([_, value]) => value > 0)
|
|||
|
|
.map(([name, value]) => {
|
|||
|
|
// 状态颜色映射
|
|||
|
|
const colorMap = {
|
|||
|
|
'已完成': '#1890ff', // 蓝色
|
|||
|
|
'已逾期': '#ff4d4f', // 红色
|
|||
|
|
'即将到期': '#faad14', // 黄色
|
|||
|
|
'进行中': '#52c41a' // 绿色
|
|||
|
|
};
|
|||
|
|
return {
|
|||
|
|
name,
|
|||
|
|
value,
|
|||
|
|
itemStyle: {
|
|||
|
|
color: colorMap[name]
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
mounted () {
|
|||
|
|
this.chart = echarts.init(this.$refs.chart);
|
|||
|
|
this.updateChart();
|
|||
|
|
window.addEventListener('resize', this.resize);
|
|||
|
|
},
|
|||
|
|
watch: {
|
|||
|
|
// 监听项目列表变化,更新图表
|
|||
|
|
projects: {
|
|||
|
|
handler: 'updateChart',
|
|||
|
|
deep: true
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
resize () {
|
|||
|
|
this.chart && this.chart.resize();
|
|||
|
|
},
|
|||
|
|
updateChart () {
|
|||
|
|
if (!this.chart) return;
|
|||
|
|
|
|||
|
|
this.chart.setOption({
|
|||
|
|
tooltip: {
|
|||
|
|
trigger: 'item',
|
|||
|
|
formatter: '{b}: {c}个 ({d}%)' // 显示数量和百分比
|
|||
|
|
},
|
|||
|
|
legend: {
|
|||
|
|
bottom: 10,
|
|||
|
|
textStyle: { fontSize: 12 }
|
|||
|
|
},
|
|||
|
|
series: [{
|
|||
|
|
name: '项目状态',
|
|||
|
|
type: 'pie',
|
|||
|
|
radius: ['50%', '70%'],
|
|||
|
|
avoidLabelOverlap: false,
|
|||
|
|
label: { show: false },
|
|||
|
|
emphasis: {
|
|||
|
|
label: { show: true, fontSize: '16', fontWeight: 'bold' }
|
|||
|
|
},
|
|||
|
|
data: this.chartData // 使用计算后的图表数据
|
|||
|
|
}]
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
beforeDestroy () {
|
|||
|
|
window.removeEventListener('resize', this.resize);
|
|||
|
|
this.chart && this.chart.dispose();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.chart {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
}
|
|||
|
|
</style>
|