<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>