From bf64e8016283b18c04d5392dd9c002b921021af2 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期六, 07 三月 2026 09:47:04 +0800
Subject: [PATCH] #

---
 src/main/webapp/views/watch/console.html |  794 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 712 insertions(+), 82 deletions(-)

diff --git a/src/main/webapp/views/watch/console.html b/src/main/webapp/views/watch/console.html
index 3dbcc3c..a1229ae 100644
--- a/src/main/webapp/views/watch/console.html
+++ b/src/main/webapp/views/watch/console.html
@@ -4,8 +4,8 @@
 				<meta charset="UTF-8">
 				<title>WCS鎺у埗涓績</title>
 				<link rel="stylesheet" href="../../static/css/animate.min.css">
-				<link rel="stylesheet" href="../../static/vue/element/element.css">
 				<link rel="stylesheet" href="../../static/css/watch/console_vue.css">
+				<link rel="stylesheet" href="../../static/vue/element/element.css">
 				<style>
 					html, body, #app {
 						width: 100%;
@@ -13,11 +13,503 @@
 						margin: 0;
 						overflow: hidden;
 					}
+					body {
+						background: linear-gradient(180deg, #eef4f8 0%, #e7edf4 100%);
+					}
+					#app {
+						position: relative;
+					}
+					.monitor-shell {
+						position: relative;
+						width: 100%;
+						height: 100%;
+						overflow: hidden;
+					}
+					.monitor-map {
+						width: 100%;
+						height: 100%;
+					}
+					.monitor-panel-wrap {
+						position: absolute;
+						top: 18px;
+						left: 18px;
+						bottom: 18px;
+						z-index: 40;
+						pointer-events: none;
+					}
+					.monitor-panel {
+						width: min(max(360px, 30vw), calc(100vw - 92px));
+						max-width: calc(100vw - 92px);
+						height: calc(100vh - 36px);
+						display: flex;
+						flex-direction: column;
+						border-radius: 20px;
+						border: 1px solid rgba(255, 255, 255, 0.42);
+						background: rgba(248, 251, 253, 0.94);
+						box-shadow: 0 10px 24px rgba(88, 110, 136, 0.08);
+						overflow: hidden;
+						pointer-events: auto;
+						transform-origin: left center;
+						will-change: transform, opacity;
+						backface-visibility: hidden;
+						contain: layout paint style;
+						transition: transform .26s cubic-bezier(0.22, 1, 0.36, 1), opacity .2s ease, box-shadow .2s ease, border-color .2s ease;
+					}
+					.monitor-panel.is-collapsed {
+						opacity: 0;
+						transform: translate3d(calc(-100% - 14px), 0, 0);
+						border-color: transparent;
+						box-shadow: 0 6px 16px rgba(88, 110, 136, 0.02);
+						pointer-events: none;
+					}
+					.monitor-panel-header {
+						padding: 14px 16px 10px;
+						border-bottom: 1px solid rgba(226, 232, 240, 0.72);
+						background: rgba(255, 255, 255, 0.24);
+					}
+					.monitor-panel-title {
+						font-size: 15px;
+						font-weight: 600;
+						color: #243447;
+						line-height: 1.2;
+					}
+					.monitor-panel-desc {
+						margin-top: 4px;
+						font-size: 12px;
+						color: #6b7b8d;
+					}
+					.monitor-panel-body {
+						flex: 1;
+						min-height: 0;
+						padding: 12px;
+						overflow: hidden;
+					}
+					.monitor-panel-body {
+						flex: 1;
+						display: flex;
+						flex-direction: column;
+						gap: 10px;
+					}
+					.monitor-card-host {
+						flex: 1;
+						min-height: 0;
+						display: flex;
+						align-items: stretch;
+						width: 100%;
+					}
+					.wb-root {
+						position: relative;
+						flex: 1;
+						min-width: 0;
+						display: flex;
+						flex-direction: column;
+						height: 100%;
+						gap: 10px;
+						color: #395066;
+					}
+					.wb-main {
+						flex: 1;
+						min-height: 0;
+						display: flex;
+						gap: 10px;
+					}
+					.wb-side {
+						flex: 0 0 38%;
+						min-width: 220px;
+						max-width: 44%;
+						display: flex;
+						flex-direction: column;
+						gap: 10px;
+						min-height: 0;
+					}
+					.wb-side-title {
+						font-size: 11px;
+						font-weight: 700;
+						letter-spacing: 0.06em;
+						text-transform: uppercase;
+						color: #7d8fa2;
+						margin-bottom: 8px;
+					}
+					.wb-list-card,
+					.wb-detail-panel {
+						min-height: 0;
+						display: flex;
+						flex-direction: column;
+					}
+					.wb-detail-panel {
+						flex: 1 1 62%;
+						min-width: 0;
+					}
+					.wb-tabs {
+						display: grid;
+						grid-template-columns: repeat(4, 1fr);
+						gap: 6px;
+						padding: 6px;
+						border-radius: 14px;
+						background: rgba(242, 246, 250, 0.78);
+						border: 1px solid rgba(224, 232, 239, 0.9);
+					}
+					.wb-tab {
+						height: 34px;
+						border: none;
+						border-radius: 10px;
+						background: transparent;
+						color: #73869b;
+						font-size: 12px;
+						font-weight: 600;
+						cursor: pointer;
+						transition: all .16s ease;
+					}
+					.wb-tab.is-active {
+						background: rgba(255, 255, 255, 0.92);
+						color: #24405c;
+						box-shadow: 0 8px 16px rgba(148, 163, 184, 0.08);
+					}
+					.wb-toolbar {
+						display: flex;
+						align-items: center;
+						gap: 8px;
+					}
+					.wb-toolbar-actions {
+						display: flex;
+						gap: 8px;
+						flex-shrink: 0;
+					}
+					.wb-input,
+					.wb-select {
+						width: 100%;
+						height: 36px;
+						padding: 0 12px;
+						border-radius: 10px;
+						border: 1px solid rgba(224, 232, 239, 0.96);
+						background: rgba(255, 255, 255, 0.76);
+						color: #334155;
+						box-sizing: border-box;
+						outline: none;
+						transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
+					}
+					.wb-input:focus,
+					.wb-select:focus {
+						border-color: rgba(128, 168, 208, 0.66);
+						box-shadow: 0 0 0 3px rgba(128, 168, 208, 0.1);
+						background: rgba(255, 255, 255, 0.92);
+					}
+					.wb-btn {
+						height: 36px;
+						padding: 0 14px;
+						border: none;
+						border-radius: 10px;
+						background: #6f95bd;
+						color: #fff;
+						font-size: 12px;
+						font-weight: 600;
+						cursor: pointer;
+						box-shadow: 0 6px 14px rgba(111, 149, 189, 0.18);
+						transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease, background .16s ease;
+					}
+					.wb-btn:hover {
+						transform: translateY(-1px);
+					}
+					.wb-btn-primary {
+						background: linear-gradient(135deg, #5e89b4 0%, #6f95bd 100%);
+						box-shadow: 0 10px 20px rgba(111, 149, 189, 0.22);
+					}
+					.wb-btn.wb-btn-ghost {
+						background: rgba(255, 255, 255, 0.76);
+						color: #4c6177;
+						border: 1px solid rgba(224, 232, 239, 0.96);
+						box-shadow: none;
+					}
+					.wb-btn.wb-btn-soft {
+						background: rgba(230, 237, 244, 0.92);
+						color: #4c6177;
+						border: 1px solid rgba(210, 221, 232, 0.98);
+						box-shadow: none;
+					}
+					.wb-control-card,
+					.wb-list-card,
+					.wb-detail {
+						border-radius: 16px;
+						border: 1px solid rgba(224, 232, 239, 0.92);
+						background: rgba(255, 255, 255, 0.62);
+						box-shadow: 0 8px 18px rgba(148, 163, 184, 0.06);
+					}
+					.wb-list-card {
+						flex: 1;
+						padding: 10px 8px 8px;
+					}
+					.wb-control-card {
+						padding: 14px;
+						background: linear-gradient(180deg, rgba(255, 255, 255, 0.82) 0%, rgba(246, 250, 253, 0.78) 100%);
+						overflow: auto;
+					}
+					.wb-control-subtitle {
+						margin-top: 8px;
+						margin-bottom: 10px;
+						font-size: 11px;
+						line-height: 1.45;
+						color: #6f8194;
+					}
+					.wb-control-target {
+						padding: 7px 9px;
+						border-radius: 12px;
+						background: rgba(234, 241, 247, 0.96);
+						border: 1px solid rgba(214, 224, 234, 0.96);
+						color: #43607c;
+						font-size: 11px;
+						font-weight: 700;
+						line-height: 1.4;
+					}
+					.wb-form-grid {
+						display: grid;
+						grid-template-columns: 1fr;
+						gap: 8px;
+					}
+					.wb-field {
+						display: flex;
+						flex-direction: column;
+						gap: 5px;
+					}
+					.wb-field-label {
+						font-size: 11px;
+						font-weight: 700;
+						letter-spacing: 0.02em;
+						color: #6d8197;
+					}
+					.wb-action-row {
+						display: flex;
+						flex-wrap: wrap;
+						gap: 8px;
+						margin-top: 2px;
+						padding-top: 8px;
+						border-top: 1px dashed rgba(216, 226, 235, 0.92);
+					}
+					.wb-section-title {
+						font-size: 13px;
+						font-weight: 700;
+						color: #28425d;
+						margin-bottom: 10px;
+					}
+					.wb-list {
+						flex: 1;
+						min-height: 0;
+						padding: 6px;
+						overflow: auto;
+					}
+					.wb-list-item {
+						width: 100%;
+						display: flex;
+						flex-direction: column;
+						align-items: flex-start;
+						justify-content: flex-start;
+						gap: 7px;
+						padding: 10px;
+						margin-bottom: 8px;
+						border: 1px solid transparent;
+						border-radius: 12px;
+						background: rgba(248, 250, 252, 0.72);
+						cursor: pointer;
+						text-align: left;
+						color: inherit;
+					}
+					.wb-list-item:last-child {
+						margin-bottom: 0;
+					}
+					.wb-list-item.is-active {
+						border-color: rgba(135, 166, 198, 0.38);
+						background: rgba(236, 243, 249, 0.94);
+					}
+					.wb-list-main {
+						min-width: 0;
+					}
+					.wb-list-title {
+						font-size: 12px;
+						font-weight: 700;
+						color: #27425c;
+						line-height: 1.35;
+					}
+					.wb-list-meta {
+						margin-top: 4px;
+						font-size: 11px;
+						color: #7b8b9c;
+						line-height: 1.4;
+						display: -webkit-box;
+						-webkit-line-clamp: 2;
+						-webkit-box-orient: vertical;
+						overflow: hidden;
+					}
+					.wb-badge {
+						flex-shrink: 0;
+						padding: 3px 8px;
+						border-radius: 999px;
+						font-size: 10px;
+						font-weight: 700;
+					}
+					.wb-badge.is-success {
+						background: rgba(82, 177, 126, 0.12);
+						color: #2d7650;
+					}
+					.wb-badge.is-working {
+						background: rgba(111, 149, 189, 0.12);
+						color: #3f6286;
+					}
+					.wb-badge.is-warning {
+						background: rgba(214, 162, 94, 0.14);
+						color: #9b6a24;
+					}
+					.wb-badge.is-danger {
+						background: rgba(207, 126, 120, 0.14);
+						color: #a14e4a;
+					}
+					.wb-badge.is-muted {
+						background: rgba(148, 163, 184, 0.14);
+						color: #748397;
+					}
+					.wb-empty {
+						padding: 28px 12px;
+						text-align: center;
+						color: #8b9aad;
+						font-size: 12px;
+					}
+					.wb-detail {
+						flex: 1;
+						min-height: 0;
+						padding: 12px;
+						overflow: auto;
+					}
+					.wb-detail-empty {
+						display: flex;
+						align-items: center;
+						justify-content: center;
+					}
+					.wb-detail-header {
+						display: flex;
+						align-items: flex-start;
+						justify-content: space-between;
+						gap: 10px;
+						margin-bottom: 12px;
+					}
+					.wb-detail-subtitle {
+						margin-top: 4px;
+						font-size: 12px;
+						color: #7c8c9d;
+					}
+					.wb-detail-actions {
+						display: flex;
+						flex-wrap: wrap;
+						gap: 8px;
+					}
+					.wb-link {
+						padding: 0;
+						border: none;
+						background: transparent;
+						color: #4677a4;
+						font-size: 12px;
+						cursor: pointer;
+					}
+					.wb-detail-grid {
+						display: grid;
+						grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
+						gap: 8px;
+					}
+					.wb-detail-cell {
+						padding: 10px 12px;
+						border-radius: 12px;
+						background: rgba(247, 250, 252, 0.86);
+						border: 1px solid rgba(233, 239, 244, 0.96);
+					}
+					.wb-detail-label {
+						font-size: 11px;
+						color: #8090a2;
+					}
+					.wb-detail-value {
+						margin-top: 5px;
+						font-size: 13px;
+						color: #31485f;
+						word-break: break-all;
+					}
+					.wb-notice {
+						position: absolute;
+						right: 18px;
+						bottom: 18px;
+						padding: 10px 14px;
+						border-radius: 12px;
+						font-size: 12px;
+						font-weight: 600;
+						color: #fff;
+						box-shadow: 0 12px 24px rgba(15, 23, 42, 0.12);
+					}
+					.wb-notice.is-success {
+						background: rgba(82, 177, 126, 0.92);
+					}
+					.wb-notice.is-warning {
+						background: rgba(214, 162, 94, 0.92);
+					}
+					.wb-notice.is-danger {
+						background: rgba(207, 126, 120, 0.92);
+					}
+					.floor-switch-button {
+						min-width: 44px;
+						height: 30px;
+						padding: 0 12px;
+						border: 1px solid rgba(185, 197, 210, 0.84);
+						border-radius: 999px;
+						background: rgba(255, 255, 255, 0.82);
+						color: #4b6177;
+						font-size: 12px;
+						font-weight: 700;
+						cursor: pointer;
+					}
+					.floor-switch-button.is-active {
+						border-color: rgba(111, 149, 189, 0.4);
+						background: rgba(236, 243, 249, 0.94);
+						color: #27425c;
+					}
+					.monitor-panel-toggle {
+						position: absolute;
+						left: 0;
+						top: 50%;
+						margin-left: 0;
+						transform: translateY(-50%);
+						width: 30px;
+						min-height: 108px;
+						padding: 10px 4px;
+						border: 1px solid rgba(148, 163, 184, 0.22);
+						border-left: none;
+						border-radius: 0 14px 14px 0;
+						background: rgba(255, 255, 255, 0.96);
+						color: #3e5974;
+						box-shadow: 0 8px 18px rgba(15, 23, 42, 0.08);
+						cursor: pointer;
+						pointer-events: auto;
+						display: inline-flex;
+						flex-direction: column;
+						align-items: center;
+						justify-content: center;
+						gap: 10px;
+						font-size: 12px;
+						line-height: 1;
+						white-space: nowrap;
+						backface-visibility: hidden;
+						transition: left .26s cubic-bezier(0.22, 1, 0.36, 1), transform .26s cubic-bezier(0.22, 1, 0.36, 1), box-shadow .18s ease, background .18s ease;
+					}
+					.monitor-panel-toggle.is-panel-open {
+						left: calc(100% + 10px);
+					}
+					.monitor-panel-toggle i {
+						font-size: 14px;
+					}
+					.monitor-panel-toggle span {
+						writing-mode: vertical-rl;
+						text-orientation: mixed;
+						letter-spacing: 0.08em;
+						user-select: none;
+					}
 				</style>
 				<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
 				<script type="text/javascript" src="../../static/layui/layui.js"></script>
 				<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
-				<script type="text/javascript" src="../../static/js/common.js"></script>
+			<script type="text/javascript" src="../../static/js/common.js"></script>
 			<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
 			<script type="text/javascript" src="../../static/vue/element/element.js"></script>
 			<script src="../../static/js/gsap.min.js"></script>
@@ -25,42 +517,43 @@
 		</head>
 	<body>
 		<div id="app">
-			<div style="display: flex;margin-left: 20px;">
-				<div style="width: 20%;height: 60vh;margin-right: 20px;margin-top: 30px;">
-					<el-tabs type="border-card" v-model="activateCard" @tab-click="handleCardClick">
-						<el-tab-pane label="鍫嗗灈鏈�" name="crn">
-							<watch-crn-card ref="watchCrnCard" :param="crnParam"></watch-crn-card>
-						</el-tab-pane>
-						<el-tab-pane label="鍙屽伐浣嶅爢鍨涙満" name="dualCrn">
-							<watch-dual-crn-card ref="watchDualCrnCard" :param="dualCrnParam"></watch-dual-crn-card>
-						</el-tab-pane>
-						<el-tab-pane label="杈撻�佺珯" name="devp">
-							<devp-card ref="devpCard" :param="devpParam"></devp-card>
-						</el-tab-pane>
-						<el-tab-pane label="RGV" name="rgv">
-							<watch-rgv-card ref="watchRgvCard" :param="rgvParam"></watch-rgv-card>
-						</el-tab-pane>
-						<!-- <el-tab-pane label="鍦板浘閰嶇疆" name="mapSetting">
-							<map-setting-card :param="mapSettingParam"></map-setting-card>
-						</el-tab-pane> -->
-					</el-tabs>
-				</div>
+			<div class="monitor-shell" ref="monitorShell">
+				<map-canvas :lev="currentLev" :lev-list="levList" :crn-param="crnParam" :rgv-param="rgvParam" :devp-param="devpParam" :station-task-range="stationTaskRange" :viewport-padding="mapViewportPadding" :hud-padding="mapHudPadding" @switch-lev="switchLev" @crn-click="openCrn" @dual-crn-click="openDualCrn" @station-click="openSite" @rgv-click="openRgv" class="monitor-map"></map-canvas>
 
-				<map-canvas :lev="currentLev" :crn-param="crnParam" :rgv-param="rgvParam" :devp-param="devpParam" @crn-click="openCrn" @dual-crn-click="openDualCrn" @station-click="openSite" @rgv-click="openRgv" style="width: 80%; height: 100vh;"></map-canvas>
-
-				<div style="position: absolute;top: 15px;left: 50%;display: flex;">
-					<div v-if="levList.length > 1" v-for="(lev,index) in levList" :key="index" style="margin-right: 10px;">
-						<el-button :type="currentLev == lev ? 'primary' : ''" @click="switchLev(lev)" size="mini">{{ lev }}F</el-button>
+				<div class="monitor-panel-wrap" ref="monitorPanelWrap">
+					<div class="monitor-panel" ref="monitorPanel" :class="{ 'is-collapsed': panelCollapsed }">
+						<div class="monitor-panel-header">
+							<div class="monitor-panel-title">鐩戞帶宸ヤ綔鍙�</div>
+							<div class="monitor-panel-desc">鍥寸粫鍦板浘鍋氭搷浣滐紝璁惧鐐瑰嚮鍚庤嚜鍔ㄥ垏鎹㈠埌瀵瑰簲闈㈡澘</div>
+						</div>
+						<div class="monitor-panel-body">
+							<div class="wb-tabs" role="tablist">
+								<button type="button" :class="['wb-tab', { 'is-active': activateCard === 'crn' }]" @click="handleWorkbenchTabChange('crn')">鍫嗗灈鏈�</button>
+								<button type="button" :class="['wb-tab', { 'is-active': activateCard === 'dualCrn' }]" @click="handleWorkbenchTabChange('dualCrn')">鍙屽伐浣�</button>
+								<button type="button" :class="['wb-tab', { 'is-active': activateCard === 'devp' }]" @click="handleWorkbenchTabChange('devp')">杈撻�佺珯</button>
+								<button type="button" :class="['wb-tab', { 'is-active': activateCard === 'rgv' }]" @click="handleWorkbenchTabChange('rgv')">RGV</button>
+							</div>
+							<div class="monitor-card-host">
+								<watch-crn-card v-if="activateCard === 'crn'" ref="watchCrnCard" :param="crnParam" :items="crnStateList" :auto-refresh="false"></watch-crn-card>
+								<watch-dual-crn-card v-else-if="activateCard === 'dualCrn'" ref="watchDualCrnCard" :param="dualCrnParam" :items="dualCrnStateList" :auto-refresh="false"></watch-dual-crn-card>
+								<devp-card v-else-if="activateCard === 'devp'" ref="devpCard" :param="devpParam" :items="stationStateList" :auto-refresh="false"></devp-card>
+								<watch-rgv-card v-else ref="watchRgvCard" :param="rgvParam" :items="rgvStateList" :auto-refresh="false"></watch-rgv-card>
+							</div>
+						</div>
 					</div>
+					<button class="monitor-panel-toggle" :class="{ 'is-panel-open': !panelCollapsed }" ref="monitorToggle" @click="toggleMonitorPanel">
+						<i>{{ panelCollapsed ? '>' : '<' }}</i>
+						<span>{{ panelCollapsed ? '灞曞紑闈㈡澘' : '鏀惰捣闈㈡澘' }}</span>
+					</button>
 				</div>
 			</div>
 
 		</div>
 
+		<script src="../../components/MonitorCardKit.js"></script>
 		<script src="../../components/WatchCrnCard.js"></script>
 		<script src="../../components/WatchDualCrnCard.js"></script>
 		<script src="../../components/DevpCard.js"></script>
-		<script src="../../components/MapSettingCard.js"></script>
 		<script src="../../components/WatchRgvCard.js"></script>
 		<script src="../../components/MapCanvas.js"></script>
 		<script>
@@ -74,6 +567,22 @@
 					systemStatus: true,//绯荤粺杩愯鐘舵��
 					consoleInterval: null,//瀹氭椂鍣ㄥ瓨鍌ㄥ彉閲�
 					rgvPosition: [],
+					panelCollapsed: false,
+					mapViewportPadding: {
+						top: 0,
+						right: 0,
+						bottom: 0,
+						left: 0
+					},
+					mapHudPadding: {
+						left: 14
+					},
+					stationTaskRange: {
+						inbound: null,
+						outbound: null
+					},
+					panelTransitionTimer: null,
+					panelPollTimer: null,
 					activateCard: 'crn',
 					crnParam: {
 						crnNo: 0
@@ -81,15 +590,16 @@
 					dualCrnParam: {
 						crnNo: 0
 					},
-					mapSettingParam: {
-						zoom: 70
-					},
 					devpParam: {
 						stationId: 0
 					},
 					rgvParam: {
 						rgvNo: 0
 					},
+					crnStateList: [],
+					dualCrnStateList: [],
+					stationStateList: [],
+					rgvStateList: [],
 					locMastData: [],//搴撲綅鏁版嵁
 					wsReconnectTimer: null,
 					wsReconnectAttempts: 0,
@@ -100,10 +610,20 @@
 					this.init()
 				},
 				mounted() {
+					this.$nextTick(() => {
+						this.updateMapViewportPadding();
+					});
+					window.addEventListener('resize', this.updateMapViewportPadding);
+					this.panelPollTimer = setInterval(() => {
+						this.refreshWorkbench(this.activateCard);
+					}, 1000);
 				},
 				beforeDestroy() {
 					if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
 					if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) { try { ws.close(); } catch (e) {} }
+					window.removeEventListener('resize', this.updateMapViewportPadding);
+					if (this.panelTransitionTimer) { clearTimeout(this.panelTransitionTimer); this.panelTransitionTimer = null; }
+					if (this.panelPollTimer) { clearInterval(this.panelPollTimer); this.panelPollTimer = null; }
 				},
 				watch: {
 
@@ -114,12 +634,13 @@
                             ws.send(data);
                         }
                     },
-                    webSocketOnOpen() {
-                        console.log("WebSocket杩炴帴鎴愬姛");
-                        if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
-                        this.wsReconnectAttempts = 0;
-                        this.getMap();
-                    },
+	                    webSocketOnOpen() {
+	                        console.log("WebSocket杩炴帴鎴愬姛");
+	                        if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
+	                        this.wsReconnectAttempts = 0;
+	                        this.getMap();
+	                        this.refreshWorkbench(this.activateCard);
+	                    },
                     webSocketOnError() {
                         console.log("WebSocket杩炴帴鍙戠敓閿欒");
                         this.scheduleWsReconnect();
@@ -128,27 +649,23 @@
                         console.log("WebSocket杩炴帴鍏抽棴");
                         this.scheduleWsReconnect();
                     },
-                    webSocketOnMessage(e) {
-                        const result = JSON.parse(e.data);
-                        if (result.url == "/crn/table/crn/state") {
-                             if(this.$refs.watchCrnCard) {
-                                 this.$refs.watchCrnCard.setCrnList(JSON.parse(result.data));
-                             }
-                        } else if (result.url == "/dualcrn/table/crn/state") {
-                             if(this.$refs.watchDualCrnCard) {
-                                 this.$refs.watchDualCrnCard.setDualCrnList(JSON.parse(result.data));
-                             }
-                        } else if (result.url == "/console/latest/data/station") {
-                             if(this.$refs.devpCard) {
-                                 this.$refs.devpCard.setStationList(JSON.parse(result.data));
-                             }
-                        } else if (result.url == "/rgv/table/rgv/state") {
-                             if(this.$refs.watchRgvCard) {
-                                 this.$refs.watchRgvCard.setRgvList(JSON.parse(result.data));
-                             }
-                        } else if (result.url == "/basMap/lev/" + this.currentLev + "/auth") {
-                            // 鍦板浘鏁版嵁
-                             let res = JSON.parse(result.data);
+	                    webSocketOnMessage(e) {
+	                        const result = JSON.parse(e.data);
+	                        if (result.url == "/crn/table/crn/state") {
+	                             const res = JSON.parse(result.data);
+	                             this.crnStateList = res && res.code === 200 ? (res.data || []) : [];
+	                        } else if (result.url == "/dualcrn/table/crn/state") {
+	                             const res = JSON.parse(result.data);
+	                             this.dualCrnStateList = res && res.code === 200 ? (res.data || []) : [];
+	                        } else if (result.url == "/console/latest/data/station") {
+	                             const res = JSON.parse(result.data);
+	                             this.stationStateList = res && res.code === 200 ? (res.data || []) : [];
+	                        } else if (result.url == "/rgv/table/rgv/state") {
+	                             const res = JSON.parse(result.data);
+	                             this.rgvStateList = res && res.code === 200 ? (res.data || []) : [];
+	                        } else if (result.url == "/basMap/lev/" + this.currentLev + "/auth") {
+	                            // 鍦板浘鏁版嵁
+	                             let res = JSON.parse(result.data);
                              if (res.code === 200) {
                                  this.map = res.data;
                              }
@@ -165,7 +682,31 @@
 
 						this.getSystemRunningStatus() //鑾峰彇绯荤粺杩愯鐘舵��
 						this.getLevList() //鑾峰彇鍦板浘灞傜骇鍒楄〃
+						this.getStationTaskRange() // 鑾峰彇鍏ュ簱/鍑哄簱宸ヤ綔鍙疯寖鍥�
 						this.getLocMastData() //鑾峰彇搴撲綅鏁版嵁
+					},
+					getStationTaskRange() {
+						this.fetchWrkLastnoRange(1, 'inbound');
+						this.fetchWrkLastnoRange(101, 'outbound');
+					},
+					fetchWrkLastnoRange(id, key) {
+						$.ajax({
+							url: baseUrl + "/wrkLastno/" + id + "/auth",
+							headers: {
+								'token': localStorage.getItem('token')
+							},
+							method: "get",
+							success: (res) => {
+								if (!res || res.code !== 200 || !res.data) { return; }
+								const data = res.data;
+								this.stationTaskRange = Object.assign({}, this.stationTaskRange, {
+									[key]: {
+										start: data.sNo,
+										end: data.eNo
+									}
+								});
+							}
+						});
 					},
 					connectWs() {
 						if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) { return; }
@@ -204,40 +745,138 @@
 						this.currentLev = lev;
 						this.getMap()
 						this.getLocMastData()
+						this.refreshWorkbench(this.activateCard)
+					},
+					handleWorkbenchTabChange(type) {
+						this.activateCard = type;
+						this.refreshWorkbench(type);
+					},
+					refreshWorkbench(type) {
+						if (!type) { return; }
+						if (type === 'crn') {
+							this.sendWs(JSON.stringify({ url: "/crn/table/crn/state", data: {} }));
+						} else if (type === 'dualCrn') {
+							this.sendWs(JSON.stringify({ url: "/dualcrn/table/crn/state", data: {} }));
+						} else if (type === 'devp') {
+							this.sendWs(JSON.stringify({ url: "/console/latest/data/station", data: {} }));
+						} else if (type === 'rgv') {
+							this.sendWs(JSON.stringify({ url: "/rgv/table/rgv/state", data: {} }));
+						}
+					},
+					updateMapViewportPadding() {
+						const shell = this.$refs.monitorShell;
+						const panelWrap = this.$refs.monitorPanelWrap;
+						if (!shell) { return; }
+						const shellRect = shell.getBoundingClientRect();
+						let leftPadding = 0;
+						let hudLeft = 14;
+						if (!this.panelCollapsed && this.$refs.monitorPanel && panelWrap) {
+							const wrapRect = panelWrap.getBoundingClientRect();
+							const panelWidth = this.$refs.monitorPanel.offsetWidth || this.$refs.monitorPanel.getBoundingClientRect().width || 0;
+							const panelLeft = Math.max(0, Math.ceil(wrapRect.left - shellRect.left));
+							const panelBaseRight = panelLeft + Math.ceil(panelWidth);
+							const overlapCompensation = Math.min(56, panelWidth * 0.18);
+							leftPadding = Math.max(0, Math.ceil(panelBaseRight - overlapCompensation));
+							hudLeft = Math.max(14, Math.ceil(panelBaseRight + 34));
+						} else {
+							leftPadding = 0;
+							hudLeft = 14;
+						}
+						this.mapViewportPadding = {
+							top: 0,
+							right: 0,
+							bottom: 0,
+							left: leftPadding
+						};
+						this.mapHudPadding = {
+							left: hudLeft
+						};
+					},
+					scheduleMapViewportPaddingUpdate(delay) {
+						if (this.panelTransitionTimer) {
+							clearTimeout(this.panelTransitionTimer);
+							this.panelTransitionTimer = null;
+						}
+						this.panelTransitionTimer = setTimeout(() => {
+							this.panelTransitionTimer = null;
+							this.updateMapViewportPadding();
+						}, delay == null ? 0 : delay);
+					},
+					toggleMonitorPanel() {
+						this.panelCollapsed = !this.panelCollapsed;
+						this.scheduleMapViewportPaddingUpdate(0);
 					},
 					openCrn(id) {
+						this.panelCollapsed = false;
 						this.crnParam.crnNo = id;
 						this.activateCard = 'crn';
+						this.scheduleMapViewportPaddingUpdate(0);
+						this.refreshWorkbench('crn');
 					},
 					openDualCrn(id) {
+						this.panelCollapsed = false;
 						this.dualCrnParam.crnNo = id;
 						this.activateCard = 'dualCrn';
+						this.scheduleMapViewportPaddingUpdate(0);
+						this.refreshWorkbench('dualCrn');
 					},
 					openRgv(id) {
+						this.panelCollapsed = false;
 						this.rgvParam.rgvNo = id;
 						this.activateCard = 'rgv';
+						this.scheduleMapViewportPaddingUpdate(0);
+						this.refreshWorkbench('rgv');
 					},
 					openSite(id) {
+						this.panelCollapsed = false;
 						this.devpParam.stationId = id;
 						this.activateCard = 'devp';
+						this.scheduleMapViewportPaddingUpdate(0);
+						this.refreshWorkbench('devp');
 					},
 					systemSwitch() {
 						// 绯荤粺寮�鍏�
-						let that = this
 						if (this.systemStatus) {
-							this.$prompt('璇疯緭鍏ュ彛浠わ紝骞跺仠姝CS绯荤粺', '鎻愮ず', {
-								confirmButtonText: '纭畾',
-								cancelButtonText: '鍙栨秷',
-							}).then(({
-								value
-							}) => {
-								that.doSwitch(0, value)
-							}).catch(() => {
-
-							});
+							const password = window.prompt('璇疯緭鍏ュ彛浠わ紝骞跺仠姝CS绯荤粺', '');
+							if (password === null) {
+								return;
+							}
+							this.doSwitch(0, password);
 						} else {
 							this.doSwitch(1)
 						}
+					},
+					showPageMessage(message, type) {
+						if (!message) {
+							return;
+						}
+						if (typeof this.$message === 'function') {
+							this.$message({
+								message: message,
+								type: type || 'info'
+							});
+							return;
+						}
+						if (window.ELEMENT && typeof window.ELEMENT.Message === 'function') {
+							window.ELEMENT.Message({
+								message: message,
+								type: type || 'info'
+							});
+							return;
+						}
+						if (window.layer && typeof window.layer.msg === 'function') {
+							const iconMap = {
+								success: 1,
+								error: 2,
+								warning: 0
+							};
+							window.layer.msg(message, {
+								icon: iconMap[type] != null ? iconMap[type] : 0,
+								time: 1800
+							});
+							return;
+						}
+						console[type === 'error' ? 'error' : 'log'](message);
 					},
 					doSwitch(operatorType, password) {
 						let that = this
@@ -267,10 +906,7 @@
 								} else if (res.code === 403) {
 									parent.location.href = baseUrl + "/login";
 								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
+									that.showPageMessage(res.msg, 'error');
 								}
 							}
 						});
@@ -300,10 +936,7 @@
 								} else if (res.code === 403) {
 									parent.location.href = baseUrl + "/login";
 								} else {
-									that.$message({
-										message: res.msg,
-										type: 'error'
-									});
+									that.showPageMessage(res.msg, 'error');
 								}
 							}
 						});
@@ -381,9 +1014,6 @@
 							return false;
 						}
 					},
-					handleCardClick(tab, event) {
-
-					},
 					//鑾峰彇搴撲綅鏁版嵁
 					getLocMastData() {
 						let that = this;
@@ -422,8 +1052,8 @@
 							return locInfo.row1 + '-' + locInfo.bay1;
 						}
 						return '';
-					},
-				}
+						},
+					}
 			})
 			</script>
 		</body>

--
Gitblit v1.9.1