vue 图片标记 可删除可编辑内容

<template>
  <div class="wrap">
    <div class="wrap-header">
      <el-form :inline="true" :model="formInline" class="demo-form-inline" size="mini">
        <el-form-item label="电压等级">
          <el-select v-model="formInline.region" placeholder="请选择">
            <el-option label="区域一" value="shanghai" />
          </el-select>
        </el-form-item>
        <el-form-item label="工单">
          <el-select v-model="formInline.region" placeholder="请选择">
            <el-option label="区域一" value="shanghai" />
          </el-select>
        </el-form-item>
        <el-form-item label="线路">
          <el-select v-model="formInline.region" placeholder="请选择">
            <el-option label="区域一" value="shanghai" />
          </el-select>
        </el-form-item>
        <el-form-item label="杆塔">
          <el-input v-model="formInline.user" placeholder="" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">此图片审核通过</el-button>
          <el-button type="primary" @click="onSubmit">完成任务</el-button>
        </el-form-item>
      </el-form>
      <div class="name">图片名称:123.jpg</div>
      <div class="total">
        <span>算法输出框总数:13</span>
        <span><i class="el-icon-circle-check" />1</span>
        <span><i class="el-icon-circle-close" />11</span>
        <span><i class="el-icon-question" />0</span>
        <span><i class="el-icon-thumb" />1</span>
      </div>
    </div>
    <el-row :gutter="0" class="container">
      <el-col :span="4"><div class="grid-content bg-purple container-item">
        <el-row :gutter="20" class="width100">
          <el-col :span="16"><div class="grid-content bg-purple">
            <div style="padding-left: 20px;font-size: 14px;">全部</div>
          </div></el-col>
          <el-col :span="8"><div class="grid-content bg-purple">23</div></el-col>
        </el-row>
        <el-row :gutter="20" class="width100">
          <el-col :span="16"><div class="grid-content bg-purple">
            <el-checkbox-group v-model="formInline.type">
              <el-checkbox label="已审" name="type" />
            </el-checkbox-group> </div></el-col>
          <el-col :span="8"><div class="grid-content bg-purple">3</div></el-col>
        </el-row>
        <el-row :gutter="20" class="width100">
          <el-col :span="16"><div class="grid-content bg-purple">
            <el-checkbox-group v-model="formInline.type">
              <el-checkbox label="未审" name="type" />
            </el-checkbox-group> </div></el-col>
          <el-col :span="8"><div class="grid-content bg-purple">20</div></el-col>
        </el-row>
        <div class="demo-image__lazy">
          <div class="block">
            <el-image v-for="url in urls" :key="url" :src="url" lazy class="active" @click="chooseImg(url)">
              <div slot="error" class="image-slot">
                <i class="el-icon-picture-outline" />
              </div>
            </el-image>
          </div>
        </div>
      </div></el-col>
      <el-col :span="16"><div class="grid-content bg-purple container-item main">
        <div ref="myedit" class="myedit">
          <el-image :src="img" fit="fill" @mousedown.prevent="onMousedown" @contextmenu.prevent="oncontextmenu" />
        </div>
        <div class="imageLabel-content">
          <span
            v-for="(item, index) in mydata"
            :key="index"
            class="myedit-span"
            :style="getSpanStyle(item)"
            title="双击修改"
            @dblclick="editImgMark(item)"
          >
            <span> {{ item.text }}</span>
            <i class="el-icon-close" title="点击删除" @click="close(item, index)" />
          </span>
        </div>
      </div></el-col>
      <el-col :span="4"><div class="grid-content bg-purple container-item">1111</div></el-col>
    </el-row>
    <el-dialog
      :visible.sync="dialog"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      width="30%"
      title="审核"
      :before-close="handleClose"
    >
      <div class="dialog-content">
        <el-input v-model="input" placeholder="请输入内容" />
      </div>
      <br>
      <div style="text-align:center;">
        <el-button @click="sureLabel(false)">取 消</el-button>
        <el-button type="primary" @click="sureLabel(true)">确 定</el-button>
      </div>
      <br>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      formInline: {
        user: '',
        region: '',
        type: []
      },
      urls: [
        'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
        'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
        'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
        'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
        'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
        'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
        'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg'
      ],
      img: '',
      mydata: [],
      mymenu: { current: null, style: { left: 0, top: 0 }},
      dialog: false,
      input: '',
      currentId: '',
      edit: false,
      doDrawing: false
    }
  },
  mounted() {
    // 事件要添加在document上,否则事件会失效
    document.addEventListener('mousemove', this.onMousemove, true)
    document.addEventListener('mouseup', this.onMouseup, true)
  },
  beforeDestroy() {
    document.removeEventListener('mousemove', this.onMouseup)
    document.removeEventListener('mouseup', this.onMouseup)
  },
  methods: {
    onSubmit() {
      console.log('submit!')
    },
    load() {
    },
    chooseImg(url) {
      this.img = url
      this.mydata = []
    },
    getXY(e) {
      if (this.$refs.myedit) {
        const rect = this.$refs.myedit.getBoundingClientRect()
        return {
          x: e.clientX - rect.left,
          y: e.clientY - rect.top
        }
      }
    },
    oncontextmenu(e) {
      return !1
    },
    onm ousedown(e) {
      this.doDrawing = true
      this.mymenu.current = null
      const { x, y } = this.getXY(e)
      this.currentItem = { x, y, w: 0, h: 0, now: Date.now(), id: this.mydata.length }
      this.startPos = { x, y }
      this.mydata.push(this.currentItem)
      document.addEventListener('mouseup', this.onMouseup, true)
    },
    onm ousemove(e) {
      if (e.target.localName !== 'img') return
      if (!this.currentItem || !this.doDrawing) return
      const { x, y } = this.getXY(e)
      this.currentItem.w = Math.abs(x - this.startPos.x)
      this.currentItem.h = Math.abs(y - this.startPos.y)
    },
    onm ouseup(e) {
      if (this.currentItem) {
        this.mydata = this.mydata.filter(_ => _.w > 10 && _.h > 10)
        this.dialog = true
        this.doDrawing = false
      }
      this.currentItem = this.startPos = null
    },
    pauseEvent(e) {
      if (e.stopPropagation) e.stopPropagation()
      if (e.preventDefault) e.preventDefault()
      e.cancelBubble = true
      e.returnValue = false
      return false
    },
    onContextmenu(item, e) {
      this.mymenu = {
        current: item,
        style: {
          top: e.clientY + 'px',
          left: e.clientX + 'px'
        }
      }
    },
    getSpanStyle(item) {
      return {
        width: `${item.w}px`,
        height: `${item.h}px`,
        top: `${item.y}px`,
        left: `${item.x}px`
      }
    },
    editImgMark(item) {
      this.input = item.text
      this.currentId = item.id
      this.edit = true
      this.dialog = true
      console.log('item', item)
    },
    // 删除
    close(item, index) {
      this.mydata.splice(index, 1)
    },
    /**
         * @desc 标注完后添加备注信息
         * @param flag {Boolean}   取消或确认
         * */
    sureLabel(flag) {
      if (this.edit) {
        this.mydata.forEach(item => {
          if (item.id === this.currentId) {
            item.text = this.input
          }
        })
      } else {
        const end = this.mydata[this.mydata.length - 1]
        if (end) {
          end.text = this.input
          this.mydata.concat([])
        }
      }

      this.input = ''
      this.dialog = false
    },
    /*
       * @desc 模态框关闭事件
       * */
    handleClose() {
      this.dialog = false
    }
  }
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>

.wrap{
    box-sizing: border-box;
    width: 100%;
    .el-header, .el-footer {
    background-color: #B3C0D1;
    color: #333;
    padding: 10px 15px;
    box-sizing: border-box;
  }
   .width100 {
      width: 110px !important;
    }

.wrap-header {
     background-color: #D3DCE6;
     height: 100px;
     width: 100%;
     display: inline-block;
     padding: 10px;
     box-sizing: border-box;
     position: relative;
     .name {
         position: absolute;
         top: 58px;
         left: 50%;
         transform: translateX(-50%);
     }
     .total {
         position: absolute;
         top: 58px;
         right: 10px;
         span {
             margin-right: 5px;
         }
         .el-icon-circle-check {
             color: #67C23A;
         }
         .el-icon-circle-close {
             color: red;
         }
         .el-icon-question {
             color: #4C6EB2;
         }
         .el-icon-thumb {
             color: #F211A1;
         }
     }
}
  .el-aside {
    background-color: #D3DCE6;
    color: #333;
    padding: 10px;
    overflow-y: auto;
  }
  .container {
    height: calc(100vh - 184px);
    .container-item {
      height: calc(100vh - 200px);
      &:first-child {
        overflow-x: hidden;
        overflow-y: auto;
        padding: 10px;
        box-sizing: border-box;
      }
    }
    .demo-image__lazy {
      margin-top: 10px;
    }
  }
  .main {
      padding: 10px;
      text-align: center;
      position: relative;
      .el-image {
          width: 100%;
          height: 100%;
          box-sizing: border-box;
      }
       .myedit {
        position: relative;
        height: calc(100vh - 200px);
        width: 100%;
        border: 1px solid #dddeea;
        .el-image {
          width: auto;
          height: 100%;
          box-sizing: border-box;
      }
       }
       .imageLabel-content {
         position: absolute;
         top: 0;
        height: calc(100vh - 200px);
       }
      .myedit-span {
        position: absolute;
        border: 1px dashed red;
        // background-color: #fff;
        z-index: 1;
        text-align: center;
        padding-top: 3px;
        &:hover {
          background-color: rgba($color: #000000, $alpha: 0.4);
        }
        i {
          cursor: pointer;
          font-size: 18px;
          color: red;
          font-weight: 700;
        }
        .el-icon-close {
          position: absolute;
          top: 0px;
          right: 5px;
        }
      }
  }
  .active {
      border: 1px solid #67C23A;
      padding: 4px;
  }
}
</style>

  

上一篇:Vue+TypeScript+TSX


下一篇:配置docker的阿里云镜像加速并安装mysql