jhbigscreen/src/pages/toAIVideoProject.vue

1068 lines
32 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="project-aivideo">
<div class="screen-content">
<el-row>
<el-col :span="6">
<module-one-2-1 label="预警概况">
<div class="labour-warning-title">
<div class="labour-warning-img">
<div class="labour-warning-bgd">
<img src="images/labour_warning_icon.png" />
</div>
</div>
<div class="labour-warning-data">
<p>今日预警</p>
<div class="labour-warning-number">
<span>{{ overviewTotalDay }}</span>
</div>
</div>
<div class="labour-warning-data">
<p>累计预警</p>
<div class="labour-warning-number">
<span>{{ overviewTotal }}</span>
</div>
</div>
</div>
<project-overview-chart
:key="'ai1' + overviewDay"
:sp="''"
txtTop="12"
gifTop="70px"
:maintitle="overviewTotalDay"
:legend-opt="legendOpt2"
:typedata="typeDistributionDataDay"
:text="overviewTextDay"
:height="250"
></project-overview-chart>
<project-overview-chart
:key="'ai2' + overview"
:sp="''"
txtTop="12"
gifTop="70px"
:maintitle="overviewTotal"
:legend-opt="legendOpt1"
:typedata="typeDistributionData"
:text="overviewText"
:height="250"
></project-overview-chart>
</module-one-2-1>
<module-one-1-1 label="预警分布">
<rank-chart
:data="availabilityData"
:showval="true"
:height="300"
></rank-chart>
</module-one-1-1>
</el-col>
<el-col :span="12">
<div class="ai-video-info">
<div class="ai-video-info-flex">
<div class="ai-content-nav-max" style="width: 100%">
<div
class="ai-content-nav-min"
v-for="(alertorType, index) in alertorTypeList"
:key="index"
>
<div class="ai-content-nav-con">
<div
:class="nav == index ? 'ai-content-nav active' : 'ai-content-nav'"
@click="aiNav(index, alertorType.dictValue)"
v-html="alertorType.dictLabel"
></div>
</div>
</div>
</div>
</div>
<div class="ai-content-info-max">
<el-row>
<el-col
style="position: relative"
:span="8"
v-for="(video, index) in videoList"
:key="index"
>
<div class="ai-content-info-min">
<div
class="ai-content-videos"
:class="video.state ? 'active-video' : 'videobo'"
>
<div v-if="video.state" :id="'vd0' + index"></div>
<div
class="ai-video-name"
style="
position: absolute;
height: 35px;
line-height: 35px;
padding: 0px 15px;
z-index: 99999;
bottom: 8px;
font-size: 13px;
"
>
<span v-if="video.state"
>{{ video.videoName }}{{ video.passageName }}</span
>
</div>
<div v-if="video.state" class="style-con style-red"></div>
<div v-if="video.state" class="style-con style-green"></div>
</div>
</div>
</el-col>
</el-row>
</div>
</div>
<div class="ai-content-padding">
<div class="ai-key-videos">
<div class="ai-video-title">
<div>重点视频</div>
<div class="ai-video-number">重点关注 视频({{ majorVideoSize }}</div>
</div>
<div class="ai-key-videos-info">
<!-- <div class="ai-slip">
<img src="/images/ai/left_slip.png" id="leftSlip">
</div> -->
<div class="ai-key-videos-content" id="videosContent">
<div
class="ai-key-videos-max"
style="position: relative"
v-for="(video, index) in majorVideoList"
:key="index"
>
<div
class="ai-key-videos-min"
:class="video.state ? 'imp-video' : 'videobo'"
>
<!-- <H265Player v-if="video.state" :url="getVideoUrl(video)"/> -->
<div v-if="video.state" :id="'wVd0' + index"></div>
<div
class="ai-video-name"
style="
position: absolute;
height: 35px;
line-height: 35px;
padding: 0px 15px;
z-index: 1;
bottom: 8px;
font-size: 13px;
"
>
<span v-if="video.state"
>{{ video.videoName }}{{ video.passageName }}</span
>
</div>
<div v-if="video.state" class="style-con style-red"></div>
<div v-if="video.state" class="style-con style-green"></div>
</div>
</div>
</div>
<!-- <div class="ai-slip">
<img src="/images/ai/right_slip.png" id="rightSlip">
</div> -->
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="analyse-map">
<div class="analyse-title">
<div class="analyse-text">最近预警</div>
</div>
<div class="afoot-content safe-afoot-content">
<div
class="afoot-overflow safe-afoot-overflow"
id="afootOverflow"
@mouseout="warningListMinMouseout"
@mouseover="warningListMinMouseover"
>
<div v-if="warningList.length == 0" class="not-data">暂无预警数据</div>
<div
v-if="warningList.length > 0"
class="afoot-con-for"
style="height: 180px"
v-for="item in warningList"
>
<div class="project-expect-con">
<div class="project-expect-title">
<div class="project-expect-title-No">
{{ item.projectName }}
</div>
</div>
<div class="project-expect-info">
<el-image
:src="getImageUrl(item)"
:preview-src-list="[$apiPath + item.imageUrl]"
></el-image>
</div>
<div class="project-expect-info">
<div class="el-row" style="padding-top: 5px">
单位名称:{{ item.deptName }}
</div>
<div class="el-row" style="padding-top: 5px">
预警类型:{{ item.alarmTypeName }}
</div>
<div class="el-row" style="padding-top: 5px">
预警时间:<span class="project-expect-time">{{
item.createTime
}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="ai-content-padding">
<div class="ai-warning-list">
<div class="ai-video-title">
<div>
最新预警
<span class="ai-video-number"
><span v-html="warningList.length"></span></span
>
</div>
</div>
<div class="ai-warning-list-content">
<div
class="ai-warning-list-max scroll"
id="warningListMax"
style="overflow-y: auto"
>
<div id="warningListMin">
<div
class="project-expect-list active"
v-for="(item, idx) in warningList"
v-if="idx < 50"
:key="idx"
>
<div class="project-expect-con">
<div class="project-expect-title">
<div class="project-expect-title-No">
{{ item.projectName }}
</div>
</div>
<div class="project-expect-info">
<el-image
:src="getImageUrl(item)"
:preview-src-list="[$apiPath + item.imageUrl]"
></el-image>
</div>
<div class="project-expect-info">
<div class="el-row" style="padding-top: 5px">
单位名称:{{ item.deptName }}
</div>
<div class="el-row" style="padding-top: 5px">
预警类型:{{ item.alarmTypeName }}
</div>
<div class="el-row" style="padding-top: 5px">
预警时间:<span class="project-expect-time">{{
item.createTime
}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import "../components/module/module-one-2-1";
import "../components/module/module-one-3-1";
import "../components/module/module-one-0-5";
import "../components/module/module-one-video";
import "../components/staff-survey-chart";
import "../components/classify-bar";
import "../components/amplify/shipinguanli/amplify-spjk";
import "../components/rank-chart";
import debounce from "lodash.debounce";
import gsap from "gsap";
export default {
data() {
return {
active: 3,
scrollLeft: "",
nav: 0,
alertorId: 0,
videoList: [],
scaleData: [],
majorVideoList: [],
alertorTypeList: [],
warningList: [],
distributeData: {},
ptz: false,
autoPlay: true,
popupUrl: "",
popupShow: false,
majorVideoSize: 0,
//预警概况
overview: 0,
overviewDay: 0,
overviewInterval: "",
overviewTotal: 0,
legendOpt1: {
icon: "rect",
textStyle: {
fontSize: 14,
color: "#c3dbfd",
rich: {
name: {
color: "#c3dbfd",
padding: [0, 20, 0, 0],
},
percent: {
color: "#4676FD",
},
},
},
},
overviewText: "累计预警",
//原因类型分析
availabilityData: [],
projectCategoryWidth: 200,
//预警概况
typeDistributionData: [
{ name: "未戴安全帽", value: "0" },
{ name: "未穿工服", value: "0" },
{ name: "反光衣/带检测", value: "0" },
],
overviewTextDay: "今日预警",
overviewTotalDay: 0,
legendOpt2: {
icon: "rect",
textStyle: {
fontSize: 14,
color: "#c3dbfd",
rich: {
name: {
color: "#c3dbfd",
padding: [0, 20, 0, 0],
},
percent: {
color: "#f73647",
},
},
},
},
typeDistributionDataDay: [
{ name: "未戴安全帽", value: "0" },
{ name: "未穿工服", value: "0" },
{ name: "反光衣/带检测", value: "0" },
],
initfunc: null,
players: [],
wPlayers: [],
warningInterval: undefined,
forIndex: 0,
};
},
beforeDestroy() {
console.log("-----beforeDestroy------>");
this.players.forEach((p) => {
if (p) {
try {
p.stop();
} catch (e) {}
}
});
this.wPlayers.forEach((wp) => {
if (wp) {
try {
wp.stop();
} catch (e) {}
}
});
clearInterval(this.warningInterval);
this.forIndex = 0;
},
mounted() {
this.$bus.$on("headerChange",()=>{
this.initMe();
});
if (this.$root.hasInitHeader) {
this.initMe();
}
},
created() {
//this.init()
},
computed: {
playDivCss() {
return {
width: (this.width + "").replace("px", "") + "px",
height: (this.height + "").replace("px", "") + "px",
position: "relative",
};
},
exStyle() {
return {
textAlign: "center",
width: (this.width + "").replace("px", "") + "px",
height: (this.height + "").replace("px", "") + "px",
};
},
PTZDiv() {
let W = parseInt((this.width + "").replace("px", ""));
let H = parseInt((this.height + "").replace("px", ""));
if (W < 400) {
W = "100px";
H = "100px";
} else {
W = "150px";
H = "150px";
}
return {
backgroundImage: "url('https://video.makalu.cc/img/jt.png')",
width: W,
height: H,
backgroundSize: "100%",
position: "relative",
};
},
PTZTop() {
return {
width: "33%",
height: "25%",
position: "absolute",
top: "0px",
left: "33%",
cursor: "pointer",
};
},
PTZBottom() {
return {
width: "33%",
height: "25%",
position: "absolute",
bottom: "0px",
left: "33%",
cursor: "pointer",
};
},
PTZLeft() {
return {
width: "25%",
height: "33%",
position: "absolute",
top: "33%",
left: "0px",
cursor: "pointer",
};
},
PTZRight() {
return {
width: "25%",
height: "33%",
position: "absolute",
top: "33%",
right: "0px",
cursor: "pointer",
};
},
VIBtnCss() {
return {
width: "30px",
height: "30px",
background: "#38314b",
border: "1px solid #38314b",
fontSize: "20px",
outline: "0",
color: "#FFFFFF",
};
},
zoomViewCss() {
return {
width: "75px",
height: "30px",
color: "#dddddd",
background: "rgba(65, 63, 70, 0.5)",
textAlign: "center",
border: "0px solid rgba(65, 63, 70, 0.5)",
outline: "0",
fontSize: "14px",
};
},
},
methods: {
initMe() {
this.projectInfo = this.$root.project;
this.dept = this.$root.dept;
this.projectInfos = this.$root.projects;
console.log("initMe");
this.init();
},
init() {
clearTimeout(this.initfunc);
clearInterval(this.warningInterval);
//最近预警 定时器
this.warningInterval = setInterval(this.safeAutomaticRoll, 5000);
this.players.forEach((p) => {
if (p) {
try {
p.stop();
} catch (e) {}
}
});
this.wPlayers.forEach((wp) => {
if (wp) {
try {
wp.stop();
} catch (e) {}
}
});
let initfunc = () => {
this.getAlertorTypeList();
this.getAiVideoInfoList("", "");
this.getMajorAiVideoInfoList();
this.getAnalysisDetailList();
this.getAiVideoAlertorTypeCount();
this.initAiVideoAlertorTypeDistribution();
};
this.initfunc = setTimeout(initfunc, 100); // 定时时间
},
//正在发生
safeAutomaticRoll() {
var height = $(".safe-afoot-overflow").innerHeight();
if (this.forIndex == this.warningList.length) {
this.forIndex = 0;
} else {
this.forIndex = parseFloat(this.forIndex + 0.22221);
}
$("#afootOverflow").animate({ scrollTop: parseInt(height * this.forIndex) + "px" });
},
warningListMinMouseover() {
clearInterval(this.warningInterval);
},
warningListMinMouseout() {
this.warningInterval = setInterval(this.safeAutomaticRoll, 5000);
},
//head选择项目返回值
onItemData(e) {
if (e.type == 1) {
location.href = "/weixin/screen/toVideo";
} else {
location.href = "/weixin/screen/toVideoProject";
}
},
amplify(url) {
this.popupUrl = url;
this.popupShow = true;
},
getAlertorTypeList() {
// axios.post(Host + "/api/video/getAiVideoAlertorTypes", {
// projectId: JSON.parse(localStorage.getItem("data")).aqzg
// }).then(res => {
// var list = [{'alertor_id': 0,'alertor_type': "", 'alertor_type_name': "全部"}];
// var data = res.data;
// data.forEach(item =>{
// list.push(item)
// })
// if(JSON.parse(localStorage.getItem("data")).id == "98") {
// var newArr = [];
// newArr.push(list[0]);
// newArr.push(data[1])
// newArr.push(data[3])
// newArr.push(data[2])
// newArr.push(data[0])
// this.alertorTypeList = newArr;
// } else {
// this.alertorTypeList = list;
// }
// }).catch(err => {
// })
this.$api.dict("aibox_alarm_type").then((d) => {
this.alertorTypeList = d || [];
if (this.alertorTypeList && this.alertorTypeList[0].dictValue != "") {
this.alertorTypeList.unshift({ dictLabel: "全部", dictValue: "" });
}
});
},
getVideoUrl(it) {
if (it.state) {
return (
"http://111.21.209.230:7086/live/cameraid/" +
it.videoDvrNumber +
"$" +
it.passageValue +
"/substream/2.m3u8"
);
} else {
return null;
}
},
getAiVideoInfoList(passageType, importance) {
// axios.post(Host + "/api/video/getAiVideoInfoList", {
// projectId:JSON.parse(localStorage.getItem("data")).aqzg,
// alertorId: this.alertorId
// }).then(res => {
// var data = res.data;
// if(data.length < 6){
// var len = 6 - data.length
// for (let i = 0; i < len ; i++) {
// data.push({})
// }
// }
// this.videoList = data;
// }).catch(err => {
// })
let that = this;
this.players.forEach((p) => {
if (p) {
try {
p.stop();
} catch (e) {}
}
});
this.$api.aiBoxVideo
.getVideoPassage(
this.dept?.id || 0,
this.projectInfo?.id || 0,
passageType,
importance
)
.then((response) => {
let list = [];
if (response.data) {
response.data.forEach((it) => {
it.surProjectVideoPassageList.forEach((v) => {
list.push({
videoName: it.videoName,
passageName: v.passageName,
videoDvrNumber: v.videoDvrNumber,
passageValue: v.passageValue,
state: true,
});
});
});
let vList = list;
//补全
let len = 6 - list.length;
for (let i = 0; i < len; i++) {
list.push({ state: false });
}
this.videoList = list;
setTimeout(() => {
if (vList.length > 0) {
vList.forEach((v, vidx) => {
if (v.state) {
let player = new WasmPlayer(null, "vd0" + vidx, null, {
Height: true,
});
that.players.push(player);
}
});
}
}, 400);
setTimeout(() => {
if (vList.length > 0) {
vList.forEach((v, vidx) => {
if (v.state) {
let url =
"https://szgc.jhncidg.com/video/live/cameraid/" +
v.videoDvrNumber +
"$" +
v.passageValue +
"/substream/2.m3u8";
that.players[vidx].play(url, 1);
}
});
}
}, 600);
} else {
for (let i = 0; i < 6; i++) {
list.push({ state: false });
}
this.videoList = list;
}
});
},
getMajorAiVideoInfoList() {
// axios.post(Host + "/api/video/getAiVideoInfoList", {
// projectId: JSON.parse(localStorage.getItem("data")).aqzg,
// majorState: "1",
// alertorId: this.alertorId
// }).then(res => {
// var data = res.data;
// /*if(data.length < 4){
// var len = 4 - data.length
// for (let i = 0; i < len ; i++) {
// data.push({})
// }
// }*/
// this.majorVideoList = data;
// }).catch(err => {
// })
let that = this;
this.wPlayers.forEach((wp) => {
if (wp) {
try {
wp.stop();
} catch (e) {}
}
});
this.$api.aiBoxVideo
.getVideoPassage(this.dept?.id || 0, this.projectInfo?.id || 0, "", "Y")
.then((response) => {
let list = [];
if (response.data) {
response.data.forEach((it) => {
it.surProjectVideoPassageList.forEach((v) => {
list.push({
videoName: it.videoName,
passageName: v.passageName,
videoDvrNumber: v.videoDvrNumber,
passageValue: v.passageValue,
state: true,
});
});
});
let zdVList = list;
that.majorVideoSize = list.length;
//补全
let len = 3 - list.length;
for (let i = 0; i < len; i++) {
list.push({ state: false });
}
that.majorVideoList = list;
setTimeout(() => {
if (zdVList.length > 0) {
zdVList.forEach((zdv, zdidx) => {
if (zdv.state) {
let player = new WasmPlayer(null, "wVd0" + zdidx, null, {
Height: true,
});
that.wPlayers.push(player);
}
});
}
}, 400);
setTimeout(() => {
if (zdVList.length > 0) {
zdVList.forEach((zdv, zdidx) => {
if (zdv.state) {
let url =
"https://szgc.jhncidg.com/video/live/cameraid/" +
zdv.videoDvrNumber +
"$" +
zdv.passageValue +
"/substream/2.m3u8";
that.wPlayers[zdidx].play(url, 1);
}
});
}
}, 600);
} else {
this.majorVideoSize = 0;
for (let i = 0; i < 6; i++) {
list.push({ state: false });
}
this.majorVideoList = list;
}
});
},
getAnalysisDetailList() {
this.$api.aiBoxVideo
.listView(this.dept?.id || 0, this.projectInfo?.id)
.then((response) => {
this.warningList = response.data || [];
});
},
getAiVideoAlertorTypeCount() {
// axios.post(Host + "/api/video/getAiVideoAlertorTypeCount", {
// projectId: JSON.parse(localStorage.getItem("data")).aqzg
// }).then(res => {
// var data = res.data;
// var num = 0;
// data.forEach(item =>{
// num += item.value;
// })
// data.forEach(item =>{
// item.percent = (item.value/num*100)
// })
// this.scaleData = data;
// }).catch(err => {
// })
//今日视图
this.$api.aiBoxVideo
.groupCountByAlarmType(this.dept?.id || 0, this.projectInfo?.id, "Y")
.then((response) => {
if (response.data) {
let sum = 0;
response.data.forEach((datum) => {
sum += datum.value;
});
this.overviewTotalDay = sum;
this.typeDistributionDataDay = response.data;
this.overviewDay++;
}
});
//累计视图
this.$api.aiBoxVideo
.groupCountByAlarmType(this.dept?.id || 0, this.projectInfo?.id, "N")
.then((response) => {
if (response.data) {
let sum = 0;
response.data.forEach((datum) => {
sum += datum.value;
});
this.overviewTotal = sum;
this.typeDistributionData = response.data;
this.overview++;
}
});
},
initAiVideoAlertorTypeDistribution() {
this.$api.aiBoxVideo
.selectGroupCountVideoConfig(this.dept?.id || 0, this.projectInfo?.id)
.then((response) => {
let list = [];
if (response.data) {
let sum = 0;
response.data.forEach((datum) => {
sum += datum.value;
});
response.data.forEach((datum) => {
datum.text = datum.name;
if (sum == 0) {
datum.prop = 0.0;
} else {
datum.prop = ((datum.value / sum) * 100).toFixed(1);
}
list.push(datum);
});
this.availabilityData = list;
}
});
},
getAiVideoAlertorTypeWarningCount() {
axios
.post(Host + "/api/video/getAiVideoAlertorTypeWarningCount", {
projectId: JSON.parse(localStorage.getItem("data")).aqzg,
})
.then((res) => {
//预警分布
var distributeData = {
legend: ["接入视频", "预警路数"],
color: [],
yAxis: [],
data: [],
};
var data = res.data;
var data1 = [];
var data2 = [];
data.forEach((item) => {
distributeData.yAxis.push(item.alertor_type_name);
data1.push(item.total);
data2.push(item.yjTotal);
});
var color1 = ["#183e65", "#4bbcff"];
var color2 = ["#225254", "#5cd6ad"];
distributeData.data.push(data1);
distributeData.data.push(data2);
distributeData.color.push(color1);
distributeData.color.push(color2);
this.distributeData = distributeData;
})
.catch((err) => {});
},
aiNav(n, id) {
this.nav = n;
this.alertorId = id;
this.getAiVideoInfoList(this.alertorId, "");
},
getImageUrl(it) {
return "/jhapi" + it.imageUrl + ".min.jpg";
},
//预警概况 Echart
warningChart(data, id) {
let newPromise = new Promise((resolve) => {
resolve();
});
//然后异步执行echarts的初始化函数
newPromise.then(() => {
var myChart = echarts.init(document.getElementById(id));
option = {
color: [
"#00fff1",
"#04c8fa",
"#aa01fe",
"#4e84fe",
"#ff7b79",
"#edae5e",
"#fe4101",
"#14d18f",
],
series: [
// 主要展示层的
{
radius: ["45%", "60%"],
center: ["50%", "50%"],
type: "pie",
label: {
normal: {
show: true,
formatter: function (params) {
return (
params.value +
" " +
params.percent +
"%\n{white|" +
params.name +
"}"
);
},
rich: {
white: {
color: "#c5d9fe",
align: "center",
padding: [0, 0, 5],
},
},
textStyle: {
fontSize: 14,
},
position: "outside",
},
emphasis: {
show: true,
},
},
labelLine: {
normal: {
show: true,
length: 20,
length2: 25,
},
emphasis: {
show: true,
},
},
data: data,
},
{
name: "外边框",
type: "pie",
clockWise: false, //顺时加载
hoverAnimation: false, //鼠标移入变大
center: ["50%", "50%"],
radius: ["70%", "70%"],
label: {
normal: {
show: false,
},
},
data: [
{
value: 1,
name: "",
itemStyle: {
normal: {
borderWidth: 3,
borderColor: "#57639d",
},
},
},
],
},
],
};
myChart.setOption(option);
window.onresize = myChart.resize;
});
},
goVideoPage() {
location.href = "/weixin/screen/toVideoProject";
},
},
};
</script>
<style lang="less">
.style-green {
background: #00c240;
}
.style-con {
position: absolute;
width: 20px;
height: 20px;
background: #00c240;
border-radius: 50%;
top: 15px;
right: 15px;
z-index: 1;
}
.active-video {
border: 1px solid #ddcd04;
}
.imp-video {
border: 2px solid aqua;
}
.videobo {
border: 1px solid #655f5f;
}
.project-expect-list {
width: 100%;
margin-bottom: 10px;
}
.project-expect-title-No {
min-width: 100px;
text-align: left;
}
.project-video {
}
.project-expect-info {
width: 50%;
float: left;
}
.project-expect-info img {
width: 90%;
}
.my-svg-icon {
width: 40px;
height: 40px;
margin-bottom: 20px;
}
.my-svg-icon * {
fill: #389de3;
}
.people-number-con div.is-split {
background: none;
}
.labour-education .number-unit {
position: relative;
bottom: -8px;
}
.number-unit {
word-break: keep-all;
}
.cost-out {
.labour-education {
height: 70px;
.people-number-con {
padding: 0px;
}
}
}
.safe-afoot-overflow {
height: 900px !important;
}
</style>