|
<template>
<div class="index" style="overflow:hidden">
<div :style="`background-image: url(${imgBg})`" class="top" >
<img src="@/assets/images/brand.png" class="top-logo">
</div>
<div>
<div class="time"><span style="color: #00d8f3;font-size: 21px;">{{ nowDate | dateFormat }}</span></div>
<div class="goto" @click="gotoSystem"><t-icon icon="arrow-right-outline"></t-icon>进入系统</div>
</div>
<div class="body">
<div class="body-left">
<div :style="`height:34%`" class="body-left-item">
<div :style="`background-image: url(${titleImgBg})`" class="title">
<span class="title-span">出勤统计</span>
</div>
<div id="doughnut" style="height: 100%;width: 100%"></div>
</div>
<div :style="`height:34%;margin-top: 3%;`" class="body-left-item">
<div :style="`background-image: url(${titleImgBg})`" class="title">
<span class="title-span">告警分析</span>
</div>
<div id="bar" style="height: 100%;width: 100%"></div>
</div>
<div :style="`height:29%;margin-top: 3%;`" class="body-left-item">
<div :style="`background-image: url(${titleImgBg})`" class="title">
<span class="title-span">近24h告警</span>
</div>
<div class="top4">
<t-row v-for="(item,index) in topData" :gutter="2" align="center" class="top4-row">
<t-col span="6">
<div :style="`background-image: url(${polygon})`" class="polygon">{{ index + 1 }}</div>
{{ item.name }}</t-col>
<t-col span="2" offset="4">{{ item.value }}个</t-col>
</t-row>
</div>
</div>
</div>
<div class="body-center">
<div :style="`background-image: url(${titleImgBg})`" class="title" style="width: 370px;">
<span class="title-span">重点区域监控</span>
</div>
<!-- <video-player ref="videoPlayer" :options="videoOptions" :playsinline="true" class="vjs-custom-skin videoPlayer"></video-player>-->
<video-player v-if="videoOptions !== {}"
ref="videoPlayer"
:options="videoOptions"
:playsinline="true"
class="vjs-custom-skin videoPlayer"
></video-player>
<div class="videoPlayers">
<div v-for="(item,index) in videoOptionsList" class="videoPlayer-sm" @click="videoSwitchover(item,index)">
<!-- <video-player ref="videoPlayer"-->
<!-- :options="item.options"-->
<!-- :playsinline="true"-->
<!-- :style="`padding: 0 2.5% 2.5% 2%;border-radius: 5px;border: ${1-index}px solid #009bf3;`"-->
<!-- class="vjs-custom-skin videoPlayer">-->
<!-- </video-player>-->
<video-player
ref="videoPlayer"
:playsinline="false"
:events="events"
:options="item.options"
:style="`padding: 0 2.5% 2.5% 2%;border-radius: 5px;`"
:class="{ 'checkedIndex': index == checkedIndex }"
class="vjs-custom-skin videoPlayer"
@dblclick="handlefullscreenchange"
></video-player>
<div style="color: white;text-align: center;">{{ item.name }}</div>
</div>
</div>
</div>
<div class="body-right">
<div :style="`background-image: url(${titleImgBg})`" class="title" style="width: 330px;">
<span class="title-span">人员进出识别</span>
</div>
<div v-for="(item,index) in distinguishData" :style="`background-image: url(${border})`" class="distinguish">
<div class="distinguish-title"> {{ item.monitorSceneName }} </div>
<div class="distinguish-row">
<div class="similarity">
<p class="p">{{ item.simi }}</p>
</div>
<img :src="item.newImg" alt="" class="distinguish-col">
<img :src="item.headerImage" class="distinguish-col">
<div style="width: 40%;margin-top: 4%;height: 79%;">
<div class="distinguish-col-row">{{ item.employeeName }}({{ item.employeeCode }})</div>
<div class="distinguish-col-row">{{ item.taskExecuteTime }}</div>
</div>
</div>
</div>
<!-- <img src="@/assets/images/indexT2.png" style="width: 95%;height: 95%;padding-left: 15px;padding-top: 10px;">-->
</div>
</div>
</div>
</template>
<script>
import imgBg from '@/assets/images/indexTop.png'
import avatar from '@/assets/images/avatar.png'
import titleImgBg from '@/assets/images/indexTitle.png'
import polygon from '@/assets/images/polygon.png'
import border from '@/assets/images/border.png'
import echarts from 'echarts'
import dasapi from '@/api/dashboard'
import sysapi from '@/api/system'
import 'video.js/dist/video-js.css'
import 'vue-video-player/src/custom-theme.css'
import 'videojs-flash'
import RtmpVideo from '../videoSurveillance/components/rtmpVideoPlay'
import videojs from 'video.js'
window.videojs = videojs
require('video.js/dist/lang/zh-CN.js')
require('video.js/dist/video-js.min.css')
export default {
filters: {
dateFormat(value) {
var year = value.getFullYear()
var month = value.getMonth() + 1
month >= 10 ? month : '0' + month
var day = value.getDate() >= 10 ? value.getDate() : '0' + value.getDate()
var hours =
value.getHours() >= 10 ? value.getHours() : '0' + value.getHours()
var minutes =
value.getMinutes() >= 10
? value.getMinutes()
: '0' + value.getMinutes()
var seconds =
value.getSeconds() >= 10
? value.getSeconds()
: '0' + value.getSeconds()
return (
year +
'年' +
month +
'月' +
day +
'日 ' +
hours +
':' +
minutes +
':' +
seconds
)
}
},
components: {
RtmpVideo
},
data() {
return {
checkedIndex: 0,
events: ['fullscreenchange'],
nowDate: new Date(),
videoOptions: {},
videoOptionsList: [],
imgBg: imgBg,
titleImgBg: titleImgBg,
avatar: avatar,
polygon: polygon,
border: border,
attendanceData: [],
population: 0,
alarmDataX: [],
alarmDataY: [],
topData: [],
topData1: [],
distinguishData: []
}
},
computed: {
player() {
return this.$refs.videoPlayer1.player
}
},
mounted () {
this.initVideo()
setInterval(() => { // 当前时间
this.nowDate = new Date()
}, 1000)
this.initRecognition()
this.initAttendance()
this.initAlarm()
this.init24Top()
setInterval(() => { // 识别记录
this.initRecognition()
}, 10000)
},
methods: {
async createMyButton () {
this.$nextTick(() => {
const bars = document.querySelectorAll('.vjs-control-bar')
let time = document.getElementsByClassName('vjs-current-time vjs-time-control vjs-control')
let start = document.getElementsByClassName('vjs-play-control vjs-control vjs-button')
let volume = document.getElementsByClassName('vjs-volume-panel vjs-control vjs-volume-panel-horizontal')
let text = document.getElementsByClassName('vjs-live-control vjs-control')
bars.forEach((item, index) => {
time.forEach(item => {
item.remove()
})
start.forEach(item => {
item.remove()
})
volume.forEach(item => {
item.remove()
})
text.forEach(item => {
item.remove()
})
})
})
},
handlefullscreenchange(val) {
// 因为我是又封装了一个组件,打印val会有相应所需的属性,全屏状态为:isFullscreen_
val.isFullscreen_ = !val.isFullscreen_
// this.$emit('fullscreenchange', val)
},
initVideo() {
sysapi.getTerminalRel(2).then(res => {
this.videoOptions = {
autoplay: true, // 如果true,浏览器准备好时开始回放。
muted: true, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: 'zh-CN',
aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
// fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
// 是否流体自适应容器宽高
fluid: true,
// // 设置视频播放器的显示宽度(以像素为单位)
// width: '100px',
// // 设置视频播放器的显示高度(以像素为单位)
// height: '300px',
sources: [{
withCredentials: false,
type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
src: res.data.data[0].videoUrl // url地址
}],
flash: { hls: { withCredentials: false } },
html5: { hls: { withCredentials: false } },
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: false,
durationDisplay: false,
remainingTimeDisplay: false,
fullscreenToggle: true, // 全屏按钮,
pictureInPictureToggle: false
}
}
this.videoOptionsList = []
res.data.data.forEach(e => {
this.videoOptionsList.push({
options: {
autoplay: true, // 如果true,浏览器准备好时开始回放。
muted: true, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: 'zh-CN',
aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
// fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
// 是否流体自适应容器宽高
fluid: true,
// // 设置视频播放器的显示宽度(以像素为单位)
// width: '100px',
// // 设置视频播放器的显示高度(以像素为单位)
// height: '400px',
sources: [{
withCredentials: false,
type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
src: e.videoUrl // url地址
}],
flash: { hls: { withCredentials: false } },
html5: { hls: { withCredentials: false } },
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: false,
durationDisplay: false,
remainingTimeDisplay: false,
fullscreenToggle: false // 全屏按钮
}
},
name: e.resourceToolName
})
this.createMyButton()
})
})
},
videoSwitchover(itme,index) {
this.videoOptions.sources = itme.options.sources
this.checkedIndex = index
},
gotoSystem() {
this.$router.push({name: 'videoSurveillance'})
},
initAttendance() {
this.attendanceData = dasapi.queryAttendanceChart().then(res => {
this.population = res.data.totalSize
res.data.dataList.forEach(e => {
if (e.name === '在岗') {
e.itemStyle = { color: '#00A7F4' }
}
if (e.name === '请假') {
e.itemStyle = { color: '#FFCE00' }
}
if (e.name === '缺勤') {
e.itemStyle = { color: '#FF3F00' }
}
})
this.attendanceData = res.data.dataList
this.initAttendanceData()
})
},
initAlarm() {
this.population = dasapi.queryAlarmAnalysisChart().then(res => {
res.data.forEach(e => {
this.alarmDataX.push(e.name)
this.alarmDataY.push(e.value)
})
this.initAlarmData()
})
},
init24Top() {
this.topData = dasapi.queryAlarmAnalysisTopList().then(res => {
this.topData = []
for (var i = 0; i < 5; i++) {
if (res.data[i]) {
this.topData.push(res.data[i])
}
}
})
},
initRecognition() {
dasapi.queryHomeLastInAndOutRecord({monitorSceneId: 3}).then(res => {
var data = res.data.data
if (data.length > 4) {
data = data.slice(0, 4)
}
data.forEach(e => {
e.simi = e.simi.split('.')[0] + '%'
e.newImg = e.idenPictureUrl
var loadTimer
var imgObject = new Image()
imgObject.setAttribute('crossOrigin', 'anonymous')
imgObject.src = e.idenPictureUrl
imgObject.onLoad = onImgLoaded()
function onImgLoaded() {
if (loadTimer != null) clearTimeout(loadTimer)
if (!imgObject.complete) {
loadTimer = setTimeout(function() {
onImgLoaded()
}, 3)
} else {
e.newImg = getImagePortion(imgObject, e.face_box[2] - e.face_box[0], e.face_box[3] - e.face_box[1], e.face_box[0], e.face_box[1])
}
}
function getImagePortion(imgObj, newWidth, newHeight, startX, startY) {
var tnCanvas = document.createElement('canvas')
var tnCanvasContext = tnCanvas.getContext('2d')
tnCanvas.width = newWidth; tnCanvas.height = newHeight
var bufferCanvas = document.createElement('canvas')
var bufferContext = bufferCanvas.getContext('2d')
bufferCanvas.width = imgObj.width
bufferCanvas.height = imgObj.height
bufferContext.drawImage(imgObj, 0, 0)
tnCanvasContext.drawImage(bufferCanvas, startX, startY, newWidth, newHeight, 0, 0, newWidth, newHeight)
return tnCanvas.toDataURL()
}
})
this.distinguishData = data
})
},
initAttendanceData() {
var dom = document.getElementById('doughnut')
var myChart = echarts.init(dom)
var option = null
option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}人 ({d}%)'
},
legend: {
bottom: '20%',
left: 'center',
data: this.attendanceData,
formatter: this.legendFormatter,
textStyle: {
color: '#fff'
}
},
graphic: [ // 为环形图中间添加文字
{
type: 'text',
left: 'center',
top: '38%',
style: {
text: this.population + '人',
textAlign: 'center',
fill: '#ffffff',
fontSize: 12
}
}
],
series: [
{
type: 'pie',
radius: ['25%', '40%'],
center: ['50%', '40%'],
name: '出勤统计',
label: {
normal: {
formatter: '{d}% '
}
},
data: this.attendanceData,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
if (option && typeof option === 'object') {
myChart.setOption(option, true)
}
},
legendFormatter(data) {
var legend
this.attendanceData.forEach(e => {
if (data === e.name) {
legend = e.value
}
})
return data + ': ' + legend + '人'
},
initAlarmData() {
var dom = document.getElementById('bar')
var myChart = echarts.init(dom)
var option = null
var gridWidth = 320 // 可以根据canvas的宽度和grid的right,left,width进行计算
var fontsize = 12 // 字体大小
var wordNum = parseInt((gridWidth / this.alarmDataX.length) / fontsize)
var flag = 0
this.alarmDataX.forEach(value => {
if (value) {
var strs = value.split('')
var str = ''
for (var i = 0, s; s = strs[i++];) {
str += s
if (!(i % wordNum)) {
flag = -20
}
}
}
})
option = {
color: ['#3398DB'],
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: '4%',
right: '7%',
bottom: '15%',
top: '10%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: this.alarmDataX,
axisTick: {
alignWithLabel: true
},
axisLabel: {
show: true,
interval: 0,
rotate: flag,
textStyle: {
fontSize: 12,
color: '#fff'
}
}
}
],
yAxis: [
{
type: 'value',
minInterval: 1,
axisLabel: {
show: true,
textStyle: {
fontSize: 13,
color: '#fff'
}
},
splitLine: {
show: false
}
}
],
series: [
{
name: '数量',
type: 'bar',
barWidth: '40%',
data: this.alarmDataY,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0, 0, 0, 1,
[
{offset: 0, color: '#00FEFF'},
{offset: 1, color: '#0C7EFC'}
]
),
label: {
show: true, // 是否展示
position: 'top', // 在上方显示
formatter: function(name) {
return name.value + '个'
},
textStyle: {
fontSize: 14,
color: '#fff'
}
}
}
}
}
]
}
if (option && typeof option === 'object') {
myChart.setOption(option, true)
}
}
}
}
</script>
<style lang="scss">
.index{
height:100vh;
background-color: #011d40;
.time{
width: 500px;
height: 28px;
padding-left: 48px;
margin-top: -14px;
}
.goto{
cursor: pointer;
margin-top: -30px;
width: 8%;
height: 40px;
border-radius: 5px;
background-color: #011d40; /* 浏览器不支持的时候显示 */
box-shadow: 0 0 30px -10px #009bf3 inset;
margin-left: 91%;
align-items: center;
text-align: center;
padding-top: 6px;
color:#00d8f3;
font-size: 18px;
}
.top{
-moz-background-size:100% 100%;
background-size:100% 100%;
display: flex;
align-items: center;
text-align: center;
height: 6%;
overflow: hidden;
position: relative;
.top-logo{
position: absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
height: 50%;
width: 25%;
vertical-align: middle
}
}
.body{
display: flex;
height: 90%;
padding-top: 1%;
justify-content: space-around;
.body-left{
width: 23%;
height: 96%;
.body-left-item{
width: 100%;
border-radius: 5px;
background-color: #011d40; /* 浏览器不支持的时候显示 */
box-shadow: 0 0 30px -10px #009bf3 inset;
.top4{
padding-left: 15px;
padding-right: 15px;
color: #00d8f3;
font-size: 15px;
height: 100%;
.top4-row{
border: 0 none;
border-bottom: 2px dotted #00466b;
height: 16%;
.col-6{
display: flex;
.polygon{
-moz-background-size:100% 100%;
background-size:100% 100%;
align-items: center;
text-align: center;
height: 100%;
width: 15%;
}
}
}
}
}
}
.body-center{
width: 50%;
height: 96%;
border-radius: 5px;
background-color: #011d40; /* 浏览器不支持的时候显示 */
box-shadow: 0 0 30px -10px #009bf3 inset;
}
.body-right{
width: 23%;
height: 96%;
border-radius: 5px;
background-color: #011d40; /* 浏览器不支持的时候显示 */
box-shadow: 0 0 30px -10px #009bf3 inset;
.distinguish{
-moz-background-size:100% 100%;
background-size:100% 100%;
width: 88%;
height: 22%;
margin-left: 6%;
margin-top: 3%;
padding-left: 1%;
padding-right: 1%;
padding-top: 1%;
padding-bottom: 1%;
.distinguish-title{
align-items: center;
text-align: center;
height: 28px;
width: 100%;
margin: 0 auto;
font-size: 16px;
color: #00d8f3;
//background-color: #003C74; 100%
background: linear-gradient(to right, #011d40,#003C74,#011D40);
}
.distinguish-row{
display: flex;
color: #00d8f3;
width: 100%;
height: 100%;
position: relative;
.similarity{
position: absolute;
left:22%;
top:27%;
border: 2px solid #00d8f3;
width: 30px;
height: 30px;
background: #090404;
opacity: 0.5;
border-radius: 50%;
padding-top: 1%;
filter:alpha(opacity=50); /*支持IE */
-moz-opacity:0.5; /*支持FF */
//opacity:0.5;
.p{
position:relative;
color: #00d8f3;
font-size: 10px
}
}
.distinguish-col{
width: 27%;
margin-top: 2%;
height: 70%;
}
.distinguish-col-row{
padding-left: 5%;
padding-top: 5%;
height: 40%;
width: 130%;
color: white;
font-size: 14px;
}
}
}
}
}
.title{
-moz-background-size:100% 100%;
background-size:100% 100%;
align-items: center;
text-align: center;
height: 28px;
width: 100%;
margin: 0 auto;
.title-span{
height: 28px;
align-items: center;
text-align: center;
font-size: 14px;
color: #00d8f3;
margin: auto;
}
}
.titleWide{
-moz-background-size:100% 100%;
background-size:100% 100%;
align-items: center;
text-align: center;
height: 28px;
width: 47%;
margin: 0 auto;
.title-span{
height: 28px;
align-items: center;
text-align: center;
font-size: 14px;
color: #00d8f3;
margin: auto;
}
}
.videoPlayer{
width: 100%;
padding: 1.5% 2.5% 0.5% 2.5%;
}
.videoPlayers{
display: flex;
width: 100%;
height: 25%;
padding: 0 2.5% 0.5% 2.5%;
justify-content: space-around;
.videoPlayer-sm{
z-index:9999;
cursor: pointer;
width: 23%;
height: 95%;
}
}
.vjs-progress-control{
visibility:hidden
}
.checkedIndex{
border: 1px solid #009bf3;
}
}
</style>
|