<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
|
>{{ zeroize(Math.floor(mark.Time / 60)) }}:{{
|
zeroize(mark.Time % 60)
|
}}</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: "",
|
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: {
|
zeroize(val) {
|
return val < 10 ? "0" + val : val;
|
},
|
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.find((item) => item.ID == video.ID);
|
//_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("删除成功");
|
// 标注
|
_this.setMarks(_this.curVideo);
|
} else {
|
this.$message.warning(rsp.msg);
|
}
|
});
|
},
|
mergeMarks(videoInfo) {
|
// debugger
|
const eMarks = videoInfo.EventLst.map(function (item) {
|
return {
|
offset: item.SecondsInVideo + "",
|
text: item.Event + (item.Desc == "" ? "" : ": " + item.Desc),
|
};
|
});
|
const labMarks = videoInfo.LableLst.map((lable) => {
|
return {
|
offset: lable.Time,
|
text: lable.Desc,
|
};
|
});
|
|
return eMarks.concat(labMarks);
|
},
|
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>
|