2026-05-25 09:10:10 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="page-container">
|
|
|
|
|
<div class="left-container">
|
|
|
|
|
<div class="robot-container">
|
|
|
|
|
<div class="robot-state">机器人状态</div>
|
|
|
|
|
<div class="robot-info" v-for="item, index in 2">
|
|
|
|
|
<div class="title-box">
|
|
|
|
|
<div><SvgIcon name="bot" :color="index === 0 ? '#00D4FF' : '#FFB300'" /></div>
|
|
|
|
|
<div class="title">巡检机器人#{{ index }}</div>
|
|
|
|
|
<div class="state" :class="robotState">在线</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="info-box">
|
|
|
|
|
<div class="item-box">
|
|
|
|
|
<div class="item-title">编号</div>
|
|
|
|
|
<div class="item-detail">RB-2024-001</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item-box">
|
|
|
|
|
<div class="item-title">当前任务</div>
|
|
|
|
|
<div class="item-detail">厂区A-定时巡检</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item-box">
|
|
|
|
|
<div class="item-title">电量</div>
|
|
|
|
|
<div class="item-detail">78%</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item-box">
|
|
|
|
|
<div class="item-title">速度</div>
|
|
|
|
|
<div class="item-detail">0.8m/s</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="split-line"></div>
|
|
|
|
|
<div class="task-container">
|
|
|
|
|
<div class="container-title">当前任务</div>
|
|
|
|
|
<div class="task-box" v-for="item, index in 2">
|
|
|
|
|
<div class="title">巡检机器人#{{ index }}</div>
|
|
|
|
|
<div class="task-info">
|
|
|
|
|
<div>执行中</div>
|
|
|
|
|
<div>厂区A定时巡检</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="map-container">
|
|
|
|
|
<div class="title-container">
|
|
|
|
|
<div class="title">
|
|
|
|
|
<SvgIcon name="map" color='#00D4FF' />
|
|
|
|
|
<span>实时地图 — 工厂园区</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="map-controller">
|
|
|
|
|
<div class="btn-container">
|
2026-05-29 13:54:45 +08:00
|
|
|
<SvgIcon name="zoom-in" color='#00D4FF' :size="16" @click="zoomCanvas(true)" />
|
2026-05-25 09:10:10 +08:00
|
|
|
</div>
|
|
|
|
|
<div class="btn-container">
|
2026-05-29 13:54:45 +08:00
|
|
|
<SvgIcon name="zoom-out" color='#00D4FF' :size="16" @click="zoomCanvas(false)" />
|
2026-05-25 09:10:10 +08:00
|
|
|
</div>
|
|
|
|
|
<div class="btn-container">
|
2026-05-29 13:54:45 +08:00
|
|
|
<SvgIcon name="locate-fixed" color='#00D4FF' :size="16" @click="centerCanvasView" />
|
2026-05-25 09:10:10 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="map-box">
|
2026-05-29 13:54:45 +08:00
|
|
|
<MapCanvas ref="mapCanvasRef" />
|
2026-05-25 09:10:10 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="right-container">
|
2026-06-12 17:27:59 +08:00
|
|
|
<!-- <div class="sensor-container">
|
2026-05-25 09:10:10 +08:00
|
|
|
<div class="sensor-title">传感器数据</div>
|
2026-06-12 17:27:59 +08:00
|
|
|
</div> -->
|
|
|
|
|
<!-- <div class="split-line"></div> -->
|
2026-05-25 09:10:10 +08:00
|
|
|
<div class="alarm-container">
|
|
|
|
|
<div class="container-title">告警记录</div>
|
|
|
|
|
<div class="alarm-box" v-for="item, index in 2">
|
|
|
|
|
<div class="title">#01 检测到异常噪声</div>
|
|
|
|
|
<div class="alarm-info">14:28:33 — 厂区A 东侧走廊</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import SvgIcon from "@/components/SvgIcon";
|
|
|
|
|
import MapCanvas from "./MapCanvas.vue";
|
|
|
|
|
import { onMounted, onUnmounted } from "vue";
|
|
|
|
|
|
2026-06-12 17:27:59 +08:00
|
|
|
console.log('sss', import.meta.env.VITE_INSPECTION_TYPE)
|
|
|
|
|
|
2026-05-25 09:10:10 +08:00
|
|
|
const robotState = ref('online')
|
|
|
|
|
|
2026-05-29 13:54:45 +08:00
|
|
|
const mapCanvasRef = ref(null)
|
2026-05-25 09:10:10 +08:00
|
|
|
|
2026-05-29 13:54:45 +08:00
|
|
|
const zoomCanvas = (isZoomIn) => {
|
|
|
|
|
if (mapCanvasRef.value) {
|
|
|
|
|
mapCanvasRef.value.zoomCanvas(isZoomIn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const centerCanvasView = () => {
|
|
|
|
|
if (mapCanvasRef.value) {
|
|
|
|
|
mapCanvasRef.value.centerCanvasView();
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-25 09:10:10 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.page-container {
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
|
|
.left-container {
|
|
|
|
|
width: 300px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
.robot-container {
|
|
|
|
|
max-height: 50%;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
|
|
|
|
.robot-state {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.robot-info {
|
|
|
|
|
width: 268px;
|
|
|
|
|
height: 148px;
|
|
|
|
|
background: #0F1E38;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
// border: 1px solid #00D4FF;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
|
|
.title-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-family: Inter;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.state {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 0 8px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.online {
|
|
|
|
|
background: #0f83;
|
|
|
|
|
color: #0f8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-box {
|
|
|
|
|
.item-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
margin: 6px 0;
|
|
|
|
|
|
|
|
|
|
.item-title {
|
|
|
|
|
color: #89B;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item-detail {
|
|
|
|
|
color: #e0e8f0;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.robot-info.last-child {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split-line {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 1px;
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
background: #1E3A5F;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-container {
|
|
|
|
|
max-height: 50%;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
|
|
|
|
.container-title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-box {
|
|
|
|
|
height: 72px;
|
|
|
|
|
background: #0F1E38;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-family: Inter;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin: 10px 0;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #E0E8F0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.map-container {
|
|
|
|
|
flex: 1;
|
|
|
|
|
border: 1px solid #1E3A5F;
|
|
|
|
|
border-top: 0;
|
|
|
|
|
|
|
|
|
|
.title-container {
|
|
|
|
|
height: 52px;
|
|
|
|
|
padding: 0 16px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.map-controller {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
|
|
.btn-container {
|
|
|
|
|
width: 32px;
|
|
|
|
|
height: 32px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
background: #1E3A5F;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
border-color: #00D4FF;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.map-box {
|
|
|
|
|
height: calc(100% - 52px);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.right-container {
|
|
|
|
|
width: 280px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
|
|
.sensor-container {
|
|
|
|
|
max-height: 50%;
|
|
|
|
|
height: 45%;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
|
|
|
|
.sensor-title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split-line {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 1px;
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
background: #1E3A5F;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.alarm-container {
|
|
|
|
|
max-height: 50%;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
|
|
|
|
.container-title {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.alarm-box {
|
|
|
|
|
height: 72px;
|
|
|
|
|
background: #0F1E38;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
color: #FF6B6B;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
font-family: Inter;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.alarm-info {
|
|
|
|
|
margin: 10px 0;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #8899BB;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|