public/apps.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/Pool/TreeData.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/area.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/panorama.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/giantTree/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/giantTree/zTree/ztree.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/gb28181/index/App.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/gb28181/index/api.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/panoramicView/components/History.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
public/apps.json
@@ -277,7 +277,6 @@ "isUpgrade": false, "progressMsg": "" }, { "id": "ee64fe23-7631-4ef9-9aca-ea09673693df", "name": "人体骨骼跟踪", @@ -332,7 +331,7 @@ "url": "/view/gb28181/", "title": "GB28181配置", "width": 1200, "height": 970, "height": 850, "iconBlob": "", "icon": "../../images/app-mid/GB-config.png", "version": "1.0.2", src/Pool/TreeData.ts
@@ -5,8 +5,10 @@ addAreaTreeData, delAreaTreeData, updateAreaTreeData, getGb28181Pool, refreshGB28181Tree, updateCameraArea updateCameraArea, getCameraBaseImage } from '@/api/area' export default class TreeDataPool { @@ -57,6 +59,11 @@ // 总摄像机个数 public gb28181ChildNodeCount: number // 国标摄像机池的底图 public cameraNameForBaseImage: string public gb28181CameraBaseImage: string public baseImageLoading: boolean constructor() { this.openeds = [true, true, false] this.activeTreeData = [] @@ -91,6 +98,10 @@ this.checkedTreeNode = [] this.gb28181CheckedCount = 0 this.gb28181ChildNodeCount = 0 this.cameraNameForBaseImage = "" this.gb28181CameraBaseImage = "" this.baseImageLoading = false } setVideoArr(index: number, value: object, vue: any): void { @@ -452,8 +463,12 @@ return arry.length } async fetchVideosvrCameras() { const rsp: any = await refreshGB28181Tree() async fetchVideosvrCameras(update: Boolean) { let fn = getGb28181Pool if (update) { fn = refreshGB28181Tree } const rsp: any = await fn() if (rsp && rsp.success) { this.selectedNode = {} @@ -503,4 +518,22 @@ return newTree } async showBaseImage(node: any) { this.baseImageLoading = true this.gb28181CameraBaseImage = "" this.cameraNameForBaseImage = node.name try { const rsp: any = await getCameraBaseImage({ id: node.id }) if (rsp && rsp.data) { this.gb28181CameraBaseImage = rsp.data } } catch (error) { console.log(error) } this.baseImageLoading = false } } src/api/area.ts
@@ -49,6 +49,21 @@ }); }; export const getCameraBaseImage = (query: any) => { return request({ url: "/data/api-v/gb28181/camera/capture", method: "get", params: query }); }; export const getGb28181Pool = () => { return request({ url: "/data/api-v/gb28181/treeSelected", method: "get" }); }; export const refreshGB28181Tree = () => { return request({ url: "/data/api-v/area/gb28181RefreshTree", src/api/panorama.ts
@@ -1,12 +1,18 @@ import request from '@/scripts/httpRequest'; import qs from 'qs' export const getPanoramaPic = ()=>request({ export const getPanoramaPic = () => request({ url: '/data/api-v/panorama/show', method: 'get' }); export const putPanoramaPic = (data:any)=>request({ url:'/data/api-v/panorama/upload', method:'post', export const putPanoramaPic = (data: any) => request({ url: '/data/api-v/panorama/upload', method: 'post', data }) export const findTraceResult = (data: any) => request({ url: '/data/api-v/panorama/findTraceResult', method: 'post', data }) src/components/giantTree/index.vue
@@ -17,6 +17,7 @@ @onImport="importCameras" @onExpand="itemExpand" @onCollapse="itemCollapse" @onShowPic="showCameraPic" /> <div class="dialog-box-bg" v-show="showDialog" @click="hideDialogBox"></div> <div @@ -323,6 +324,9 @@ dropNode(node, item, draggedItem, e) { // console.log('dropNode', node, item, draggedItem); this.TreeDataPool.dropNode(draggedItem.id, item.id) }, showCameraPic(nodeId) { this.TreeDataPool.showBaseImage(nodeId) } } }; src/components/giantTree/zTree/ztree.vue
@@ -59,6 +59,7 @@ }, onClick: (...arg) => { this.$emit("onClick", ...arg); this.removeHoverIcon(...arg); }, onCollapse: (...arg) => { this.$emit("onCollapse", ...arg); @@ -83,6 +84,7 @@ }, onMouseUp: (...arg) => { this.$emit("onMouseUp", ...arg); }, onRemove: (...arg) => { this.$emit("onRemove", ...arg); @@ -226,6 +228,27 @@ item.appendChild(btn); } // 查看底图按钮 if (item && !item.querySelector('.icontupian1') && treeNode.type == "camera") { const btn = document.createElement('i'); btn.id = `${treeid}_${treeNode.id}_btn`; btn.classList.add('iconfont'); btn.classList.add('icontupian1'); btn.classList.add('primary'); btn.classList.add('icon-fix'); // btn.innerText = '删除'; btn.addEventListener('click', (e) => { e.stopPropagation() // this.clickRemove(treeNode) _vue.$emit("onShowPic", treeNode); }) item.appendChild(btn); } }, removeHoverIcon(evt, treeId, item) { this.removeHoverDom(treeId, item); }, removeHoverDom(treeid, treeNode) { const item = document.getElementById(`${treeNode.tId}_a`); @@ -254,6 +277,11 @@ if (btn) { item.removeChild(item.querySelector('.icondaoru')) } btn = item.querySelector('.icontupian1'); if (btn) { item.removeChild(item.querySelector('.icontupian1')) } } }, } src/pages/gb28181/index/App.vue
@@ -10,106 +10,113 @@ @tab-click="hanleTabClick" > <el-tab-pane label="国标ID" name="gb28181"> <!-- GB28181设置 --> <el-form :model="gb28181" :rules="rules" label-width="130px" class="alarmSetting" ref="gb28181" > <!-- <el-form-item label="国际服务器IP" prop="ServerIp"> <div style="width: 775px"> <!-- GB28181设置 --> <el-form :model="gb28181" :rules="rules" label-width="130px" class="alarmSetting" ref="gb28181" > <!-- <el-form-item label="国际服务器IP" prop="ServerIp"> <ip-input :ip="gb28181.ServerIp" @on-blur="gb28181.ServerIp = arguments[0]"></ip-input> </el-form-item>--> </el-form-item>--> <div style="text-align: left;margin-bottom: 16px;"> <el-radio-group v-model="gb28181.idType"> <el-radio :label="0">输入已有ID</el-radio> <el-radio :label="1">生成新的ID</el-radio> </el-radio-group> </div> <div style="text-align: left;margin-bottom: 16px;"> <el-radio-group v-model="gb28181.idType"> <el-radio :label="0">输入已有ID</el-radio> <el-radio :label="1">生成新的ID</el-radio> </el-radio-group> </div> <el-form-item label="所在地"> <el-select v-model="locationCity.province" @change="changeProvince" size="small" placeholder="请选择省份" :disabled="gb28181.idType === 0" > <el-option v-for="item in locationCity.provinceOptions" :key="item.id" :label="item.name" <el-form-item label="所在地"> <el-select v-model="locationCity.province" @change="changeProvince" size="small" :value="item.id" ></el-option> </el-select> <el-select class="ml10 mr10" v-model="locationCity.city" :disabled="!locationCity.province" @change="changeCity" size="small" placeholder="请选择城市" > <el-option v-for="item in locationCity.cityOptions" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> <el-select v-model="locationCity.county" :disabled="!locationCity.city" size="small" placeholder="请选择区县" > <el-option v-for="item in locationCity.countyOptions" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> <el-button type="text" style="position: absolute" v-show="gb28181.idType === 1" @click="newGBID" >生成ID</el-button> </el-form-item> placeholder="请选择省份" :disabled="gb28181.idType === 0" > <el-option v-for="item in locationCity.provinceOptions" :key="item.id" :label="item.name" size="small" :value="item.id" ></el-option> </el-select> <el-select class="ml10 mr10" v-model="locationCity.city" :disabled="!locationCity.province" @change="changeCity" size="small" placeholder="请选择城市" > <el-option v-for="item in locationCity.cityOptions" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> <el-select v-model="locationCity.county" :disabled="!locationCity.city" size="small" placeholder="请选择区县" > <el-option v-for="item in locationCity.countyOptions" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> <el-button type="text" style="position: absolute" v-show="gb28181.idType === 1" @click="newGBID" >生成ID</el-button> </el-form-item> <!-- <el-form-item label="国际服务器端口" prop="GbServerPort"> <!-- <el-form-item label="国际服务器端口" prop="GbServerPort"> <el-input v-model.number="gb28181.ServerPort" placeholder="请输入" size="small"></el-input> </el-form-item>--> </el-form-item>--> <el-form-item label="国标ID"> <el-input v-model="gb28181.PublicId" placeholder="请输入" size="small" :disabled="gb28181.idType === 1" ></el-input> </el-form-item> <el-form-item label="国标ID"> <el-input v-model="gb28181.PublicId" placeholder="请输入" size="small" :disabled="gb28181.idType === 1" ></el-input> </el-form-item> <el-form-item label="国标端口" prop="GbServerPort"> <el-input v-model.number="gb28181.GbServerPort" placeholder="请输入" size="small"></el-input> </el-form-item> <el-form-item label="国标端口" prop="GbServerPort"> <el-input v-model.number="gb28181.GbServerPort" placeholder="请输入" size="small"></el-input> </el-form-item> <el-form-item label="开启鉴权"> <el-switch v-model="gb28181.IsAuth"></el-switch> </el-form-item> <el-form-item label="开启鉴权" style="text-align: left"> <el-switch v-model="gb28181.IsAuth"></el-switch> </el-form-item> <el-form-item label="鉴权密码" v-show="gb28181.IsAuth"> <el-input v-model="gb28181.Password" placeholder="请输入" size="small"></el-input> </el-form-item> <el-form-item label="鉴权密码"> <el-input v-model="gb28181.Password" placeholder="请输入" size="small" :disabled="!gb28181.IsAuth" ></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitGB28281" size="small">保存</el-button> </el-form-item> </el-form> <el-form-item style="float: right"> <el-button type="primary" @click="submitGB28281" size="small">保存</el-button> </el-form-item> </el-form> </div> </el-tab-pane> <el-tab-pane label="接入平台列表" name="subordinates"> @@ -128,16 +135,16 @@ <el-table-column prop="status" label="状态" align="center"> <template slot-scope="scope"> <span :style="scope.row.active ? `color:#047d19` : 'color:#f11a1a;' " >{{scope.row.active ? "在线": "离线"}}</span> :style="scope.row.alive ? `color:#047d19` : 'color:#f11a1a;' " >{{scope.row.alive ? "在线": "离线"}}</span> </template> </el-table-column> <el-table-column prop="mark" label="备注" align="center"></el-table-column> <el-table-column prop="corp" label="备注" align="center"></el-table-column> </el-table> </el-tab-pane> <el-tab-pane label="国标摄像机" name="cameras"> <div style="text-align:left"> <el-button type="primary" size="small" @click="getCamerasFromVideosvr">刷新</el-button> <el-button type="primary" size="small" @click="updateCamerasFromVideosvr">刷新</el-button> </div> <div class="camera-title"> <b>国标摄像机配置</b> @@ -150,8 +157,18 @@ :node="TreeDataPool.treeData" :height="treeHeight" :setting="treeSettings" style="width:600px;min-height:500px" /> <div class="base-image" v-loading="TreeDataPool.baseImageLoading"> <span>{{TreeDataPool.cameraNameForBaseImage}}</span> <div class="camera-image" v-show="TreeDataPool.cameraNameForBaseImage.length"> <img :src="'data:image/png;base64,' + TreeDataPool.gb28181CameraBaseImage" width="450px" alt /> </div> </div> <el-divider></el-divider> <span class="camera-seleted-text"> @@ -256,6 +273,12 @@ mounted() { this.TreeDataPool.multiple = true; // 记录目录是否折叠 let foldList = localStorage.getItem("ztree_fold_list") if (foldList) { this.TreeDataPool.foldNodeList = JSON.parse(foldList) } this.initGB28181Conf(); }, methods: { @@ -274,10 +297,17 @@ }, async getCamerasFromVideosvr() { this.loading = true; await this.TreeDataPool.fetchVideosvrCameras(); await this.TreeDataPool.fetchVideosvrCameras(false); this.loading = false; }, async updateCamerasFromVideosvr() { this.loading = true; await this.TreeDataPool.fetchVideosvrCameras(true); this.loading = false; }, saveChecked() { localStorage.setItem('ztree_fold_list', JSON.stringify(this.TreeDataPool.foldNodeList)) if (this.TreeDataPool.gb28181CheckedCount > 500) { this.$message({ type: "warning", @@ -499,5 +529,17 @@ color: #3d68e1; } } .base-image { position: absolute; top: 18%; left: 57%; width: 450px; .camera-image { background-color: black; height: 254px; } } } </style> src/pages/gb28181/index/api.ts
@@ -69,4 +69,4 @@ method: "post", data: query }); }; }; src/pages/panoramicView/components/History.vue
@@ -34,14 +34,30 @@ </div> </div> <div class="videos"> <div class="video-item" v-for="v in videoList" :key="v.name"> <video :src="'/httpImage/' + v.videoUrl" controls="controls" width="480px" height="270px"></video> <div class="video-item" v-for="v in videoList" :key="v.reid"> <video :src="'/traceFiles/' + v.reid + '.avi'" controls="controls" width="480px" height="270px" ></video> <span>{{v.date}}</span> <div class="image-preview"> <el-image :src="'/traceFiles/' + v.reid + '.jpg'" :preview-src-list="['/traceFiles/' + v.reid + '.jpg']" height="10px" ></el-image> </div> </div> </div> </div> </template> <script> import { findTraceResult } from "@/api/panorama" export default { name: "histroy", data() { @@ -142,19 +158,19 @@ }); return; } clearInterval(this.timer); //判断是否是查历史数据 if (Date.parse(this.searchTime[1]) < Date.now()) { this.filterData() } else { this.activeObjHashMap = {}; //实时查 this.searchData(); } this.searchData(); }, checkTarget(item) { this.selectedID = item.id; }, searchData() { findTraceResult({ searchTime: this.searchTime }).then(rsp => { if (rsp && rsp.success && rsp.data) { this.videoList = rsp.data; } }) } } } @@ -226,15 +242,24 @@ height: 88%; display: flex; flex-wrap: wrap; overflow: auto; .video-item { width: 500px; height: 320px; margin-left: 10px; margin-top: 10px; background-color: #fff; video { margin: 10px; } .image-preview { width: 25px; float: right; margin: 0px 10px; cursor: pointer; } } } }