TransFlow/src/views/AnalysisMain.vue

873 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="content-box">
<!-- v-if="videoTypeShow" -->
<div class="videoTypeBox" v-if="videoTypeShow">
<el-form :inline="true" :model="videoTypeForm" class="demo-form-inline" >
<el-form-item label="视频源类型:" >
<el-radio-group v-model="videoTypeForm.videoType" @change="changeRadio">
<el-radio label="实时视频"></el-radio>
<el-radio label="离线视频"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
<div>
<el-row>
<el-col :span="6" v-for="(item, index) in videoList" :key="item.id" :offset="index > 0 ? 0 : 0" ref="typeCard" >
<el-card :body-style="{ padding: '0px' }" class="card" :loading="loading">
<div class="type">
<img src="@/assets/img/AnalysisMain/leftTop.png" alt="" v-if="item.type=='实时视频'">
<img src="@/assets/img/AnalysisMain/leftTop2.png" alt="" v-if="item.type=='离线视频'">
</div>
<div class="name">
<img src="@/assets/img/AnalysisMain/ssVideo.png" alt="" v-if="item.type=='实时视频'">
<img src="@/assets/img/AnalysisMain/lxVideo.png" alt="" v-if="item.type=='离线视频'">
</div>
<div class="statusN">
<img src="@/assets/img/AnalysisMain/status.png" alt="" >
<span class="statusName" v-if="item.type=='实时视频'">{{ item.status }}</span>
<span class="statusName" v-if="item.type=='离线视频'">{{ item.videoAnalysisStatus }}</span>
</div>
<!-- <div class="middleN" v-if="item.type=='离线视频'&&item.videoAnalysisStatus=='分析中'"> -->
<div class="middleN" v-if=" (item.type=='离线视频' && item.videoAnalysisStatus=='分析中') || (item.type=='离线视频' &&item.videoAnalysisStatus=='未分析')">
<el-progress type="circle" :percentage="item.numSatus" text-color='#fff'></el-progress>
</div>
<div class="typeRight">
<el-button type="primary" icon="el-icon-refresh-right" @click="openRight(item)" v-if="item.type=='离线视频'&&item.videoAnalysisStatus=='分析异常'"></el-button>
</div>
<!-- <div class="del" @click="open(item.id)"> <i class='el-icon-delete'></i></div> -->
<img :src="item.img" class="image" @click="goToPage(item.videoAnalysisStatus
,item.id,item.num,item.title,item.type,item.status,item.msg,item.videoPath)">
<div class="bot">
<span style=" vertical-align: middle;">
<img src="@/assets/img/AnalysisMain/video (1).png" alt="">
<!-- <img :src="item.img" alt=""> -->
</span>
<div class="bottom clearfix">
<time class="time">{{ item.title }}</time>
<!-- <el-button type="text" class="button">操作按钮</el-button> -->
<!-- <div class="streamAddress" :content="item.videoStreamAddress!=''? item.videoStreamAddress:item.videoPath">{{item.videoStreamAddress!=''? item.videoStreamAddress:item.videoPath}}</div> -->
<div class="streamAddress" :content="item.videoStreamAddress!=''? item.videoStreamAddress:item.videoPath">{{item.videoStreamAddress!=''? item.videoStreamAddress:item.videoPath}}</div>
</div>
<div class="st">
<!-- <span>{{ item.status }}</span> -->
<el-button type="primary" icon="el-icon-delete" @click="open(item.id)"></el-button>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card :body-style="{ padding: '0px' }">
<div class="middle">
<div style="width: 50%;height: 100%;margin: auto;padding-top: 15%;cursor: pointer;text-align: center;" @click="informationInfo('新增')">
<img src="@/assets/img/AnalysisMain/add.png" width="80%">
</div>
</div>
</el-card>
</el-col>
</el-row>
<div class="btn" v-if="videoTypeForm.videoType=='实时视频'">
<el-button type="primary" @click="applicationBtn">保存</el-button>
<!-- <el-button type="primary" @click="stopAlgorithmBtn">关闭程序</el-button> -->
</div>
</div>
<!-- <div id="dialog" class="margin-top: 0px !important;"> -->
<el-dialog
title="视频源配置"
width="40%"
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
>
<!-- <editModal ></editModal> -->
<el-form :model="form">
<el-form-item label="视频源名称" :label-width="formLabelWidth">
<el-input v-model="form.videoName" autocomplete="off" style="width:50%" placeholder="请输入视频源名称"></el-input>
</el-form-item>
<!-- <el-form-item label="视频源类型" :label-width="formLabelWidth">
<el-radio-group v-model="form.videoType">
<el-radio label="实时视频"></el-radio>
<el-radio label="离线视频"></el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item label="视频源地址" :label-width="formLabelWidth" v-if="videoTypeForm.videoType=='实时视频'">
<el-input v-model="form.videoStreamAddress" autocomplete="off" style="width:80%" placeholder="请输入视频源地址" >
<template slot="prepend">rtsp://</template>
</el-input>
<!-- <el-input v-model="form.videoStreamAddress" autocomplete="off" style="width:80%"></el-input> -->
</el-form-item>
<el-form-item label="车牌识别开关:" :label-width="formLabelWidth" v-if="videoTypeForm.videoType=='离线视频'">
<el-switch
v-model="form.LicensePlateRecognitionSwitch"
active-value="1"
inactive-value="0"
@change="changeChepai($event)"
></el-switch>
</el-form-item>
<el-form-item label="离线视频上传" :label-width="formLabelWidth" v-if="videoTypeForm.videoType=='离线视频'">
<!-- <el-button slot="trigger" size="small" type="primary">选取文件</el-button> -->
<input type="file" id="fileExport" @change="handleFileChange" ref="inputer">
<el-button size="small" type="primary" @click="load">点击上传</el-button>
<!-- <el-upload
class="upload-demo"
action="#"
:file-list="fileList"
@change="handleFileChange"
multiple >
<el-button type="file" id="fileExport" ref="inputer">选取文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="load">点击上传</el-button>
<div slot="tip" class="el-upload__tip">上传文件名称请勿空格!</div>
</el-upload> -->
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false" :disabled="dis">取 消</el-button>
<el-button type="primary" @click="commit(form)" :disabled="dis"> </el-button>
</div>
</el-dialog>
<!-- </div> -->
</div>
</template>
<script>
import editModal from "@/views/bounced/maintenanceRemind";
import {getGetShipjk,getDeleteShipjk,getApplication,getStopAlgorithm,startVideoAnalysis,getSetVideoMode,getVideoMode} from "../api/index";
import serverUrl from "../config/apiurl.js"
import axios from 'axios'
const os = require('os');
export default {
data(){
return{
receiveNews: "",
topicSends:[],
componentShow: "",
numArr:[],
currentDate: new Date(),
closeStatus: null,
dis:false,
dialogFormVisible: false,
videoTypeShow: false,
loading:true,
fileList: [],
form: {
radio:'',
videoName:'视频01',
city:'',
videoStreamAddress:'',
videoPath:'',
numSatus:0,
LicensePlateRecognitionSwitch:0
},
formLabelWidth: '120px',
formLabelWidth: '200px',
videoTypeForm:{
videoType:'实时视频'
// videoType:'离线视频'
},
videoList:[],
fullscreenLoading: false,
ip:'',
numSatus:0,
newNumber:0,
}
},
//离开当前页面后执行
destroyed: function () {
// console.log("离开当前页")
// client.end();
},
created() {
this.getVideoList()
},
mounted() {
this.createMqtt()
},
watch: {
videoList: {
handler(newVal) {
if (newVal) {
newVal.forEach((item)=>{
if(item.status=='加载中'){
console.log("加载中",item)
setTimeout(() => {
this.getVideoList()
}, 10000);
}
})
}
},
deep: true
}
},
methods: {
changeChepai(){},
//传输视频源类型
SetVideoMode(val){
getSetVideoMode({Mode:val}).then(res=>{
console.log("res",res)
})
},
changeRadio(){
this.SetVideoMode(this.videoTypeForm.videoType)
},
//获取视频源类型
getVideoType(){
getVideoMode().then(res=>{
console.log("res",res.data.data)
this.videoTypeForm.videoType = res.data.data
})
},
/** 创建mqtt */
createMqtt() {
//创建链接,接收数据
if(this.videoTypeForm.videoType=='实时视频'){
console.log("this.videoTypeForm.videoType",this.videoTypeForm.videoType)
window.PubScribe(null,-1,this.realInfo,'videoId');
window.publish('Custom',JSON.stringify({"type":'getImage',"videoid":'all'}));
}else if(this.videoTypeForm.videoType=='离线视频'){
console.log("this.videoTypeForm.videoType",this.videoTypeForm.videoType)
this.topicSends = ['VideoStatusData'];
window.PubScribe(this.topicSends,'001', this.realInfo,'videoId');
}
},
//停止订阅mqtt
disConnect() {
// if (client != null) {
// client.unsubscribe(this.topicSends);
// client = null;
// }
},
/** 实时数据分类 */
realInfo(topic, message) {
// console.log("topic",topic)
switch (topic) {
// 接收托片
case "img0":
case "img1":
case "img2":
case "img3":
case "img4":
case "img5":
case "img6":
case "img7":
case "img8":
try {
const utf8decoder = new TextDecoder()
const u8arr = new Uint8Array(message)
const temp = utf8decoder.decode(u8arr) // 将二进制数据转为字符串
const msg = JSON.parse(temp) //这一步报错则返回的是二进制流图片不报错则返回的是JSON的错误提示数据
// var newArr = []
//msg为转换后的JSON数据
if(msg.rate=='low'){
console.log("msg", msg)
if(this.videoList.length!=0){
for (let i = 0; i < this.videoList.length; i++) {
if(msg.id==this.videoList[i].id){
this.videoList[i].img ='data:image/png;base64,' + msg.pic
this.videoList[i].msg = msg
}
}
}
}
// this.imgUrl3 = 'data:image/png;base64,' + msg.pic;
// console.log("imageUrl", imageUrl)
} catch (error) {
}
break;
case "hert":
try {
const utf8decoder = new TextDecoder()
const u8arr = new Uint8Array(message)
const temp = utf8decoder.decode(u8arr) // 将二进制数据转为字符串
const msg = JSON.parse(temp) //这一步报错则返回的是二进制流图片不报错则返回的是JSON的错误提示数据
// console.log("hert", msg) //msg为转换后的JSON数据
if(msg==''){
}
} catch (error) {
}
break;
case "VideoStatusData":
try {
const utf8decoder = new TextDecoder()
const u8arr = new Uint8Array(message)
const temp = utf8decoder.decode(u8arr) // 将二进制数据转为字符串
const msg = JSON.parse(temp) //这一步报错则返回的是二进制流图片不报错则返回的是JSON的错误提示数据
console.log("VideoStatusData", msg) //msg为转换后的JSON数据
this.changeStatus(msg)
} catch (error) {
}
break;
}
this.receiveNews = "";
},
changeStatus(msg){
for (let i = 0; i < this.videoList.length; i++) {
//分析中
if(msg.type=='video_under_analysis'&&msg.video_id==this.videoList[i].id){
var numSatusN=''
// loadingcard.close();
this.videoList[i].videoAnalysisStatus = '分析中'
numSatusN=msg.number_frames/msg.total_frames*100
this.videoList[i].numSatus =parseFloat(numSatusN.toFixed(2))
}else if(msg.type=='video_analyzed'&&msg.video_id==this.videoList[i].id){
//已分析
console.log("已分析")
this.videoList[i].videoAnalysisStatus = '已分析'
}else if(msg.type=='video_analyse_unusual'&&msg.video_id==this.videoList[i].id){
//分析异常
console.log("分析异常")
this.videoList[i].videoAnalysisStatus = '分析异常'
}else if(msg.type=='video_loading'&&msg.video_id==this.videoList[i].id){
//分析异常
console.log("加载中")
this.videoList[i].videoAnalysisStatus = '加载中'
}
}
},
generateMixed(n) {
var chars = ['0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
var res = "";
for(var i = 0; i < n ; i++) {
var id = Math.floor(Math.random()*36);
res += chars[id];
}
return res;
},
informationInfo(data,item) {
if(data=='新增'){
var random = this.generateMixed(3)
console.log("random",random)
// console.log("this.file",this.file)
// this.file = undefined
console.log("this.$refs.inputer",this.$refs.inputer)
this.form={
radio: '',
videoName:'视频'+random,
city:'',
videoStreamAddress:'',
LicensePlateRecognitionSwitch:0,
videoPath:''
},
this.dialogFormVisible = true;
}
},
open(item) {
console.log("item",item)
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
getDeleteShipjk({VideoId:item}).then(res=>{
console.log("res",res)
this.$message({
type: 'success',
message: '删除成功!'
});
this.getVideoList()
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
openRight(item){
console.log("item",item)
startVideoAnalysis(item.id).then(res => {
//
if(res.data.msg=='请求成功'){
this.$message({
message: '启动成功',
type: 'success'
});
// setTimeout(() => {
// this.getAnalysisStatus()
// }, 5000);
// if(this.videoAnalysisSta=='已分析'){
// }else if(this.videoAnalysisSta=='分析中'){
// this.description = '正在分析中'
// setTimeout(() => {
// this.getAnalysisStatus()
// }, 5000);
// }else if(this.videoAnalysisSta=='未分析'){
// }
}
});
},
//
commit(form){
console.log("form",form)
let formData = new FormData();
formData.append("VideoName",form.videoName);
formData.append("VideoType",this.videoTypeForm.videoType);
window.publish('Custom',JSON.stringify({"type":'getImage',"videoid":'all'}));
if(this.videoTypeForm.videoType=='离线视频'){
formData.append("VideoPath",form.videoStreamAddress);
formData.append("LicensePlateRecognitionSwitch",form.LicensePlateRecognitionSwitch)
}else{
formData.append("VideoStreamAddress",form.videoStreamAddress);
}
axios({
method: "post",
url: serverUrl.dataUrl,
data:formData
}).then((res) => {
console.log("提交按钮",res)
if(res.data.msg=='添加成功'){
this.$message({
message: res.data.msg,
type: 'success'
});
this.getVideoList()
// if(this.videoTypeForm.videoType=='离线视频'){
// startVideoAnalysis(res.data.data).then(res => {
// if(res.data.msg=='请求成功'){
// this.$message({
// message: '启动成功',
// type: 'success'
// });
// }
// });
// }else{
// }
}else{
this.$message({
message: res.data.msg,
type: 'warning'
});
}
this.dialogFormVisible = false;
});
},
handleFileChange(e) {
let inputDOM = this.$refs.inputer;
this.file = inputDOM.files[0];// 通过DOM取文件数据
},
//应用
applicationBtn(){
// this.createMqtt()
getApplication().then(res=>{
console.log("res",res)
if(res.data.code==200){
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
setTimeout(() => {
loading.close();
setTimeout(() => {
this.getVideoList()
}, 5000);
this.$message({
message: res.data.msg,
type: 'success'
});
// setTimeout(() => {
// window.publish('Custom',JSON.stringify({"type":'getImage',"videoid":'all'}));
// }, 3000);
}, 15000);
}
})
},
//停止
stopAlgorithmBtn(){
getStopAlgorithm().then(res=>{
console.log("res",res)
if(res.data.code==200){
this.getVideoList()
this.$message({
message: res.data.msg,
type: 'success'
});
}
})
},
S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
},
guid() {
return (this.S4() + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + this.S4() + this.S4());
},
load() {
let size = this.file.size;//文件大小
// this.fileList = []
let maxZrea = 8; //设置每个分区大小 MB
let bufferSize = maxZrea * (1024 * 1024);
let fileStart = 0;
let fileEnd = bufferSize;
let arrFile = [];
while (fileStart < size) {
var fileInfo = {
File: this.file.slice(fileStart, fileEnd),
Start: fileStart,
End: fileEnd
}
arrFile.push(fileInfo);
fileStart = fileEnd;
fileEnd = fileStart + bufferSize;
}
let newNumber= 0
var loadingN = this.$loading({
lock: true,
text: newNumber +'/'+arrFile.length,
target: '.el-dialog',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
console.log("loadingN",loadingN.text)
let count = arrFile.length;
let filename = this.file.name + "~" + this.guid();
for (var i = 0; i < count; i++) {
let formData = new FormData();//new一个formData事件
formData.append("file", arrFile[i].File); //将file属性添加到formData里
var url = serverUrl.getSpareElementOrder+"?Name=" + filename + "&Number=" + i + "&BufferSize=" + bufferSize + "&Count=" + count + "&Start=" + arrFile[i].Start + "&End=" + arrFile[i].End + "&Size=" + size;
axios.post(url, formData, {
headers: {
"Content-Type": "multipart/form-data;",
}
}).then(r => {
if (r.data.code!=200) {
}else{
if(r.data.data==null){
this.dis = true
// var newN = i
this.newNumber = newNumber++
loadingN.text = this.newNumber +'/'+arrFile.length
}else{
this.dis = false
loadingN.close();
this.$message({
message: r.data.msg,
type: 'success'
});
this.form.videoStreamAddress=r.data.data
this.fileList.push(r.data.data)
}
}
}).catch(e => {
console.log(e);
});
}
},
goToPage(videoAnalysisStatus,id,num,name,type,status,msg,videoPath) {
console.log("id",id)
console.log("num",num)
console.log("name",name)
console.log("type",type)
console.log("status",status)
console.log("msg",msg)
console.log("videoAnalysisStatus",videoAnalysisStatus)
if(type=='离线视频'){
if(videoAnalysisStatus!='已分析'){
}else if(videoAnalysisStatus=='已分析'){
this.$router.push({path:'index',query: {id:id,num:num,name:name,type:type,status:status,msg:msg,videoPath:videoPath}})
}
}else{
this.$router.push({path:'index',query: {id:id,num:num,name:name,type:type,status:status,msg:msg,videoPath:videoPath}})
}
},
//获取视频数据
getVideoList(){
getGetShipjk().then(res=>{
console.log("res",res)
if(res.data.msg=='成功'){
// if(val=='重启'){
setTimeout(() => {
window.publish('Custom',JSON.stringify({"type":'getImage',"videoid":'all'}));
}, 2000);
// }
if(res.data.data.length!=0){
this.videoTypeForm.videoType = res.data.data[0].videoType
if(this.videoTypeForm.videoType=='离线视频'){
this.createMqtt()
}
this.getVideoType()
}else{
this.SetVideoMode(this.videoTypeForm.videoType)
}
// console.log("this.videoTypeForm.videoType",this.videoTypeForm.videoType)
var arr = [];
res.data.data.forEach((item)=>{
arr.push({
id: item.videoId,
type: item.videoType,
title: item.videoName,
num:item.number,
status:item.status,
videoStreamAddress:item.videoStreamAddress,
videoPath:item.videoPath,
img: require('@/assets/img/AnalysisMain/img1.png'),
// img:'',
trafficAnalysisStatus:item.trafficAnalysisStatus,
videoAnalysisStatus:item.videoAnalysisStatus,
numberFrames:item.numberFrames,
totalFrames:item.totalFrames,
numSatus:0,
msg:{},
});
})
this.videoList=arr
if(this.videoList.length=='0'){
this.videoTypeShow = true
}else{
this.videoTypeShow = false
}
}
})
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${ file.name }`);
},
},
components: {
editModal
},
}
</script>
<style>
.time {
font-size: 13px;
color: #999;
}
.bot{
/* padding: 14px; */
padding: 8px 15px;
}
.streamAddress{
color: coral;
font-size: 12px;
padding-top: 5px;
}
.bottom {
margin-top: 10px;
line-height: 12px;
display: inline-block;
margin-left: 15px;
width: 67%;
text-overflow:ellipsis;
white-space:nowrap;
overflow:hidden;
}
.st{
position: absolute;
right: 4%;
top: 80%;
display: inline-block;
}
.st span{
color: #999;
}
.button {
padding: 0;
float: right;
}
.image {
width: 100%;
display: block;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.middle{
width: 100%;
/* height: 100%; */
height: 284px;
}
.el-col-6 {
width: 25%;
padding-left: 20px;
padding-top: 20px;
}
.type{
position: absolute;
left: 0;
top:0px;
z-index: 98;
}
.typeRight{
position: absolute;
right: 10px;
top: 5px;
z-index: 98;
}
.middleN{
position: absolute;
left: 35%;
top: 15%;
z-index: 98;
}
.del{
position: absolute;
right: 0px;
top:0px;
width: 25px;
height: 25px;
z-index: 9999;
/* background-color: #999 */
}
.videoTypeBox{
background: #fff;
/* width: 98%; */
margin-left: 1%;
display: flex;
padding-top: 20px;
padding-left: 30px;
}
.card{
position: relative;
cursor: pointer;
}
.name{
position: absolute;
left: 7px;
top:0px;
z-index: 99;
}
.statusN{
position: absolute;
left: 30px;
top:0px;
z-index: 97;
}
.statusName{
position: absolute;
left: 13px;
top: 6px;
z-index: 99;
color: #eee;
}
.middleN .el-progress__text {
color: #fff;
}
.el-loading-spinner{
font-size: 30px;
}
.el-loading-text{
font-size: 18px!important;
}
.el_dialog {
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
}
.el_dialog__content {
width: v-bind(width1);
height: 400px;
background-color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#dialog .el-dialog__header {
border-bottom: 1px solid #eee;
}
#dialog .el-dialog__title {
font-weight: bold;
color: #000;
}
.btn{
position: absolute;
right: 10%;
bottom: 18%;
}
</style>