From ecb6cadc3f016cf9968f48e0cc77479a1e56365b Mon Sep 17 00:00:00 2001 From: hanbaoshan <hanbaoshan@aiotlink.com> Date: 星期日, 20 十二月 2020 17:32:06 +0800 Subject: [PATCH] 标定添加关联摄像机tab,绘制区域组件参数更新 --- src/pages/labelMark-copy/index/App.vue | 118 ++ src/components/canvas/Dialog.vue | 26 src/pages/desktop/index/components/ToolsEntry.vue | 16 src/pages/labelMark/index/main.ts | 3 src/components/canvas/index.vue | 18 src/pages/labelMark-copy/index/main.ts | 17 src/pages/cameraAccess/components/scene/SlideScene.vue | 22 src/pages/labelMark-copy/components/RightSide.vue | 986 +++++++++++++++++ src/scripts/util.js | 19 src/api/camera.ts | 27 src/pages/labelMark/components/RightSide.vue | 831 ++++++++++++-- src/pages/labelMark/components/SlideCanvas.vue | 222 +++ src/api/polygon.ts | 31 src/pages/labelMark/components/RightSide-COPY.vue | 862 ++++++++++++++ src/pages/labelMark/index/App.vue | 10 src/pages/labelMark-copy/index/mixins.ts | 14 src/pages/labelMark-copy/components/SlideCanvas.vue | 225 +++ 17 files changed, 3,275 insertions(+), 172 deletions(-) diff --git a/src/api/camera.ts b/src/api/camera.ts index 4705f56..e830ecf 100644 --- a/src/api/camera.ts +++ b/src/api/camera.ts @@ -189,4 +189,29 @@ method: 'post', data }) -} \ No newline at end of file +} + +//淇濆瓨鎽勫儚鏈哄垎缁� +export const saveCameraGroupInfo = (data:any) => { + return request({ + url: '/data/api-v/camera/group/save', + method: 'post', + data + }) +} + +//鏌ヨ鎽勫儚鏈哄垎缁勪俊鎭� +export const findCameraGroups = () => { + return request({ + url: '/data/api-v/camera/group/findAll', + method: 'get' + }) +} + +export const delCameraGroup = (groupId:string)=>{ + return request({ + url:'/data/api-v/camera/group/del?groupId='+groupId, + method: 'post' + }) +} + diff --git a/src/api/polygon.ts b/src/api/polygon.ts index cfa4bf9..c7d1202 100644 --- a/src/api/polygon.ts +++ b/src/api/polygon.ts @@ -23,3 +23,34 @@ data: params }); }; + +export const findByCamGroup = (query: any) => { + return request({ + url:'/data/api-v/polygon/findByCamGroup', + method: 'get', + params: query + }); +} + +export const saveRelationPolygon = (data: any) => { + return request({ + url: "/data/api-v/polygon/relation/save", + method: "post", + data + }); +} + +export const findByGroup = (query:any) =>{ + return request({ + url:"/data/api-v/polygon/relation/findByGroup", + method: "get", + params: query + }) +} + +export const delRelation = (id:string) => { + return request({ + url: "/data/api-v/polygon/relation/del?id="+id, + method: "post" + }) +} \ No newline at end of file diff --git a/src/components/canvas/Dialog.vue b/src/components/canvas/Dialog.vue index e0f11e1..da99d2b 100644 --- a/src/components/canvas/Dialog.vue +++ b/src/components/canvas/Dialog.vue @@ -198,7 +198,8 @@ methods: { // 鍒濆鍖栧嚱鏁� init() { - this.c = document.querySelector("#canvasDialog"); + //this.c = document.querySelector("#canvasDialog"); + this.c = this.$refs['canvasDialog']; this.ctx = this.c.getContext("2d"); this.drawCanvasInit(); this.canvasData = JSON.parse(JSON.stringify(this.canvasDataToChild)); @@ -394,7 +395,6 @@ }, // 鍒犻櫎鍏冪礌 del() { - debugger let delEle = {}; switch (this.delCursor.type) { case "1": @@ -411,7 +411,7 @@ break; case "5": delEle = this.canvasData.polygon[this.delCursor.index]; - this.canvasData.polygon.splice(this.delCursor.index+1, 1); + this.canvasData.polygon.splice(this.delCursor.index, 1); break; } this.clickSelect(); @@ -522,6 +522,7 @@ } }); _this.canvasData.rect.forEach(function (v, i) { + _this.ctx.strokeStyle = "yellow"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x, v.location[0].y); @@ -788,6 +789,7 @@ // console.log("鎾ら攢锛�",this.canvasData); }, disabledOthers(type) { + console.log("褰撳墠type:", type) switch (type) { case "1": @@ -825,6 +827,7 @@ console.log("绂佺敤澶氳竟褰細", this.disablePolygon) }, undisabled() { + this.disableLine = false this.disableRect = false this.disableArrow = false @@ -854,7 +857,7 @@ width = typeof width !== "undefined" ? width : 1; // color = typeof color !== 'undefined' ? color : 'yellow' // 璁$畻鍚勮搴﹀拰瀵瑰簲鐨凱2,P3鍧愭爣 - debugger + let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI; let angle1 = ((angle + theta) * Math.PI) / 180; let angle2 = ((angle - theta) * Math.PI) / 180; @@ -884,6 +887,7 @@ }, // 鑾峰彇鐩稿鍧愭爣(鏆備笉鐢�) getLocation(x, y, c) { + let bbox = c.getBoundingClientRect(); return { x: (x - bbox.left) * (c.width / bbox.width), @@ -898,6 +902,7 @@ }, // 鐢熸垚鍥惧舰澶囨敞 remarks(x, y, type) { + this.ctx.moveTo(x, y - 20); this.ctx.fillStyle = "green"; // 璁剧疆濉厖棰滆壊涓虹豢鑹� this.ctx.font = '20px "寰蒋闆呴粦"'; // 璁剧疆瀛椾綋 @@ -927,6 +932,7 @@ }, // 鍥炴樉鍥惧舰澶囨敞 showRemarks(x, y, remarks, isHightlight) { + this.ctx.moveTo(x, y - 20); if (isHightlight) { this.ctx.fillStyle = "#8ae22e"; // 璁剧疆濉厖棰滆壊涓虹豢鑹� @@ -940,6 +946,7 @@ }, // 閲嶇幇淇濆瓨鐢婚潰 loadImage() { + if (this.step > -1) { let img = new Image(); img.src = this.canvasHistory[this.step].src; @@ -948,6 +955,7 @@ }, // 鍒囨崲鐢荤嚎绫诲瀷 changeType(num) { + if (num === '0') { this.c.style.cursor = "pointer"; } else { @@ -957,6 +965,7 @@ }, // 缁樺埗澶氳竟褰㈡柟娉� drawPolygonUtil(points) { + this.ctx.strokeStyle = "yellow"; this.ctx.lineWidth = 2; this.ctx.beginPath(); @@ -983,6 +992,7 @@ }, // 鐢荤煩褰㈢Щ鍔ㄥ嚱鏁� drawRect(e) { + if (this.flag) { this.ctx.clearRect(0, 0, this.c.width, this.c.height); this.loadImage(); @@ -1017,11 +1027,13 @@ } }, twoPointDistance(p1, p2) { + let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2)); return dep; }, // 鐢诲杈瑰舰绉诲姩鍑芥暟 drawPolygon(e) { + if (this.flag) { this.ctx.clearRect(0, 0, this.c.width, this.c.height); this.loadImage(); @@ -1040,6 +1052,7 @@ }, // 鐢荤洿绾挎姮璧� lineMouseUp(e) { + if ( Math.abs(this.originX - e.offsetX) < 5 && Math.abs(this.originY - e.offsetY) < 5 @@ -1096,6 +1109,7 @@ }, // 鐢荤煩褰㈡姮璧� rectMouseUp(e) { + if ( Math.abs(this.originX - e.offsetX) < 5 && Math.abs(this.originY - e.offsetY) < 5 @@ -1218,6 +1232,7 @@ }, // 鐢诲杈瑰舰缁撴潫鏃跺弻鍑� polygonDblclick(e) { + this.flag = false; this.points.pop(); // 鍙屽嚮涔嬪悗澶氫竴涓偣鐨勯噸澶嶅潗鏍囷紝闇�瑕佸垹闄� let Id @@ -1265,6 +1280,7 @@ }, // 閲婃斁缂栬緫鐘舵�� freedEdit() { + this.editObj = {} }, // 鍥炴樉鍘嗗彶鏁版嵁鏃惰绠椾竴涓嬪洖鏄剧殑姣忕鍏冪礌鐨勬暟閲忎互渚跨敓鎴愬浘褰㈡敞瑙f椂鑾峰緱姝g‘鐨勫紑澶� @@ -1279,6 +1295,7 @@ }, // 鐢熸垚uuid getUuid() { + let originStr = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; let originChar = "0123456789abcdef"; let len = originChar.length; @@ -1288,6 +1305,7 @@ }, // 鍒ゆ柇涓�涓偣鏄惁绂讳竴涓浘褰㈢殑鏈�灏忚窛绂讳负n鍍忕礌浠ュ唴 minDistance(x, y, locations, n) { + let flag = false for (let i = 0; i < locations.length; i++) { if (i == locations.length - 1) { diff --git a/src/components/canvas/index.vue b/src/components/canvas/index.vue index c26ef7b..a7dae5a 100644 --- a/src/components/canvas/index.vue +++ b/src/components/canvas/index.vue @@ -1,10 +1,10 @@ <template> - <div class="s-cavas"> + <div class="s-cavas" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"> <canvas ref="myCanvas" :width="canvasWidth" :height="canvasHeight" - :style="`background:url(${canvasBg}) center / 576px 324px no-repeat; background-size: contain;`" + :style="`background:url(${canvasBg}) center / ${canvasWidth}px ${canvasHeight}px no-repeat; background-size: contain;`" ></canvas> <el-tooltip content="鍒锋柊搴曞浘" placement="bottom" popper-class="atooltip" v-if="isShowRefresh"> @@ -93,6 +93,10 @@ canvasHeight: { type: Number, default: 324 + }, + showProportion: { + type: Number, + default: 1.666 } }, computed: { @@ -124,7 +128,7 @@ ctx: null, visible: false, baseImg: undefined, - showProportion: 1.666 + //showProportion: 1.666 }; }, watch: { @@ -193,10 +197,11 @@ this.$nextTick(() => { // this.$refs.bigCanvas.delCursor = {} }) + }, cancelFunc() { this.visible = false; - this.$refs.bigCanvas.cancel() + this.$refs.bigCanvas.cancel(); // console.log("鍏抽棴浜�"); }, handleOk() { @@ -220,6 +225,7 @@ // 椤轰究鐢╁埌鏇村灞傚幓 this.$emit("fromCanvas", this.$refs.bigCanvas.canvasData); // console.log("浣犲ソ", this.canvasData); + this.clickSelect(this.canvasData); this.visible = false; }, @@ -501,8 +507,8 @@ left: 0; } .s-cavas { - width: 576px; - height: 324px; + // width: 576px; + // height: 324px; margin-top: 10px; position: relative; overflow: auto; diff --git a/src/pages/cameraAccess/components/scene/SlideScene.vue b/src/pages/cameraAccess/components/scene/SlideScene.vue index 4bf640f..ee755f0 100644 --- a/src/pages/cameraAccess/components/scene/SlideScene.vue +++ b/src/pages/cameraAccess/components/scene/SlideScene.vue @@ -79,6 +79,7 @@ </template> <script> +import {chunkArr} from '@/scripts/util'; export default { props: [ // 'swiperOption', @@ -130,27 +131,10 @@ // this.mySwiper = this.$refs.sceneSwiper.swiper; }, - methods: { - //鎷嗗垎浜岀淮鏁扮粍 - chunk(arr, size = 1) { - if (arr.length == 0) return; - const tempContainer = []; - let innerArr = []; - arr.forEach(item => { - if (innerArr.length == 0) { - tempContainer.push(innerArr); - } - innerArr.push(item); - if (innerArr.length == size) { - innerArr = []; - } - }); - return tempContainer; - } - }, + computed: { slides() { - return this.chunk(this.mockSceneData, 5); + return chunkArr(this.mockSceneData, 5); } } }; diff --git a/src/pages/desktop/index/components/ToolsEntry.vue b/src/pages/desktop/index/components/ToolsEntry.vue index cbc5e4f..6d329c8 100644 --- a/src/pages/desktop/index/components/ToolsEntry.vue +++ b/src/pages/desktop/index/components/ToolsEntry.vue @@ -64,6 +64,7 @@ <script> import draggable from "vuedraggable" import { findAllSdk } from '@/api/taskMange'; +import {chunkArr} from '@/scripts/util'; export default { name: 'toolsEntry', components: { draggable }, @@ -84,7 +85,7 @@ title: '浜哄憳璺熻釜' } ], - rowSize: 3, + //rowSize: 3, badgeNum: 0, } }, @@ -100,14 +101,23 @@ let arr = null; //鏍规嵁灞忓箷楂樺害鏉ュ垽鏂槸灞曠ず3鎺掕繕鏄�4鎺� 闃堝��:970 if (window.innerHeight >= 930) { - this.rowSize = 4; + //this.rowSize = 4; arr = this.chunk(tempArr, 24); + //arr = chunkArr(tempArr,24); } else { - this.rowSize = 3; + //this.rowSize = 3; arr = this.chunk(tempArr, 18); + //arr = chunkArr(tempArr, 18); } console.log(arr) return arr + }, + rowSize (){ + if (window.innerHeight >= 930) { + return 4; + }else{ + return 3; + } } }, mounted () { diff --git a/src/pages/labelMark-copy/components/RightSide.vue b/src/pages/labelMark-copy/components/RightSide.vue new file mode 100644 index 0000000..a6a86c1 --- /dev/null +++ b/src/pages/labelMark-copy/components/RightSide.vue @@ -0,0 +1,986 @@ +<template> + <div class="right-side"> + + <div class="figure s-system-manage"> + <el-tabs + id="e-basic-setting" + @tab-click="changeTab" + v-model="actPage" + v-loading="loading" + element-loading-text="鍔犺浇涓�" + type="border-card" + > + <el-tab-pane label="浣嶇疆鏍囨敞" name="1"> + <el-tabs type="border-card"> + <el-tab-pane label="鎽勫儚鏈烘爣娉�" name="11"> + <div class> + <div class="action-bar"> + <div class="tool-bar"> + <div> + <!-- <input type="color" ref="colorPicker" v-model="color"> --> + <label for>鎷捐壊鍣�:</label> + <el-color-picker v-model="colorPick" show-alpha size="mini"></el-color-picker> + </div> + <div style="width:250px;"> + <label for>绗旇Е:</label> + <el-slider v-model="dotSize" :min="1" :max="20"></el-slider> + </div> + <div> + <el-button + v-if="!isEdit" + class="drawboard-trigger" + size="small" + @click="editCameraData" + icon="el-icon-edit" + >缂栬緫</el-button> + + <el-button + v-if="isEdit" + class="drawboard-trigger save" + size="small" + @click="submitInfo" + icon="el-icon-lock" + >淇濆瓨</el-button> + </div> + </div> + </div> + <div class="drawboard shadow-box"> + <div class="mask" :class="{'edit-status-mask':isEdit}" ref="editBoard"> + <div + class="label" + @click="editLabel(item)" + v-for="(item,index) in curCameraData.coords" + :key="index" + :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: colorPick, width: `${dotSize}px`, height: `${dotSize}px` }" + ></div> + </div> + <img v-show="snapshot_url" :src="`/httpImage/${snapshot_url}`" alt /> + <div + class="popBox" + v-show="isShowPop" + :style="`top:${curLabel.y0 + 22}px;left:${curLabel.x0}px`" + > + <div class="title">鏍囨敞淇℃伅</div> + <div class="details"> + <el-form :model="curLabel" :rules="rules" ref="labelForm"> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="x0"> + <label for>骞抽潰鍧愭爣X:</label> + <span class="fix-width">{{curLabel.x0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="x1"> + <label for>瀹為檯鍧愭爣X:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.x1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="y0"> + <label for>骞抽潰鍧愭爣Y:</label> + <span class="fix-width">{{curLabel.y0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="y1"> + <label for>瀹為檯鍧愭爣Y:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.y1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="btns"> + <el-button size="mini" type="danger" @click="deleteLabel">鍒犻櫎</el-button> + <el-button size="mini" type="primary" @click="cancle">鍙栨秷</el-button> + <el-button size="mini" type="success" @click="sure">纭畾</el-button> + </div> + </el-form> + </div> + </div> + </div> + </div> + </el-tab-pane> + <el-tab-pane label="瀹炴櫙鍧愭爣" name="12"> + <div class="user-upload"> + <div class="img-card"> + <el-upload + class="upload-demo" + drag + action="https://jsonplaceholder.typicode.com/posts/" + :http-request="definedUpload" + :on-change="onChange" + :show-file-list="false" + > + <el-image + class="preview" + v-if="userImg" + :src="userImg" + fit="contain" + @mousemove="showCurPos" + @mouseout="isShowCurPos=false" + ></el-image> + <div class="el-upload__text"> + 灏嗘枃浠舵嫋鍒版澶勶紝鎴� + <em>鐐瑰嚮涓婁紶</em> + </div> + </el-upload> + </div> + <div class="info"> + <div class="input-area"> + <div> + <label for>绌洪棿瀹�:</label> + <el-input v-model="spaceWidth" placeholder="璇疯緭鍏ュ疄闄呯┖闂村" size="small"></el-input> + </div> + <div> + <label for>绌洪棿楂�:</label> + <el-input v-model="spaceHeight" placeholder="璇疯緭鍏ュ疄闄呯┖闂撮珮" size="small"></el-input> + </div> + </div> + <div class="pos" v-show="isShowCurPos"> + 褰撳墠浣嶇疆: + <b>{{traceX}}</b>, + <b>{{traceY}}</b> + </div> + </div> + </div> + </el-tab-pane> + </el-tabs> + </el-tab-pane> + <el-tab-pane label="杞ㄨ抗鍥�" name="2"></el-tab-pane> + <!-- <el-tab-pane label="杩借釜瀹炴櫙鍧愭爣" name="2"> + <div class="user-upload"> + <div class="img-card"> + <el-upload + class="upload-demo" + drag + action="https://jsonplaceholder.typicode.com/posts/" + :http-request="definedUpload" + :on-change="onChange" + :show-file-list="false" + > + <el-image + class="preview" + v-if="userImg" + :src="userImg" + fit="contain" + @mousemove="showCurPos" + @mouseout="isShowCurPos=false" + ></el-image> + <div class="el-upload__text"> + 灏嗘枃浠舵嫋鍒版澶勶紝鎴� + <em>鐐瑰嚮涓婁紶</em> + </div> + </el-upload> + </div> + <div class="info"> + <div class="input-area"> + <div> + <label for>绌洪棿瀹�:</label> + <el-input v-model="spaceWidth" placeholder="璇疯緭鍏ュ疄闄呯┖闂村" size="small"></el-input> + </div> + <div> + <label for>绌洪棿楂�:</label> + <el-input v-model="spaceHeight" placeholder="璇疯緭鍏ュ疄闄呯┖闂撮珮" size="small"></el-input> + </div> + </div> + <div class="pos" v-show="isShowCurPos"> + 褰撳墠浣嶇疆: + <b>{{traceX}}</b>, + <b>{{traceY}}</b> + </div> + </div> + </div> + </el-tab-pane>--> + <el-tab-pane label="鍏宠仈鎽勫儚鏈�" name="3"> + <div class="tab-relation"> + <div class="part"> + <div class="title"> + <span>鍏宠仈璁惧鍒嗙粍</span> + <el-button @click="newGroup" icon="el-icon-plus" size="mini" type="primary">鏂板缓鍒嗙粍</el-button> + </div> + <el-alert + type="info" + title="鎻愮ず:璇风偣鍑讳笂鏂�'鏂板缓鍒嗙粍'鎸夐挳寤虹珛鍒嗙粍" + show-icon + v-if="groupList.length==0" + ></el-alert> + <div class="flex-box"> + <div + class="group-card" + v-for="(group,index) in groupList" + :key="index" + @click="checkCurrentGroup(group)" + > + <div class="top"> + <div class="left"> + <span class="icon el-icon-video-camera"></span> + </div> + <div class="right"> + <div class="name">{{group.name}}</div> + <div class="details"> + 鎽勫儚鏈�: + <span + class="sub" + v-for="camera in group" + :key="camera.id" + >{{camera.name}}</span> + </div> + </div> + </div> + <div class="bottom"> + <span @click.stop="editGroup(group)">缂栬緫鍒嗙粍</span> + <span @click.stop="removeGroup(group)">鍒犻櫎鍒嗙粍</span> + </div> + </div> + </div> + </div> + <!-- <div class="part" v-if="groupList.length"> --> + <div class="part" v-if="Object.keys(curGroup)"> + <div class="title">缁樺埗鍖哄煙(鐢ㄤ簬绠楁硶鍒嗘瀽)</div> + <div class="relative-partment" v-if="curGroup.cameras&&curGroup.cameras.length"> + <div class="area-wrap" v-for="i in 2" :key="'sc'+i"> + <slide-canvas :cameras="curGroup.cameras"></slide-canvas> + </div> + </div> + </div> + <div class="part relative-config" v-if="Object.keys(curGroup)"> + <div class="title"> + <div class="left"> + <span>鍏宠仈鍖哄煙閰嶇疆</span> + </div> + <div class="right"> + <el-button + icon="el-icon-plus" + size="mini" + type="primary" + @click="addRelation" + >娣诲姞鍏宠仈</el-button> + </div> + </div> + <div class="relative-list"> + <div class="relative-item" v-for="(item,index) in relativeList" :key="index"> + <div class="left"> + <el-select v-model="item.cameraArea1" size="small"> + <el-option></el-option> + </el-select> + <i class="el-icon-connection"></i> + <el-select v-model="item.cameraArea2" size="small"> + <el-option></el-option> + </el-select> + </div> + <div class="right"> + <div class="btn-del" @click="delRelation(item)"> + <i class="el-icon-delete"></i> + </div> + </div> + </div> + </div> + </div> + </div> + </el-tab-pane> + </el-tabs> + <el-dialog class="dialog-group" title="鏂板缓鍒嗙粍" :visible.sync="groupModelVisible"> + <el-form :model="groupForm" ref="groupForm"> + <el-form-item> + <label>鍒嗙粍鍚嶇О</label> + <div> + <el-input v-model="groupForm.name"></el-input> + </div> + </el-form-item> + <el-form-item> + <label>閫夋嫨鎽勫儚鏈�</label> + <div> + <el-select v-model="groupForm.cameras" value-key="id" multiple> + <el-option + :label="camera.name" + :value="camera" + v-for="camera in cameraData" + :key="camera.id" + ></el-option> + </el-select> + </div> + </el-form-item> + <div class="btns"> + <el-button @click="groupModelVisible=false;">鍙栨秷</el-button> + <el-button type="primary" @click="confirmGroupDialog">纭畾</el-button> + </div> + </el-form> + </el-dialog> + </div> + </div> +</template> + +<script> +import { getCamerasByServer } from '@/api/pollConfig'; +import { getCameraMarks, updateCameraMarks } from '@/api/camera'; +import { getSearchList } from '@/api/search'; +import TreeDataPool from "@/Pool/TreeData"; +import { isNonnegativeInteger } from '@/scripts/validate'; +import { getAllPolygon } from '@/api/polygon'; +import SlideCanvas from './SlideCanvas'; + +export default { + components: { SlideCanvas }, + data () { + return { + labels: [], + colorPick: '#79f2fb', + dotSize: 3, + isEdit: false, + isShowPop: false, + isNewLabel: false, + // curLabel: { + // id: '', + // posX: '', + // posY: '', + // x: '', + // y: '' + // }, + curLabel: { + id: '', + x1: '', + y1: '', + x0: '', + y0: '' + }, + rules: { + x1: [ + { validator: isNonnegativeInteger, trigger: 'change' } + ], + y1: [ + { validator: isNonnegativeInteger, trigger: 'change' } + ] + }, + baseUrl: '', + snapshot_url: '', + userImg: '', + cameraData: [], + traceX: 0, + traceY: 0, + isShowCurPos: false, + actPage: '1', + loading: false, + spaceWidth: '', + spaceHeight: '', + curCameraData: { + cameraId: '', + coords: [] + }, + relativeCameras: [], + relativeList: [], + groupModelVisible: false, + groupList: [], + curGroup: {}, + groupForm: { + name: '', + cameras: [] + }, + groupCameras: [], + groupCamera: { + + }, + + } + }, + computed: { + + }, + mounted () { + this.getAllCameraData(); + //mock鍥炴樉鏍囨敞 + setTimeout(() => { + let mockData = [{ id: 'a1', x0: 15, y0: 33, x1: 150, y1: 330 }, { id: 'b2', x0: 56, y0: 87, x1: 560, y1: 870 }]; + //this.curCameraData.coords = mockData; + }, 1000); + }, + watch: { + 'TreeDataPool.selectedNode': { + handler (n, o) { + let curCamera = this.cameraData.find(item => item.id == n.id); + //璁剧疆鎽勫儚鏈哄簳鍥� + this.snapshot_url = curCamera.snapshot_url; + this.findCameraMarks(n.id); + }, + deep: true + }, + 'TreeDataPool.selectedNodes': { + handler (n, o) { + debugger + if (n.length >= 2) { + + + } + }, + deep: true + }, + isEdit (n, o) { + if (n) { + this.$refs['editBoard'].addEventListener('click', this.bindListen); + } else { + this.$refs['editBoard'].removeEventListener('click', this.bindListen); + } + } + }, + methods: { + addRelation () { + let obj = { cameraArea1: '', cameraArea2: '' }; + this.relativeList.push(obj) + }, + swiperOption () { + return { + slidesPerView: 1, + spaceBetween: 0, + pagination: { + el: ".swiper-pagination", + clickable: true + }, + navigation: { + nextEl: ".swiper-next-border", + prevEl: ".swiper-pre-border" + }, + observer: true,//淇敼swiper鑷繁鎴栧瓙鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + observeParents: true,//淇敼swiper鐨勭埗鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + } + }, + editGroup (gruop) { + this.groupModelVisible = true; + debugger + this.$refs['groupForm'].resetFields(); + }, + removeGroup (group) { + + }, + checkCurrentGroup (group) { + debugger + this.curGroup = group; + }, + confirmGroupDialog () { + //璇锋眰淇濆瓨鏂板缓鎴栫紪杈戝垎缁� + let _this = this; + this.groupForm.cameras.forEach(camera => { + getAllPolygon({ cameraId: camera.id }).then(res => { + _this.groupCameras.push(res.data); + }).catch(e => { + console.log(e) + }); + }) + this.groupList.push(this.groupForm); + + this.groupModelVisible = false; + //鏍规嵁鍒嗙粍鍐呮憚鍍忔満id鏌ュ悇鑷尯鍩� + }, + newGroup () { + this.groupModelVisible = true; + this.$nextTick(() => { + this.$refs['groupForm'].resetFields(); + }) + }, + changeTab () { + if (this.actPage == '1') { + this.$parent.$children[0].$el.parentNode.parentElement.style.display = 'block'; + } else { + this.$parent.$children[0].$el.parentNode.parentElement.style.display = 'none'; + } + }, + sure () { + let _this = this; + this.$refs['labelForm'].validate(valid => { + console.log(valid) + if (valid) { + _this.isShowPop = false; + debugger + //缂栬緫纭畾 + if (_this.curLabel.id) { + let editedIndex = _this.curCameraData.coords.findIndex(one => one.id == _this.curLabel.id); + _this.curCameraData.coords[editedIndex] = JSON.parse(JSON.stringify(_this.curLabel)); + + } + console.log(_this.curCameraData.coords) + this.$refs['labelForm'].clearValidate(); + } + }); + }, + //鑾峰彇鎽勫儚鏈烘爣娉� + findCameraMarks (id) { + getCameraMarks({ cameraId: id }).then(res => { + if (res.success) { + this.curCameraData.cameraId = id; + this.curCameraData.coords = res.data.map((item, index) => ({ id: 'm' + index, x0: item.x0, y0: item.y0, x1: item.x1, y1: item.y1 })); + } + }).catch(e => { + console.log(e) + }); + }, + editCameraData () { + if (!this.TreeDataPool.selectedNode.id) { + this.$notify({ + message: '璇峰厛閫夋嫨鎽勫儚鏈�', + type: 'warning' + }); + return; + } + this.isEdit = !this.isEdit; + }, + async submitInfo () { + this.isEdit = false; + let res = await updateCameraMarks(this.curCameraData); + if (res.success) { + this.findCameraMarks(this.curCameraData.cameraId); + } + }, + chnageActPage () { + + }, + showCurPos (e) { + console.log(e); + this.isShowCurPos = true; + this.traceX = e.offsetX; + this.traceY = e.offsetY; + }, + onChange (file, fileList) { + fileList = [file] + this.isShowCurPos = false; + // this.traceX = e.offsetX; + // this.traceY = e.offsetY; + //fileList.push(file) + }, + definedUpload (params) { + let _file = params.file + let fileReader = new FileReader() + fileReader.onload = () => { + this.userImg = fileReader.result + } + if (_file) { + fileReader.readAsDataURL(_file) + } + }, + getAllCameraData () { + getCamerasByServer().then(res => { + if (res.success) { + this.cameraData = res.data; + debugger + } + }).catch(e => { + console.log(e) + }) + }, + bindListen (e) { + this.newLabel(e); + }, + newLabel (e) { + console.log('鐐瑰嚮浜嗙敾鏉�') + if (this.isShowPop) return; + //鑾峰彇榧犳爣鐩稿浜庣敾鏉跨殑瀹氫綅 + console.log('鑾峰彇褰撳墠瀹氫綅淇℃伅'); + this.$refs['labelForm'].resetFields(); + let target = { + id: '', + x0: e.offsetX, + y0: e.offsetY, + x1: '', + y1: '' + }; + target.id = 'n' + (this.curCameraData.coords.length - 1); + //this.labels.push(target); + this.curCameraData.coords.push(target); + this.curLabel = target; + this.isShowPop = true; + this.isNewLabel = true; + }, + editLabel (label) { + debugger + if (!this.isEdit) return; + this.isShowPop = true; + this.$refs['labelForm'].clearValidate(); + this.curLabel = JSON.parse(JSON.stringify(label)); + console.log(this.curLabel) + //this.curLabel = label; + }, + cancle () { + this.isShowPop = false; + //濡傛灉鏄湭淇濆瓨杩囩殑label鐩存帴鍒犻櫎(鏈繚瀛樼殑灏辨槸labels鏁扮粍涓渶鍚庝竴涓�) + if (!this.curLabel.id) { + //this.labels.pop(); + this.curCameraData.coords.pop(); + } + }, + deleteLabel () { + if (this.curLabel.id) { + let index = this.curCameraData.coords.findIndex(item => item.id == this.curLabel.id); + this.curCameraData.coords.splice(index, 1); + + } else { + //this.labels.pop(); + this.curCameraData.coords.pop(); + } + this.isShowPop = false; + }, + } +} +</script> + +<style lang="scss"> +.right-side { + background: #d2dcea; + + .figure { + .el-tabs__content { + background: #d2dcea; + height: calc(100vh - 85px); + } + } + .tool-bar { + //width: 40px; + height: 100%; + padding: 10px 0 10px 20px; + box-sizing: border-box; + //background: rgb(250, 250, 250); + background: rgba(26, 45, 74, 0.6); + //margin-bottom: 40px; + display: flex; + align-items: center; + justify-content: flex-end; + > div { + cursor: pointer; + //background: rgba(245, 245, 245, 0.3); + padding: 0 5px; + height: 40px; + margin: 7px; + display: flex; + align-items: center; + label { + margin-right: 10px; + color: rgb(161, 161, 161); + color: #fff; + } + .el-slider { + width: 110px; + } + } + } + .shadow-box { + box-shadow: 3px 3px 3px 1px rgba(0, 0, 0, 0.1); + } + .action-bar { + width: 960px; + margin: auto; + margin-top: 30px; + //margin-bottom: 20px; + text-align: right; + .drawboard-trigger { + background: transparent; + color: #fff; + border-color: rgba(255, 255, 255, 0.3); + } + } + .drawboard { + margin: auto; + width: 960px; + height: 540px; + margin-bottom: 130px; + position: relative; + //background: #fff; + background: #f0ffca; + //box-shadow: 3px 3px 3px 1px rgba(0, 0, 0, 0.1); + .mask { + position: absolute; + background: transparent; + width: 100%; + height: 100%; + overflow: hidden; + &.edit-status-mask { + background: rgba(20, 181, 255, 0.1); + } + .label { + position: absolute; + z-index: 2; + border-radius: 50%; + } + } + img { + width: 960px; + height: 540px; + background: #f0ffca; + } + .right-panel { + width: 150px; + height: 100%; + background: rgba(26, 45, 74, 0.7); + } + .popBox { + position: absolute; + z-index: 99; + padding: 14px; + border-radius: 3px; + color: #fff; + background: rgba(26, 45, 74, 0.7); + .title { + font-weight: bold; + text-align: left; + font-size: 15px; + margin-bottom: 14px; + letter-spacing: 2px; + } + .details { + .detail-item { + display: flex; + margin: 5px 0; + label { + color: #a9a9a9; + width: 65px; + display: inline-block; + } + .left { + width: 110px; + text-align: left; + line-height: 28px; + .fix-width { + display: inline-block; + width: 23px; + } + } + .right { + width: 160px; + } + .devide { + width: 10px; + height: 1px; + background: #a9a9a9; + margin: 14px 3px; + } + } + .btns { + margin-top: 10px; + } + .el-form-item { + margin-bottom: 12px; + } + .el-form-item__content { + font-size: 12px; + line-height: 30px; + } + .el-form-item__error { + left: 70px; + top: 94%; + } + } + } + } + .user-upload { + margin: auto; + padding: 50px; + display: flex; + .info { + margin-left: 20px; + margin-top: 20px; + text-align: left; + font-size: 15px; + .input-area { + width: 300px; + label { + width: 80px; + color: rgba(39, 68, 111, 0.67); + } + > div { + display: flex; + align-items: center; + height: 40px; + } + } + .pos { + margin-top: 10px; + text-align: left; + color: rgba(39, 68, 111, 0.67); + b { + font-style: italic; + } + //color: #4966b7 + } + } + .img-card { + } + .upload-demo, + .el-upload { + height: 100%; + width: 100%; + margin: 0 auto; + } + .upload-demo .el-upload__input { + visibility: hidden; + } + .upload-demo .el-upload-dragger { + width: 100%; + height: 90%; + width: 962px; + height: 542px; + margin: 20px 0 0; + background: transparent; + /* border: none; */ + //position: relative; + overflow: visible; + } + .upload-demo .el-upload__text { + position: absolute; + top: -24px; + left: 50%; + margin-left: -91px; + } + .upload-demo .preview { + object-fit: contain; + //position: relative; + // width: 100%; + // height: 100%; + } + .upload-demo .preview img { + // position: absolute; + // top: 50%; + // left: 50%; + // transform: translate(-50%, -50%); + // width: 100%; + // height: 100%; + } + } + .tab-relation { + .el-alert--info { + background: rgba(230, 247, 255, 1); + border-color: rgba(145, 213, 255, 1); + color: #666; + .el-alert__icon.el-icon-info { + color: #1890ff; + } + } + .title { + text-align: left; + font-size: 15px; + line-height: 40px; + .el-button { + margin-left: 14px; + } + } + .group-card { + background: #fff; + width: 293px; + height: 152px; + box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1); + .top { + height: 104px; + display: flex; + padding-left: 20px; + align-items: center; + .icon { + font-size: 40px; + } + .name { + font-size: 16px; + padding-left: 14px; + font-weight: bold; + } + } + .bottom { + border-top: 1px solid #e9e9e9; + height: 48px; + line-height: 48px; + background: #f7f9fa; + position: relative; + display: flex; + &:after { + content: ''; + position: absolute; + font-size: 0; + width: 1px; + height: 14px; + background: #0000006d; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + span { + cursor: pointer; + width: 50%; + font-size: 14px; + color: #0000006d; + } + } + } + .part { + margin-bottom: 20px; + .relative-partment { + width: 1200px; + margin: 0 auto; + display: flex; + justify-content: space-between; + .area-wrap { + width: 576px; + } + } + } + .relative-config { + width: 700px; + .title { + display: flex; + justify-content: space-between; + } + .relative-list { + .relative-item { + width: 680px; + height: 48px; + padding-left: 20px; + background: #ecf2f5; + margin-bottom: 6px; + display: flex; + align-items: center; + .left { + width: 650px; + text-align: left; + } + i { + font-size: 20px; + padding: 0 10px; + cursor: pointer; + } + } + } + } + } + .dialog-group { + .el-form { + .el-form-item__content { + display: flex; + label { + width: 80px; + text-align: left; + } + & > div { + flex: 1; + .el-select { + width: 100%; + } + } + } + } + } +} +.el-input__inner:focus { + outline: none; + border-color: rgba(42, 56, 93, 71%) !important; +} +.el-upload-dragger:hover { + border-color: rgba(42, 56, 93, 71%) !important; +} +</style> \ No newline at end of file diff --git a/src/pages/labelMark-copy/components/SlideCanvas.vue b/src/pages/labelMark-copy/components/SlideCanvas.vue new file mode 100644 index 0000000..71821f4 --- /dev/null +++ b/src/pages/labelMark-copy/components/SlideCanvas.vue @@ -0,0 +1,225 @@ +<template> + <div class="swiper-box"> + <p class="task-tip" v-if="cameras.length == 0 "></p> + <swiper + ref="cameraSwiper" + v-if="cameras.length>=1" + :options="swiperOption" + class="swiper-box-container" + > + <swiper-slide v-for="camera in cameras" :key="camera.id+'s'"> + <div class="swiper-draw-box-title"> + <b>{{camera.name}}</b> + <b style="margin-left:14px;">缁樺埗鍖哄煙</b> + <span + class="el-dropdown-link" + @click="drawBaseImg(camera.id)" + style="position: relative;top: 5px; cursor:pointer" + > + <i class="iconfont iconbianji1" style="font-size: 28px; "></i> + </span> + </div> + <polygon-canvas + class="polygon-canvas" + :ref="`polygonCanvas_${camera.id}`" + :snapshot_url="camera.snapshot_url" + :canvasDataShow="camera.canvasData" + :canvasWidth="576" + :canvasHeight="324" + ></polygon-canvas> + </swiper-slide> + </swiper> + <div class="swiper-pre-border" slot="button-prev" @click="pre" > + <div class="icon-btn" > + <i class="iconfont iconzuo"></i> + </div> + </div> + <div class="swiper-next-border" slot="button-next" @click="next"> + <div class="icon-btn" > + <i class="iconfont iconyou1"></i> + </div> + </div> + <!-- <div class="swiper-pre-border" slot="button-prev" @click="pre" > + <div class="icon-btn" > + <i class="iconfont iconzuo"></i> + </div> + </div> + <div class="swiper-next-border" slot="button-next" @click="next"> + <div class="icon-btn" > + <i class="iconfont iconyou1"></i> + </div> + </div> --> + </div> +</template> + +<script> +import { chunkArr } from '@/scripts/util'; +import PolygonCanvas from '@/components/canvas'; + +export default { + //cameras: [{ id: '',snapshot_url:'', canvasData: {} }] + props: [ + 'cameras', + //'swiperOption' + ], + watch: { + cameras: { + handler (n, o) { + debugger + }, + deep: true + } + }, + components: { PolygonCanvas }, + data () { + return { + swiperOption: this.newOption(), + //mySwiper: {} + } + }, + computed: { + swiper () { + return this.$refs['cameraSwiper'].swiper + } + }, + mounted () { + debugger + //this.mySwiper = this.$refs.sceneSwiper.swiper; + console.log(this.swiper) + }, + methods: { + newOption () { + return { + slidesPerView: 1, + spaceBetween: 0, + pagination: { + el: ".swiper-pagination", + clickable: true + }, + observer: true,//淇敼swiper鑷繁鎴栧瓙鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + observeParents: true,//淇敼swiper鐨勭埗鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + } + }, + + pre () { + this.swiper.activeIndex-- + this.swiper.slideTo(this.swiper.activeIndex) + }, + next () { + this.swiper.activeIndex++ + this.swiper.slideTo(this.swiper.activeIndex) + }, + drawBaseImg (id) { + this.$refs[`polygonCanvas_${id}`][0].showModal(); + } + } +}; +</script> + +<style lang="scss"> +.icon { + width: 1em; + height: 1em; + vertical-align: -0.15em; + fill: currentColor; + overflow: hidden; +} +.task-tip { + font-family: PingFangSC-Regular; + font-size: 12px; + color: #cccccc; + margin-top: 10%; +} +.swiper-box { + position: relative; +} +.swiper-pre-border, +.swiper-next-border { + width: 40px; + height: 40px; + position: absolute; + background: #8888; + top: 50%; + margin-top: -20px; + z-index: 99; + border-radius: 4em; + outline: none; + .icon-btn { + color: rgb(255, 255, 255); + text-align: center; + line-height: 38px; + cursor: pointer; + } +} +.swiper-pre-border { + left: 10px; +} +.swiper-pre-border:hover { + background: #666; +} +.swiper-next-border { + right: 10px; +} +.swiper-next-border:hover { + background: #666; +} +.swiper-draw-box-title { + display: flex; + justify-content: center; + align-items: center; + height: 24px; + b { + font-size: 14px; + } +} +.wrap-box { + width: 100%; + display: inline-block; + .inner { + width: 90%; + box-sizing: border-box; + position: relative; + font-size: 14px; + padding: 7px 0 48px; + transition: all 1s; + background: #ffffff; + border: 1px solid #e2e2e2; + box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); + border-radius: 4px; + margin: auto; + &:hover { + .mask { + display: block; + } + } + .mask { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.65); + backdrop-filter: blur(1px) brightness(100%); + text-align: center; + z-index: 1; + border-radius: 3px; + display: none; + .tool { + position: absolute; + top: 49%; + left: 50%; + transform: translate(-50%, -50%); + i { + font-size: 50px; + } + i:nth-of-type(1) { + margin-right: 30px; + } + i:nth-of-type(2) { + color: red; + } + } + } + } +} +</style> \ No newline at end of file diff --git a/src/pages/labelMark-copy/index/App.vue b/src/pages/labelMark-copy/index/App.vue new file mode 100644 index 0000000..afbfc81 --- /dev/null +++ b/src/pages/labelMark-copy/index/App.vue @@ -0,0 +1,118 @@ +<template> + <div class="column"> + <!-- <div class="column-left" ref="leftTree"> + <div class="resize-bar"></div> + <div class="resize-line"></div> + <div class="resize-save"> + <left-nav :appName="'Camera'" :height="screenHeight - 40"></left-nav> + </div> + </div> --> + <div class="column-right"> + <right-side /> + </div> + </div> +</template> +<script> + +import RightSide from "../components/RightSide"; +import TreeDataPool from "@/Pool/TreeData"; +export default { + components: { RightSide }, + data () { + return { + screenHeight: 0, + } + }, + created(){ + this.TreeDataPool.multiple = true; + }, + mounted() { + this.screenHeight = document.documentElement.clientHeight - 20; + window.onresize = () => { + return (() => { + this.screenHeight = document.documentElement.clientHeight - 20; + })(); + }; + }, +} +</script> + +<style lang="scss" scoped> + +.column { + overflow: hidden; + min-width: 1399px; + height: 100%; +} +.column-left { + background-color: #fff; + position: relative; + float: left; + height: 100vh; + //height: inherit; +} +.column-right { + height: 100vh; + background-color: #f5f5f5; + box-sizing: border-box; + //overflow: hidden; + overflow-x: auto; + overflow-y: auto; +} +.resize-save { + position: absolute; + top: 0; + right: 5px; + bottom: 0; + left: 0; + padding: 14px; + overflow-x: hidden; +} +.resize-bar { + width: 310px; + height: inherit; + resize: horizontal; + cursor: ew-resize; + opacity: 0; + overflow: scroll; + max-width: 500px; //璁惧畾鏈�澶ф媺浼搁暱搴� + min-width: 33px; //璁惧畾鏈�灏忓搴� +} +/* 鎷栨嫿绾� */ +.resize-line { + position: absolute; + right: 0; + top: 0; + bottom: 0; + border-right: 2px solid #efefef; + border-left: 1px solid #e0e0e0; + pointer-events: none; +} +.resize-bar:hover ~ .resize-line, +.resize-bar:active ~ .resize-line { + border-left: 1px dashed skyblue; +} +.resize-bar::-webkit-scrollbar { + width: 200px; + height: inherit; +} + +/* Firefox鍙湁涓嬮潰涓�灏忓潡鍖哄煙鍙互鎷変几 */ +@supports (-moz-user-select: none) { + .resize-bar:hover ~ .resize-line, + .resize-bar:active ~ .resize-line { + border-left: 1px solid #bbb; + } + .resize-bar:hover ~ .resize-line::after, + .resize-bar:active ~ .resize-line::after { + content: ""; + position: absolute; + width: 16px; + height: 16px; + bottom: 0; + right: -8px; + // background: url(./resize.svg); + background-size: 100% 100%; + } +} +</style> diff --git a/src/pages/labelMark-copy/index/main.ts b/src/pages/labelMark-copy/index/main.ts new file mode 100644 index 0000000..b9b1993 --- /dev/null +++ b/src/pages/labelMark-copy/index/main.ts @@ -0,0 +1,17 @@ +import Vue from 'vue'; +import App from './App.vue'; + +import ElementUI from 'element-ui'; +import 'element-ui/lib/theme-chalk/index.css'; +import "@/assets/css/element-variables.scss"; +import VueAwesomeSwiper from "vue-awesome-swiper"; +import "swiper/dist/css/swiper.css"; +import Mixin from "./mixins"; + +Vue.use(ElementUI); +Vue.use(VueAwesomeSwiper as any); +Vue.mixin(Mixin); +new Vue({ + el: '#app', + render: h => h(App) +}); \ No newline at end of file diff --git a/src/pages/labelMark-copy/index/mixins.ts b/src/pages/labelMark-copy/index/mixins.ts new file mode 100644 index 0000000..feda309 --- /dev/null +++ b/src/pages/labelMark-copy/index/mixins.ts @@ -0,0 +1,14 @@ +import TreeDataPool from "@/Pool/TreeData"; + +/* eslint-disable */ +const onlyTreeDataPool = new TreeDataPool + +const mixin = { + data() { + return { + TreeDataPool: onlyTreeDataPool + + }; + }, +}; +export default mixin; \ No newline at end of file diff --git a/src/pages/labelMark/components/RightSide-COPY.vue b/src/pages/labelMark/components/RightSide-COPY.vue new file mode 100644 index 0000000..a846575 --- /dev/null +++ b/src/pages/labelMark/components/RightSide-COPY.vue @@ -0,0 +1,862 @@ +<template> + <div class="right-side"> + <div class="figure s-system-manage"> + <el-tabs + id="e-basic-setting" + v-model="actPage" + v-loading="loading" + element-loading-text="鍔犺浇涓�" + type="border-card" + > + <el-tab-pane label="鎽勫儚鏈烘爣娉�" name="1"> + <div class v-for="camera in relativeCameras" :key="camera.id"> + <div class="action-bar"> + <div class="tool-bar"> + <div> + <!-- <input type="color" ref="colorPicker" v-model="color"> --> + <label for>鎷捐壊鍣�:</label> + <el-color-picker v-model="camera.colorPick" show-alpha size="mini"></el-color-picker> + </div> + <div style="width:250px;"> + <label for>绗旇Е:</label> + <el-slider v-model="camera.dotSize" :min="1" :max="20"></el-slider> + </div> + <div> + <el-button type="text" @click="editPolygon(camera.id)">缂栬緫鍖哄煙</el-button> + <el-button @click="editCoor(camera.id)">缂栬緫鏍囨敞淇℃伅</el-button> + </div> + <div> + <el-button + v-if="!camera.isEdit" + class="drawboard-trigger" + size="small" + @click="editCameraData(camera)" + icon="el-icon-edit" + >缂栬緫</el-button> + + <el-button + v-if="camera.isEdit" + class="drawboard-trigger save" + size="small" + @click="submitInfo" + icon="el-icon-lock" + >淇濆瓨</el-button> + </div> + </div> + </div> + <el-dialog :visible.sync="coordsDialogVisible" width="1150px"> + <div class="drawboard shadow-box"> + <div + class="mask" + :class="{'edit-status-mask':camera.isEdit}" + :ref="`editBoard_${camera.id}`" + > + <polygon-canvas + class="polygon-canvas" + :ref="`polygonCanvas_${camera.id}`" + :snapshot_url="camera.snapshot_url" + :canvasWidth="960" + :canvasHeight="540" + ></polygon-canvas> + <!-- <div + class="label" + @click="editLabel(item)" + v-for="(item,index) in curCameraData.coords" + :key="index" + :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: colorPick, width: `${dotSize}px`, height: `${dotSize}px` }" + ></div>--> + <div + class="label" + @click="editLabel(item)" + v-for="(item,index) in camera.coords" + :key="index" + :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: camera.colorPick, width: `${camera.dotSize}px`, height: `${camera.dotSize}px` }" + ></div> + </div> + <img v-show="camera.snapshot_url" :src="`/httpImage/${camera.snapshot_url}`" alt /> + <div + class="popBox" + v-show="camera.isShowPop" + :style="`top:${curLabel.y0 + 22}px;left:${curLabel.x0}px`" + > + <div class="title">鏍囨敞淇℃伅</div> + <div class="details"> + <el-form :model="curLabel" :rules="rules" :ref="`labelForm_${camera.id}`"> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="x0"> + <label for>骞抽潰鍧愭爣X:</label> + <span class="fix-width">{{curLabel.x0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="x1"> + <label for>瀹為檯鍧愭爣X:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.x1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="y0"> + <label for>骞抽潰鍧愭爣Y:</label> + <span class="fix-width">{{curLabel.y0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="y1"> + <label for>瀹為檯鍧愭爣Y:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.y1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="btns"> + <el-button size="mini" type="danger" @click="deleteLabel">鍒犻櫎</el-button> + <el-button size="mini" type="primary" @click="cancle">鍙栨秷</el-button> + <el-button size="mini" type="success" @click="sure">纭畾</el-button> + </div> + </el-form> + </div> + </div> + </div> + </el-dialog> + <!-- <div class="drawboard shadow-box"> + <div class="mask" :class="{'edit-status-mask':camera.isEdit}" :ref="`editBoard_${camera.id}`"> + <polygon-canvas + class="polygon-canvas" + :ref="`polygonCanvas_${camera.id}`" + :snapshot_url="camera.snapshot_url" + :canvasWidth="960" + :canvasHeight="540" + ></polygon-canvas> + <div + class="label" + @click="editLabel(item)" + v-for="(item,index) in camera.coords" + :key="index" + :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: camera.colorPick, width: `${camera.dotSize}px`, height: `${camera.dotSize}px` }" + ></div> + </div> + <img v-show="camera.snapshot_url" :src="`/httpImage/${camera.snapshot_url}`" alt /> + <div + class="popBox" + v-show="camera.isShowPop" + :style="`top:${curLabel.y0 + 22}px;left:${curLabel.x0}px`" + > + <div class="title">鏍囨敞淇℃伅</div> + <div class="details"> + <el-form :model="curLabel" :rules="rules" :ref="`labelForm_${camera.id}`"> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="x0"> + <label for>骞抽潰鍧愭爣X:</label> + <span class="fix-width">{{curLabel.x0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="x1"> + <label for>瀹為檯鍧愭爣X:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.x1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="y0"> + <label for>骞抽潰鍧愭爣Y:</label> + <span class="fix-width">{{curLabel.y0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="y1"> + <label for>瀹為檯鍧愭爣Y:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.y1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="btns"> + <el-button size="mini" type="danger" @click="deleteLabel">鍒犻櫎</el-button> + <el-button size="mini" type="primary" @click="cancle">鍙栨秷</el-button> + <el-button size="mini" type="success" @click="sure">纭畾</el-button> + </div> + </el-form> + </div> + </div> + </div>--> + </div> + </el-tab-pane> + <el-tab-pane label="杩借釜瀹炴櫙鍧愭爣" name="2"> + <div class="user-upload"> + <canvas id="trackArea" width="960" height="540"></canvas> + <div class="img-card"> + <el-upload + class="upload-demo" + drag + action="https://jsonplaceholder.typicode.com/posts/" + :http-request="definedUpload" + :on-change="onChange" + :show-file-list="false" + > + <el-image + class="preview" + v-if="userImg" + :src="userImg" + fit="contain" + @mousemove="showCurPos" + @mouseout="isShowCurPos=false" + ></el-image> + <div class="el-upload__text"> + 灏嗘枃浠舵嫋鍒版澶勶紝鎴� + <em>鐐瑰嚮涓婁紶</em> + </div> + </el-upload> + </div> + <div class="info"> + <div class="input-area"> + <div> + <label for>绌洪棿瀹�:</label> + <el-input v-model="spaceWidth" placeholder="璇疯緭鍏ュ疄闄呯┖闂村" size="small"></el-input> + </div> + <div> + <label for>绌洪棿楂�:</label> + <el-input v-model="spaceHeight" placeholder="璇疯緭鍏ュ疄闄呯┖闂撮珮" size="small"></el-input> + </div> + </div> + <div class="pos" v-show="isShowCurPos"> + 褰撳墠浣嶇疆: + <b>{{traceX}}</b>, + <b>{{traceY}}</b> + </div> + </div> + </div> + </el-tab-pane> + </el-tabs> + <!-- <el-collapse v-model="actPage"> + <el-collapse-item title="鎽勫儚鏈烘爣娉�" name="1"> + + </el-collapse-item> + <el-collapse-item title="杩借釜瀹炴櫙鍧愭爣" name="2"> + <div class="user-upload"> + <div class="img-card"> + <el-upload + class="upload-demo" + drag + action="https://jsonplaceholder.typicode.com/posts/" + :http-request="definedUpload" + :on-change="onChange" + :show-file-list="false" + > + <el-image + class="preview" + v-if="userImg" + :src="userImg" + fit="contain" + @mousemove="showCurPos" + @mouseout="isShowCurPos=false" + ></el-image> + <div class="el-upload__text"> + 灏嗘枃浠舵嫋鍒版澶勶紝鎴� + <em>鐐瑰嚮涓婁紶</em> + </div> + </el-upload> + </div> + <div class="info" v-show="isShowCurPos">褰撳墠浣嶇疆:{{traceX}},{{traceY}}</div> + </div> + </el-collapse-item> + </el-collapse>--> + </div> + </div> +</template> + +<script> +import { getCamerasByServer } from '@/api/pollConfig'; +import { getCameraMarks, updateCameraMarks } from '@/api/camera'; +import TreeDataPool from "@/Pool/TreeData"; +import { isNonnegativeInteger } from '@/scripts/validate'; +import polygonCanvas from "@/components/canvas"; +export default { + components: { polygonCanvas }, + data () { + return { + labels: [], + // colorPick: '#79f2fb', + // dotSize: 3, + // isEdit: false, + // isShowPop: false, + // isNewLabel: false, + curLabel: { + id: '', + x1: '', + y1: '', + x0: '', + y0: '' + }, + rules: { + x1: [ + { validator: isNonnegativeInteger, trigger: 'change' } + ], + y1: [ + { validator: isNonnegativeInteger, trigger: 'change' } + ] + }, + baseUrl: '', + //snapshot_url: '', + userImg: '', + cameraData: [], + traceX: 0, + traceY: 0, + isShowCurPos: false, + actPage: '1', + loading: false, + spaceWidth: '', + spaceHeight: '', + curCameraData: { + cameraId: '', + coords: [] + }, + relativeCameras: [], + relativeCamera: { + colorPick: '#79f2fb', + cameraId: '', + snapshot_url: '', + dotSize: 3, + isEdit: false, + isShowPop: false, + isNewLabel: false, + coords: [], + polygons: {} + }, + trackData: [] + } + }, + computed: { + + }, + mounted () { + this.getAllCameraData(); + //mock鍥炴樉鏍囨敞 + setTimeout(() => { + let mockData = [{ id: 'a1', x0: 15, y0: 33, x1: 150, y1: 330 }, { id: 'b2', x0: 56, y0: 87, x1: 560, y1: 870 }]; + //this.curCameraData.coords = mockData; + //this.trackData = [[950,370],[945,368],[940,360],[936,350],[930,340],[930,340]]; + let tempArr = []; + for (var i = 0; i < 1000; i++) { + //let x = 960-i*9, y = 370 - i*3; + let x = Math.floor(Math.random() * 960); + let y = Math.floor(Math.random() * 540) + tempArr.push([x, y]) + } + this.trackData = tempArr; + let canvas = document.querySelector('#trackArea'); + let ctx = canvas.getContext('2d'); + ctx.strokeStyle = 'yellow'; + ctx.fillStyle = 'aqua'; + // ctx.globalAlpha=0.5; + ctx.lineWidth = 1; + //ctx.lineJoin='round'; + ctx.lineCap = 'round'; + for (var i = 0; i < this.trackData.length; i++) { + ctx.fillRect(this.trackData[i][0], this.trackData[i][1], 5, 5); + ctx.lineTo(this.trackData[i][0], this.trackData[i][1]); + } + ctx.stroke(); + }, 1000); + debugger + }, + watch: { + // 'TreeDataPool.selectedNode': { + // handler (n, o) { + // let curCamera = this.cameraData.find(item => item.id == n.id); + // //璁剧疆鎽勫儚鏈哄簳鍥� + // this.snapshot_url = curCamera.snapshot_url; + // this.findCameraMarks(n.id); + // }, + // deep: true + // }, + 'TreeDataPool.selectedNodes': { + handler (n, o) { + debugger + // if (n.length > 2) { + // this.$notify({ + // type: 'warning', + // message: '鏈�澶氫粎鑳藉叧鑱斾袱涓憚鍍忔満' + // }); + // this.TreeDataPool.selectedNodes.length = 2; + // //鐩綍鏍戣鍥炬湭鏇存柊 + // } + var tempArr = []; + //鏍规嵁id鍙栨憚鍍忔満鏍囨敞淇℃伅鍙婂尯鍩� + let _this = this; + n.forEach(cameraId => { + //this.findCameraMarks(cameraId); + getCameraMarks({ cameraId }).then(res => { + let obj = _this.newCameraData(); + //Object.assign(obj,) + //寰呰仈璋� + tempArr.push(res.data) + }) + }) + //mock + tempArr = [ + { id: '81b4c468-9828-41ad-a681-e90feb59490e', isEdit: false, isShowPop: false, colorPick: '#79f2fb', isNewLabel: false, dotSize: 3 }, + { id: '28477df1-78ec-49bc-8734-e977992667cc', isEdit: false, isShowPop: false, colorPick: '#79f2fb', isNewLabel: false, dotSize: 3 } + ]; + tempArr.forEach(item => { + this.cameraData.find(camera => { + if (camera.id == item.id) { + item.snapshot_url = camera.snapshot_url; + } + }) + }) + + this.relativeCameras = tempArr + }, + deep: true + }, + relativeCameras: { + handler (n, o) { + var _this = this; + n.forEach(camera => { + debugger + // if(camera.isEdit){ + // _this.$refs[`editBoard_${camera.id}`][0].addEventListener('click', this.bindListen); + // }else{ + // _this.$refs[`editBoard_${camera.id}`][0].removeEventListener('click', this.bindListen); + // } + }) + }, + deep: true + }, + // isEdit (n, o) { + // if (n) { + // this.$refs['editBoard'].addEventListener('click', this.bindListen); + // } else { + // this.$refs['editBoard'].removeEventListener('click', this.bindListen); + // } + // } + }, + methods: { + newCameraData () { + return { + colorPick: '#79f2fb', + id: '', + snapshot_url: '', + dotSize: 3, + isEdit: false, + isShowPop: false, + isNewLabel: false, + coords: [], + polygons: {} + } + }, + editPolygon (cameraId) { + debugger + this.$refs[`polygonCanvas_${cameraId}`][0].showModal(); + }, + sure () { + let _this = this; + // this.$refs[`labelForm_${}`].validate(valid => { + // console.log(valid) + // if (valid) { + // _this.isShowPop = false; + // debugger + // //缂栬緫纭畾 + // if (_this.curLabel.id) { + // // let editedIndex = _this.curCameraData.coords.findIndex(one => one.id == _this.curLabel.id); + // // _this.curCameraData.coords[editedIndex] = JSON.parse(JSON.stringify(_this.curLabel)); + // let editedIndex = _this.relativeCamera.coords.findIndex(one => one.id == _this.curLabel.id); + // _this.relativeCamera.coords[editedIndex] = JSON.parse(JSON.stringify(_this.curLabel)); + // } + // console.log(_this.curCameraData.coords) + // this.$refs['labelForm'].clearValidate(); + // } + // }); + }, + //鑾峰彇鎽勫儚鏈烘爣娉� + findCameraMarks (id) { + getCameraMarks({ cameraId: id }).then(res => { + if (res.success) { + this.curCameraData.cameraId = id; + this.curCameraData.coords = res.data.map((item, index) => ({ id: 'm' + index, x0: item.x0, y0: item.y0, x1: item.x1, y1: item.y1 })); + + } + }).catch(e => { + console.log(e) + }); + }, + editCameraData (camera) { + if (!this.TreeDataPool.selectedNode.id) { + this.$notify({ + message: '璇峰厛閫夋嫨鎽勫儚鏈�', + type: 'warning' + }); + return; + } + camera.isEdit = !camera.isEdit; + this.$refs[`editBoard_${camera.id}`][0].addEventListener('click', this.bindListen); + }, + async submitInfo () { + this.isEdit = false; + let res = await updateCameraMarks(this.curCameraData); + if (res.success) { + this.findCameraMarks(this.curCameraData.cameraId); + } + }, + showCurPos (e) { + console.log(e); + this.isShowCurPos = true; + this.traceX = e.offsetX; + this.traceY = e.offsetY; + }, + onChange (file, fileList) { + fileList = [file] + this.isShowCurPos = false; + // this.traceX = e.offsetX; + // this.traceY = e.offsetY; + //fileList.push(file) + }, + definedUpload (params) { + let _file = params.file + let fileReader = new FileReader() + fileReader.onload = () => { + this.userImg = fileReader.result + } + if (_file) { + fileReader.readAsDataURL(_file) + } + }, + getAllCameraData () { + getCamerasByServer().then(res => { + if (res.success) { + this.cameraData = res.data; + } + }).catch(e => { + console.log(e) + }) + }, + bindListen (e) { + this.newLabel(e); + }, + newLabel (e) { + debugger + console.log('鐐瑰嚮浜嗙敾鏉�') + if (this.isShowPop) return; + //鑾峰彇榧犳爣鐩稿浜庣敾鏉跨殑瀹氫綅 + console.log('鑾峰彇褰撳墠瀹氫綅淇℃伅'); + this.$refs['labelForm'].resetFields(); + let target = { + id: '', + x0: e.offsetX, + y0: e.offsetY, + x1: '', + y1: '' + }; + target.id = 'n' + (this.curCameraData.coords.length - 1); + //this.labels.push(target); + this.curCameraData.coords.push(target); + this.curLabel = target; + this.isShowPop = true; + this.isNewLabel = true; + }, + editLabel (label) { + debugger + if (!this.isEdit) return; + this.isShowPop = true; + this.$refs['labelForm'].clearValidate(); + this.curLabel = JSON.parse(JSON.stringify(label)); + console.log(this.curLabel) + //this.curLabel = label; + }, + cancle () { + this.isShowPop = false; + //濡傛灉鏄湭淇濆瓨杩囩殑label鐩存帴鍒犻櫎(鏈繚瀛樼殑灏辨槸labels鏁扮粍涓渶鍚庝竴涓�) + if (!this.curLabel.id) { + //this.labels.pop(); + this.curCameraData.coords.pop(); + } + }, + deleteLabel () { + if (this.curLabel.id) { + let index = this.curCameraData.coords.findIndex(item => item.id == this.curLabel.id); + this.curCameraData.coords.splice(index, 1); + + } else { + //this.labels.pop(); + this.curCameraData.coords.pop(); + } + this.isShowPop = false; + }, + } +} +</script> + +<style lang="scss"> +.right-side { + background: #d2dcea; + .figure { + .el-tabs__content { + background: #d2dcea; + height: calc(100vh - 85px); + } + } + .tool-bar { + //width: 40px; + height: 100%; + padding: 10px 0 10px 20px; + box-sizing: border-box; + //background: rgb(250, 250, 250); + background: rgba(26, 45, 74, 0.6); + //margin-bottom: 40px; + display: flex; + align-items: center; + justify-content: flex-end; + > div { + cursor: pointer; + //background: rgba(245, 245, 245, 0.3); + padding: 0 5px; + height: 40px; + margin: 7px; + display: flex; + align-items: center; + label { + margin-right: 10px; + color: rgb(161, 161, 161); + color: #fff; + } + .el-slider { + width: 110px; + } + } + } + .shadow-box { + box-shadow: 3px 3px 3px 1px rgba(0, 0, 0, 0.1); + } + .action-bar { + width: 960px; + margin: auto; + margin-top: 30px; + //margin-bottom: 20px; + text-align: right; + .drawboard-trigger { + background: transparent; + color: #fff; + border-color: rgba(255, 255, 255, 0.3); + } + } + .drawboard { + margin: auto; + width: 960px; + height: 540px; + margin-bottom: 130px; + position: relative; + //background: #fff; + background: #f0ffca; + //box-shadow: 3px 3px 3px 1px rgba(0, 0, 0, 0.1); + .mask { + position: absolute; + background: transparent; + width: 100%; + height: 100%; + overflow: hidden; + &.edit-status-mask { + background: rgba(20, 181, 255, 0.1); + } + .label { + position: absolute; + z-index: 2; + border-radius: 50%; + } + } + .polygon-canvas { + position: absolute; + top: 0; + left: 0; + } + img { + width: 960px; + height: 540px; + background: #f0ffca; + } + .polygon-canvas { + position: absolute; + } + .right-panel { + width: 150px; + height: 100%; + background: rgba(26, 45, 74, 0.7); + } + .popBox { + position: absolute; + z-index: 99; + padding: 14px; + border-radius: 3px; + color: #fff; + background: rgba(26, 45, 74, 0.7); + .title { + font-weight: bold; + text-align: left; + font-size: 15px; + margin-bottom: 14px; + letter-spacing: 2px; + } + .details { + .detail-item { + display: flex; + margin: 5px 0; + label { + color: #a9a9a9; + width: 65px; + display: inline-block; + } + .left { + width: 110px; + text-align: left; + line-height: 28px; + .fix-width { + display: inline-block; + width: 23px; + } + } + .right { + width: 160px; + } + .devide { + width: 10px; + height: 1px; + background: #a9a9a9; + margin: 14px 3px; + } + } + .btns { + margin-top: 10px; + } + .el-form-item { + margin-bottom: 12px; + } + .el-form-item__content { + font-size: 12px; + line-height: 30px; + } + .el-form-item__error { + left: 70px; + top: 94%; + } + } + } + } + .user-upload { + margin: auto; + padding: 50px; + display: flex; + position: relative; + #trackArea { + position: absolute; + background: rgba(136, 214, 228, 0.1); + } + .info { + margin-left: 20px; + margin-top: 20px; + text-align: left; + font-size: 15px; + .input-area { + width: 300px; + label { + width: 80px; + color: rgba(39, 68, 111, 0.67); + } + > div { + display: flex; + align-items: center; + height: 40px; + } + } + .pos { + margin-top: 10px; + text-align: left; + color: rgba(39, 68, 111, 0.67); + b { + font-style: italic; + } + //color: #4966b7 + } + } + .img-card { + } + .upload-demo, + .el-upload { + height: 100%; + width: 100%; + margin: 0 auto; + } + .upload-demo .el-upload__input { + visibility: hidden; + } + .upload-demo .el-upload-dragger { + width: 100%; + height: 90%; + width: 962px; + height: 542px; + margin: 20px 0 0; + background: transparent; + /* border: none; */ + //position: relative; + overflow: visible; + } + .upload-demo .el-upload__text { + position: absolute; + top: -24px; + left: 50%; + margin-left: -91px; + } + .upload-demo .preview { + object-fit: contain; + //position: relative; + // width: 100%; + // height: 100%; + } + .upload-demo .preview img { + // position: absolute; + // top: 50%; + // left: 50%; + // transform: translate(-50%, -50%); + // width: 100%; + // height: 100%; + } + } +} +.el-input__inner:focus { + outline: none; + border-color: rgba(42, 56, 93, 71%) !important; +} +.el-upload-dragger:hover { + border-color: rgba(42, 56, 93, 71%) !important; +} +</style> \ No newline at end of file diff --git a/src/pages/labelMark/components/RightSide.vue b/src/pages/labelMark/components/RightSide.vue index e1f2177..e243da4 100644 --- a/src/pages/labelMark/components/RightSide.vue +++ b/src/pages/labelMark/components/RightSide.vue @@ -3,116 +3,166 @@ <div class="figure s-system-manage"> <el-tabs id="e-basic-setting" + @tab-click="changeTab" v-model="actPage" v-loading="loading" element-loading-text="鍔犺浇涓�" type="border-card" > - <el-tab-pane label="鎽勫儚鏈烘爣娉�" name="1"> - <div class> - <div class="action-bar"> - <div class="tool-bar"> - <div> - <!-- <input type="color" ref="colorPicker" v-model="color"> --> - <label for>鎷捐壊鍣�:</label> - <el-color-picker v-model="colorPick" show-alpha size="mini"></el-color-picker> - </div> - <div style="width:250px;"> - <label for>绗旇Е:</label> - <el-slider v-model="dotSize" :min="1" :max="20"></el-slider> - </div> - <div> - <el-button - v-if="!isEdit" - class="drawboard-trigger" - size="small" - @click="editCameraData" - icon="el-icon-edit" - >缂栬緫</el-button> + <el-tab-pane label="浣嶇疆鏍囨敞" name="1"> + <el-tabs type="border-card"> + <el-tab-pane label="鎽勫儚鏈烘爣娉�" name="11"> + <div class> + <div class="action-bar"> + <div class="tool-bar"> + <div> + <!-- <input type="color" ref="colorPicker" v-model="color"> --> + <label for>鎷捐壊鍣�:</label> + <el-color-picker v-model="colorPick" show-alpha size="mini"></el-color-picker> + </div> + <div style="width:250px;"> + <label for>绗旇Е:</label> + <el-slider v-model="dotSize" :min="1" :max="20"></el-slider> + </div> + <div> + <el-button + v-if="!isEdit" + class="drawboard-trigger" + size="small" + @click="editCameraData" + icon="el-icon-edit" + >缂栬緫</el-button> - <el-button - v-if="isEdit" - class="drawboard-trigger save" - size="small" - @click="submitInfo" - icon="el-icon-lock" - >淇濆瓨</el-button> + <el-button + v-if="isEdit" + class="drawboard-trigger save" + size="small" + @click="submitInfo" + icon="el-icon-lock" + >淇濆瓨</el-button> + </div> + </div> + </div> + <div class="drawboard shadow-box"> + <div class="mask" :class="{'edit-status-mask':isEdit}" ref="editBoard"> + <div + class="label" + @click="editLabel(item)" + v-for="(item,index) in curCameraData.coords" + :key="index" + :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: colorPick, width: `${dotSize}px`, height: `${dotSize}px` }" + ></div> + </div> + <img v-show="snapshot_url" :src="`/httpImage/${snapshot_url}`" alt /> + <div + class="popBox" + v-show="isShowPop" + :style="`top:${curLabel.y0 + 22}px;left:${curLabel.x0}px`" + > + <div class="title">鏍囨敞淇℃伅</div> + <div class="details"> + <el-form :model="curLabel" :rules="rules" ref="labelForm"> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="x0"> + <label for>骞抽潰鍧愭爣X:</label> + <span class="fix-width">{{curLabel.x0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="x1"> + <label for>瀹為檯鍧愭爣X:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.x1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="detail-item"> + <div class="left"> + <el-form-item prop="y0"> + <label for>骞抽潰鍧愭爣Y:</label> + <span class="fix-width">{{curLabel.y0}}</span> + <i>px</i> + </el-form-item> + </div> + <span class="devide"></span> + <div class="right"> + <el-form-item prop="y1"> + <label for>瀹為檯鍧愭爣Y:</label> + <el-input + type="text" + size="mini" + style="width:90px" + v-model.number="curLabel.y1" + ></el-input> + </el-form-item> + </div> + </div> + <div class="btns"> + <el-button size="mini" type="danger" @click="deleteLabel">鍒犻櫎</el-button> + <el-button size="mini" type="primary" @click="cancle">鍙栨秷</el-button> + <el-button size="mini" type="success" @click="sure">纭畾</el-button> + </div> + </el-form> + </div> + </div> </div> </div> - </div> - <div class="drawboard shadow-box"> - <div class="mask" :class="{'edit-status-mask':isEdit}" ref="editBoard"> - <div - class="label" - @click="editLabel(item)" - v-for="(item,index) in curCameraData.coords" - :key="index" - :style="{left:`${item.x0}px`, top:`${item.y0}px`, backgroundColor: colorPick, width: `${dotSize}px`, height: `${dotSize}px` }" - ></div> - </div> - <img v-show="snapshot_url" :src="`/httpImage/${snapshot_url}`" alt /> - <div - class="popBox" - v-show="isShowPop" - :style="`top:${curLabel.y0 + 22}px;left:${curLabel.x0}px`" - > - <div class="title">鏍囨敞淇℃伅</div> - <div class="details"> - <el-form :model="curLabel" :rules="rules" ref="labelForm"> - <div class="detail-item"> - <div class="left"> - <el-form-item prop="x0"> - <label for>骞抽潰鍧愭爣X:</label> - <span class="fix-width">{{curLabel.x0}}</span> - <i>px</i> - </el-form-item> - </div> - <span class="devide"></span> - <div class="right"> - <el-form-item prop="x1"> - <label for>瀹為檯鍧愭爣X:</label> - <el-input - type="text" - size="mini" - style="width:90px" - v-model.number="curLabel.x1" - ></el-input> - </el-form-item> - </div> + </el-tab-pane> + <el-tab-pane label="瀹炴櫙鍧愭爣" name="12"> + <div class="user-upload"> + <div class="img-card"> + <el-upload + class="upload-demo" + drag + action="https://jsonplaceholder.typicode.com/posts/" + :http-request="definedUpload" + :on-change="onChange" + :show-file-list="false" + > + <el-image + class="preview" + v-if="userImg" + :src="userImg" + fit="contain" + @mousemove="showCurPos" + @mouseout="isShowCurPos=false" + ></el-image> + <div class="el-upload__text"> + 灏嗘枃浠舵嫋鍒版澶勶紝鎴� + <em>鐐瑰嚮涓婁紶</em> </div> - <div class="detail-item"> - <div class="left"> - <el-form-item prop="y0"> - <label for>骞抽潰鍧愭爣Y:</label> - <span class="fix-width">{{curLabel.y0}}</span> - <i>px</i> - </el-form-item> - </div> - <span class="devide"></span> - <div class="right"> - <el-form-item prop="y1"> - <label for>瀹為檯鍧愭爣Y:</label> - <el-input - type="text" - size="mini" - style="width:90px" - v-model.number="curLabel.y1" - ></el-input> - </el-form-item> - </div> + </el-upload> + </div> + <div class="info"> + <div class="input-area"> + <div> + <label for>绌洪棿瀹�:</label> + <el-input v-model="spaceWidth" placeholder="璇疯緭鍏ュ疄闄呯┖闂村" size="small"></el-input> </div> - <div class="btns"> - <el-button size="mini" type="danger" @click="deleteLabel">鍒犻櫎</el-button> - <el-button size="mini" type="primary" @click="cancle">鍙栨秷</el-button> - <el-button size="mini" type="success" @click="sure">纭畾</el-button> + <div> + <label for>绌洪棿楂�:</label> + <el-input v-model="spaceHeight" placeholder="璇疯緭鍏ュ疄闄呯┖闂撮珮" size="small"></el-input> </div> - </el-form> + </div> + <div class="pos" v-show="isShowCurPos"> + 褰撳墠浣嶇疆: + <b>{{traceX}}</b>, + <b>{{traceY}}</b> + </div> </div> </div> - </div> - </div> + </el-tab-pane> + </el-tabs> </el-tab-pane> - <el-tab-pane label="杩借釜瀹炴櫙鍧愭爣" name="2"> + <el-tab-pane label="杞ㄨ抗鍥�" name="2"></el-tab-pane> + <!-- <el-tab-pane label="杩借釜瀹炴櫙鍧愭爣" name="2"> <div class="user-upload"> <div class="img-card"> <el-upload @@ -155,51 +205,155 @@ </div> </div> </div> + </el-tab-pane>--> + <el-tab-pane label="鍏宠仈鎽勫儚鏈�" name="3"> + <div class="tab-relation"> + <div class="part"> + <div class="title"> + <span>鍏宠仈璁惧鍒嗙粍</span> + <el-button @click="newGroup" icon="el-icon-plus" size="mini" type="primary">鏂板缓鍒嗙粍</el-button> + </div> + <el-alert + type="info" + title="鎻愮ず:璇风偣鍑讳笂鏂�'鏂板缓鍒嗙粍'鎸夐挳寤虹珛鍒嗙粍" + show-icon + v-if="groupList.length==0" + ></el-alert> + <div class="flex-box"> + <div + class="group-card" + :class="{'checked':group.checked}" + v-for="(group,index) in groupList" + :key="index" + @click="checkCurrentGroup(group)" + > + <div class="top"> + <div class="left"> + <span class="icon el-icon-video-camera"></span> + </div> + <div class="right"> + <div class="name">{{group.groupName}}</div> + <div class="details"> + <label>鎽勫儚鏈�:</label> + <span + class="sub" + v-for="(camera,index) in group.cameras" + :key="camera.id" + >{{camera.name}} {{index!==group.cameras.length-1?'/':''}}</span> + </div> + </div> + </div> + <div class="bottom"> + <span @click.stop="editGroup(group)">缂栬緫鍒嗙粍</span> + <el-popconfirm title="纭畾鍒犻櫎鏀瑰垎缁勫悧?" @onConfirm="removeGroup(group)"> + <el-button slot="reference" type="text">鍒犻櫎鍒嗙粍</el-button> + </el-popconfirm> + </div> + </div> + </div> + </div> + <!-- <div class="part" v-if="groupList.length"> --> + <div class="part" v-if="Object.keys(curGroup)"> + <div class="title">缁樺埗鍖哄煙(鐢ㄤ簬绠楁硶鍒嗘瀽)</div> + <div class="relative-partment" v-if="curGroup.cameras&&curGroup.cameras.length"> + <div class="area-wrap" v-for="i in 2" :key="'sc'+i"> + <slide-canvas :cameras="curGroup.cameras" @polygonDataUpdate="polygonUpdate"></slide-canvas> + </div> + </div> + </div> + <div class="part relative-config" v-if="Object.keys(curGroup)"> + <div class="title"> + <div class="left"> + <span>鍏宠仈鍖哄煙閰嶇疆</span> + </div> + <div class="right" v-if="curGroup.id"> + <el-button + icon="el-icon-plus" + size="mini" + type="primary" + @click="addRelation" + >娣诲姞鍏宠仈</el-button> + </div> + </div> + <div class="relative-list"> + <div class="relative-item" v-for="(item,index) in relativeList" :key="index"> + <div class="left"> + <el-select v-model="item.sourceObj" value-key="polygonId" size="small"> + <el-option + v-for="area in cameraAreas" + :key="area.polygonId" + :label="area.name" + :value="area" + ></el-option> + </el-select> + <i class="el-icon-connection"></i> + <el-select v-model="item.targetObj" value-key="polygonId" size="small"> + <el-option + v-for="area in cameraAreas" + :key="area.polygonId" + :label="area.name" + :value="area" + ></el-option> + </el-select> + </div> + <div class="right"> + <el-button type="text" @click="saveRelativePolygon(item)">淇濆瓨</el-button> + <div class="btn-del" @click="delRelation(item)"> + <i class="el-icon-delete"></i> + </div> + </div> + </div> + </div> + <!-- <div class="btns"> + <el-button size="small" >鍙栨秷</el-button> + <el-button size="small" type="primary" @click="saveRelativeList">淇濆瓨</el-button> + </div>--> + </div> + </div> </el-tab-pane> </el-tabs> - <!-- <el-collapse v-model="actPage" @change="chnageActPage"> - <el-collapse-item title="鎽勫儚鏈烘爣娉�" name="1"> - - </el-collapse-item> - <el-collapse-item title="杩借釜瀹炴櫙鍧愭爣" name="2"> - <div class="user-upload"> - <div class="img-card"> - <el-upload - class="upload-demo" - drag - action="https://jsonplaceholder.typicode.com/posts/" - :http-request="definedUpload" - :on-change="onChange" - :show-file-list="false" - > - <el-image - class="preview" - v-if="userImg" - :src="userImg" - fit="contain" - @mousemove="showCurPos" - @mouseout="isShowCurPos=false" - ></el-image> - <div class="el-upload__text"> - 灏嗘枃浠舵嫋鍒版澶勶紝鎴� - <em>鐐瑰嚮涓婁紶</em> - </div> - </el-upload> + <el-dialog class="dialog-group" title="鏂板缓鍒嗙粍" :visible.sync="groupModelVisible"> + <el-form :model="groupForm" ref="groupForm"> + <el-form-item> + <label>鍒嗙粍鍚嶇О</label> + <div> + <el-input v-model="groupForm.groupName"></el-input> </div> - <div class="info" v-show="isShowCurPos">褰撳墠浣嶇疆:{{traceX}},{{traceY}}</div> + </el-form-item> + <el-form-item> + <label>閫夋嫨鎽勫儚鏈�</label> + <div> + <el-select v-model="groupForm.cameras" value-key="id" multiple> + <el-option + :label="camera.name" + :value="camera" + v-for="camera in cameraData" + :key="camera.id" + ></el-option> + </el-select> + </div> + </el-form-item> + <div class="btns"> + <el-button @click="groupModelVisible=false;">鍙栨秷</el-button> + <el-button type="primary" @click="confirmGroupDialog">纭畾</el-button> </div> - </el-collapse-item> - </el-collapse>--> + </el-form> + </el-dialog> </div> </div> </template> <script> import { getCamerasByServer } from '@/api/pollConfig'; -import { getCameraMarks, updateCameraMarks } from '@/api/camera'; +import { getCameraMarks, updateCameraMarks, findCameraGroups, saveCameraGroupInfo, delCameraGroup } from '@/api/camera'; +import { getSearchList } from '@/api/search'; import TreeDataPool from "@/Pool/TreeData"; import { isNonnegativeInteger } from '@/scripts/validate'; +import { getAllPolygon, saveRelationPolygon, findByCamGroup, findByGroup, delRelation } from '@/api/polygon'; +import SlideCanvas from './SlideCanvas'; + export default { + components: { SlideCanvas }, data () { return { labels: [], @@ -244,7 +398,22 @@ curCameraData: { cameraId: '', coords: [] - } + }, + relativeCameras: [], + relativeList: [], + cameraAreas: [], + groupModelVisible: false, + groupList: [], + curGroup: {}, + groupForm: { + groupName: '', + cameras: [] + }, + groupCameras: [], + groupCamera: { + + }, + cameraAndPolygonData: [] } }, computed: { @@ -268,6 +437,12 @@ }, deep: true }, + 'TreeDataPool.selectedNodes': { + handler (n, o) { + + }, + deep: true + }, isEdit (n, o) { if (n) { this.$refs['editBoard'].addEventListener('click', this.bindListen); @@ -277,18 +452,248 @@ } }, methods: { + polygonUpdate(){ + debugger + this.getAllGroups(); + }, + delRelation (item) { + let _this = this; + delRelation(item.id).then(res => { + if (res.success) { + this.$notify({ + type: 'success', + message: res.data + }); + _this.findRelationByGroup(); + } + }) + }, + findRelationByGroup () { + let _this = this; + findByGroup({ groupId: this.curGroup.id }).then(res => { + + _this.relativeList = res.data.map(relation => { + let obj = { sourceObj: {}, targetObj: {} }; + obj.sourceObj.cameraId = relation.source_camera_id; + obj.sourceObj.polygonId = relation.source_polygon_id; + obj.targetObj.cameraId = relation.target_camera_id; + obj.targetObj.polygonId = relation.target_polygon_id; + obj.sourceObj.name = relation.source_polygon.name; + obj.targetObj.name = relation.target_polygon.name; + obj.id = relation.id; + return obj; + }) + }) + }, + saveRelativePolygon (item) { + let _this = this; + let params = { + groupId: this.curGroup.id, + source_camera_id: item.sourceObj.cameraId, + target_camera_id: item.targetObj.cameraId, + source_polygon_id: item.sourceObj.polygonId, + target_polygon_id: item.targetObj.polygonId, + id: item.id || '' + } + + saveRelationPolygon(params).then(res => { + if (res.success) { + this.$notify({ + type: 'success', + message: '淇濆瓨鎴愬姛', + }); + _this.findRelationByGroup() + } + }) + }, + saveRelativeList () { + let params = { + groupId: this.curGroup.id, + + } + //saveRelationPolygon().then() + }, + async findPolygonByIds (cameras) { + for (var i = 0; i < cameras.length; i++) { + let res = await getAllPolygon({ cameraId: cameras[i].id }); + cameras[i].canvasData = res.data; + } + return cameras + }, + + async getAllGroupInfo () { + let _this = this; + let res = await findCameraGroups(); + let groupArr = res.data.map(item => { + let obj = {}; //group + obj.groupName = item.groupName; + obj.id = item.id; + let cameras = []; //cameras + item.cameraIds.forEach(id => { + let camera = {}; + _this.cameraData.find(one => { + if (one.id == id) { + camera.name = one.name; + camera.id = id; + } + }); + cameras.push(camera) + }); + //cameras [{id,name}] + obj.cameras = cameras; + return obj; + + }); + return groupArr; + }, + // async getAllGroups () { + // let _this = this; + // let groups = await this.getAllGroupInfo(); + // let promiseArr = []; + // for (var i = 0; i < groups.length; i++) { + // let pro = new Promise(resolve => { + // resolve(_this.findPolygonByIds(groups[i].cameras)) + // }); + // promiseArr.push(pro) + // } + // Promise.allSettled(promiseArr).then(camerasArr => { + + // for (var i = 0; i < camerasArr.length; i++) { + // groups[i].cameras = camerasArr[i].value + // } + // _this.groupList = groups; + // //閫変腑绗竴涓� + // _this.checkCurrentGroup(_this.groupList[0]); + // }) + // }, + async getAllGroups(){ + let _this = this; + let groups = await this.getAllGroupInfo(); + for(var i = 0; i< groups.length; i++){ + groups[i].cameras = await _this.findPolygonByIds(groups[i].cameras) + } + this.groupList = groups + //閫変腑绗竴涓� + this.checkCurrentGroup(_this.groupList[0]); + }, + + addRelation () { + let obj = { cameraArea1: '', cameraArea2: '' }; + this.relativeList.push(obj) + }, + + editGroup (group) { + this.groupModelVisible = true; + //this.$refs['groupForm'].resetFields(); + this.groupForm = group; + }, + removeGroup (group) { + let _this = this; + delCameraGroup(group.id).then(res => { + _this.getAllGroups() + }) + }, + checkCurrentGroup (group) { + this.groupList.forEach(group => { + group.checked = false; + }) + this.curGroup = group; + this.curGroup.checked = true; + this.findRelationByGroup(); + //鏌ヨ绗竴涓垎缁勪笅鎽勫儚鏈哄尯鍩� + findByCamGroup({ groupId: group.id }).then(res => { + let tempArr = []; + res.data.forEach(camera => { + let cameraArea = []; + camera.polygon.forEach(item => { + let area = {}; + area.name = camera.camera_name + '' + item.name; + area.cameraId = camera.camera_id; + area.polygonId = item.id; + cameraArea.push(area); + }); + camera.rect.forEach(item => { + let area = {}; + area.name = camera.camera_name + '' + item.name; + area.cameraId = camera.camera_id; + area.polygonId = item.id; + cameraArea.push(area); + }); + tempArr = tempArr.concat(cameraArea) + }); + this.cameraAreas = tempArr; + console.log(this.cameraAreas) + }) + }, + confirmGroupDialog () { + //璇锋眰淇濆瓨鏂板缓鎴栫紪杈戝垎缁� + let _this = this; + let params = { + cameraIds: [], + groupName: '', + id: '' + }; + if (!this.groupForm.groupName.trim()) { + this.$notify({ + type: 'warning', + message: '璇疯緭鍏ュ垎缁勫悕绉�' + }); + return + } + if (this.groupForm.cameras.length < 2) { + this.$notify({ + type: 'warning', + message: '璇烽�夋嫨鑷冲皯涓や釜鎽勫儚鏈�' + }); + return + } + params.groupName = this.groupForm.groupName; + params.id = this.groupForm.id || ''; + this.groupForm.cameras.forEach(camera => { + params.cameraIds.push(camera.id); + //鏍规嵁鍒嗙粍鍐呮憚鍍忔満id鏌ュ悇鑷尯鍩� + getAllPolygon({ cameraId: camera.id }).then(res => { + _this.groupCameras.push(res.data); + }).catch(e => { + console.log(e) + }); + }) + //this.groupList.push(this.groupForm); + saveCameraGroupInfo(params).then(res => { + _this.getAllGroups(); + }) + this.groupModelVisible = false; + + }, + newGroup () { + this.groupModelVisible = true; + this.$nextTick(() => { + this.$refs['groupForm'].resetFields(); + }) + this.groupForm = { + groupName: '', + cameras: [] + } + + }, + changeTab () { + if (this.actPage == '1') { + this.$parent.$children[0].$el.parentNode.parentElement.style.display = 'block'; + } else { + this.$parent.$children[0].$el.parentNode.parentElement.style.display = 'none'; + } + }, sure () { let _this = this; this.$refs['labelForm'].validate(valid => { console.log(valid) if (valid) { _this.isShowPop = false; - debugger //缂栬緫纭畾 if (_this.curLabel.id) { let editedIndex = _this.curCameraData.coords.findIndex(one => one.id == _this.curLabel.id); _this.curCameraData.coords[editedIndex] = JSON.parse(JSON.stringify(_this.curLabel)); - + } console.log(_this.curCameraData.coords) this.$refs['labelForm'].clearValidate(); @@ -350,14 +755,28 @@ } }, getAllCameraData () { + let _this = this; getCamerasByServer().then(res => { if (res.success) { - this.cameraData = res.data; + _this.cameraData = res.data; + _this.getAllGroups(); } }).catch(e => { console.log(e) }) }, + // async getAllCameraData () { + // let res = await getCamerasByServer(); + // this.cameraData = res.data; + // let tempArr = []; + // this.cameraData.forEach(camera=>{ + // getAllPolygon({ cameraId: camera.id }).then(res=>{ + // tempArr.push(res.data); + // }) + // }); + // this.cameraAndPolygonData = tempArr; + // console.log(this.cameraAndPolygonData) + // }, bindListen (e) { this.newLabel(e); }, @@ -374,7 +793,7 @@ x1: '', y1: '' }; - target.id = 'n'+(this.curCameraData.coords.length-1); + target.id = 'n' + (this.curCameraData.coords.length - 1); //this.labels.push(target); this.curCameraData.coords.push(target); this.curLabel = target; @@ -393,7 +812,7 @@ cancle () { this.isShowPop = false; //濡傛灉鏄湭淇濆瓨杩囩殑label鐩存帴鍒犻櫎(鏈繚瀛樼殑灏辨槸labels鏁扮粍涓渶鍚庝竴涓�) - if (!this.curLabel.id) { + if (this.curLabel.id.startsWith('n')) { //this.labels.pop(); this.curCameraData.coords.pop(); } @@ -420,6 +839,7 @@ .el-tabs__content { background: #d2dcea; height: calc(100vh - 85px); + overflow-y: auto; } } .tool-bar { @@ -633,6 +1053,149 @@ // height: 100%; } } + .tab-relation { + .el-alert--info { + background: rgba(230, 247, 255, 1); + border-color: rgba(145, 213, 255, 1); + color: #666; + .el-alert__icon.el-icon-info { + color: #1890ff; + } + } + .title { + text-align: left; + font-size: 15px; + line-height: 40px; + .el-button { + margin-left: 14px; + } + } + .group-card { + background: #fff; + width: 293px; + height: 153px; + margin-right: 10px; + box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1); + border: 1px solid transparent; + &.checked { + border-color: #1890ff; + } + .top { + height: 104px; + display: flex; + padding-left: 20px; + padding-top: 20px; + box-sizing: border-box; + //align-items: center; + .right { + text-align: left; + padding-left: 14px; + } + .icon { + font-size: 40px; + } + .name { + font-size: 16px; + margin-bottom: 10px; + font-weight: bold; + } + .details { + display: flex; + flex-wrap: wrap; + label { + width: 46px; + } + .sub { + } + } + } + .bottom { + border-top: 1px solid #e9e9e9; + height: 48px; + line-height: 48px; + background: #f7f9fa; + position: relative; + display: flex; + &:after { + content: ''; + position: absolute; + font-size: 0; + width: 1px; + height: 14px; + background: #0000006d; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + span { + cursor: pointer; + width: 50%; + font-size: 14px; + color: #0000006d; + } + } + } + .part { + margin-bottom: 20px; + .relative-partment { + width: 1200px; + margin: 0 auto; + display: flex; + justify-content: space-between; + .area-wrap { + width: 576px; + } + } + } + .relative-config { + width: 700px; + .title { + display: flex; + justify-content: space-between; + } + .relative-list { + .relative-item { + width: 680px; + height: 48px; + padding-left: 20px; + background: #ecf2f5; + margin-bottom: 6px; + display: flex; + align-items: center; + .left { + width: 650px; + text-align: left; + } + .right { + display: flex; + align-items: center; + } + i { + font-size: 20px; + padding: 0 10px; + cursor: pointer; + } + } + } + } + } + .dialog-group { + .el-form { + .el-form-item__content { + display: flex; + label { + width: 80px; + text-align: left; + } + & > div { + flex: 1; + .el-select { + width: 100%; + } + } + } + } + } } .el-input__inner:focus { outline: none; diff --git a/src/pages/labelMark/components/SlideCanvas.vue b/src/pages/labelMark/components/SlideCanvas.vue new file mode 100644 index 0000000..ba82824 --- /dev/null +++ b/src/pages/labelMark/components/SlideCanvas.vue @@ -0,0 +1,222 @@ +<template> + <div class="swiper-box"> + <p class="task-tip" v-if="cameras.length == 0 "></p> + <swiper + ref="cameraSwiper" + v-if="cameras.length>=1" + :options="swiperOption" + class="swiper-box-container" + > + <swiper-slide v-for="camera in cameras" :key="camera.id+'c'"> + <div class="swiper-draw-box-title"> + <b>{{camera.name}}</b> + <b style="margin-left:14px;">缁樺埗鍖哄煙</b> + <span + class="el-dropdown-link" + @click="drawBaseImg(camera.id)" + style="position: relative;top: 5px; cursor:pointer" + > + <i class="iconfont iconbianji1" style="font-size: 28px; "></i> + </span> + </div> + <polygon-canvas + class="polygon-canvas" + :ref="`polygonCanvas_${camera.id}`" + :snapshot_url="camera.canvasData.snapshot_url" + :canvasDataShow="camera.canvasData" + :canvasWidth="576" + :canvasHeight="324" + @fromCanvas="getCanvasData" + ></polygon-canvas> + </swiper-slide> + </swiper> + <div class="swiper-pre-border" slot="button-prev" @click="pre" > + <div class="icon-btn" > + <i class="iconfont iconzuo"></i> + </div> + </div> + <div class="swiper-next-border" slot="button-next" @click="next"> + <div class="icon-btn" > + <i class="iconfont iconyou1"></i> + </div> + </div> + + </div> +</template> + +<script> +import { chunkArr } from '@/scripts/util'; +import PolygonCanvas from '@/components/canvas'; +import { savePolygon } from "@/api/polygon"; +export default { + //cameras: [{ id: '',snapshot_url:'', canvasData: {} }] + props: [ + 'cameras', + //'swiperOption' + ], + watch:{ + cameras:{ + handler(n,o){ + console.log('slidecanvas cameras',n) + }, + deep: true + } + }, + components: { PolygonCanvas }, + data () { + return { + swiperOption: this.newOption(), + //mySwiper: {} + } + }, + computed: { + swiper () { + return this.$refs['cameraSwiper'].swiper + } + }, + mounted () { + //this.mySwiper = this.$refs.sceneSwiper.swiper; + console.log(this.swiper) + }, + methods: { + getCanvasData(data) { + let _this = this; + savePolygon(data).then(rsp => { + _this.$emit('polygonDataUpdate') + }); + }, + newOption () { + return { + slidesPerView: 1, + spaceBetween: 0, + pagination: { + el: ".swiper-pagination", + clickable: true + }, + observer: true,//淇敼swiper鑷繁鎴栧瓙鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + observeParents: true,//淇敼swiper鐨勭埗鍏冪礌鏃讹紝鑷姩鍒濆鍖杝wiper + } + }, + + pre () { + this.swiper.activeIndex-- + this.swiper.slideTo(this.swiper.activeIndex); + }, + next () { + this.swiper.activeIndex++ + this.swiper.slideTo(this.swiper.activeIndex); + }, + drawBaseImg (id) { + this.$refs[`polygonCanvas_${id}`][0].showModal(); + } + } +}; +</script> + +<style lang="scss"> +.icon { + width: 1em; + height: 1em; + vertical-align: -0.15em; + fill: currentColor; + overflow: hidden; +} +.task-tip { + font-family: PingFangSC-Regular; + font-size: 12px; + color: #cccccc; + margin-top: 10%; +} +.swiper-box { + position: relative; +} +.swiper-pre-border, +.swiper-next-border { + width: 40px; + height: 40px; + position: absolute; + background: #8888; + top: 50%; + margin-top: -20px; + z-index: 99; + border-radius: 4em; + outline: none; + .icon-btn { + color: rgb(255, 255, 255); + text-align: center; + line-height: 38px; + cursor: pointer; + } +} +.swiper-pre-border { + left: 10px; +} +.swiper-pre-border:hover { + background: #666; +} +.swiper-next-border { + right: 10px; +} +.swiper-next-border:hover { + background: #666; +} +.swiper-draw-box-title { + display: flex; + justify-content: center; + align-items: center; + height: 24px; + b { + font-size: 14px; + } +} +.wrap-box { + width: 100%; + display: inline-block; + .inner { + width: 90%; + box-sizing: border-box; + position: relative; + font-size: 14px; + padding: 7px 0 48px; + transition: all 1s; + background: #ffffff; + border: 1px solid #e2e2e2; + box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07); + border-radius: 4px; + margin: auto; + &:hover { + .mask { + display: block; + } + } + .mask { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.65); + backdrop-filter: blur(1px) brightness(100%); + text-align: center; + z-index: 1; + border-radius: 3px; + display: none; + .tool { + position: absolute; + top: 49%; + left: 50%; + transform: translate(-50%, -50%); + i { + font-size: 50px; + } + i:nth-of-type(1) { + margin-right: 30px; + } + i:nth-of-type(2) { + color: red; + } + } + } + } +} +</style> \ No newline at end of file diff --git a/src/pages/labelMark/index/App.vue b/src/pages/labelMark/index/App.vue index df72374..2624781 100644 --- a/src/pages/labelMark/index/App.vue +++ b/src/pages/labelMark/index/App.vue @@ -1,6 +1,6 @@ <template> <div class="column"> - <div class="column-left"> + <div class="column-left" ref="leftTree"> <div class="resize-bar"></div> <div class="resize-line"></div> <div class="resize-save"> @@ -8,22 +8,24 @@ </div> </div> <div class="column-right"> - <right-side /> + <right-side ref="content"/> </div> </div> </template> <script> import LeftNav from "@/components/LeftNav"; import RightSide from "../components/RightSide"; - +import TreeDataPool from "@/Pool/TreeData"; export default { components: { LeftNav, RightSide }, data () { return { screenHeight: 0, - } }, + // created(){ + // this.TreeDataPool.multiple = true; + // }, mounted() { this.screenHeight = document.documentElement.clientHeight - 20; window.onresize = () => { diff --git a/src/pages/labelMark/index/main.ts b/src/pages/labelMark/index/main.ts index a8cc111..b9b1993 100644 --- a/src/pages/labelMark/index/main.ts +++ b/src/pages/labelMark/index/main.ts @@ -4,9 +4,12 @@ import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import "@/assets/css/element-variables.scss"; +import VueAwesomeSwiper from "vue-awesome-swiper"; +import "swiper/dist/css/swiper.css"; import Mixin from "./mixins"; Vue.use(ElementUI); +Vue.use(VueAwesomeSwiper as any); Vue.mixin(Mixin); new Vue({ el: '#app', diff --git a/src/scripts/util.js b/src/scripts/util.js index 19cd19d..2f4261f 100644 --- a/src/scripts/util.js +++ b/src/scripts/util.js @@ -249,6 +249,22 @@ } } +//鎷嗗垎浜岀淮鏁扮粍 +const chunkArr = (arr, size = 1)=>{ + if (arr.length == 0) return; + const tempContainer = []; + let innerArr = []; + arr.forEach(item => { + if (innerArr.length == 0) { + tempContainer.push(innerArr); + } + innerArr.push(item); + if (innerArr.length == size) { + innerArr = []; + } + }); + return tempContainer; +} export { thisRouterObjFn, json2url, @@ -264,5 +280,6 @@ guid, cloneDeep, getYearWeek, - getContainerRect + getContainerRect, + chunkArr } -- Gitblit v1.8.0