Browse Source

feat: 完善调用后端,实现标签追踪展示

master
fajiao 2 years ago
parent
commit
aaff187cbf
  1. 3
      Frontend/package.json
  2. 7
      Frontend/src/api/cameraBase/cameraApi.ts
  3. 7
      Frontend/src/api/cameraMark/markGroupApi.ts
  4. 22
      Frontend/src/api/cameraMark/markLabelApi.ts
  5. 25
      Frontend/src/api/cameraMark/markSearchApi.ts
  6. 1
      Frontend/src/api/index.ts
  7. 0
      Frontend/src/api/onvif/onvif.ts
  8. 0
      Frontend/src/api/webrtcStreamer/webrtcStreamer.ts
  9. 4
      Frontend/src/utils/axios.ts
  10. 201
      Frontend/src/views/page/cameraCenter.vue

3
Frontend/package.json

@ -9,9 +9,12 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@types/qs": "^6.9.7",
"ant-design-vue": "^3.2.13", "ant-design-vue": "^3.2.13",
"axios": "^1.1.3", "axios": "^1.1.3",
"less": "^4.1.3",
"pinia": "^2.0.23", "pinia": "^2.0.23",
"qs": "^6.11.0",
"vue": "^3.2.37", "vue": "^3.2.37",
"vue-router": "^4.1.5" "vue-router": "^4.1.5"
}, },

7
Frontend/src/api/cameraBase/cameraApi.ts

@ -1,5 +1,6 @@
import {axios} from '@/utils/axios'; import {axios} from '@/utils/axios';
import {apiUrl} from "@/api"; import {apiUrl} from "@/api";
import qs from "qs";
enum Api { enum Api {
Add = '/cbCamera/add', Add = '/cbCamera/add',
@ -12,11 +13,11 @@ enum Api {
const CisApiUrl = apiUrl.CisApiUrl; const CisApiUrl = apiUrl.CisApiUrl;
export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, params) export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, qs.stringify(params))
export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, params) export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, qs.stringify(params))
export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, params) export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, qs.stringify(params))
export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params}) export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params})

7
Frontend/src/api/cameraMark/cameraGroupApi.ts → Frontend/src/api/cameraMark/markGroupApi.ts

@ -1,5 +1,6 @@
import {axios} from '@/utils/axios'; import {axios} from '@/utils/axios';
import {apiUrl} from "@/api"; import {apiUrl} from "@/api";
import qs from "qs";
enum Api { enum Api {
Add = '/cmMarkGroup/add', Add = '/cmMarkGroup/add',
@ -12,11 +13,11 @@ enum Api {
const CisApiUrl = apiUrl.CisApiUrl; const CisApiUrl = apiUrl.CisApiUrl;
export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, params) export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, qs.stringify(params))
export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, params) export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, qs.stringify(params))
export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, params) export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, qs.stringify(params))
export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params}) export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params})

22
Frontend/src/api/cameraMark/cameraLabelApi.ts → Frontend/src/api/cameraMark/markLabelApi.ts

@ -1,22 +1,26 @@
import {axios} from '@/utils/axios'; import {axios} from '@/utils/axios';
import {apiUrl} from "@/api"; import {apiUrl} from "@/api";
import qs from 'qs';
enum Api { enum Api {
Add = '/cmMarkGroup/add', Add = '/cmMarkLabel/add',
Update = '/cmMarkGroup/update', AddReturnId = '/cmMarkLabel/addReturnId',
Delete = '/cmMarkGroup/delete', Update = '/cmMarkLabel/update',
Get = '/cmMarkGroup/get', Delete = '/cmMarkLabel/delete',
GetList = '/cmMarkGroup/getList', Get = '/cmMarkLabel/get',
GetPageList = '/cmMarkGroup/getPageList', GetList = '/cmMarkLabel/getList',
GetPageList = '/cmMarkLabel/getPageList',
} }
const CisApiUrl = apiUrl.CisApiUrl; const CisApiUrl = apiUrl.CisApiUrl;
export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, params) export const Add = (params?: any) => axios.post(CisApiUrl + Api.Add, qs.stringify(params))
export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, params) export const AddReturnId = (params?: any) => axios.post(CisApiUrl + Api.AddReturnId, qs.stringify(params))
export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, params) export const Update = (params?: any) => axios.post(CisApiUrl + Api.Update, qs.stringify(params))
export const Delete = (params?: any) => axios.post(CisApiUrl + Api.Delete, qs.stringify(params))
export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params}) export const Get = (params?: any) => axios.get(CisApiUrl + Api.Get, {params: params})

25
Frontend/src/api/cameraMark/markSearchApi.ts

@ -1,22 +1,29 @@
import {axios} from '@/utils/axios'; import {axios} from '@/utils/axios';
import {apiUrl} from "@/api"; import {apiUrl} from "@/api";
import qs from 'qs';
enum Api { enum Api {
ActiveCamera = '/markSearch/activeCamera', ActivateSearcher = '/markSearch/activateSearcher',
DeActiveCamera = '/markSearch/deActiveCamera', DeActiveSearcher = '/markSearch/deActiveSearcher',
AddCameraMarkLabel = '/markSearch/addCameraMarkLabel', IsExistSearcher = '/markSearch/isExistSearcher',
DeleteCameraMarkLabel = '/markSearch/deleteCameraMarkLabel', ActivateMarkLabel = '/markSearch/activateMarkLabel',
GetMarkLabelCalcResultList = '/markSearch/GetMarkLabelCalcResultList', DeactivateMarkLabel = '/markSearch/deactivateMarkLabel',
IsExistMarkLabel = '/markSearch/isExistMarkLabel',
GetMarkLabelCalcResultList = '/markSearch/getMarkLabelCalcResultList',
} }
const CisApiUrl = apiUrl.CisApiUrl; const CisApiUrl = apiUrl.CisApiUrl;
export const ActiveCamera = (params?: any) => axios.post(CisApiUrl + Api.ActiveCamera, params) export const ActiveSearcher = (params?: any) => axios.post(CisApiUrl + Api.ActivateSearcher, qs.stringify(params))
export const DeActiveCamera = (params?: any) => axios.post(CisApiUrl + Api.DeActiveCamera, params) export const DeActiveSearcher = (params?: any) => axios.post(CisApiUrl + Api.DeActiveSearcher, qs.stringify(params))
export const AddCameraMarkLabel = (params?: any) => axios.post(CisApiUrl + Api.AddCameraMarkLabel, params) export const IsExistSearcher = (params?: any) => axios.get(CisApiUrl + Api.IsExistSearcher, {params: params})
export const DeleteCameraMarkLabel = (params?: any) => axios.post(CisApiUrl + Api.DeleteCameraMarkLabel, params) export const ActivateMarkLabel = (params?: any) => axios.post(CisApiUrl + Api.ActivateMarkLabel, qs.stringify(params))
export const DeactivateMarkLabel = (params?: any) => axios.post(CisApiUrl + Api.DeactivateMarkLabel, qs.stringify(params))
export const IsExistMarkLabel = (params?: any) => axios.get(CisApiUrl + Api.IsExistMarkLabel, {params: params})
export const GetMarkLabelCalcResultList = (params?: any) => axios.get(CisApiUrl + Api.GetMarkLabelCalcResultList, {params: params}) export const GetMarkLabelCalcResultList = (params?: any) => axios.get(CisApiUrl + Api.GetMarkLabelCalcResultList, {params: params})

1
Frontend/src/api/index.ts

@ -1,5 +1,6 @@
export const apiUrl = { export const apiUrl = {
CisApiUrl: 'http://192.168.1.119:5000/api', CisApiUrl: 'http://192.168.1.119:5000/api',
WebRtcUrl: 'http://192.168.1.119:8000', WebRtcUrl: 'http://192.168.1.119:8000',
OnvifApiUrl: ''
// CisApiUrl: 'https://192.168.1.119:5001/api' // CisApiUrl: 'https://192.168.1.119:5001/api'
} }

0
Frontend/src/api/onvif/onvif.ts

0
Frontend/src/api/webrtcStreamer/webrtcStreamer.ts

4
Frontend/src/utils/axios.ts

@ -4,8 +4,8 @@ let apiBaseUrl = "/api";
const service = axios.create({ const service = axios.create({
baseURL: apiBaseUrl, // api base_url baseURL: apiBaseUrl, // api base_url
timeout: 9000 // 请求超时时间 timeout: 9000, // 请求超时时间
}) });
export { export {
service as axios, service as axios,

201
Frontend/src/views/page/cameraCenter.vue

@ -4,27 +4,36 @@
<a-layout-sider width="200" style="background: #fff"> <a-layout-sider width="200" style="background: #fff">
<div style="background: aqua; height: 50%"> <div style="background: aqua; height: 50%">
<a-tree <a-tree style="background: aqua;"
:tree-data="treeData" :tree-data="treeData"
@select="selectTreeNode" @select="selectTreeNode"
/> />
</div> </div>
<div style="background: bisque; height: 50%"> <div style="background: bisque; height: 50%">
<a-button @click="activateChoose">添加标签</a-button>
<a-button @click="deactivateChoose">取消添加标签</a-button>
</div> </div>
</a-layout-sider> </a-layout-sider>
<a-layout style="padding: 0 16px 16px;"> <a-layout style="padding: 4px;">
<div id="videoWrapper"> <div id="videoWrapper">
<div id="videoCanvas"> <canvas ref="videoCanvas" id="videoCanvas"
<video id="videoPlayer" autoplay muted> :width="canvasWidth" :height="canvasHeight"
:style="{width:canvasWidth+'px',height:canvasHeight+'px'}"
>
</canvas>
<video ref="videoPlayer" id="videoPlayer" style="height: 100%;width: 100%" autoplay muted
@loadedmetadata="changeVideoCanvasSize"
@mouseover="mouseOverVideo"
@mouseout="mouseOutVideo"
@mousedown="mouseDownVideo"
>
</video> </video>
</div> </div>
</div>
</a-layout> </a-layout>
@ -35,36 +44,41 @@
import {defineComponent, ref} from 'vue'; import {defineComponent, ref} from 'vue';
import type {TreeProps} from 'ant-design-vue'; import type {TreeProps} from 'ant-design-vue';
import * as cameraApi from '@/api/cameraBase/cameraApi'; import * as cameraApi from '@/api/cameraBase/cameraApi';
import * as markLabelApi from '@/api/cameraMark/markLabelApi';
import * as markSearchApi from '@/api/cameraMark/markSearchApi';
import {apiUrl} from "@/api"; import {apiUrl} from "@/api";
export default defineComponent({ export default defineComponent({
data() { data() {
return { return {
player: <HTMLVideoElement>document.querySelector('#videoPlayer'),
canvas: <HTMLCanvasElement>document.querySelector('#videoCanvas'),
canvasWidth: 0,
canvasHeight: 0,
curSelectKey: '', curSelectKey: '',
treeData: ref<TreeProps['treeData']>([]),
cameraMap: new Map<string, any>(), cameraMap: new Map<string, any>(),
webRtcServer: WebRtcStreamer webRtcServer: WebRtcStreamer,
isActiveChoose: false,
} }
}, },
setup() {
let treeData = ref<TreeProps['treeData']>([]);
return {
treeData,
};
},
created() { created() {
this.$nextTick(() => { this.$nextTick(() => {
this.player = <HTMLVideoElement>document.querySelector('#videoPlayer');
this.canvas = <HTMLCanvasElement>document.querySelector('#videoCanvas');
this.loadTreeData(); this.loadTreeData();
this.loadVideoPlayer(); this.loadVideoPlayer();
this.loadVideoCanvas();
}); });
}, },
methods: { methods: {
loadTreeData() { loadTreeData() {
let that: any = this;
cameraApi.GetList().then((res) => { cameraApi.GetList().then((res) => {
let list = res.data.data; let list: Array<any> = res.data.data;
for (let item of list) { for (let item of list) {
this.cameraMap.set(item.id, item); this.cameraMap.set(item.id, item);
that.treeData.push({title: item.ip, key: item.id}); this.treeData!.push({title: item.ip, key: item.id});
} }
}); });
}, },
@ -73,43 +87,170 @@ export default defineComponent({
let key = selectedKeys[0]; let key = selectedKeys[0];
if (this.curSelectKey !== key) { if (this.curSelectKey !== key) {
this.curSelectKey = key; this.curSelectKey = key;
//
setTimeout(() => {
if (this.curSelectKey === key) {
this.switchCamera(key); this.switchCamera(key);
} }
}, 1000);
}
}, },
loadVideoPlayer() { loadVideoPlayer() {
let elmId = 'videoPlayer'; let elmId = 'videoPlayer';
let url = apiUrl.WebRtcUrl; let url = apiUrl.WebRtcUrl;
this.webRtcServer = new WebRtcStreamer(elmId, url); this.webRtcServer = new WebRtcStreamer(elmId, url);
document.querySelector('#videoPlayer').addEventListener('loadmetadata',function (){ },
console.log("============================================================"); loadVideoCanvas() {
console.log(this); window.addEventListener('resize', () => {
console.log("============================================================"); this.changeVideoCanvasSize();
});
},
changeVideoCanvasSize() {
this.canvasWidth = this.player.clientWidth;
this.canvasHeight = this.player.clientHeight;
},
mouseOverVideo() {
if (!this.isActiveChoose) return;
this.player.classList.add('activeChoose');
},
mouseOutVideo() {
if (!this.isActiveChoose) return;
this.player.classList.remove('activeChoose');
},
mouseDownVideo(e: MouseEvent) {
if (!this.isActiveChoose) return;
let cameraId = this.cameraMap.get(this.curSelectKey).id;
let name = 'markLabel-' + Date.now();
let videoWidth = this.player.videoWidth | 1920;
let videoHeight = this.player.videoHeight | 1080;
let canvasWidth = this.player.clientWidth;
let canvasHeight = this.player.clientHeight;
let canvasLeft = e.offsetX;
let canvasTop = e.offsetY;
let canvasLeftRatio = canvasLeft / canvasWidth;
let canvasTopRatio = canvasTop / canvasHeight;
let entity = {
CbCameraId: cameraId,
Name: name,
VideoWidth: videoWidth,
VideoHeight: videoHeight,
CanvasLeftRatio: canvasLeftRatio,
CanvasTopRatio: canvasTopRatio
}
console.log(entity);
markLabelApi.AddReturnId({
'entity': entity
}).then((res) => {
let markLabelId: number = res.data.data;
if (markLabelId <= 0) return;
markSearchApi.ActivateMarkLabel({
'cameraId': cameraId,
'markLabelId': markLabelId
}).then((res) => {
let ret: boolean = res.data.data;
}); });
})
},
activateChoose() {
if (this.curSelectKey.length == 0) return;
this.isActiveChoose = true;
},
deactivateChoose() {
if (this.curSelectKey.length == 0) return;
this.isActiveChoose = false;
}, },
switchCamera(cameraId: string) { switchCamera(cameraId: string) {
console.log('camera switch.'); console.log('camera switch.');
let cameraObj = this.cameraMap.get(cameraId);
// step1, get camera obj. // step1, get camera obj.
if (cameraObj == null) { console.log('get camera obj.');
console.log('camera not found.'); let cameraObj = this.cameraMap.get(cameraId);
if (!cameraObj) {
console.log('camera obj not found.');
return; return;
} }
// object to proxy, ?
console.log(cameraObj,);
// step2, get camera rtsp url. // step2, get camera rtsp url.
console.log('get camera rtsp url.');
let rtspUrl = this.getRtspUrl(cameraObj); let rtspUrl = this.getRtspUrl(cameraObj);
// step3, connect webrtc-steamer. // step3, connect webrtc-steamer.
console.log('connect webrtc-steamer.');
this.webRtcServer.disconnect(); this.webRtcServer.disconnect();
this.webRtcServer.connect(rtspUrl); this.webRtcServer.connect(rtspUrl);
// step4, active camera searcher.
markSearchApi.IsExistSearcher({
'cameraId': cameraObj.id
}).then((res) => {
let flag: boolean = res.data.data;
if (!flag) {
console.log('not exist searcher.');
markSearchApi.ActiveSearcher({
'cameraId': cameraObj.id
}).then((res) => {
let flag: boolean = res.data.data;
console.log('activate searcher : ', flag);
if (flag) {
console.log('load camera labels');
this.loadMarkLabelsByLoop(cameraObj);
}
});
} else {
console.log('load camera labels');
this.loadMarkLabelsByLoop(cameraObj);
}
})
// step5, load camera labels.
}, },
getRtspUrl(cameraObj: any): string { getRtspUrl(cameraObj: any): string {
return "rtsp://admin:hk123456@192.168.1.65:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1" // onvif
return "rtsp://admin:hk123456@192.168.1.65:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_1";
},
loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
if (this.curSelectKey !== cameraObj.id) {
console.log('load camera labels end.');
return;
} }
this.loadMarkLabels(cameraObj);
setTimeout(() => {
this.loadMarkLabelsByLoop(cameraObj, ms);
}, ms);
}, },
beforeDestroy() { loadMarkLabels(cameraObj: any) {
markSearchApi.GetMarkLabelCalcResultList({
'cameraId': cameraObj.id
}).then((res) => {
let list: Array<any> = res.data.data;
this.drawMarkLabels(list);
});
},
drawMarkLabels(markLabels: Array<any>) {
let ctx = this.canvas.getContext('2d');
if (!ctx) return;
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
for (let markLabel of markLabels) {
if (!markLabel.inFlag) continue;
let x = Math.round(this.canvasWidth * markLabel.canvasLeftRatio);
let y = Math.round(this.canvasHeight * markLabel.canvasTopRatio);
x = this.canvasWidth * markLabel.canvasLeftRatio;
y = this.canvasHeight * markLabel.canvasTopRatio;
console.log(markLabel);
ctx.beginPath();
ctx.arc(x, y, 5, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
}
},
},
beforeUnmount() {
console.log('beforeUnmount.');
// webRtcServer // webRtcServer
if (this.webRtcServer === null) return; if (!this.webRtcServer) return;
this.webRtcServer.disconnect(); this.webRtcServer.disconnect();
this.webRtcServer = null; this.webRtcServer = null;
} }
@ -117,5 +258,13 @@ export default defineComponent({
</script> </script>
<style> <style>
.activeChoose {
cursor: pointer;
}
#videoCanvas {
position: absolute;
width: 100%;
height: 100%;
}
</style> </style>
Loading…
Cancel
Save