<template>
|
<div class="content">
|
<div class="content-top">
|
<div class="grid-check">
|
<span
|
:class="guid === 1 ? 'iconfont icongongge1 activegongge':'iconfont icongongge1'"
|
@click="setGuid(1)"
|
></span>
|
<span
|
:class="guid === 2 ? 'iconfont icongongge activegongge':'iconfont icongongge'"
|
@click="setGuid(2)"
|
></span>
|
<span
|
:class="guid === 3 ? 'iconfont icongongge2 activegongge':'iconfont icongongge2'"
|
@click="setGuid(3)"
|
></span>
|
</div>
|
<div class="video-area">
|
<div class="info-list block">
|
<p class="title-partment">相关视频</p>
|
<!-- <div class="video-name" v-for="video in videoDetails.videoList" :key="video.id">
|
<i class="el-icon-film"></i>
|
<span>{{video.name}}</span>
|
</div>-->
|
<div
|
class="video-name"
|
:class="{'current':curVideo.ID==video.ID}"
|
@click="checkVideo(video,index)"
|
v-for="(video,index) in relativeVideos"
|
:key="video.ID"
|
>
|
<i class="el-icon-film"></i>
|
<span>{{video.Camera}}</span>
|
</div>
|
</div>
|
<div class="players" ref="playerWrap">
|
<template v-if="guid==1">
|
<div
|
class="video-item"
|
:ref="`gridVideoItem_${index}`"
|
v-for="(item,index) in videoWrapArr"
|
:key="index"
|
>
|
<div class="currentPlayer">
|
<!-- {{curVideo.ID}} -->
|
<!-- <img :src="curVideo.VideoCover" style="width:100px" /> -->
|
<ali-player
|
:source="'http://' + curVideo.VideoPath"
|
:markers="curVideo.marks"
|
:ref="`player_${curVideo.ID}`"
|
/>
|
</div>
|
</div>
|
</template>
|
<template v-else>
|
<div
|
class="video-item"
|
:ref="`gridVideoItem_${index}`"
|
v-for="(item,index) in videoWrapArr"
|
:key="index"
|
@click="checkCurVideo(index)"
|
>
|
<template v-if="index<=videoArrs.length-1">
|
<div :class="{'currentPlayer':curVideo.ID==videoArrs[index].ID}">
|
<!-- {{videoArrs[index].ID}} -->
|
<!-- <img
|
:src="videoArrs[index].VideoCover"
|
style="width:100px"
|
/>-->
|
<ali-player
|
:source="'http://' + videoArrs[index].VideoPath"
|
:markers="videoArrs[index].marks"
|
:ref="`player_${videoArrs[index].ID}`"
|
/>
|
</div>
|
</template>
|
</div>
|
</template>
|
|
<!-- <div
|
class="video-item"
|
:class="{'active':item.ID==curVideo.ID}"
|
:ref="`gridVideoItem_${index}`"
|
v-for="(item,index) in videoWrapArr"
|
:key="index"
|
>
|
</div>-->
|
</div>
|
</div>
|
</div>
|
<div class="content-bottom">
|
<div class="bot-left block">
|
<p class="title-partment">快速标注</p>
|
<div class="flex-box" style="height:28px;">
|
<label style="padding-right:10px;">隐患问题:</label>
|
<el-radio-group v-model="isUnusual">
|
<el-radio :label="0">无异常</el-radio>
|
<el-radio :label="1">有异常</el-radio>
|
</el-radio-group>
|
|
<el-button
|
icon="el-icon-plus"
|
size="mini"
|
v-show="isUnusual==1"
|
type="primary"
|
@click="addLabel(curVideo)"
|
>添加标注</el-button>
|
</div>
|
<div class="flex-box fixed-height-box">
|
<label>标注信息:</label>
|
<div class="mark-list">
|
<div class="mark" v-for="mark in curVideo.LableLst" :key="mark.ID">
|
<div class="time">
|
<span>{{mark.Time}}</span>
|
<i class="el-icon-edit" @click="editCurLabel(mark)"></i>
|
<i class="el-icon-delete" @click="removeCurLabel(mark)"></i>
|
</div>
|
<div class="label-content">
|
<span>{{mark.Desc}}</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="bot-right block">
|
<p class="title-partment">视频详情</p>
|
<div class="base-info">
|
<div>
|
<label>车号:</label>
|
<span>{{videoDetails.CarNumber}}</span>
|
</div>
|
<div>
|
<label>车次:</label>
|
<span>{{videoDetails.TrainNumber}}</span>
|
</div>
|
<div>
|
<label>时间:</label>
|
<span>{{videoDetails.VideoDate}}</span>
|
</div>
|
<div>
|
<label>司机|副司机:</label>
|
<span>{{videoDetails.Driver1}}|{{videoDetails.Driver2}}</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<el-dialog
|
class="label-dialog"
|
:visible="labelDialogVisible"
|
@close="labelDialogVisible=false"
|
:append-to-body="false"
|
>
|
<div class="label-radio">
|
<p class="label">选择将要标注的视频:</p>
|
<el-radio-group v-model="isCheckAllVideo">
|
<el-radio :label="1">标注在全部位置的视频段</el-radio>
|
<el-radio :label="0">仅标注选中的视频段</el-radio>
|
</el-radio-group>
|
</div>
|
<div class="label-check">
|
<p class="label">隐患问题:</p>
|
<el-checkbox-group v-model="labelCheckedList">
|
<el-checkbox v-for="item in labelOptions" :key="item.ID" :label="item.ID">{{item.Name}}</el-checkbox>
|
</el-checkbox-group>
|
</div>
|
<div class="btns">
|
<el-button @click="cancelLabelChecked" size="small">取消</el-button>
|
<el-button @click="submitLabelChecked()" size="small" type="primary">确定</el-button>
|
</div>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import { getlstInit, updateVideoAnalyze, getlst, getRelatedVideoInfo, getLabelMap, delLabel, editLabel } from '@/api/shuohuang';
|
import AliPlayer from './aliPlayer/index';
|
|
export default {
|
name: "VideoAnalyze",
|
components: {
|
AliPlayer
|
},
|
props: {
|
videoDetails: {
|
default: () => { return {} },
|
type: Object
|
}
|
},
|
data () {
|
return {
|
guid: 1,
|
labelDialogVisible: false,
|
curVideo: {},
|
isUnusual: 0,
|
videoArrs: [],
|
relativeVideos: [],
|
labelCheckedList: [],
|
videoWrapArr: [],
|
labelOptions: [],
|
selectedLabelId: '',
|
setLabelTime: 0,
|
isCheckAllVideo: 1,
|
}
|
},
|
watch: {
|
'curVideo.LableLst': {
|
handler (n, o) {
|
if (n.length > 0) {
|
this.isUnusual = 1
|
} else {
|
this.isUnusual = 0
|
}
|
},
|
deep: true
|
},
|
videoDetails: {
|
handler (newVal, oldVal) {
|
this.getVideos(newVal)
|
},
|
deep: true
|
},
|
},
|
mounted () {
|
console.log('analyze mount')
|
this.renderLabelOpts();
|
this.setGuid(1);
|
this.getVideos(this.videoDetails);
|
},
|
methods: {
|
checkCurVideo (index) {
|
if (this.relativeVideos[index]) {
|
this.curVideo = this.relativeVideos[index];
|
this.refreshCurVideoLabel(this.curVideo);
|
}
|
},
|
getVideos (video) {
|
let _this = this;
|
getRelatedVideoInfo({ UniqeID: video.UniqeID }).then(res => {
|
console.log(res)
|
res.data.forEach(element => {
|
element.marks = _this.mergeMarks(element)
|
console.log(element.marks)
|
});
|
_this.curVideo = res.data[0];
|
_this.videoArrs = res.data;
|
_this.relativeVideos = res.data;
|
this.$nextTick(() => {
|
_this.$refs[`player_${_this.curVideo.ID}`][0].init();
|
})
|
|
})
|
},
|
renderLabelOpts () {
|
let _this = this;
|
getLabelMap().then(res => {
|
_this.labelOptions = res.data
|
})
|
},
|
refreshCurVideoLabel (video) {
|
getRelatedVideoInfo({ UniqeID: video.UniqeID }).then(res => {
|
res.data.forEach(d => {
|
if(d.ID === video.ID){
|
video.LableLst = d.LableLst
|
}
|
// let someVideo = _this.videoArrs.find(video => video.ID === d.ID);
|
// someVideo.LableLst = d.LableLst
|
})
|
})
|
},
|
checkVideo (video, index) {
|
this.refreshCurVideoLabel(video);
|
this.curVideo = video;
|
this.$nextTick(() => {
|
this.$refs[`player_${this.curVideo.ID}`][0].init();
|
})
|
|
},
|
|
setGuid (guid) {
|
let _this = this;
|
this.guid = guid;
|
// for(var i = 0; i < Math.pow(guid,2); i++){
|
// if(i>this.videoArrs.length-1){
|
// this.videoWrapArr[i] = this.videoArrs[i]
|
// }else{
|
// this.videoWrapArr[i] = {}
|
// }
|
// }
|
this.videoWrapArr = Math.pow(guid, 2);
|
this.$nextTick(() => {
|
for (var i = 0; i < Math.pow(guid, 2); i++) {
|
this.$refs[`gridVideoItem_${i}`][0].style.width = this.$refs['playerWrap'].offsetWidth / guid + 'px';
|
this.$refs[`gridVideoItem_${i}`][0].style.height = this.$refs['playerWrap'].offsetHeight / guid + 'px';
|
}
|
})
|
},
|
|
cancelLabelChecked () {
|
this.labelDialogVisible = false;
|
},
|
submitLabelChecked () {
|
let _this = this;
|
let tempArr = [];
|
if (this.isCheckAllVideo == 1) {
|
tempArr = this.videoArrs.map(video => video.ID)
|
}
|
let desc = this.labelCheckedList.map(lableId => {
|
for (let label of this.labelOptions) {
|
if (label.ID == lableId) {
|
return label.Name;
|
}
|
}
|
})
|
|
let query = {
|
ID: this.selectedLabelId,
|
ParentID: this.isCheckAllVideo ? tempArr.join(',') : this.curVideo.ID + '',
|
ParentUniqID:this.curVideo.UniqeID+ '',
|
Time: Math.round(this.setLabelTime) + '',
|
Codes: this.labelCheckedList.join(','),
|
Desc: desc.join(',')
|
};
|
editLabel(query).then(rsp => {
|
if (rsp && rsp.success) {
|
_this.labelDialogVisible = false;
|
this.$set(_this.curVideo,'LableLst',[]);
|
//_this.curVideo.LableLst = [];
|
rsp.data.forEach(label=>{
|
if(label.ParentID == _this.curVideo.ID){
|
_this.curVideo.LableLst.push(label)
|
}
|
})
|
// getRelatedVideoInfo({ UniqeID: _this.videoDetails.UniqeID }).then(res => {
|
// res.data.forEach(d => {
|
// let someVideo = _this.videoArrs.find(video => video.ID === d.ID);
|
// someVideo.LableLst = d.LableLst
|
// })
|
// })
|
|
this.$message.success("添加成功")
|
// 标注
|
_this.setMarks(this.curVideo)
|
} else {
|
this.$message.warning(rsp.msg)
|
}
|
})
|
},
|
addLabel (video) {
|
this.labelCheckedList = [];
|
this.selectedLabelId = '';
|
this.labelDialogVisible = true;
|
|
// 保存点击标注的时间
|
this.setLabelTime = this.$refs[`player_${video.ID}`][0].getCurrentTime();
|
},
|
editCurLabel (mark) {
|
this.selectedLabelId = mark.ID;
|
this.labelCheckedList = mark.Codes.split(" ,");
|
this.labelDialogVisible = true;
|
},
|
removeCurLabel (mark) {
|
let _this = this;
|
delLabel({ ID: mark.ID, ParentID: this.curVideo.ID }).then(rsp => {
|
if (rsp && rsp.success) {
|
_this.curVideo.LableLst = rsp.data;
|
this.$message.success("删除成功")
|
// 标注
|
debugger
|
_this.setMarks(_this.curVideo)
|
} else {
|
this.$message.warning(rsp.msg)
|
}
|
})
|
},
|
mergeMarks (videoInfo) {
|
let marks = videoInfo.HotPoint.concat(videoInfo.LableLst).map(lable => {
|
return {
|
offset: lable.Time,
|
text: lable.Desc
|
}
|
})
|
|
return marks;
|
},
|
setMarks (video) {
|
let marks = this.mergeMarks(video);
|
this.$refs[`player_${video.ID}`][0].setProgressMarkers(marks);
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.content {
|
padding: 15px;
|
text-align: left;
|
.content-top {
|
margin-bottom: 10px;
|
.grid-check {
|
text-align: right;
|
margin-bottom: 6px;
|
span {
|
font-size: 20px;
|
color: #cacaca;
|
padding-left: 12px;
|
cursor: pointer;
|
&.activegongge {
|
color: #3d68e1;
|
}
|
}
|
}
|
.video-area {
|
display: flex;
|
.info-list {
|
width: 160px;
|
margin-right: 10px;
|
.video-name {
|
cursor: pointer;
|
color: #777;
|
margin-bottom: 10px;
|
&.current {
|
color: #409eff;
|
}
|
i {
|
padding-right: 4px;
|
}
|
}
|
}
|
.players {
|
width: 960px;
|
height: 540px;
|
display: flex;
|
flex-wrap: wrap;
|
.video-item {
|
background: black;
|
border: 1px solid #fff;
|
box-sizing: border-box;
|
& > div {
|
height: 100%;
|
& > div {
|
height: 100%;
|
}
|
}
|
.currentPlayer {
|
border: 2px solid aqua;
|
height: 100%;
|
box-sizing: border-box;
|
& > div {
|
height: 100%;
|
}
|
}
|
}
|
}
|
}
|
}
|
.content-bottom {
|
display: flex;
|
.bot-left {
|
flex: 1;
|
.flex-box {
|
align-items: baseline;
|
label {
|
padding-right: 10px;
|
}
|
.mark-list {
|
.time {
|
cursor: pointer;
|
font-size: 15px;
|
font-weight: bold;
|
color: #409eff;
|
span {
|
padding-right: 5px;
|
}
|
i[class^='el-icon'] {
|
padding: 3px;
|
}
|
}
|
.label-content {
|
font-size: 13px;
|
padding: 4px 0;
|
color: #888;
|
}
|
}
|
}
|
.fixed-height-box {
|
height: 200px;
|
overflow-y: auto;
|
}
|
}
|
.bot-right {
|
width: 210px;
|
margin-left: 10px;
|
label {
|
color: #999;
|
padding-right: 8px;
|
}
|
}
|
}
|
|
.label-dialog {
|
.el-dialog {
|
width: 700px !important;
|
height: 670px !important;
|
.el-dialog__header {
|
height: 20px;
|
}
|
p.label {
|
line-height: 36px;
|
}
|
.label-radio {
|
padding: 20px;
|
}
|
.label-check {
|
padding: 20px;
|
min-height: 400px;
|
margin-bottom: 20px;
|
.el-checkbox-group {
|
display: flex;
|
flex-wrap: wrap;
|
> label {
|
width: 50%;
|
text-align: left;
|
margin: 0;
|
margin-bottom: 4px;
|
}
|
}
|
}
|
.btns {
|
display: flex;
|
justify-content: center;
|
padding: 20px;
|
}
|
}
|
}
|
}
|
</style>
|