| | |
| | | <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> |
| | |
| | | <script> |
| | | import { getCustomer, getOrder, getReportToday, getTobeToday, getPieChart, getChart } from "@/api/home"; |
| | | import { noticeToday } from "@/api/system/notice"; |
| | | import { initWebSocket } from "@/utils/websocket"; |
| | | const echarts = require('echarts/lib/echarts'); |
| | | require('echarts/lib/component/title'); |
| | | require('echarts/lib/component/tooltip'); |
| | |
| | | teamYYNum: [], |
| | | PieChart: [], |
| | | PieChart2: [], |
| | | noticeList: [], |
| | | groupedNoticeList: [], // 分组后的通知列表 |
| | | loading: false |
| | | }; |
| | | }, |
| | | |
| | | created() { |
| | | this.getList(); |
| | | this.initWebSocket(); |
| | | }, |
| | | |
| | | watch: { |
| | | $route(to, from) { |
| | | window.location.reload(); |
| | | }, |
| | | noticeList: { |
| | | handler(newList) { |
| | | // 将通知按每组三条分组 |
| | | this.groupedNoticeList = this.chunkArray(newList, 3); |
| | | console.log('groupedNoticeList:', this.groupedNoticeList); // 调试 |
| | | }, |
| | | deep: true |
| | | } |
| | | }, |
| | | |
| | |
| | | query: { noticeId } |
| | | }); |
| | | }, |
| | | |
| | | // 初始化 WebSocket 连接 |
| | | initWebSocket() { |
| | | const token = this.$store.state.user.token || ''; |
| | | initWebSocket(token, (type, data) => { |
| | | if (type === 'error') { |
| | | this.$notify.error({ |
| | | title: '错误', |
| | | message: data, |
| | | duration: 5000, |
| | | position: 'top-right' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | const message = JSON.parse(data); |
| | | console.log('WebSocket 解析后消息:', message); |
| | | if (message.noticeId && message.noticeTitle) { |
| | | const noticeTypeLabel = message.noticeType === '1' ? '通知' : '公告'; |
| | | this.$notify({ |
| | | title: `新${noticeTypeLabel}`, |
| | | message: message.noticeTitle || '无标题', |
| | | type: 'success', |
| | | duration: 5000, // 悬停 5 秒 |
| | | position: 'top-right', |
| | | offset: 50, |
| | | onClick: () => { |
| | | this.goToNotice(message.noticeId); |
| | | } |
| | | }); |
| | | } else { |
| | | console.log('未知消息类型:', message); |
| | | } |
| | | } catch (error) { |
| | | console.error('消息解析失败:', error, '原始数据:', data); |
| | | this.$notify.info({ |
| | | title: '消息', |
| | | message: `服务器回应字符串: ${data}`, |
| | | duration: 5000, |
| | | position: 'top-right', |
| | | offset: 50 |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | 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.$notify.error({ |
| | | title: '错误', |
| | | message: `获取通知失败:${error.message}`, |
| | | duration: 5000, |
| | | position: 'top-right' |
| | | }); |
| | | 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.loading = false; |
| | | }); |
| | | |
| | | // 饼状图 |
| | | getPieChart().then(response => { |
| | | if (response.data) { |
| | | if (response.data.tjdj == 0 || !response.data.tjdj?.length) { |
| | |
| | | }); |
| | | }, |
| | | |
| | | // 数组分组方法 |
| | | 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 { |
| | |
| | | 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 { |
| | |
| | | background-color: #fff; |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | /* 自定义 Element UI 通知样式 */ |
| | | .el-notification { |
| | | min-width: 300px; |
| | | background-color: #f0f9eb; |
| | | border-color: #e1f3d8; |
| | | color: #67c23a; |
| | | font-size: 16px; |
| | | padding: 15px 20px; |
| | | } |
| | | |
| | | .el-notification__title { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .el-notification__content { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| | | |
| | | .el-notification__closeBtn { |
| | | color: #999; |
| | | } |
| | | </style> |