<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"
|
: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-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>
|
</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, 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: [],
|
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: [],
|
cameraAreas: [],
|
groupModelVisible: false,
|
groupList: [],
|
curGroup: {},
|
groupForm: {
|
groupName: '',
|
cameras: []
|
},
|
groupCameras: [],
|
groupCamera: {
|
|
},
|
cameraAndPolygonData: []
|
}
|
},
|
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) {
|
|
},
|
deep: true
|
},
|
isEdit (n, o) {
|
if (n) {
|
this.$refs['editBoard'].addEventListener('click', this.bindListen);
|
} else {
|
this.$refs['editBoard'].removeEventListener('click', this.bindListen);
|
}
|
}
|
},
|
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;
|
//编辑确定
|
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 () {
|
let _this = this;
|
getCamerasByServer().then(res => {
|
if (res.success) {
|
_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);
|
},
|
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.startsWith('n')) {
|
//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);
|
overflow-y: auto;
|
}
|
}
|
.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: 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;
|
border-color: rgba(42, 56, 93, 71%) !important;
|
}
|
.el-upload-dragger:hover {
|
border-color: rgba(42, 56, 93, 71%) !important;
|
}
|
</style>
|