<script setup lang="ts"> import { ElMessage, ElMessageBox, ElTooltip } from 'element-plus' import controlImg from '@/assets/tempImages/control.png' import dog from '@/assets/tempImages/dog-picture.jpg' import dogArm from '@/assets/tempImages/dog-arm.jpg' import sgjc from '@/assets/tempImages/sgjc.jpg' import tyx from '@/assets/tempImages/tyx.jpg' import yrg from '@/assets/tempImages/yrg.jpg' const currentDevice = ref({ deviceName: '机器狗1号', deviceStatus: '工作中', battery: '80%', route: '路线一', speed: '2m/s', }) // 点击更换设备 const changeDevice = () => { ElMessageBox.confirm( '确定更换设备吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }, ).then(() => { ElMessage.success('更换成功') currentDevice.value = { deviceName: '机器狗2号', deviceStatus: '工作中', battery: '98%', route: '路线二', speed: '1.8m/s', } }) } // 点击解除绑定 const unbind = () => { ElMessageBox.confirm( '确定解除绑定吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }, ).then(() => { ElMessage.success('已解除绑定') }) } // -----------------------------------------------表格------------------------------------------------------ // 表格表头 const columns = ref([ { text: '巡检内容', value: 'content', align: 'center' }, { text: '巡检情况', value: 'situation', align: 'center' }, // { text: '附件', value: 'picture', align: 'center' }, ]) const listQuery = ref({ limit: 10, offset: 1, }) const list: any = ref([]) // 数据列表 const loading = ref(false) // ---------------------------------------图片----------------------------------------------------------------------- // 图片地址 const imageUrl = ref(null) // 图片引用 const imageRef = ref(null) // 画布引用 const canvasRef = ref(null) // 四个点的坐标 const points = ref([ { x: 100, y: 100, image: sgjc }, { x: 200, y: 200, image: tyx }, { x: 300, y: 100, image: yrg }, { x: 600, y: 50, image: dogArm }, ]) // 鼠标悬停的点 const hoveredPoint = ref(null) // 悬停点对应的图片 const hoveredPointImage = ref('') // 图片加载完成事件 const onImageLoad = () => { const canvas = canvasRef.value const ctx = canvas.getContext('2d') const image = imageRef.value // 设置画布大小与图片一致 canvas.width = image.width canvas.height = image.height // 绘制线段 for (let i = 0; i < points.value.length - 1; i++) { const p1 = points.value[i] const p2 = points.value[i + 1] ctx.beginPath() ctx.moveTo(p1.x, p1.y) ctx.lineTo(p2.x, p2.y) ctx.stroke() } // 绘制点和数字 points.value.forEach((point, index) => { ctx.beginPath() ctx.arc(point.x, point.y, 10, 0, 2 * Math.PI) ctx.fillStyle = 'rgba(12, 116, 210, 1)' ctx.fill() ctx.font = '16px Arial' ctx.fillStyle = 'white' ctx.textAlign = 'center' ctx.textBaseline = 'middle' ctx.fillText(index + 1, point.x, point.y) }) } // 鼠标移动事件 const onMouseMove = (event) => { console.log('鼠标移动事件', event) const rect = canvasRef.value.getBoundingClientRect() const mouseX = event.clientX - rect.left const mouseY = event.clientY - rect.top hoveredPoint.value = null hoveredPointImage.value = '' points.value.forEach((point) => { const dx = mouseX - point.x const dy = mouseY - point.y const distance = Math.sqrt(dx * dx + dy * dy) if (distance <= 10) { hoveredPoint.value = point hoveredPointImage.value = point.image console.log('悬浮图片', hoveredPointImage.value) } }) } // ---------------------------------------图片----------------------------------------------------------------------- onMounted(() => { list.value = [ { content: '施工监测', situation: '发现施工,请及时处置', picture: sgjc, }, { content: '调压箱检测', situation: '正常', picture: tyx, }, { content: '引入管检测', situation: '正常', picture: yrg, }, { content: '闸井检测', situation: '正常', picture: dogArm, }, ] // 如果图片已经加载完成,手动调用 onImageLoad 函数 // if (mainImageRef.value.complete) { onImageLoad() // } }) </script> <template> <app-container> <div class="patrol-manage"> <div class="box box-top"> <div class="box-top-item"> <!-- <img style="width: 100%; height: 300px" src="../../../assets/tempImages/2.jpg" > --> <div style="position: relative; width: fit-content;margin: 0 auto;"> <!-- 图片 --> <img ref="imageRef" style="width: 100%; height: 300px" src="../../../assets/tempImages/map.png" alt="Image" @mousemove="onMouseMove" @load="onImageLoad"> <!-- 画布 --> <canvas ref="canvasRef" /> </div> </div> <img v-if="hoveredPointImage" :src="hoveredPointImage" alt="Point Image" style="width: 600px; height: 500px;position: fixed;top: 100px;right: 10px;"> <div style="height: 100%; background-color: #ccc; width: 1px;" /> <div class="box-top-item"> <div class="box-title"> <div class="title"> <span>关联设备</span> <img style="width: 20px; height: 20px" src="../../../assets/tempImages/icon-link.svg" > </div> <div> <el-button type="primary" link @click="changeDevice"> 更换设备 </el-button> <el-button type="danger" link @click="unbind"> 解除绑定 </el-button> </div> </div> <div class="box-main"> <img style="width: 200px; height: 200px" src="../../../assets/tempImages/dog.png" > <div class="box-device"> <span> <span class="title">设备名称: </span> <span class="text">{{ currentDevice.deviceName }}</span> </span> <span> <span class="title">设备状态: </span> <span class="text" style="color: #afcc85">{{ currentDevice.deviceStatus }}</span> </span> <span> <span class="title">设备电量: </span> <span class="text">{{ currentDevice.battery }}</span> </span> <span> <span class="title">巡检路线: </span> <span class="text">{{ currentDevice.route }}</span> </span> <span> <span class="title">当前速度: </span> <span class="text">{{ currentDevice.speed }}</span> </span> </div> </div> </div> </div> <div class="box-middle"> <table-container title="巡检情况" style="margin-top: 0px !important;"> <normal-table :data="list" :total="total" :pagination="false" :columns="columns" :query="listQuery" :list-loading="listLoading" @change="changePage" > <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ (listQuery.offset - 1) * listQuery.limit + scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column label="附件" width="160" align="center" fixed="right"> <template #default="scope"> <el-image style="width: 100px; height: 100px" :src="scope.row.picture" :preview-src-list="[scope.row.picture]" /> </template> </el-table-column> <!-- <el-table-column label="操作" width="160" align="center" fixed="right"> <template #default="scope"> <el-button type="primary" link size="small" class="table-text-button" @click="handleEdit(scope.row)" > 详情 </el-button> </template> </el-table-column> --> </template> </normal-table> </table-container> </div> <!-- <div class="box box-bottom"> <div class="title"> <span>设备控制</span> <div> <el-button type="danger" @click="stop"> 急停 </el-button> <el-button type="primary" @click="restore"> 恢复 </el-button> </div> </div> <div style="margin-top: 10px;display: flex;justify-content: space-around;"> <div style="position: relative;"> <div class="control-title"> 机器狗控制 </div> <div name="four" style="width: 150px; height: 130px;"> <el-image style="width: 130px; height: 130px;position: absolute;top: 5px;left: 50px;" :src="controlImg" fit="fill"/> <el-image style="width: 200px; height: 200px;position: absolute;top: 5px;left: 200px;" :src="dog" fit="fill" /> <div> <div class="round-btn" style="top: 8px;left: 95px;" @mousedown="controlWithSpeed($event, 'up')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 90px;left: 95px;" @mousedown="controlWithSpeed($event, 'down')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 48px;left: 53px;" @mousedown="controlWithSpeed($event, 'left')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 48px;left: 135px;" @mousedown="controlWithSpeed($event, 'right')" @mouseup="controlWithSpeed($event, 'stop')" /> </div> </div> </div> <div style="position: relative;"> <div class="control-title" style="background-color: #a43bd1;"> 机械臂控制 </div> <div name="four" style="width: 320px; height: 130px;"> <img style="width: 130px; height: 130px;position: absolute;top: 5px;left: 50px;" :src="controlImg" fit="fill"> <img style="width: 200px; height: 200px;position: absolute;top: 5px;left: 200px;" :src="dogArm" fit="fill"> <div> <div class="round-btn" style="top: 8px;left: 95px;" @mousedown="controlWithSpeed($event, 'up')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 90px;left: 95px;" @mousedown="controlWithSpeed($event, 'down')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 48px;left: 53px;" @mousedown="controlWithSpeed($event, 'left')" @mouseup="controlWithSpeed($event, 'stop')" /> <div class="round-btn" style="top: 48px;left: 135px;" @mousedown="controlWithSpeed($event, 'right')" @mouseup="controlWithSpeed($event, 'stop')" /> </div> </div> </div> </div> </div> --> </div> </app-container> </template> <style scoped lang="scss"> .patrol-manage { display: flex; flex-direction: column; // gap: 10px; } .box { width: 100%; background-color: #fff; padding: 10px; border-radius: 7px; } .box-top { display: grid; /* 将容器划分为两列,左边占 2 份,右边占 1 份 */ grid-template-columns: 2fr 0.05fr 1fr; /* 设置列之间的间距为 20 像素 */ gap: 20px; .box-top-item { display: flex; flex-direction: column; // justify-content: center; // align-items: center; .box-title { font-size: 14px; font-weight: 600; display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; .title { display: flex; justify-content: space-between; align-items: center; } } .box-main { display:flex; height: 100%; // flex-direction: column; justify-content: space-around; align-items: center; .box-device { display: flex; flex-direction: column; line-height: 29px; color: rgba(0,0,0,1); font-size: 14px; text-align: left; font-family: SourceHanSansSC-regular; .text { font-weight: 600; } } } } } .box-bottom { display: flex; flex-direction: column; margin-top: 10px; .title { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .control-title { color: white; background-color: #ff9f11; border-bottom-right-radius: 10px; border-top-right-radius: 10px; line-height: 30px; font-weight: bold; text-align: center; letter-spacing: 1px; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif; writing-mode: vertical-rl; text-orientation: upright; width: 30px; height: 100px; } .round-btn { position: absolute; top: 14px; left: 129px; width: 42px; height: 42px; z-index: 111111; border-radius: 21px; cursor: pointer; &:hover { background-color: rgb(61 125 254 / 53%); } } } .image-points-container { position: relative; display: inline-block; } canvas { position: absolute; top: 0; left: 0; pointer-events: none; } .hover-point { position: absolute; width: 20px; height: 20px; border-radius: 50%; background-color: rgba(0, 30, 66, 0.5); pointer-events: none; } </style> <style lang="scss"> .patrol-manage { // 单元格样式 .el-table__cell { position: static !important; // 解决el-image 和 el-table冲突层级冲突问题 z-index: 99999999; } /* 隐藏默认的悬浮提示内容 */ .el-tooltip__content { display: none; } .el-tooltip.is-open .el-tooltip__content { display: block; } } </style>