|
@@ -4,17 +4,95 @@
|
|
|
您的浏览器不支持 video 标签。
|
|
|
</video>
|
|
|
<div class="mask" @click="showVideo(id)"></div>
|
|
|
+ <div class="txt">{{ name }}</div>
|
|
|
+
|
|
|
+ <basic-modal
|
|
|
+ width="80%"
|
|
|
+ top="120px"
|
|
|
+ ref="cameraModal"
|
|
|
+ title="视频监控"
|
|
|
+ :appendToBody="true"
|
|
|
+ @opened="opened"
|
|
|
+ >
|
|
|
+ <div class="camera-container">
|
|
|
+ <div class="left">
|
|
|
+ <el-select
|
|
|
+ v-model="param.qx"
|
|
|
+ placeholder="区域"
|
|
|
+ clearable
|
|
|
+ @change="changeArea"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ :value="item.areaTitle"
|
|
|
+ :label="item.areaTitle"
|
|
|
+ v-for="(item, index) in areaData"
|
|
|
+ :key="index"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <div class="tree-container">
|
|
|
+ <el-tree
|
|
|
+ class="carema-tree"
|
|
|
+ :data="treeData"
|
|
|
+ v-loading="treeLoading"
|
|
|
+ highlight-current
|
|
|
+ :expand-on-click-node="true"
|
|
|
+ ref="tree"
|
|
|
+ @node-click="handleNodeClick"
|
|
|
+ node-key="id"
|
|
|
+ >
|
|
|
+ <template slot-scope="{ node, data }">
|
|
|
+ <div class="tree-node" :title="node.label" :id="data.id">
|
|
|
+ {{ node.label }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="right" v-loading="rightLoading">
|
|
|
+ <video
|
|
|
+ :src="rightUrl"
|
|
|
+ v-if="rightUrl"
|
|
|
+ width="100%"
|
|
|
+ height="100%"
|
|
|
+ autoplay
|
|
|
+ muted
|
|
|
+ controls
|
|
|
+ >
|
|
|
+ 您的浏览器不支持 video 标签。
|
|
|
+ </video>
|
|
|
+ <!-- <iframe :src="rightUrl" v-if="rightUrl" /> -->
|
|
|
+ <div class="empty" v-if="rightUrl === ''">暂无播放资源</div>
|
|
|
+ <div class="txt">{{ rightName }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </basic-modal>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
|
import { getCameraUrl } from "@/api/camera.js";
|
|
|
+import { getDeviceList } from "@/api/iot.js";
|
|
|
+import { area } from "@/api/area";
|
|
|
export default {
|
|
|
name: "CameraContainer",
|
|
|
components: {},
|
|
|
data() {
|
|
|
return {
|
|
|
url: null,
|
|
|
+ name: null,
|
|
|
loading: false,
|
|
|
+ treeData: [],
|
|
|
+ treeLoading: false,
|
|
|
+ tmpData: [],
|
|
|
+ rightUrl: null,
|
|
|
+ rightName: null,
|
|
|
+ rightLoading: false,
|
|
|
+ areaData: [],
|
|
|
+ param: {
|
|
|
+ qx: null,
|
|
|
+ },
|
|
|
+ currentId: null,
|
|
|
+ currentExpand: [],
|
|
|
+ nodeParentAll: [],
|
|
|
};
|
|
|
},
|
|
|
props: {
|
|
@@ -26,29 +104,125 @@ export default {
|
|
|
type: Array,
|
|
|
default: [],
|
|
|
},
|
|
|
+ zjid: {
|
|
|
+ type: String,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+ qx: {
|
|
|
+ type: String,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
},
|
|
|
mounted() {
|
|
|
this.getData();
|
|
|
+ this.getAreaList();
|
|
|
},
|
|
|
methods: {
|
|
|
+ // 通过节点的key(这里使用的是数据中的code属性,node-key="code")获取并高亮显示指定节点,并展开其所有父级节点
|
|
|
+ getAndExpandAll(nodeKey) {
|
|
|
+ if (nodeKey) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 等待树组件渲染完成再执行相关操作
|
|
|
+ // 获取节点
|
|
|
+ const node = this.$refs.tree.getNode(nodeKey);
|
|
|
+ if (node) {
|
|
|
+ // 获取其所有父级节点
|
|
|
+ this.getParentAll(node);
|
|
|
+ console.log(this.nodeParentAll);
|
|
|
+ if (this.nodeParentAll.length > 0) {
|
|
|
+ // 将获取到的所有父级节点进行展开
|
|
|
+ for (var i = 0, n = this.nodeParentAll.length; i < n; i++) {
|
|
|
+ this.$refs.tree.store.nodesMap[
|
|
|
+ this.nodeParentAll[i].data.id
|
|
|
+ ].expanded = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将节点高亮显示
|
|
|
+ this.$refs.tree.setCurrentKey(nodeKey);
|
|
|
+ this.handleNodeClick({ id: nodeKey })
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取所有父级节点
|
|
|
+ getParentAll(node) {
|
|
|
+ if (node) {
|
|
|
+ this.nodeParentAll = [];
|
|
|
+ // 节点的第一个父级
|
|
|
+ var parentNode = node.parent;
|
|
|
+ // level为节点的层级 level=1 为顶级节点
|
|
|
+ for (var j = 0, lv = node.level; j < lv; j++) {
|
|
|
+ if (parentNode.level > 0) {
|
|
|
+ // 将所有父级节点放入集合中
|
|
|
+ this.nodeParentAll.push(parentNode);
|
|
|
+ }
|
|
|
+ // 继续获取父级节点的父级节点
|
|
|
+ parentNode = parentNode.parent;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.nodeParentAll.length > 1) {
|
|
|
+ // 如果集合长度>1 则将数组进行倒叙.reverse() 其是就是将所有节点按照 从 顶级节点 依次往下排
|
|
|
+ this.nodeParentAll.reverse();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ opened() {
|
|
|
+ if (this.currentId) {
|
|
|
+ this.getAndExpandAll(this.currentId);
|
|
|
+
|
|
|
+ // 定位到选中的节点
|
|
|
+ const node = document.getElementById(this.currentId);
|
|
|
+
|
|
|
+ setTimeout(function () {
|
|
|
+ node.scrollIntoView();
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ changeArea() {
|
|
|
+ this.getDevices();
|
|
|
+ },
|
|
|
+ getAreaList() {
|
|
|
+ area({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ }).then((res) => {
|
|
|
+ this.areaData = res.data.rows;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleNodeClick(data) {
|
|
|
+ this.rightUrl = null;
|
|
|
+ if (data.id) {
|
|
|
+ // 获取播放地址
|
|
|
+ this.rightLoading = true;
|
|
|
+ getCameraUrl(data.id).then((res) => {
|
|
|
+ this.rightLoading = false;
|
|
|
+ this.rightUrl = res.data.data[0].mp4;
|
|
|
+ this.rightName = res.data.data[0].deviceName;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
getData() {
|
|
|
this.loading = true;
|
|
|
// TO-DO
|
|
|
getCameraUrl(this.id).then((res) => {
|
|
|
this.loading = false;
|
|
|
this.url = res.data.data[0].mp4;
|
|
|
+ this.name = res.data.data[0].deviceName;
|
|
|
if (!this.url && this.byList && this.byList.length > 0) {
|
|
|
this.loading = true;
|
|
|
getCameraUrl(this.byList[this.byList.length - 1].sbbm).then(
|
|
|
(res2) => {
|
|
|
this.loading = false;
|
|
|
this.url = res2.data.data[0].mp4;
|
|
|
+ this.name = res2.data.data[0].deviceName;
|
|
|
if (!this.url) {
|
|
|
this.loading = true;
|
|
|
getCameraUrl(this.byList[this.byList.length - 2].sbbm).then(
|
|
|
(res3) => {
|
|
|
this.loading = false;
|
|
|
this.url = res3.mp4;
|
|
|
+ this.name = res3.data.data[0].deviceName;
|
|
|
}
|
|
|
);
|
|
|
}
|
|
@@ -60,10 +234,84 @@ export default {
|
|
|
// this.url =
|
|
|
// "https://ycjk.cq119.gov.cn/rtp/77746e2c33126146cb83c81be23d0492.live.mp4?deviceId=50015200002000000001&key=";
|
|
|
},
|
|
|
- showVideo(id) {
|
|
|
- console.log(id);
|
|
|
+ async showVideo(id) {
|
|
|
+ await this.getDevices();
|
|
|
|
|
|
+ // 选中当前
|
|
|
+ this.currentId = id;
|
|
|
+ // console.log(this.currentId);
|
|
|
// 弹窗显示视频播放组件
|
|
|
+ this.showModal("cameraModal");
|
|
|
+ },
|
|
|
+ async getDevices() {
|
|
|
+ this.treeLoading = true;
|
|
|
+ let caremaData = [];
|
|
|
+ // 获取视频数据
|
|
|
+ const deviceParam = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10000,
|
|
|
+ qx: this.param.qx === "重庆市" ? "" : this.param.qx,
|
|
|
+ zt: "在线",
|
|
|
+ sblx: "生命通道监测",
|
|
|
+ };
|
|
|
+ if (this.jzid) {
|
|
|
+ deviceParam.jzid = this.jzid;
|
|
|
+ }
|
|
|
+ const res = await getDeviceList(deviceParam);
|
|
|
+ caremaData = caremaData.concat(res.data.rows);
|
|
|
+
|
|
|
+ const deviceParam2 = {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10000,
|
|
|
+ qx: this.param.qx === "重庆市" ? "" : this.param.qx,
|
|
|
+ zt: "在线",
|
|
|
+ sblx: "消防控制室监控",
|
|
|
+ };
|
|
|
+ if (this.jzid) {
|
|
|
+ deviceParam2.jzid = this.jzid;
|
|
|
+ }
|
|
|
+ const res2 = await getDeviceList(deviceParam2);
|
|
|
+ caremaData = caremaData.concat(res2.data.rows);
|
|
|
+ console.log(caremaData);
|
|
|
+ this.tmpData = caremaData;
|
|
|
+ this.createTreeDate(caremaData);
|
|
|
+ this.treeLoading = false;
|
|
|
+ },
|
|
|
+ createTreeDate(caremaData) {
|
|
|
+ // 区县第一级
|
|
|
+ const qxData = [];
|
|
|
+ caremaData.forEach((p) => {
|
|
|
+ if (!qxData.find((k) => k.label === p.qx)) {
|
|
|
+ qxData.push({
|
|
|
+ id: p.qx,
|
|
|
+ label: p.qx,
|
|
|
+ children: [],
|
|
|
+ disabled: true,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ qxData.forEach((p) => {
|
|
|
+ p.children.push({
|
|
|
+ id: p.id + "-生命通道监测",
|
|
|
+ label: "生命通道监测",
|
|
|
+ children: caremaData
|
|
|
+ .filter((k) => k.qx === p.label && k.sblx === "生命通道监测")
|
|
|
+ .map((i) => {
|
|
|
+ return { label: i.sbmc, id: i.sbbm };
|
|
|
+ }),
|
|
|
+ });
|
|
|
+ p.children.push({
|
|
|
+ id: p.id + "-消防控制室监控",
|
|
|
+ label: "消防控制室监控",
|
|
|
+ children: caremaData
|
|
|
+ .filter((k) => k.qx === p.label && k.sblx === "消防控制室监控")
|
|
|
+ .map((i) => {
|
|
|
+ return { label: i.sbmc, id: i.sbbm };
|
|
|
+ }),
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.treeData = qxData;
|
|
|
},
|
|
|
},
|
|
|
};
|
|
@@ -84,5 +332,198 @@ export default {
|
|
|
z-index: 99;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
+ .txt {
|
|
|
+ position: absolute;
|
|
|
+ font-family: "Abel";
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 24px;
|
|
|
+ right: 11px;
|
|
|
+ top: 6px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.camera-container {
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+ display: flex;
|
|
|
+ background: rgba(0, 16, 55, 0.94);
|
|
|
+
|
|
|
+ .left {
|
|
|
+ width: 300px;
|
|
|
+ height: auto;
|
|
|
+ padding: 0 30px 0 22px;
|
|
|
+
|
|
|
+ .tree-container {
|
|
|
+ width: 300px;
|
|
|
+ height: 540px;
|
|
|
+ overflow-y: auto;
|
|
|
+ margin-top: 15px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right {
|
|
|
+ width: 50%;
|
|
|
+ flex-grow: 1;
|
|
|
+ height: 600px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ position: relative;
|
|
|
+ .txt {
|
|
|
+ position: absolute;
|
|
|
+ font-family: "Abel";
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 24px;
|
|
|
+ right: 20px;
|
|
|
+ top: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.carema-tree {
|
|
|
+ background: transparent !important;
|
|
|
+ color: #f5fdff !important;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep(
|
|
|
+ .el-tree--highlight-current
|
|
|
+ .el-tree-node.is-current
|
|
|
+ > .el-tree-node__content
|
|
|
+ ) {
|
|
|
+ background: linear-gradient(
|
|
|
+ 180deg,
|
|
|
+ rgba(0, 148, 255, 0.5) 0%,
|
|
|
+ rgba(0, 148, 255, 0) 100%
|
|
|
+ ) !important;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-left: 36px;
|
|
|
+ margin-right: 13px;
|
|
|
+ padding-left: 0 !important;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+::v-deep(.el-tree-node__content:hover) {
|
|
|
+ // background: linear-gradient(
|
|
|
+ // 180deg,
|
|
|
+ // rgba(0, 148, 255, 0.5) 0%,
|
|
|
+ // rgba(0, 148, 255, 0) 100%
|
|
|
+ // ) !important;
|
|
|
+ // border-radius: 4px;
|
|
|
+ // margin-left: 36px;
|
|
|
+ // margin-right: 13px;
|
|
|
+ // padding-left: 0 !important;
|
|
|
+ // overflow: hidden;
|
|
|
+ background: transparent !important;
|
|
|
+}
|
|
|
+::v-deep(.el-tree-node:focus > .el-tree-node__content) {
|
|
|
+ background: transparent !important;
|
|
|
+}
|
|
|
+
|
|
|
+.tree-node {
|
|
|
+ width: 90%;
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ overflow: hidden;
|
|
|
+ margin-right: 13px;
|
|
|
+}
|
|
|
+
|
|
|
+video {
|
|
|
+ object-fit: fill;
|
|
|
+}
|
|
|
+
|
|
|
+.empty {
|
|
|
+ text-align: center;
|
|
|
+ padding-top: 200px;
|
|
|
+}
|
|
|
+
|
|
|
+/** 滚动条 */
|
|
|
+::-webkit-scrollbar,
|
|
|
+::-webkit-scrollbar,
|
|
|
+::-webkit-scrollbar,
|
|
|
+::-webkit-scrollbar {
|
|
|
+ /*滚动条整体样式*/
|
|
|
+ width: 8px;
|
|
|
+ /*高宽分别对应横竖滚动条的尺寸*/
|
|
|
+ height: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-thumb,
|
|
|
+::-webkit-scrollbar-thumb,
|
|
|
+::-webkit-scrollbar-thumb,
|
|
|
+::-webkit-scrollbar-thumb {
|
|
|
+ /*滚动条里面小方块*/
|
|
|
+ border-radius: 4px;
|
|
|
+ /* box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); */
|
|
|
+ background: rgba(0, 213, 255, 0.73);
|
|
|
+ opacity: 0.7;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-track,
|
|
|
+::-webkit-scrollbar-track,
|
|
|
+::-webkit-scrollbar-track,
|
|
|
+::-webkit-scrollbar-track {
|
|
|
+ /*滚动条里面轨道*/
|
|
|
+ /* box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); */
|
|
|
+ border-radius: 3px;
|
|
|
+ background: rgba(0, 213, 255, 0.3);
|
|
|
+ opacity: 0.7;
|
|
|
+}
|
|
|
+
|
|
|
+.camera-container {
|
|
|
+ display: flex;
|
|
|
+ gap: 2px;
|
|
|
+ ::v-deep(.el-select) {
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ .el-input__inner {
|
|
|
+ border-radius: 0px;
|
|
|
+ font-size: 18px;
|
|
|
+ border: 0px;
|
|
|
+ color: #9bc3ff;
|
|
|
+ background: url("../assets/images/border.png") no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-color: transparent;
|
|
|
+ }
|
|
|
+ .el-input__inner::placeholder {
|
|
|
+ color: #9bc3ff;
|
|
|
+ }
|
|
|
+ .el-input .el-select__caret {
|
|
|
+ color: #9bc3ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep(.el-input.search-box-input) {
|
|
|
+ .el-input__inner {
|
|
|
+ border-radius: 0px;
|
|
|
+ font-size: 18px;
|
|
|
+ border: 1px solid #132444;
|
|
|
+ color: #9bc3ff;
|
|
|
+ background-color: transparent;
|
|
|
+ }
|
|
|
+ .el-input__inner::placeholder {
|
|
|
+ color: #6c83a7;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep(.el-button) {
|
|
|
+ border: none;
|
|
|
+ width: 120px;
|
|
|
+ height: 40px;
|
|
|
+ color: #9bc3ff;
|
|
|
+ background: url("../assets/images/border.png") no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-color: transparent;
|
|
|
+ display: flex;
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
+ display: inline-block;
|
|
|
+ background: url("../assets/images/search-box-icon.png") no-repeat;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ margin-left: 5px;
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|