shuishen
2023-02-08 8afb1cbbeeccc488b43d33da8ca83f4e3ff1f2b4
视频监控树结构更改,地图添加影像服务
4 files modified
381 ■■■■■ changed files
src/api/video/index.js 15 ●●●● patch | view | raw | blame | history
src/components/map/index.vue 57 ●●●● patch | view | raw | blame | history
src/styles/media/index.scss 11 ●●●● patch | view | raw | blame | history
src/views/video/list.vue 298 ●●●●● patch | view | raw | blame | history
src/api/video/index.js
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-11-15 15:10:41
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-01-11 11:29:09
 * @LastEditTime: 2023-02-08 10:11:23
 * @FilePath: \srs-police-affairs\src\api\video\index.js
 * @Description: 
 * 
@@ -145,9 +145,18 @@
 */
export const getTreeDevices = (params) => {
    return request({
        url: '/device/query/tree/36110000002009999000',
        url: '/api/deviceChannel/deviceChannel/lazy-tree',
        method: 'get',
        requestBaseUrl: 'outside',
        params: {
            ...params
        }
    })
}
export const getSearchTreeDevices = (params) => {
    return request({
        url: '/api/deviceChannel/deviceChannel/tree',
        method: 'get',
        params: {
            ...params
        }
src/components/map/index.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 17:00:30
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-02-07 18:01:22
 * @LastEditTime: 2023-02-08 16:49:29
 * @FilePath: \srs-police-affairs\src\components\map\index.vue
 * @Description: 公用地图组件
 * 
@@ -186,38 +186,41 @@
            // 上饶部署,内网使用的
            // global.viewer.imageryLayers.addImageryProvider(
            //     new global.DC.Namespace.Cesium.WebMapTileServiceImageryProvider({
            //         url: "http://10.141.11.11:8090/MapTileService/wmts?STORETYPE=merged-dat&PROJECTION=4326",
            //         layer: "wmts_4326_361100",
            //         style: "default",
            //         format: "image/png",
            //         tileMatrixSetID: "c",
            //         tileMatrixLabels: new Array(18).fill(0).map((v, i) => i + 1),
            //         tilingScheme: new global.DC.Namespace.Cesium.GeographicTilingScheme(),
            //     })
            // )
            var gridsetName = 'EPSG:4490_test'
            var gridNames = ['EPSG:4490_test:0', 'EPSG:4490_test:1', 'EPSG:4490_test:2', 'EPSG:4490_test:3', 'EPSG:4490_test:4', 'EPSG:4490_test:5', 'EPSG:4490_test:6', 'EPSG:4490_test:7', 'EPSG:4490_test:8', 'EPSG:4490_test:9', 'EPSG:4490_test:10', 'EPSG:4490_test:11', 'EPSG:4490_test:12', 'EPSG:4490_test:13', 'EPSG:4490_test:14', 'EPSG:4490_test:15', 'EPSG:4490_test:16', 'EPSG:4490_test:17', 'EPSG:4490_test:18', 'EPSG:4490_test:19', 'EPSG:4490_test:20', 'EPSG:4490_test:21', 'EPSG:4490_test:22']
            // 影像图层
            global.viewer.imageryLayers.addImageryProvider(
                new global.DC.Namespace.Cesium.WebMapTileServiceImageryProvider({
                    url: "http://10.141.11.12:18088/geoserver/gwc/service/wmts",
                    layer: "test",
                    style: "",
                    url: "http://10.141.11.11:8090/MapTileService/wmts?STORETYPE=merged-dat&PROJECTION=4326",
                    layer: "wmts_4326_361100",
                    style: "default",
                    format: "image/png",
                    tileMatrixSetID: gridsetName,
                    tileMatrixLabels: gridNames.map(item => {
                        let arr = item.split(':')
                        arr[2] = arr[2] - 1
                        return arr.join(':')
                    }),
                    // tilingScheme: new global.DC.Namespace.Cesium.GeographicTilingScheme(),
                    tileMatrixSetID: "c",
                    tileMatrixLabels: new Array(18).fill(0).map((v, i) => i + 1),
                    tilingScheme: new global.DC.Namespace.Cesium.GeographicTilingScheme(),
                })
            )
            global.viewer.imageryLayers.addImageryProvider(
                new global.DC.Namespace.Cesium.UrlTemplateImageryProvider({
                    url: 'http://10.141.11.11:80/ysapi/geoserver/gwc/service/wmts/{z}/{y}/{x}.png',
                })
            )
            // 影像图层
            // const ysWmts = global.viewer.imageryLayers.addImageryProvider(
            //     new global.DC.Namespace.Cesium.WebMapTileServiceImageryProvider({
            //         url: "http://10.141.11.11:80/ysapi/geoserver/gwc/service/wmts",
            //         layer: "test",
            //         style: "",
            //         format: "image/png",
            //         tileMatrixSetID: gridsetName,
            //         tileMatrixLabels: gridNames.map(item => {
            //             let arr = item.split(':')
            //             arr[2] = arr[2] - 1
            //             return arr.join(':')
            //         }),
            //         // tilingScheme: new global.DC.Namespace.Cesium.GeographicTilingScheme(),
            //     })
            // )
            // 设置地图初始位置,角度等
            global.viewer.camera.setView({
                // Cesium的坐标是以地心为原点,一向指向南美洲,一向指向亚洲,一向指向北极州
src/styles/media/index.scss
@@ -1081,9 +1081,9 @@
                                height: countSizeVh(52);
                                input {
                                    font-size: countSizeVh(18);
                                    height: countSizeVh(32);
                                    font-size: countSizeVh(16);
                                    border: countSizeVh(1) solid rgb(0, 92, 169);
                                    border-radius: countSizeVh(20) 0 0 countSizeVw(20, 1920);
                                }
                                button {
@@ -2649,7 +2649,7 @@
        .date-day-style.el-picker-panel {
            width: countSizeVw(536, 1920) !important;
        }
        .el-date-range-picker__header div {
@@ -2691,11 +2691,12 @@
            margin-left: countSizeVw(110, 1920);
            display: flex;
        }
        .el-picker-panel__body {
            display: flex;
        }
        .el-date-table .disabled div{
        .el-date-table .disabled div {
            background-color: $sub-tab-border-color;
        }
src/views/video/list.vue
@@ -2,7 +2,7 @@
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2022-08-18 16:18:17
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-01-12 17:08:15
 * @LastEditTime: 2023-02-08 11:21:57
 * @FilePath: \srs-police-affairs\src\views\video\list.vue
 * @Description: 辖区管理
 * 
@@ -14,13 +14,7 @@
        <div v-show="boxShow" class="container-content">
            <div class="search-box">
                点位名称:
                <input
                    v-model="searchValue"
                    @input="searchChange"
                    type="text"
                    placeholder="请输入搜索条件"
                />
                <button @click="searchClick" class="el-icon-search"></button>
                <input v-model="searchValue" @input="searchChange" type="text" placeholder="请输入搜索条件" />
            </div>
            <div class="draw-btn">
@@ -37,79 +31,49 @@
                <button @click="changeRange" class="btn">确定</button>
            </div>
            <div v-show="searchValBoxShow" class="search-val-box">
                <div
                    @click="searchVlaClick(item)"
                    v-for="(item, index) in searchArray"
                    :key="index"
                >{{ item.name }}</div>
                <div @click="searchVlaClick(item)" v-for="(item, index) in searchArray" :key="index">{{ item.name }}
                </div>
            </div>
            <div class="down-tree">
                <el-scrollbar>
                    <el-tree :props="props" :load="loadNode" lazy @node-click="treeClick"></el-tree>
                    <el-tree v-show="searchLazyFlag" :props="props" :load="loadNode" lazy
                        @node-click="treeClick"></el-tree>
                    <el-tree v-show="searchLazyFlag == false" :data="searchTreeData" :props="defaultProps"
                        :default-expand-all="true" @node-click="treeClick"></el-tree>
                </el-scrollbar>
            </div>
            <div class="list-show" v-if="false">
                <div class="car-list">
                    <div class="list-box">
                        <el-table
                            :data="monitoringList"
                            style="width: 100%"
                        <el-table :data="monitoringList" style="width: 100%"
                            :header-cell-style="{ 'text-align': 'center', 'background-color': 'rgba(9, 40, 199, 0.5)', 'borderColor': '#324e75' }"
                            :cell-style="{ 'text-align': 'center', 'borderColor': '#324e75' }"
                            @cell-click="rowClick"
                        >
                            <el-table-column
                                :show-overflow-tooltip="true"
                                prop="name"
                                label="点位名称"
                                min-width="35%"
                            ></el-table-column>
                            <el-table-column
                                :show-overflow-tooltip="true"
                                prop="pTZTypeText"
                                label="点位类型"
                                min-width="35%"
                            ></el-table-column>
                            <el-table-column
                                :show-overflow-tooltip="true"
                                prop="status"
                                label="状态"
                                min-width="30%"
                            >
                            :cell-style="{ 'text-align': 'center', 'borderColor': '#324e75' }" @cell-click="rowClick">
                            <el-table-column :show-overflow-tooltip="true" prop="name" label="点位名称"
                                min-width="35%"></el-table-column>
                            <el-table-column :show-overflow-tooltip="true" prop="pTZTypeText" label="点位类型"
                                min-width="35%"></el-table-column>
                            <el-table-column :show-overflow-tooltip="true" prop="status" label="状态" min-width="30%">
                                <template slot-scope="scope">
                                    <div
                                        class="state-box"
                                        :class="{ online: scope.row.status == '1' }"
                                    ></div>
                                    <div class="state-box" :class="{ online: scope.row.status == '1' }"></div>
                                </template>
                            </el-table-column>
                        </el-table>
                    </div>
                    <div class="pages">
                        <el-pagination
                            background
                            layout="prev, pager, next"
                            :page-size="pagesize"
                            :page-count="pagesCount"
                            :current-page="currentPage"
                            pager-count="5"
                            @current-change="handleCurrentChange"
                        ></el-pagination>
                        <el-pagination background layout="prev, pager, next" :page-size="pagesize"
                            :page-count="pagesCount" :current-page="currentPage" pager-count="5"
                            @current-change="handleCurrentChange"></el-pagination>
                    </div>
                </div>
            </div>
        </div>
        <div class="search-content">
            <input
                v-model="searchExtensivelyValue"
                @input="searchExtensivelyChange"
                @focus="searchExtensivelyFocus"
                type="text"
                placeholder="请输入搜索条件"
            />
            <input v-model="searchExtensivelyValue" @input="searchExtensivelyChange" @focus="searchExtensivelyFocus"
                type="text" placeholder="请输入搜索条件" />
            <div class="clear" v-show="isShowClearBtn" @click="clearSearchValue" title="清空">
                <img src="../../../public/img/icon/clear.png" alt />
            </div>
@@ -117,39 +81,17 @@
        </div>
        <div v-show="searchExtensivelyValBoxShow" class="searchExtensively-val-box">
            <div>
                <div
                    @click="searchExtensivelyVlaClick(item)"
                    v-for="(item, index) in searchExtensivelyArray"
                    :key="index"
                >{{ item.name }}</div>
                <div @click="searchExtensivelyVlaClick(item)" v-for="(item, index) in searchExtensivelyArray"
                    :key="index">{{ item.name }}</div>
            </div>
        </div>
        <el-dialog
            :title="dialogTitle"
            :modal="false"
            :visible.sync="dialogVisible"
            :before-close="dialogBeforeClose"
            :close-on-click-modal="true"
            class="car-video-box"
        >
            <video
                id="videoElement"
                autoplay
                controls
                width="100%"
                height="100%"
                style="object-fit: fill"
            ></video>
        <el-dialog :title="dialogTitle" :modal="false" :visible.sync="dialogVisible" :before-close="dialogBeforeClose"
            :close-on-click-modal="true" class="car-video-box">
            <video id="videoElement" autoplay controls width="100%" height="100%" style="object-fit: fill"></video>
        </el-dialog>
        <el-dialog
            :title="drawDialogTitle"
            :modal="false"
            :visible.sync="drawDialogVisible"
            :before-close="drawDialogBeforeClose"
            :close-on-click-modal="true"
            class="video-draw-box"
        >
        <el-dialog :title="drawDialogTitle" :modal="false" :visible.sync="drawDialogVisible"
            :before-close="drawDialogBeforeClose" :close-on-click-modal="true" class="video-draw-box">
            <input type="text" v-model="drawName" placeholder="请输入绘制线或面的名称" />
            <button @click="saveDrawInfo">保存</button>
        </el-dialog>
@@ -159,13 +101,15 @@
<script>
import EntityDraw from "@/utils/EntityDraw.js"
import { listQuery, accurateSearch } from "@/utils/search.js"
import { getVideoList, getDevices, getRegionList, insertRegionSaveList, getTreeDevices } from '@/api/video/index.js'
import { getVideoList, getDevices, getRegionList, insertRegionSaveList, getTreeDevices, getSearchTreeDevices } from '@/api/video/index.js'
import { getSearchExtensively } from '@/api/dept/index.js'
import flvjs from 'flv.js'
let graphicLayer = null
export default {
    inject: ['userInfo'],
    data () {
        return {
            currentPage: 1,
@@ -195,12 +139,16 @@
            props: {
                label: 'name',
                children: 'zones',
                isLeaf: (data, node) => {
                    if (data.parent == false) {
                        return true
                    }
                }
                isLeaf: 'leaf'
            },
            defaultProps: {
                children: "children", //代表children为子级
                label: "name", //根据name渲染tree列表
            },
            searchLazyFlag: true,
            searchTreeData: []
        }
    },
@@ -325,31 +273,21 @@
            this.drawName = ''
        },
        searchChange () {
            if (this.searchValue == '') {
                this.searchValBoxShow = false
                this.searchArray = []
                this.getVideoList(this.currentPage, this.pagesize, this.searchValue)
                this.$message({
                    message: '请输入搜索内容',
                    type: 'warning'
                })
            } else {
                this.searchArray = listQuery(this.monitoringSaveList, this.searchValue, 'name')
                this.searchValBoxShow = true
                this.getVideoList(this.currentPage, this.pagesize, this.searchValue)
            }
        },
        searchChange (e) {
            if (e.target.value.trim() != '') {
                this.searchLazyFlag = false
        searchClick () {
            if (this.searchValue != '') {
                this.searchValBoxShow = false
                this.getVideoList(this.currentPage, this.pagesize, this.searchValue)
            } else {
                this.$message({
                    message: '请输入搜索内容',
                    type: 'warning'
                this.searchTreeData = []
                getSearchTreeDevices({
                    deviceId: '36110000002009999000',
                    parentId: '361102',
                    deptId: this.userInfo.dept_id,
                    name: this.searchValue.trim()
                }).then(res => {
                    this.searchTreeData = res.data.data
                })
            } else {
                this.searchLazyFlag = true
            }
        },
@@ -592,62 +530,71 @@
        },
        async loadNode (node, resolve) {
            if (node.level === 0) {
                return resolve([{ name: '信州分局' }])
            let type = Number(node.level) + 1
            let data = null
            let parentId = null
            if (type == 1 || type == 2) {
                parentId = 361102
            } else {
                parentId = node.data.id
            }
            if (node.level === 1) {
                let data = []
                await getTreeDevices({ page: 1, count: 100, parentId: 361102, onlyCatalog: false }).then(res => {
                    data = res.data.data.list
                })
                return resolve(data)
            }
            if (node.level > 1) {
                let data = []
                await getTreeDevices({ page: 1, count: 100, parentId: node.data.id, onlyCatalog: false }).then(res => {
                    data = res.data.data.list
                })
                return resolve(data)
            }
            await getTreeDevices({
                deviceId: '36110000002009999000',
                parentId,
                deptId: this.userInfo.dept_id,
                type,
                sourceId: type == 4 ? '' : '36110202',
            }).then(res => {
                data = res.data.data
                data.forEach(item => item.leaf = !item.parent)
            })
            return resolve(data)
        },
        async treeClick (node) {
            if (node.parent == false) {
                console.log(node, node.name, node.id, node.basicData.channelId, node.basicData.longitude, node.basicData.latitude)
                this.$EventBus.$emit('toPosition', {
                    siteJd: node.basicData.longitude,
                    siteWd: node.basicData.latitude,
                    siteGd: 600,
                })
                this.$EventBus.$emit('mapClearLayer', {
                    layerName: 'searchLayer',
                    type: 'VectorLayer'
                })
                this.$EventBus.$emit('layerPointAdd', {
                    layerName: 'searchLayer',
                    type: 'label',
                    params: {
                        lng: node.basicData.longitude,
                        lat: node.basicData.latitude,
                        alt: 0,
                        text: node.name
                    }
                })
                this.$EventBus.$emit('layerPointAdd', {
                    layerName: 'searchLayer',
                    type: "billboard",
                    params: {
                        name: node.name,
                        lng: node.basicData.longitude,
                        lat: node.basicData.latitude,
                        alt: 100,
                        url: '/img/icon/video.png',
                        channelId: node.id
                    },
                    incident: this.siteClick
                })
            if (node.parent == true) return
            }
            this.$EventBus.$emit('toPosition', {
                siteJd: node.longitude,
                siteWd: node.latitude,
                siteGd: 600,
            })
            this.$EventBus.$emit('mapClearLayer', {
                layerName: 'searchLayer',
                type: 'VectorLayer'
            })
            this.$EventBus.$emit('layerPointAdd', {
                layerName: 'searchLayer',
                type: 'label',
                params: {
                    lng: node.longitude,
                    lat: node.latitude,
                    alt: 0,
                    text: node.name
                }
            })
            this.$EventBus.$emit('layerPointAdd', {
                layerName: 'searchLayer',
                type: "billboard",
                params: {
                    name: node.name,
                    lng: node.longitude,
                    lat: node.latitude,
                    alt: 100,
                    url: '/img/icon/video.png',
                    channelId: node.id
                },
                incident: this.siteClick
            })
        },
    },
@@ -699,14 +646,12 @@
            input {
                flex: 1;
                height: 100%;
                font-size: 18px;
                font-size: 16px;
                text-indent: 1em;
                color: #ffffff;
                background-color: rgba(24, 79, 202, 0.6);
                // border: 1px solid rgb(0, 92, 169);
                border: 1px solid rgb(24, 79, 202);
                border-radius: 20px 0 0 20px;
            }
            input:focus {
@@ -750,7 +695,7 @@
            border-radius: 10px;
            overflow-y: auto;
            & > div {
            &>div {
                height: 100%;
                padding: 0 10px;
                line-height: 36px;
@@ -824,7 +769,7 @@
        .list-show {
            flex: 1;
            & > div {
            &>div {
                height: 100%;
                display: flex;
                flex-direction: column;
@@ -858,12 +803,15 @@
        }
        .down-tree {
            height: 100%;
            flex: 1;
            overflow: hidden;
            :deep(.el-tree-node.is-expanded > .el-tree-node__children) {
                display: inline;
            }
            :deep(.el-scrollbar) {
                height: calc(100% - 80px);
                height: 100%;
            }
        }
    }
@@ -944,7 +892,7 @@
        border-radius: 10px;
        overflow: hidden;
        & > div {
        &>div {
            height: 100%;
            overflow-y: auto;