|
@@ -100,48 +100,28 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 左侧面板 2:巡检任务 -->
|
|
|
|
|
|
|
+ <!-- 左侧面板 2:视觉巡查 -->
|
|
|
<div class="data-card video-monitor">
|
|
<div class="data-card video-monitor">
|
|
|
<div class="panel-header">
|
|
<div class="panel-header">
|
|
|
- <h3>巡检任务</h3>
|
|
|
|
|
|
|
+ <h3>视觉巡查</h3>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="panel-content">
|
|
<div class="panel-content">
|
|
|
- <!-- 任务列表 -->
|
|
|
|
|
- <div class="task-table">
|
|
|
|
|
- <div class="task-table-header">
|
|
|
|
|
- <div class="task-table-col task-name-col">任务名称</div>
|
|
|
|
|
- <div class="task-table-col task-duration-col">时长</div>
|
|
|
|
|
- <div class="task-table-col task-action-col">操作</div>
|
|
|
|
|
|
|
+ <!-- 巡查视角选择 -->
|
|
|
|
|
+ <div class="view-buttons">
|
|
|
|
|
+ <div class="sub-title view-btn" @click="selectView('map')">
|
|
|
|
|
+ 地图
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="task-table-body">
|
|
|
|
|
- <div class="task-table-row">
|
|
|
|
|
- <div class="task-table-col task-name-col">1号监测断面巡检</div>
|
|
|
|
|
- <div class="task-table-col task-duration-col">30分钟</div>
|
|
|
|
|
- <div class="task-table-col task-action-col">
|
|
|
|
|
- <button class="execute-btn">执行</button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="task-table-row">
|
|
|
|
|
- <div class="task-table-col task-name-col">测验设备区巡检</div>
|
|
|
|
|
- <div class="task-table-col task-duration-col">45分钟</div>
|
|
|
|
|
- <div class="task-table-col task-action-col">
|
|
|
|
|
- <button class="execute-btn">执行</button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="task-table-row">
|
|
|
|
|
- <div class="task-table-col task-name-col">汇水区巡检</div>
|
|
|
|
|
- <div class="task-table-col task-duration-col">20分钟</div>
|
|
|
|
|
- <div class="task-table-col task-action-col">
|
|
|
|
|
- <button class="execute-btn">执行</button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="task-table-row">
|
|
|
|
|
- <div class="task-table-col task-name-col">全站设备检查</div>
|
|
|
|
|
- <div class="task-table-col task-duration-col">60分钟</div>
|
|
|
|
|
- <div class="task-table-col task-action-col">
|
|
|
|
|
- <button class="execute-btn">执行</button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div class="sub-title view-btn" @click="selectView('robot')">
|
|
|
|
|
+ 机器人
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 视角显示区域 -->
|
|
|
|
|
+ <div class="view-display">
|
|
|
|
|
+ <img v-if="selectedView === 'map'" src="/src/assets/images/Heilin/导航.png" alt="地图视角" class="view-image" />
|
|
|
|
|
+ <img v-else-if="selectedView === 'robot'" src="/src/assets/images/Heilin/机器人视角.png" alt="机器人视角" class="view-image" />
|
|
|
|
|
+ <div v-else class="view-placeholder">
|
|
|
|
|
+ 请选择巡查视角
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -163,8 +143,33 @@
|
|
|
<div class="right-sidebar">
|
|
<div class="right-sidebar">
|
|
|
<!-- 右侧数据框容器 -->
|
|
<!-- 右侧数据框容器 -->
|
|
|
<div class="right-container">
|
|
<div class="right-container">
|
|
|
- <!-- 右侧面板 1:预警成果 -->
|
|
|
|
|
|
|
+ <!-- 右侧面板 1:任务详情 -->
|
|
|
<div class="data-card data-card-1">
|
|
<div class="data-card data-card-1">
|
|
|
|
|
+ <div class="panel-header">
|
|
|
|
|
+ <h3>任务详情</h3>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="panel-content">
|
|
|
|
|
+ <div class="task-detail-container">
|
|
|
|
|
+ <!-- 左侧:图标和文字 -->
|
|
|
|
|
+ <div class="task-detail-left">
|
|
|
|
|
+ <div class="task-status">执行中..</div>
|
|
|
|
|
+ <div class="task-icon">
|
|
|
|
|
+ <img src="/src/assets/images/Heilin/icon/cap/缆道.png" alt="缆道图标" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="task-time">开始时间:2026-03-11 10:00</div>
|
|
|
|
|
+ <div class="task-name">缆道巡检任务</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 右侧:仪表盘 -->
|
|
|
|
|
+ <div class="task-detail-right">
|
|
|
|
|
+ <div id="taskGauge" class="gauge-container"></div>
|
|
|
|
|
+ <div class="task-location">当前位置-水位自己台</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右侧面板 2:预警成果 -->
|
|
|
|
|
+ <div class="data-card data-card-2">
|
|
|
<div class="panel-header">
|
|
<div class="panel-header">
|
|
|
<h3>预警成果</h3>
|
|
<h3>预警成果</h3>
|
|
|
</div>
|
|
</div>
|
|
@@ -256,8 +261,8 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 右侧面板 2:历史任务 -->
|
|
|
|
|
- <div class="data-card data-card-2">
|
|
|
|
|
|
|
+ <!-- 右侧面板 3:历史任务 -->
|
|
|
|
|
+ <div class="data-card data-card-3">
|
|
|
<div class="panel-header">
|
|
<div class="panel-header">
|
|
|
<h3>历史任务</h3>
|
|
<h3>历史任务</h3>
|
|
|
</div>
|
|
</div>
|
|
@@ -400,13 +405,20 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, onMounted } from 'vue'
|
|
|
|
|
|
|
+import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
import { useRouter } from 'vue-router'
|
|
|
import GradientOverlay from '../components/gradient-overlay.vue'
|
|
import GradientOverlay from '../components/gradient-overlay.vue'
|
|
|
|
|
+import * as echarts from 'echarts'
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
const router = useRouter()
|
|
|
const showDetailModal = ref(false)
|
|
const showDetailModal = ref(false)
|
|
|
|
|
|
|
|
|
|
+// 视觉巡查相关变量
|
|
|
|
|
+const selectedView = ref('')
|
|
|
|
|
+const selectView = (view) => {
|
|
|
|
|
+ selectedView.value = view
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 巡检任务相关变量
|
|
// 巡检任务相关变量
|
|
|
const selectedRoute = ref('route1')
|
|
const selectedRoute = ref('route1')
|
|
|
const taskArea = ref('all')
|
|
const taskArea = ref('all')
|
|
@@ -448,10 +460,121 @@ const issueTask = () => {
|
|
|
alert('任务下达成功!')
|
|
alert('任务下达成功!')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+let taskGaugeChart = null
|
|
|
|
|
+
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
// 页面加载时的初始化逻辑
|
|
// 页面加载时的初始化逻辑
|
|
|
console.log('智能巡检页面加载完成')
|
|
console.log('智能巡检页面加载完成')
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化仪表盘
|
|
|
|
|
+ initTaskGauge()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ // 清理ECharts实例
|
|
|
|
|
+ if (taskGaugeChart) {
|
|
|
|
|
+ taskGaugeChart.dispose()
|
|
|
|
|
+ taskGaugeChart = null
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+const initTaskGauge = () => {
|
|
|
|
|
+ // 获取仪表盘容器
|
|
|
|
|
+ const gaugeContainer = document.getElementById('taskGauge')
|
|
|
|
|
+ if (gaugeContainer) {
|
|
|
|
|
+ console.log('Gauge container found:', gaugeContainer)
|
|
|
|
|
+ console.log('Container width:', gaugeContainer.clientWidth)
|
|
|
|
|
+ console.log('Container height:', gaugeContainer.clientHeight)
|
|
|
|
|
+
|
|
|
|
|
+ // 确保容器有足够的高度
|
|
|
|
|
+ if (gaugeContainer.clientHeight === 0) {
|
|
|
|
|
+ gaugeContainer.style.height = '150px'
|
|
|
|
|
+ console.log('Set container height to 150px')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 清理旧实例
|
|
|
|
|
+ if (taskGaugeChart) {
|
|
|
|
|
+ taskGaugeChart.dispose()
|
|
|
|
|
+ taskGaugeChart = null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化ECharts实例
|
|
|
|
|
+ taskGaugeChart = echarts.init(gaugeContainer)
|
|
|
|
|
+ console.log('ECharts instance initialized:', taskGaugeChart)
|
|
|
|
|
+
|
|
|
|
|
+ // 配置仪表盘选项
|
|
|
|
|
+ const option = {
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'gauge',
|
|
|
|
|
+ startAngle: 180,
|
|
|
|
|
+ endAngle: 0,
|
|
|
|
|
+ pointer: {
|
|
|
|
|
+ show: true
|
|
|
|
|
+ },
|
|
|
|
|
+ progress: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ overlap: false,
|
|
|
|
|
+ roundCap: true,
|
|
|
|
|
+ clip: false,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: '#00d5ff'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ axisLine: {
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ width: 10
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ splitLine: {
|
|
|
|
|
+ show: false
|
|
|
|
|
+ },
|
|
|
|
|
+ axisTick: {
|
|
|
|
|
+ show: false
|
|
|
|
|
+ },
|
|
|
|
|
+ axisLabel: {
|
|
|
|
|
+ show: false
|
|
|
|
|
+ },
|
|
|
|
|
+ detail: {
|
|
|
|
|
+ valueAnimation: true,
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ offsetCenter: [0, '70%'],
|
|
|
|
|
+ color: '#00d5ff'
|
|
|
|
|
+ },
|
|
|
|
|
+ data: [
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 75,
|
|
|
|
|
+ name: '任务进度',
|
|
|
|
|
+ title: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ offsetCenter: [0, '30%'],
|
|
|
|
|
+ color: '#ffffff'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 设置选项
|
|
|
|
|
+ taskGaugeChart.setOption(option)
|
|
|
|
|
+ console.log('Chart option set')
|
|
|
|
|
+
|
|
|
|
|
+ // 立即调整图表大小
|
|
|
|
|
+ taskGaugeChart.resize()
|
|
|
|
|
+ console.log('Chart resized')
|
|
|
|
|
+
|
|
|
|
|
+ // 监听窗口大小变化,调整图表大小
|
|
|
|
|
+ window.addEventListener('resize', () => {
|
|
|
|
|
+ if (taskGaugeChart) {
|
|
|
|
|
+ taskGaugeChart.resize()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error('Gauge container not found!')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
@@ -646,6 +769,10 @@ onMounted(() => {
|
|
|
padding: 15px;
|
|
padding: 15px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.data-card-1 .panel-content {
|
|
|
|
|
+ padding: 10px 15px 15px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.station-intro {
|
|
.station-intro {
|
|
|
min-height: 500px;
|
|
min-height: 500px;
|
|
|
}
|
|
}
|
|
@@ -655,7 +782,7 @@ onMounted(() => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.video-monitor {
|
|
.video-monitor {
|
|
|
- min-height: 350px;
|
|
|
|
|
|
|
+ min-height: 500px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* 设备状态区域 */
|
|
/* 设备状态区域 */
|
|
@@ -1645,10 +1772,164 @@ onMounted(() => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.data-card-1 {
|
|
.data-card-1 {
|
|
|
- min-height: 380px;
|
|
|
|
|
|
|
+ min-height: 250px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.data-card-2 {
|
|
.data-card-2 {
|
|
|
|
|
+ min-height: 200px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.data-card-3 {
|
|
|
min-height: 290px;
|
|
min-height: 290px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 任务详情相关样式 */
|
|
|
|
|
+.task-detail-container {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 15px;
|
|
|
|
|
+ height: 210px;
|
|
|
|
|
+ min-height: 210px;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ padding-top: 0;
|
|
|
|
|
+ margin-top: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-detail-left {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: flex-start;
|
|
|
|
|
+ gap: 2px;
|
|
|
|
|
+ margin-top: 0;
|
|
|
|
|
+ padding-top: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-status {
|
|
|
|
|
+ font-size: 25px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #00d5ff;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.8);
|
|
|
|
|
+ margin-bottom: 1px;
|
|
|
|
|
+ margin-top: 0;
|
|
|
|
|
+ padding-top: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-icon {
|
|
|
|
|
+ width: 105px;
|
|
|
|
|
+ height: 105px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ margin: 1px 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-icon img {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ object-fit: contain;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-time {
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(255, 255, 255, 0.3);
|
|
|
|
|
+ margin-top: 1px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-name {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #00ff88;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(0, 255, 136, 0.5);
|
|
|
|
|
+ margin-top: 1px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-detail-right {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: flex-start;
|
|
|
|
|
+ gap: 2px;
|
|
|
|
|
+ margin-top: 0;
|
|
|
|
|
+ padding-top: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.gauge-container {
|
|
|
|
|
+ width: 150px;
|
|
|
|
|
+ height: 150px;
|
|
|
|
|
+ min-width: 150px;
|
|
|
|
|
+ min-height: 150px;
|
|
|
|
|
+ max-width: 180px;
|
|
|
|
|
+ max-height: 180px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.task-location {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #00d5ff;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.8);
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 视觉巡查相关样式 */
|
|
|
|
|
+.view-buttons {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 5px;
|
|
|
|
|
+ margin-bottom: 2px;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ margin-top: -12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.view-btn {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100px;
|
|
|
|
|
+ height: 35px;
|
|
|
|
|
+ background-image: url('/src/assets/images/顶部小标题.png');
|
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
|
+ background-position: center;
|
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ padding-top: 4px;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #e0fcff;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.8);
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: transform 0.3s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.view-btn:hover {
|
|
|
|
|
+ transform: scale(1.05);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.view-display {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ min-height: 180px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ background: rgba(0, 20, 40, 0.7);
|
|
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ margin-top: 2px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.view-image {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ object-fit: cover;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.view-placeholder {
|
|
|
|
|
+ color: #00d5ff;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|