<template>
|
<div class="centre">
|
<!-- 今日通知 -->
|
<div style="display: flex; justify-content: center; align-items: center;">
|
<h4>今日通知</h4>
|
</div>
|
<div class="notice-area">
|
<el-carousel :interval="2000" direction="vertical" :autoplay="true" :loop="true" height="120px"
|
v-if="groupedNoticeList.length > 0" class="carousel">
|
<el-carousel-item v-for="(group, index) in groupedNoticeList" :key="index">
|
<div class="notice-group">
|
<div class="notice-item" v-for="notice in group" :key="notice.noticeId"
|
@click="goToNotice(notice.noticeId)">
|
<el-tag size="small" :type="notice.noticeType === '1' ? 'info' : 'warning'">
|
{{ notice.noticeType === '1' ? '通知' : '公告' }}
|
</el-tag>
|
<span class="notice-title">{{ notice.noticeTitle || '无标题' }}</span>
|
<span class="notice-time">{{ parseTime(notice.createTime, '{y}-{m}-{d}') || '无时间' }}</span>
|
</div>
|
</div>
|
</el-carousel-item>
|
</el-carousel>
|
<div v-else class="no-notice">暂无通知</div>
|
</div>
|
|
<!-- 今日统计 -->
|
<div style="display: flex; justify-content: center; align-items: center;">
|
<h4>今日统计</h4>
|
</div>
|
<div class="top">
|
<div class="add">
|
<div class="img">
|
<img class="image" src="../assets/images/jrbg.png" alt="" />
|
</div>
|
<div class="txt">
|
<div class="day">今日登记 {{ Customer }}</div>
|
</div>
|
</div>
|
<div class="add">
|
<div class="img">
|
<img class="image" src="../assets/images/jrdj.png" alt="" />
|
</div>
|
<div class="txt">
|
<div class="day">今日已检 {{ Order }}</div>
|
</div>
|
</div>
|
<div class="add">
|
<div class="img">
|
<img class="image" src="../assets/images/jrwj.png" alt="" />
|
</div>
|
<div class="txt">
|
<div class="day">今日报告 {{ ReportToday }}</div>
|
</div>
|
</div>
|
<div class="add">
|
<div class="img">
|
<img class="image" src="../assets/images/jryj.png" alt="" />
|
</div>
|
<div class="txt">
|
<div class="day">今日待检 {{ TobeToday }}</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 近一月统计 -->
|
<div style="display: flex; justify-content: center; align-items: center;">
|
<h4>近一月统计</h4>
|
</div>
|
<div class="data-view">
|
<div id="main" style="width: 95%; height: 330px"></div>
|
</div>
|
<div class="view">
|
<div id="main2"></div>
|
<div id="main3"></div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import { getCustomer, getOrder, getReportToday, getTobeToday, getPieChart, getChart } from "@/api/home";
|
import { noticeToday } from "@/api/system/notice";
|
const echarts = require('echarts/lib/echarts');
|
require('echarts/lib/component/title');
|
require('echarts/lib/component/tooltip');
|
require('echarts/lib/component/legend');
|
require('echarts/lib/chart/pie');
|
require('echarts/lib/chart/line');
|
|
export default {
|
data() {
|
return {
|
min: '',
|
max: '',
|
Customer: "",
|
Order: "",
|
ReportToday: "",
|
TobeToday: "",
|
LineChart: [],
|
personYYNum: [],
|
reportNum: [],
|
teamYYNum: [],
|
PieChart: [],
|
PieChart2: [],
|
noticeList: [],
|
groupedNoticeList: [], // 分组后的通知列表
|
loading: false
|
};
|
},
|
|
created() {
|
this.getList();
|
},
|
|
watch: {
|
$route(to, from) {
|
window.location.reload();
|
},
|
noticeList: {
|
handler(newList) {
|
// 将通知按每组三条分组
|
this.groupedNoticeList = this.chunkArray(newList, 3);
|
console.log('groupedNoticeList:', this.groupedNoticeList); // 调试
|
},
|
deep: true
|
}
|
},
|
|
methods: {
|
goToNotice(noticeId) {
|
this.$router.push({
|
path: '/notice',
|
query: { noticeId }
|
});
|
},
|
getList() {
|
this.loading = true;
|
|
// 查询所有公告
|
noticeToday().then(response => {
|
console.log('Notice API response:', response);
|
this.noticeList = response.rows || response.data || [];
|
console.log('noticeList:', this.noticeList);
|
this.loading = false;
|
this.$nextTick(() => {
|
console.log('Carousel updated');
|
});
|
}).catch(error => {
|
console.error('Notice API error:', error);
|
this.$message.error("获取通知失败:" + error.message);
|
this.loading = false;
|
});
|
|
// 查询今日登记
|
getCustomer().then(response => {
|
this.Customer = response.data || response;
|
this.loading = false;
|
});
|
|
// 查询今日已检
|
getOrder().then(response => {
|
this.Order = response.data || response;
|
this.loading = false;
|
});
|
|
// 查询今日报告
|
getReportToday().then(response => {
|
this.ReportToday = response.data || response;
|
this.loading = false;
|
});
|
|
// 查询今日待检
|
getTobeToday().then(response => {
|
this.TobeToday = response.data || response;
|
this.loading = false;
|
});
|
|
// 折线图
|
getChart().then(response => {
|
response.data.forEach(item => {
|
this.LineChart.push(item.date);
|
this.reportNum.push(item.tdcoun);
|
this.personYYNum.push(item.grcoun);
|
this.teamYYNum.push(item.bgcoun);
|
});
|
|
let myChart = this.$echarts.init(document.getElementById('main'));
|
myChart.setOption({
|
tooltip: { trigger: 'axis' },
|
legend: { data: ['每日体检登记数', '每日团体登记数', '每日发布报告数'] },
|
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
|
toolbox: { feature: { saveAsImage: {} } },
|
xAxis: {
|
type: 'category',
|
boundaryGap: false,
|
axisLine: {
|
show: true,
|
lineStyle: { width: 0, color: 'blue', type: 'solid' }
|
},
|
data: this.LineChart
|
},
|
yAxis: { type: 'value', min: 0, max: 400, interval: 20 },
|
series: [
|
{ name: '每日体检登记数', type: 'line', stack: 'Total', data: this.personYYNum },
|
{ name: '每日团体登记数', type: 'line', stack: 'Total', data: this.reportNum },
|
{ name: '每日发布报告数', type: 'line', stack: 'Total', data: this.teamYYNum }
|
]
|
});
|
|
const sizeFun = () => myChart.resize();
|
window.addEventListener('resize', sizeFun);
|
this.loading = false;
|
});
|
|
// 饼状图
|
getPieChart().then(response => {
|
if (response.data) {
|
if (response.data.tjdj == 0 || !response.data.tjdj?.length) {
|
this.PieChart = [{ name: '体检登记人数分布', count: 1, value: 10 }];
|
} else {
|
this.PieChart = response.data.tjdj;
|
this.PieChart.forEach(item => { item.value = item.count; });
|
this.PieChart.reverse();
|
this.PieChart.push(this.PieChart[0]);
|
this.PieChart.splice(0, 1);
|
}
|
|
let myChart2 = this.$echarts.init(document.getElementById('main2'));
|
myChart2.setOption({
|
title: { text: '体检登记人数分布', top: '5' },
|
tooltip: { trigger: 'item' },
|
legend: { top: '80%', left: 'center' },
|
series: [{
|
type: 'pie',
|
radius: ['16%', '54%'],
|
center: ['50%', '43%'],
|
avoidLabelOverlap: false,
|
startAngle: 180,
|
minAngle: 10,
|
data: this.PieChart,
|
emphasis: {
|
itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' }
|
}
|
}]
|
});
|
|
if (response.data.tjyc == 0 || !response.data.tjyc?.length) {
|
this.PieChart2 = [{ name: '体检结果异常人数分布', count: 1, value: 0 }];
|
} else {
|
this.PieChart2 = response.data.tjyc;
|
this.PieChart2.reverse();
|
this.PieChart2.push(this.PieChart2[0]);
|
this.PieChart2.splice(0, 1);
|
this.PieChart2.forEach(item => { item.value = item.count; });
|
}
|
|
let myChart3 = this.$echarts.init(document.getElementById('main3'));
|
myChart3.setOption({
|
title: { text: '体检结果异常人数分布', top: '5' },
|
tooltip: { trigger: 'item' },
|
legend: { top: '80%', left: 'center' },
|
series: [{
|
type: 'pie',
|
radius: ['16%', '54%'],
|
center: ['50%', '43%'],
|
avoidLabelOverlap: false,
|
startAngle: 180,
|
minAngle: 10,
|
data: this.PieChart2,
|
emphasis: {
|
itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' }
|
}
|
}]
|
});
|
|
window.onresize = () => {
|
myChart2.resize();
|
myChart3.resize();
|
};
|
}
|
this.loading = false;
|
});
|
},
|
|
// 数组分组方法
|
chunkArray(array, size) {
|
if (!array || array.length === 0) return [];
|
const result = [];
|
for (let i = 0; i < array.length; i += size) {
|
result.push(array.slice(i, i + size));
|
}
|
// 确保循环滚动平滑,若不足 size 条,补齐
|
if (array.length % size !== 0 && array.length > size) {
|
const lastGroup = result[result.length - 1];
|
while (lastGroup.length < size) {
|
lastGroup.push(array[lastGroup.length % array.length]);
|
}
|
}
|
return result;
|
},
|
|
parseTime(time, cFormat) {
|
if (!time) return '';
|
try {
|
const date = new Date(time);
|
if (isNaN(date.getTime())) return '';
|
const formatObj = {
|
y: date.getFullYear(),
|
m: String(date.getMonth() + 1).padStart(2, '0'),
|
d: String(date.getDate()).padStart(2, '0'),
|
h: String(date.getHours()).padStart(2, '0'),
|
i: String(date.getMinutes()).padStart(2, '0'),
|
s: String(date.getSeconds()).padStart(2, '0')
|
};
|
return cFormat.replace(/{([ymdhis]+)}/g, (result, key) => formatObj[key] || '');
|
} catch (error) {
|
console.error('parseTime error:', error, 'time:', time);
|
return '';
|
}
|
}
|
}
|
};
|
</script>
|
|
<style>
|
.centre {
|
min-height: 820px;
|
margin: 15px;
|
background-color: #f3f3f3;
|
padding: 10px;
|
}
|
|
.notice-area {
|
width: 100%;
|
min-height: 120px;
|
/* 调整为三条通知高度 */
|
background-color: #fff;
|
margin: 10px 0;
|
padding: 0 20px;
|
}
|
|
.carousel {
|
width: 100% !important;
|
}
|
|
.notice-group {
|
display: flex;
|
flex-direction: column;
|
height: 120px;
|
/* 确保包含三条通知 */
|
}
|
|
.notice-item {
|
display: flex;
|
align-items: center;
|
width: 100%;
|
height: 40px;
|
line-height: 40px;
|
font-size: 14px;
|
cursor: pointer;
|
}
|
|
.notice-title {
|
margin-left: 10px;
|
font-size: 14px;
|
color: #333;
|
flex-grow: 1;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.notice-time {
|
font-size: 12px;
|
color: #999;
|
margin-left: 20px;
|
}
|
|
.no-notice {
|
width: 100%;
|
height: 120px;
|
/* 与轮播高度一致 */
|
line-height: 120px;
|
text-align: center;
|
color: #999;
|
font-size: 14px;
|
}
|
|
.top {
|
width: 100%;
|
display: flex;
|
height: 120px;
|
}
|
|
.add {
|
width: 320px;
|
height: 75px;
|
margin-top: 20px;
|
margin-left: 20px;
|
margin-right: 20px;
|
background-color: #fff;
|
display: flex;
|
}
|
|
.img {
|
width: 60%;
|
height: 100%;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
}
|
|
.image {
|
width: 60px;
|
height: 60px;
|
}
|
|
.txt {
|
display: flex;
|
align-items: center;
|
}
|
|
.day {
|
height: 40px;
|
line-height: 40px;
|
font-size: 12px;
|
}
|
|
.data-view {
|
margin: 0 15px;
|
height: 323px !important;
|
}
|
|
#main {
|
padding: 10px;
|
}
|
|
.view {
|
margin: 0 15px;
|
padding-top: 15px;
|
min-height: 350px;
|
display: flex;
|
}
|
|
#main2,
|
#main3 {
|
width: 820px;
|
height: 350px;
|
background-color: #fff;
|
margin-right: 20px;
|
}
|
</style>
|