Newer
Older
robot_dog_patrol_front / src / views / patrol / manage / index.vue
<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>