CmcDashboard.vue 7.95 KB
<template>
	<!-- 整个页面容器 -->
	<div class="single-page-container">
		<!-- 顶部通栏:左-系统名 + 中-品牌 + 右-时间+下拉框-->
		<div class="top-header">
			<!-- 左侧:系统标识区 -->
			<div class="header-left">
				<img src="../assets/img/logo.png" alt="系统图标" class="sys-icon" />
				<span class="sys-name">软控一体管理平台</span>
			</div>

			<!-- 中间:报警-->
			<div class="header-center">
				<span class="brand-name">{{ sonData }}</span>
			</div>

			<!-- 右侧:时间 + 下拉选择器(保留时间,替换管理员/退出) -->
			<div class="header-right">
				<span class="info-item" id="current-time">{{ currentTime }}</span>
				<el-select
					ref="areaSelect"
					v-model="selectedArea"
					clearable
					size="mini"
					class="area-selector"
					popper-class="area-select-popper"
					placement="bottom-start"
					:popper-append-to-body="true"
					:popper-options="areaSelectPopperOptions"
					@change="handleAreaChange"
					@visible-change="handleAreaSelectVisibleChange"
				>
					<el-option v-for="item in areaOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
				</el-select>
			</div>
		</div>

		<!-- 左右分栏布局 -->
		<div class="layout-wrap">
			<!-- 左侧导航栏 -->
			<div class="left-nav">
				<ul class="nav-menu">
					<li class="menu-item" :class="{ active: currentActive === 'home' }" @click="switchContent('home')">
						<img src="../assets/img/当前任务.png" alt="任务" class="menu-icon" />
						当前任务
					</li>
					<li class="menu-item" :class="{ active: currentActive === 'device' }" @click="switchContent('device')">
						<img src="../assets/img/历史任务.png" alt="任务" class="menu-icon" />
						历史任务
					</li>
					<li class="menu-item" :class="{ active: currentActive === 'task' }" @click="switchContent('task')">
						<img src="../assets/img/设备状态.png" alt="任务" class="menu-icon" />
						设备状态
					</li>
					<li class="menu-item" :class="{ active: currentActive === 'about' }" @click="switchContent('about')">
						<img src="../assets/img/年.png" alt="任务" class="menu-icon" />
						今日摘要
					</li>
				</ul>
			</div>

			<!-- 右侧内容展示区:只有 pageReady 为 true 才渲染!! -->
			<div class="right-content" v-if="pageReady">
				<current-task-view ref="currentTaskView" @send-data="getSonData" :userName="selectedArea" v-if="currentActive === 'home'" />
				<history-task-view ref="historyTaskView" :userName="selectedArea" v-if="currentActive === 'device'" />
				<device-status-view ref="deviceStatusView" v-if="currentActive === 'task'" />
				<today-summary-view ref="todaySummaryView" :userName="selectedArea" v-if="currentActive === 'about'" />
			</div>
		</div>
	</div>
</template>

<script>
import { CMC_OFFLINE_TASK_API, CMC_REQUEST_URL } from '@/api/cmcApi'
import CurrentTaskView from '@/components/task/CurrentTaskView'
import HistoryTaskView from '@/components/task/HistoryTaskView'
import DeviceStatusView from '@/components/task/DeviceStatusView'
import TodaySummaryView from '@/components/task/TodaySummaryView'

export default {
	name: 'CmcDashboard',
	data() {
		return {
			baseUrlOffOne: CMC_OFFLINE_TASK_API,
			baseUrlOnLineOne: window.appConfig.baseUrlintTotalConversion,
			sysData: {},
			currentActive: 'home',
			currentTime: '',
			selectedArea: '',
			areaOptions: [{ code: '', name: '全部' }],
			timeTimer: null,
			sonData: '',
			show: '',
			areaSelectPopperOptions: {
				modifiers: {
					computeStyle: {
						gpuAcceleration: false,
					},
					flip: {
						enabled: false,
					},
					preventOverflow: {
						enabled: false,
					},
				},
			},

			// 核心:控制页面是否准备好(接口加载完才变true)
			pageReady: false,
		}
	},
	components: {
		CurrentTaskView,
		HistoryTaskView,
		DeviceStatusView,
		TodaySummaryView,
	},
	methods: {
		getData() {
			const opt = {
				urlSuffix: window.baseOnLineOrOff ? this.baseUrlOnLineOne : this.baseUrlOffOne,
				logTitle: '总转换接口',
				isUrlALL: true,
				headers: window.baseOnLineOrOff,
				header: window.baseOnLineOrOff,
				type: 'post',
				data: {
					requestMethod: 'post',
					requestUrl: CMC_REQUEST_URL.getZones,
					requestService: 'WMS',
					requestBody: {
						zoneTypeList: ['L'],
					},
				},
			}
			const callBackFn = (res) => {
				if (!this.ajaxSuccessDataBefore(res, opt.logTitle)) return

				let temp = { code: '', name: '全部' }
				res.data.result.push(temp)

				// 赋值
				this.selectedArea = res.data.result[0].code
				this.areaOptions = res.data.result

				// ==============================================
				// 接口加载完成 ✅ 现在才允许渲染子页面
				// ==============================================
				this.pageReady = true
			}
			''.ajax(this, opt, callBackFn)
		},
		ajaxSuccessDataBefore(res, title) {
			if (!res || !res.data || res.data.result == null || res.data.result.length === 0) {
				this.sysData = []
				''.Log(`${title}无数据`, 'getData')
				return false
			}
			return true
		},
		getSonData(data) {
			this.sonData = data
		},
		switchContent(navKey) {
			this.currentActive = navKey
		},
		updateTime() {
			const now = new Date()
			const year = now.getFullYear()
			const month = String(now.getMonth() + 1).padStart(2, '0')
			const day = String(now.getDate()).padStart(2, '0')
			const hh = String(now.getHours()).padStart(2, '0')
			const mm = String(now.getMinutes()).padStart(2, '0')
			const ss = String(now.getSeconds()).padStart(2, '0')
			this.currentTime = `${year}/${month}/${day} ${hh}:${mm}:${ss}`
		},
		handleAreaChange() {
			const activePage = this.currentActive
			this.currentActive = ''
			this.$nextTick(() => {
				this.currentActive = activePage
			})
		},
		handleAreaSelectVisibleChange(visible) {
			if (!visible) return
			this.$nextTick(() => {
				this.alignAreaSelectPopper()
				window.setTimeout(() => {
					this.alignAreaSelectPopper()
				}, 0)
			})
		},
		getAreaSelectPopperEl() {
			const poppers = Array.from(document.querySelectorAll('.area-select-popper'))
			return poppers.find((el) => {
				const style = window.getComputedStyle(el)
				return style.display !== 'none' && style.visibility !== 'hidden'
			})
		},
		vwToPx(vw) {
			return (window.innerWidth * vw) / 100
		},
		alignAreaSelectPopper() {
			const selectComp = this.$refs.areaSelect
			const triggerEl = selectComp && selectComp.$el
			const popperEl = this.getAreaSelectPopperEl()
			if (!triggerEl || !popperEl) return

			const triggerRect = triggerEl.getBoundingClientRect()
			const left = Math.round(triggerRect.left)
			const gapPx = this.vwToPx(0.16)
			const top = Math.round(triggerRect.bottom + gapPx)
			const width = Math.round(triggerRect.width)

			popperEl.style.position = 'fixed'
			popperEl.style.left = `${left}px`
			popperEl.style.top = `${top}px`
			popperEl.style.width = `${width}px`
			popperEl.style.minWidth = `${width}px`
			popperEl.style.transform = 'none'
			popperEl.style.marginTop = '0'
		},
		handleWindowResize() {
			this.alignAreaSelectPopper()
		},
		bindWheelScroll() {
			const container = document.querySelector('.device-management')
			if (!container) return
			container.addEventListener(
				'wheel',
				(e) => {
					const target = e.target
					const scrollEl = target.closest('.field-display-area, .right-top-box, .left-div, .parent-container')
					if (!scrollEl) return
					if (scrollEl.scrollWidth > scrollEl.clientWidth) {
						e.preventDefault()
						scrollEl.scrollLeft += e.deltaY * 1.5
					}
				},
				{ passive: false },
			)
		},
	},
	mounted() {
		// 先加载接口 → 接口成功后才会打开 pageReady → 渲染子组件
		this.getData()

		this.updateTime()
		this.bindWheelScroll()
		window.addEventListener('resize', this.handleWindowResize)
		this.timeTimer = setInterval(() => {
			this.updateTime()
		}, 1000)
	},
	beforeDestroy() {
		clearInterval(this.timeTimer)
		window.removeEventListener('resize', this.handleWindowResize)
	},
}
</script>

<style src="../styles/cmc-dashboard.css"></style>