Browse Source

添加标签删除、编辑功能

master
chendingwei 2 years ago
parent
commit
62ff5a6f6e
  1. 1
      components.d.ts
  2. 97
      src/utils/popup.ts
  3. 82
      src/views/page/Aside/cameraRightMenu.vue
  4. 22
      src/views/page/aside/cameraLeftMenu.vue
  5. 185
      src/views/page/cameraCenter.vue

1
components.d.ts

@ -11,6 +11,7 @@ declare module '@vue/runtime-core' {
AMenu: typeof import('ant-design-vue/es')['Menu'] AMenu: typeof import('ant-design-vue/es')['Menu']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
ATree: typeof import('ant-design-vue/es')['Tree'] ATree: typeof import('ant-design-vue/es')['Tree']
Model: typeof import('./src/components/model.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }

97
src/utils/popup.ts

@ -0,0 +1,97 @@
import { Button, notification } from "ant-design-vue";
import { CloseSquareTwoTone } from "@ant-design/icons-vue";
import { h, VNode } from "vue";
/**
* Notification
* @param {string} title
* @param {string} content
* @param {string} id
* @param {number} duration
* @param {string} btnAText 1
* @param {string} btnBText 2
* @param {Event} btnAEvent 1
* @param {Event} btnBEvent 2
*/
export default function popup(
title = "标题",
content: VNode[] | string = "请输入内容",
id = "",
duration = 0,
btnAText = "", btnBText = "",
btnAEvent = () => {/* do nothing.*/ },
btnBEvent = () => {/* do nothing.*/ }
): void {
const key = id === "" ? `id-${Date.now()}` : id;
notification.open({
key,
duration: duration,
message: h(
"h2",
{
style: { color: "#fff",
textAlign: "center"
},
},
title
),
description: h(
"div",
{
style: { color: "#fff" },
},
content
),
placement: 'topLeft',
style: {
width: "540px",
// height: "600px",
// marginLeft: `-200px`,
/**rightmacWindows
*/
top: "50%",
left: `50%`,
transform: 'translate(-50%,-50%)',
backgroundColor: "rgba(0 ,64 ,64 , 0.8)",
userSelect: "none",
//boxShadow: "inset 0 0 15px 4px #56ffff",
// boxShadow: "inset 0 0 4px 2px #56ffff",
borderRadius:"5px",
border:"2px solid #56ffff88",
color: "white",
position: 'fixed',
},
btn: h("div", null, [
btnAText == "" ? null : h(
Button,
{
type: "primary",
size: "small",
danger: true,
onClick: btnAEvent,
},
btnAText
),
btnBText == "" ? null : h(
Button,
{
type: "primary",
size: "small",
style: {
marginLeft: "7px",
},
danger: true,
onClick: btnBEvent,
},
btnBText
),
]),
closeIcon: h(CloseSquareTwoTone, {
style: {
display:"none"
},
}) ,
onClose: () => {
notification.close(key);
},
});
}

82
src/views/page/Aside/cameraRightMenu.vue

@ -0,0 +1,82 @@
<template>
<div class="buttomList">
<div class="buttomItem">
<div class="buttomName">标签标志</div>
</div>
<div class="buttomItem">
<div class="buttomName">截图</div>
</div>
<div class="buttomItem">
<div class="buttomName">录像</div>
</div>
<div class="buttomItem">
<div class="buttomName">3D缩放</div>
</div>
<div class="buttomItem">
<div class="buttomName">设备标记</div>
</div>
<div class="buttomItem">
<div class="buttomName">工具箱</div>
</div>
</div>
</template>
<script setup lang='ts'>
</script>
<style scoped lang='less'>
.buttomList {
position: absolute;
right: 1%;
top: 15%;
width: 80px;
}
@keyframes rounte {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.buttomItem {
position: relative;
width: 80px;
height: 80px;
}
.buttomItem::before {
content: '';
background: url(@/assets/images/buttonBG01.png);
background-size: 100% 100%;
position: absolute;
animation: rounte 5s linear infinite;
top: 5%;
bottom: 5%;
left: 5%;
right: 5%;
z-index: 1;
}
.buttomItem:hover::before {
background: url(@/assets/images/buttonBG02.png);
background-size: 100% 100%;
}
.buttomName {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #fff;
line-height: 3vw;
width: 100%;
z-index: 2;
font-size: 0.8em;
}
</style>

22
src/views/page/aside/cameraLeftMenu.vue

@ -18,8 +18,9 @@
<span>{{ title }}</span> <span>{{ title }}</span>
<template #overlay> <template #overlay>
<a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey)"> <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey)">
<a-menu-item key="1">打开</a-menu-item> <a-menu-item key="open">打开</a-menu-item>
<a-menu-item key="2">删除</a-menu-item> <a-menu-item key="close" >关闭</a-menu-item>
<a-menu-item key="delete">删除</a-menu-item>
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
@ -53,6 +54,20 @@ const treeData = ref<any>([
]); ]);
const onContextMenuClick = (treeKey: string, menuKey: string) => { const onContextMenuClick = (treeKey: string, menuKey: string) => {
console.log(`treeKey: ${treeKey}, menuKey: ${menuKey}`); console.log(`treeKey: ${treeKey}, menuKey: ${menuKey}`);
//key
if(menuKey=="open"){
let arr=[...expandedKeys.value]
arr.push(treeKey)
arr=[...new Set(arr)]
expandedKeys.value=arr
}else if(menuKey=="close"){
expandedKeys.value=expandedKeys.value.filter((item:any)=>{
return item != treeKey
})
}else if(menuKey=="delete"){
}
}; };
let searchStr = ref(''); let searchStr = ref('');
const expandedKeys = ref<any[]>([]); const expandedKeys = ref<any[]>([]);
@ -60,6 +75,7 @@ const expandedKeys = ref<any[]>([]);
onMounted(() => { onMounted(() => {
loadTreeData() loadTreeData()
}) })
//
watch(searchStr, (newVal, oldVal) => { watch(searchStr, (newVal, oldVal) => {
let expandedKeyArr: any[] = [] let expandedKeyArr: any[] = []
if (newVal.length == 0) return if (newVal.length == 0) return
@ -74,11 +90,13 @@ watch(searchStr, (newVal, oldVal) => {
}); });
expandedKeys.value = expandedKeyArr expandedKeys.value = expandedKeyArr
}) })
//
function selectCamera(e: any) { function selectCamera(e: any) {
if (e.length && !isNaN(parseInt(e[0]))) { if (e.length && !isNaN(parseInt(e[0]))) {
piniaStore.updateCurSelectKey(e[0].toString()) piniaStore.updateCurSelectKey(e[0].toString())
} }
} }
//
function searchFn(newVal: string, arr: any[]): any { function searchFn(newVal: string, arr: any[]): any {
let expandedKeyArr: any[] = [] let expandedKeyArr: any[] = []
arr.forEach(element => { arr.forEach(element => {

185
src/views/page/cameraCenter.vue

@ -9,54 +9,50 @@
</video> </video>
<div v-for="item in labelList" class="labels" :key="item.id" <div v-for="item in labelList" class="labels" :key="item.id"
:style="`top:${canvasHeight * item.canvasTopRatio}px;left:${canvasWidth * item.canvasLeftRatio}px`"> :style="`top:${canvasHeight * item.canvasTopRatio}px;left:${canvasWidth * item.canvasLeftRatio}px`">
<div class="labels-item" @click="test(item.id)" @contextmenu.prevent="mouseRightFn"> <a-dropdown :trigger="['contextmenu']">
<!-- <div class="labels-item" v-if="item.inFlag"> --> <div class="labels-item">
<img src="@/assets/images/dialog.png" width="80" height="50" alt=""> <!-- <div class="labels-item" v-if="item.inFlag"> -->
<span>{{ item.name }}</span> <img src="@/assets/images/dialog.png" alt="">
</div> <span>{{ item.name }}</span>
</div>
<template #overlay>
<a-menu @click="({ key: menuKey }) => onContextMenuClick(item.id, menuKey)">
<a-menu-item key="edit">编辑</a-menu-item>
<a-menu-item key="delete">删除</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div> </div>
<div class="labels" v-if="addLabel.isAddLabel" <div class="labels" v-if="addLabel.isAddLabel"
:style="`position: fixed;transform: translate(-50%,-100%);top:${addLabelTop}px;left:${addLabelLeft}px`"> :style="`position: fixed;transform: translate(-50%,-100%);top:${addLabelTop}px;left:${addLabelLeft}px`">
<div class="labels-item"> <div class="labels-item">
<img src="@/assets/images/dialog.png" width="80" height="50" alt=""> <img src="@/assets/images/dialog.png" width="80" height="50" alt="">
<span>1</span> <span>1</span>
</div> </div>
</div> </div>
<div class="buttomList">
<div class="buttomItem">
<div class="buttomName">标签标志</div>
</div>
<div class="buttomItem">
<div class="buttomName">截图</div>
</div>
<div class="buttomItem">
<div class="buttomName">录像</div>
</div>
<div class="buttomItem">
<div class="buttomName">3D缩放</div>
</div>
<div class="buttomItem">
<div class="buttomName">设备标记</div>
</div>
<div class="buttomItem">
<div class="buttomName">工具箱</div>
</div>
</div>
<CameraLeftMenu></CameraLeftMenu> <CameraLeftMenu></CameraLeftMenu>
<CameraRightMenu></CameraRightMenu>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
////@ts-nocheck ////@ts-nocheck
import { ref, h, onMounted, getCurrentInstance, ComponentInternalInstance, onUnmounted, watch } from "vue"; import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { ref, h, onMounted, getCurrentInstance, ComponentInternalInstance, onUnmounted, watch, createVNode } from "vue";
import * as markLabelApi from '@/axios/cameraMark/markLabelApi'; import * as markLabelApi from '@/axios/cameraMark/markLabelApi';
import * as markSearchApi from '@/axios/core/markSearchApi'; import * as markSearchApi from '@/axios/core/markSearchApi';
import { useStore } from '@/store/index'; import { useStore } from '@/store/index';
import { apiUrl } from "@/axios"; import { apiUrl } from "@/axios";
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import Msg from "@/utils/message"; import Msg from "@/utils/message";
import * as cameraApi from '@/axios/cameraBase/cameraApi'; import CameraLeftMenu from '@/views/page/Aside/cameraLeftMenu.vue'
import CameraLeftMenu from '@/views/page/aside/cameraLeftMenu.vue' import CameraRightMenu from '@/views/page/Aside/cameraRightMenu.vue'
import { Modal } from 'ant-design-vue';
import popup from "@/utils/popup";
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
let piniaStore = useStore(); let piniaStore = useStore();
let player = <HTMLVideoElement>document.querySelector('#videoPlayer') let player = <HTMLVideoElement>document.querySelector('#videoPlayer')
@ -85,6 +81,7 @@ onMounted(() => {
watch(curSelectKey, (newVal, oldVal) => { watch(curSelectKey, (newVal, oldVal) => {
labelList.value=[]
switchCamera(newVal) switchCamera(newVal)
}) })
watch(addLabel, (newVal, oldVal) => { watch(addLabel, (newVal, oldVal) => {
@ -99,7 +96,7 @@ watch(addLabel, (newVal, oldVal) => {
}) })
// //
function test(id: number) { function deleteLabel(id: number) {
markLabelApi.Delete({ id }).then((res: any) => { markLabelApi.Delete({ id }).then((res: any) => {
console.log(res.data); console.log(res.data);
@ -117,10 +114,6 @@ function test(id: number) {
}) })
} }
function mouseRightFn(e: any) {
console.log(1111111111, e);
}
function loadVideoPlayer() { function loadVideoPlayer() {
let elmId = 'videoPlayer'; let elmId = 'videoPlayer';
let url = apiUrl.WebRtcUrl; let url = apiUrl.WebRtcUrl;
@ -131,6 +124,46 @@ function loadVideoCanvas() {
changeVideoCanvasSize(); changeVideoCanvasSize();
}); });
} }
const onContextMenuClick = (labelId: string, menuKey: string) => {
console.log(`labelId: ${labelId}, menuKey: ${menuKey}`);
//key
if (menuKey == "edit") {
popup("编辑标签", [h( "span",
{ style: { color: "black" } },
"是否确认删除该标签?")], "editLabel");
} else if (menuKey == "delete") {
Modal.confirm({
zIndex: 10000,
title: () => "警示",
icon: () => createVNode(ExclamationCircleOutlined),
content: () =>
h(
"span",
{ style: { color: "black" } },
"是否确认删除该标签?"
),
okText:
// () => h('span', { style: { color: 'black' } }, ''),
"确定",
// okType: 'primary',
cancelText: () => "取消",
cancelButtonProps: {
type: "default",
danger: true,
},
okButtonProps: {
type: "primary",
danger: true,
},
onOk() {
deleteLabel(parseInt(labelId))
},
style: "top: 250px",
});
}
};
function changeVideoCanvasSize() { function changeVideoCanvasSize() {
canvasWidth.value = player.clientWidth; canvasWidth.value = player.clientWidth;
canvasHeight.value = player.clientHeight; canvasHeight.value = player.clientHeight;
@ -203,22 +236,15 @@ function mouseDownVideo(e: MouseEvent) {
}); });
}) })
} }
function activateChoose() {
if (curSelectKey.value.length == 0) return;
isActiveChoose.value = true;
}
function deactivateChoose() {
if (curSelectKey.value.length == 0) return;
isActiveChoose.value = false;
}
function switchCamera(cameraId: string) { function switchCamera(cameraId: string) {
console.log('camera switch.',cameraId,typeof cameraId); console.log('camera switch.', cameraId, typeof cameraId);
// step1, get camera obj. // step1, get camera obj.
console.log('get camera obj.',cameraMap.value); console.log('get camera obj.', cameraMap.value);
let cameraObj = cameraMap.value.get(cameraId); let cameraObj = cameraMap.value.get(cameraId);
console.log(cameraObj,'cameraObj'); console.log(cameraObj, 'cameraObj');
if (!cameraObj) { if (!cameraObj) {
console.log('camera obj not found.'); console.log('camera obj not found.');
return; return;
@ -283,8 +309,9 @@ function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
return; return;
} }
loadMarkLabels(cameraObj); loadMarkLabels(cameraObj);
setTimeout(() => { let timer = setTimeout(() => {
loadMarkLabelsByLoop(cameraObj, ms); loadMarkLabelsByLoop(cameraObj, ms);
clearTimeout(timer)
}, ms); }, ms);
} }
function loadMarkLabels(cameraObj: any) { function loadMarkLabels(cameraObj: any) {
@ -371,70 +398,20 @@ onUnmounted(() => {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -55%);
}
img{
width: 150px;
height: 100px;
} }
} }
} }
.buttomList {
position: absolute;
right: 1%;
top: 15%;
width: 80px;
}
@keyframes rounte {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.buttomItem {
position: relative;
width: 80px;
height: 80px;
}
.buttomItem::before {
content: '';
background: url(@/assets/images/buttonBG01.png);
background-size: 100% 100%;
position: absolute;
animation: rounte 5s linear infinite;
top: 5%;
bottom: 5%;
left: 5%;
right: 5%;
z-index: 1;
}
.buttomItem:hover::before {
background: url(@/assets/images/buttonBG02.png);
background-size: 100% 100%;
}
.buttomName {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #fff;
line-height: 3vw;
width: 100%;
z-index: 2;
font-size: 0.8em;
}
} }
:deep(.ant-dropdown-menu-title-content) {
color: #000 !important;
}
</style> </style>

Loading…
Cancel
Save