Files
Agriculture-front-end/src/views/plough/VideoSurveillance/index.vue
2023-09-11 21:56:39 +08:00

786 lines
25 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="fatherDiv">
<div class="tabulation">
<div class="tabulationCente">
<div class="left">
<p>
当前选择
<span style="color: rgba(100, 195, 164, 1)">{{ label2 }}</span>
</p>
<el-tree
:data="devicesArr"
:props="defaultProps"
@node-click="handleNodeClick"
/>
</div>
<div class="freckle">
<!-- <div class="searchDiv">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item style="width: 180px" label="预警情况:">
<el-select
popper-class="selectCity"
v-model="formInline.flag"
placeholder="请选择"
>
<el-option label="有" value="有" />
<el-option label="无" value="无" />
</el-select>
</el-form-item>
<el-form-item style="width: 300px" label="监测时间:">
<el-date-picker
v-model="value1"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
<el-button plain @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div> -->
<div class="chartModeFather">
<div class="tableBox">
<el-table
:data="tableNewData"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
header-row-class-name="tabth"
height="calc(100vh - 200px)"
highlight-current-row
>
<el-table-column
type="index"
width="80"
label="序号"
:index="Nindex"
/>
<el-table-column prop="village" label="位置" width="180" />
<el-table-column prop="cameraName" label="摄像头名称" width="180" />
<el-table-column label="操作">
<template #default="scope">
<span
style="color: rgba(100, 195, 164, 1); cursor: pointer"
@click="onDetail(scope.row)"
>
播放
</span>
</template>
</el-table-column>
</el-table>
<div class="example-pagination-block">
{{ tabulation.length }}
<el-pagination
background
layout="prev, pager, next"
:total="tabulation.length"
:current-page="currentPage"
:page-size="pageSize"
@current-change="tabulationCurrentChange"
/>
</div>
</div>
</div>
</div>
<div class="centent">
<div class="arrow" @click="foldClick">
<p v-if="!flags">
<img style="width: 300%" src="@/assets/images/shouhui.png" />
</p>
<p v-if="flags">
<img style="width: 300%" src="@/assets/images/zhankai.png" />
</p>
</div>
</div>
<div v-show="!flags" class="cesiumContainersDiv">
<div id="cesiumContainers" class="detailed"></div>
</div>
</div>
<el-dialog
v-model="dialogVisible"
append-to-body
class="video"
destroy-on-close
title="实时监控"
width="40%"
:before-close="handleClose"
>
<div id="myVideo" style="width: 100%; height: 100%">
<!-- <VideoJs :videoSrc="data.videoSrc" :sonData="fatherData" autoPlay /> -->
</div>
</el-dialog>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, inject, reactive, watch } from 'vue';
import * as echarts from 'echarts';
import { useEcharts } from '@/hooks/useEcharts';
import axios from 'axios';
import '@/assets/monitor/imouplayer.js';
import {
getTreeData,
getCameraName,
getCameraNameS,
getQuery,
getSxtbf,
} from '../../../api/plough/VideoSurveillance';
import VideoJs from '@/components/video/video.vue';
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import iconShadow from '/img/marker/mark.png';
import { TileWMS } from 'ol/source';
import md5 from 'js-md5';
import CryptoJS from 'crypto-js';
import { ElMessage } from 'element-plus';
let map = L.Map;
let tabulation = ref([]);
let popdata = ref({});
let devicesArr = ref([]); //树结构数据
let label1 = ref('');
let label2 = ref('全部');
let tableNewData = ref([]);
const dialogVisible = ref(false);
let formInline = ref({
yearMonth: '',
flag: '',
divisions: '',
});
let flags = ref(false);
let currentPage = ref(1); //当前页
let pageSize = ref(18); //每页条数
let center = null; // 指定中心点
const newData = ref({});
let fatherData = ref('');
let baseLayers = null;
const data = reactive({
videoSrc:
'http://cmgw-vpc.lechange.com:8888/LCO/9C023C5FACFE48F/0/1/20230530T033445/a44e6e04b0608347f0209ab2b25aa258.m3u8',
});
onMounted(() => {
getTreeDatas();
initLeafletMap();
getCameraNames();
getCameraNameSs();
});
onUpdated(() => {
document.querySelector('.mode').style.display = 'none';
window.document.querySelector('#screenfull').style.display = 'none';
});
const initLeafletMap = () => {
map = L.map('cesiumContainers', {
center: [36.4, 119.166326], // 地图中心
zoom: 7, //缩放比列
zoomControl: false, //禁用 + - 按钮
doubleClickZoom: false, // 禁用双击放大
attributionControl: false, // 移除右下角leaflet标识
maxZoom: 16,
crs: serverAPI.tiandituzhuji=='http://59.206.203.34/tileservice/SDRasterPubMapDJ?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=sdcia&STYLE=default&TILEMATRIXSET=sdcia&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=application%2Fpng' ? L.CRS.EPSG4326 : L.CRS.EPSG3857
});
// 创建底图图层
let imgBaseLayer = null;
let ciaBaseLayer = null;
if (
serverAPI.tiandituzhuji ==
'http://59.206.203.34/tileservice/SDRasterPubMapDJ?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=sdcia&STYLE=default&TILEMATRIXSET=sdcia&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=application%2Fpng'
) {
imgBaseLayer = L.tileLayer(serverAPI.tiandituLayers, {
maxZoom: 20,
tileSize: 256,
zoomOffset: 1,
});
ciaBaseLayer = L.tileLayer(serverAPI.tiandituzhuji, {
maxZoom: 20,
tileSize: 256,
zoomOffset: 1,
});
} else {
// 创建底图图层
imgBaseLayer = L.tileLayer(serverAPI.tiandituLayers, {
// maxZoom: 20,
// tileSize: 256,
// zoomOffset: 1,
});
ciaBaseLayer = L.tileLayer(serverAPI.tiandituzhuji, {
// maxZoom: 20,
// tileSize: 256,
// zoomOffset: 1,
});
}
// 将底图图层添加到地图
imgBaseLayer.addTo(map);
ciaBaseLayer.addTo(map);
baseLayers = {
'Image Base Map': imgBaseLayer,
'CIA Base Map': ciaBaseLayer,
};
L.Util.requestAnimFrame(map.invalidateSize, map, !1, map._container); //解决首次加载不完全问题
};
/*-----------接口---------------*/
const getTreeDatas = () => {
getTreeData({ divisions: window.localStorage.getItem('deptName') }).then(res => {
res.data.forEach(item => {
devicesArr.value.push(item);
});
});
};
const getCameraNames = videoName => {
getCameraName({ name: videoName }).then(res => {
res.data.forEach((item, index) => {
center = L.latLng(item.latitude, item.longitude);
map.setView(center, 17);
L.marker([item.latitude, item.longitude], { icon: greenIcon })
.addTo(map)
.bindPopup(
`<b>${item.cameraName}</b><br><br>经度:${item.longitude}<br><br>纬度:${item.latitude}`
)
.openPopup();
});
});
};
const getCameraNameSs = () => {
getCameraNameS().then(res => {
tabulation.value = res.data;
if (newData.value.children !== null) {
tableNewData.value = res.data.slice(
(currentPage.value - 1) * pageSize.value,
currentPage.value * pageSize.value
);
}
});
};
const tabulationCurrentChange = e => {
currentPage.value = e;
tableNewData.value = tabulation.value.slice(
(currentPage.value - 1) * pageSize.value,
currentPage.value * pageSize.value
);
};
/*------------事件----------------*/
//树结构
const handleNodeClick = (data, node, data1, data2) => {
label2.value = data.label;
formInline.value.flag = '';
// let oriFatherId = node.parent.parent.data;
// label1.value = oriFatherId.label;
newData.value = data;
getCameraNames(label2.value);
};
function getRandom(a, b) {
var max = a;
var min = b;
if (a < b) {
max = b;
min = a;
}
return parseInt(Math.random() * (max - min)) + min;
}
function suijione(num, maxA, minlA, fqy) {
let arr = [];
let arr1 = [];
let arr2 = [];
if (num) {
for (let m = 0; m <= 9; m++) {
arr.push(m);
}
}
if (maxA) {
for (let m = 65; m <= 90; m++) {
arr1.push(m);
}
}
if (minlA) {
for (let m = 97; m <= 122; m++) {
arr2.push(m);
}
}
if (!fqy) {
console.log('生成位数必传');
}
let mergeArr = arr.concat(arr1);
let mergeArr1 = mergeArr.concat(arr2);
let _length = mergeArr1.length;
let text = '';
for (let m = 0; m < fqy; m++) {
let text1 = '';
let random = getRandom(0, _length);
if (mergeArr1[random] <= 9) {
text1 = mergeArr1[random];
} else if (mergeArr1[random] > 9) {
text1 = String.fromCharCode(mergeArr1[random]);
}
text += text1;
}
return text;
}
let deviceId = ref('');
let channelId = ref('');
let token = ref('');
let code = ref('');
let streamId = ref(0);
let type = ref(1);
let recordType = ref(null);
let onDetail = e => {
fatherData.value = e.cameraName;
data.videoSrc = e.hdStreaming;
dialogVisible.value = true;
getQuery({ name: e.cameraName }).then(res => {
let API_KEY = res.data[0].appId;
let SECRET = res.data[0].appSecret;
let time = new Date().getTime() / 1000;
let nonce = suijione(true, false, true, 32);
const inputString = `time:${parseInt(time)},nonce:${nonce},appSecret:${SECRET}`;
let id = res.data[0].id;
getSxtbf({ deviceId: e.cameraName })
.then(response => {
let player = new imouPlayer({
id: 'myVideo',
// 设备序列号
deviceId: res.data[0].deviceId,
token: response.data.data.kitToken,
channelId: 0,
// 1 直播 2 录播
type: 1,
// 直播 0 高清 1 标清 默认
streamId: 0,
// 录播 云录像 1 本地录像 localRecord 默认 云录像
recordType: 'cloud',
// 如果设备设置了自定义音视频加密秘钥,则输入此秘钥;
// 如果设备只设置了设备密码,则输入设备密码;其他情况默认设备序列号。
code: '',
});
player.on('play', res => {
console.log('开始播放 play', res);
});
player.on('pause', () => {
console.log('播放器暂停 pause');
});
player.on('error', res => {
console.log('播放器错误 error', res);
});
player.on('volume', res => {
console.log('声音控制', res);
});
player.on('talk', res => {
console.log('对讲 talk', res);
});
})
.catch(error => {
console.log(error);
});
});
};
const Nindex = index => {
// 当前页数 - 1 * 每页数据条数 + 1
const page = currentPage.value; // 当前页码
const pagesize = pageSize.value; // 每页条数
return index + 1 + (page - 1) * pagesize;
};
//创建ICON构造函数相当于继承于ICON可以重新设置属性
var LeafIcon = L.Icon.extend({
options: {
// shadowUrl: './icon/leaf-shadow.png', //阴影地址
iconSize: [50, 50], //图标宽高
shadowSize: [50, 64], //阴影宽高
iconAnchor: [22, 94], //图标锚点
shadowAnchor: [4, 62], //阴影锚点
popupAnchor: [0, -86], //弹出框弹出位置,相对于图标锚点
},
});
//创建多个icon
var greenIcon = new LeafIcon({
iconUrl: iconShadow,
});
//tabs
const foldClick = () => {
flags.value = !flags.value;
};
</script>
<style src="./imouplayer.css" />
<style lang="scss" scoped>
$height: calc(100vh - 100px);
.fatherDiv {
width: 100%;
height: 108%;
}
.tabulation,
.centerBox {
width: 100%;
height: 98%;
.imgrotate {
transform: rotate(180deg);
}
.title {
width: 100%;
height: 45px;
background: url('@/assets/images/title.png');
background-repeat: no-repeat;
background-size: 110% 100%;
color: #fff;
font-size: 18px;
font-weight: 700;
line-height: 45px;
padding-left: 46px;
display: flex;
cursor: pointer;
align-items: center;
justify-content: space-between;
span {
width: 80%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background: linear-gradient(
180deg,
rgba(255, 255, 255, 1) 33.33%,
rgba(41, 255, 219, 1) 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
p {
width: 110px;
height: 25px;
border-radius: 20px;
font-size: 14px;
background: linear-gradient(
180deg,
rgba(16, 111, 111, 1) 0%,
rgba(47, 214, 214, 1) 100%
);
border: 1.5px solid rgba(23, 194, 180, 1);
display: flex;
justify-content: center;
align-items: center;
}
}
}
.demo-tabs {
// width: 100%;
// height: 98%;
:deep(.el-tabs__nav.is-top) {
transform: translateX(60px) !important;
}
}
.tabulationCente {
width: 100%;
height: 89%;
display: flex;
padding: 10px;
.left {
width: 15%;
height: 100%;
box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.08);
margin-right: 20px;
font-size: 14px;
color: rgba(0, 0, 0, 1);
padding: 10px 20px;
overflow-y: scroll;
}
.cesiumContainersDiv {
width: 30%;
height: 100%;
background: #ccc;
box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.08);
position: relative;
overflow: hidden;
.VideoPlayDiv {
width: 100%;
}
.detailed {
width: 100%;
height: 100%;
}
#pops {
opacity: 1;
border-radius: 5px;
background: rgba(2, 31, 26, 0.6);
display: none;
flex-direction: column;
justify-content: flex-start;
align-items: flex-end;
padding: 6px 8px 6px 8px;
color: rgba(255, 255, 255, 1);
font-size: 14px;
.content {
div {
display: flex;
align-items: center;
justify-content: space-between;
p {
width: 100px;
border-radius: 2px;
background: rgba(217, 231, 255, 0.2);
display: flex;
justify-content: center;
align-items: center;
}
}
}
.cancel {
position: absolute;
right: 10px;
top: 5px;
color: rgba(255, 255, 255, 1);
cursor: pointer;
}
}
}
.centent {
width: 20px;
height: 100%;
position: relative;
z-index: 99;
.arrow {
width: 22px;
height: 22px;
// background: #ccc;
position: absolute;
top: 50%;
transform: translate(-80%, -50%);
z-index: 99;
border-radius: 50%;
cursor: pointer;
}
}
.freckle {
width: 50%;
flex: 1;
// background: #ccc;
box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.08);
:deep(.el-input__wrapper) {
opacity: 1;
border-radius: 4px;
background: #fff;
border: none;
box-shadow: 0px 3px 9px 0px rgba(0, 0, 0, 0.25);
width: 20%;
.el-input__inner {
color: rgba(170, 170, 170, 1);
}
}
.searchDiv {
margin: 20px;
display: flex;
}
.tableBox {
:deep(
.el-table .el-table__header-wrapper th,
.el-table .el-table__fixed-header-wrapper th
) {
color: rgba(0, 0, 0, 1);
}
height: 93%;
:deep(.el-table__inner-wrapper) {
height: 96% !important;
}
.example-pagination-block {
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-end;
}
:deep(.tabth) {
background-color: rgba(247, 247, 247, 1);
.el-table-fixed-column--left {
background: rgba(247, 247, 247, 1) !important;
}
}
.insectDiv {
width: 100%;
height: 90%;
overflow: hidden;
.gutters {
width: 100%;
height: 100%;
overflow-y: scroll;
.ins {
position: relative;
.yj {
color: rgba(255, 255, 255, 1);
position: absolute;
font-size: 14px;
border-radius: 0px 30px, 0px, 30px;
top: 0;
right: 0;
text-align: center;
line-height: 24px;
padding: 1px 5px;
}
}
}
}
}
}
:deep().el-dialog__body {
width: 300px;
height: 300px;
}
.chartMode {
:deep(
.el-table .el-table__header-wrapper th,
.el-table .el-table__fixed-header-wrapper th
) {
color: rgba(0, 0, 0, 1);
}
height: 93%;
:deep(.el-table__inner-wrapper) {
height: 96% !important;
}
.example-pagination-block {
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-end;
}
:deep(.tabth) {
background-color: rgba(247, 247, 247, 1);
}
.insectDiv {
width: 100%;
height: 90%;
overflow: hidden;
.gutters {
width: 100%;
height: 100%;
overflow-y: scroll;
.ins {
position: relative;
.yj {
color: rgba(255, 255, 255, 1);
position: absolute;
font-size: 14px;
border-radius: 0px 30px, 0px, 30px;
top: 0;
right: 0;
text-align: center;
line-height: 24px;
padding: 1px 5px;
}
}
}
}
.tableBoxs {
width: 100%;
height: 100%;
overflow: hidden;
.gutters {
width: 100%;
height: 100%;
overflow-y: scroll;
.ins {
position: relative;
.yj {
color: rgba(255, 255, 255, 1);
position: absolute;
font-size: 14px;
border-radius: 0px 30px, 0px, 30px;
top: 0;
right: 0;
text-align: center;
line-height: 24px;
padding: 1px 5px;
}
}
}
}
.chartModeDiv {
width: 100%;
height: 50%;
}
.depth {
width: 50%;
height: 26px;
opacity: 1;
border-radius: 4px;
font-size: 12px;
color: rgba(102, 102, 102, 1);
margin-top: 20px;
cursor: pointer;
background: linear-gradient(
180deg,
rgba(16, 111, 111, 0.1) 0%,
rgba(47, 214, 214, 0.1) 100%
);
border: 1px solid rgba(228, 231, 237, 1);
display: flex;
align-items: center;
p {
flex: 1;
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.SelectedDiv {
opacity: 1;
border-radius: 4px;
background: rgba(100, 195, 164, 1);
}
margin: 0 auto;
}
}
}
.myVideo {
width: 100%;
height: 100%;
}
:deep().icon {
font-size: 35px !important;
color: #f18d00;
position: absolute;
bottom: 10px;
cursor: pointer;
}
:deep().record-icon {
font-size: 35px !important;
color: #f18d00;
position: absolute;
bottom: 60px;
}
</style>
<style lang="scss">
.video {
.el-dialog__body {
width: 100%;
height: 400px;
}
}
.el-date-range-picker__header {
.arrow-left {
position: unset !important;
pointer-events: all !important;
}
.arrow-right {
position: unset !important;
pointer-events: all !important;
border-left: none;
border-bottom: none;
border-top: none;
right: none;
top: none;
transform: none;
width: 30px;
height: none;
}
}
</style>