| | |
| | | <!-- 中间区域 --> |
| | | <div class="center-panel"> |
| | | <CenterTop /> |
| | | |
| | | <CenterBottom /> |
| | | </div> |
| | | |
| | | <!-- 右侧区域 --> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue' |
| | | import { ref, onMounted, onBeforeUnmount, nextTick, provide } from 'vue' |
| | | import autofit from 'autofit.js' |
| | | import LeftTop from './components/basic/left-top.vue' |
| | | import LeftBottom from './components/basic/left-bottom.vue' |
| | | import CenterTop from './components/basic/center-top.vue' |
| | | import CenterBottom from './components/basic/center-bottom.vue' |
| | | import RightTop from './components/basic/right-top.vue' |
| | | import RightBottom from './components/basic/right-bottom.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | |
| | | |
| | | // 用户store |
| | | const userStore = useUserStore() |
| | | |
| | | // 大屏接口轮询间隔 |
| | | const DASHBOARD_REFRESH_MS = 60 * 1000 |
| | | const dataDashboardRefreshTick = ref(0) |
| | | provide('dataDashboardRefreshTick', dataDashboardRefreshTick) |
| | | let dashboardPollTimer = null |
| | | |
| | | // 计算缩放比例 |
| | | const calculateScale = () => { |
| | |
| | | window.addEventListener('fullscreenchange', handleFullscreenChange) |
| | | window.addEventListener('webkitfullscreenchange', handleFullscreenChange) |
| | | window.addEventListener('MSFullscreenChange', handleFullscreenChange) |
| | | |
| | | dashboardPollTimer = setInterval(() => { |
| | | dataDashboardRefreshTick.value++ |
| | | }, DASHBOARD_REFRESH_MS) |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | if (dashboardPollTimer) { |
| | | clearInterval(dashboardPollTimer) |
| | | dashboardPollTimer = null |
| | | } |
| | | window.removeEventListener('resize', handleResize) |
| | | window.removeEventListener('fullscreenchange', handleFullscreenChange) |
| | | window.removeEventListener('webkitfullscreenchange', handleFullscreenChange) |
| | |
| | | justify-content: center; |
| | | background-color: #000; |
| | | overflow: hidden; |
| | | position: relative; |
| | | } |
| | | |
| | | /* 动态网格背景 */ |
| | | .scale-container::before { |
| | | content: ''; |
| | | position: absolute; |
| | | inset: 0; |
| | | background-image: |
| | | linear-gradient(rgba(0, 212, 255, 0.03) 1px, transparent 1px), |
| | | linear-gradient(90deg, rgba(0, 212, 255, 0.03) 1px, transparent 1px); |
| | | background-size: 50px 50px; |
| | | animation: gridMove 20s linear infinite; |
| | | z-index: 0; |
| | | } |
| | | |
| | | @keyframes gridMove { |
| | | 0% { transform: translate(0, 0); } |
| | | 100% { transform: translate(50px, 50px); } |
| | | } |
| | | |
| | | /* 内部内容区域 - 固定设计尺寸 */ |
| | |
| | | color: #FFFFFF; |
| | | top: 16px; |
| | | position: absolute; |
| | | animation: titleGlow 3s ease-in-out infinite; |
| | | } |
| | | |
| | | @keyframes titleGlow { |
| | | 0%, 100% { text-shadow: 0 0 20px rgba(0, 212, 255, 0.3); } |
| | | 50% { text-shadow: 0 0 40px rgba(0, 212, 255, 0.6), 0 0 60px rgba(0, 212, 255, 0.3); } |
| | | } |
| | | |
| | | .fullscreen-btn { |
| | |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .left-panel { |
| | | animation: slideInLeft 0.8s ease-out; |
| | | } |
| | | |
| | | .right-panel { |
| | | animation: slideInRight 0.8s ease-out; |
| | | } |
| | | |
| | | .center-panel { |
| | | animation: slideInUp 0.8s ease-out; |
| | | } |
| | | |
| | | @keyframes slideInLeft { |
| | | from { opacity: 0; transform: translateX(-50px); } |
| | | to { opacity: 1; transform: translateX(0); } |
| | | } |
| | | |
| | | @keyframes slideInRight { |
| | | from { opacity: 0; transform: translateX(50px); } |
| | | to { opacity: 1; transform: translateX(0); } |
| | | } |
| | | |
| | | @keyframes slideInUp { |
| | | from { opacity: 0; transform: translateY(30px); } |
| | | to { opacity: 1; transform: translateY(0); } |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | flex: 1; |