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. 183
      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']
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
ATree: typeof import('ant-design-vue/es')['Tree']
Model: typeof import('./src/components/model.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
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>
<template #overlay>
<a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey)">
<a-menu-item key="1">打开</a-menu-item>
<a-menu-item key="2">删除</a-menu-item>
<a-menu-item key="open">打开</a-menu-item>
<a-menu-item key="close" >关闭</a-menu-item>
<a-menu-item key="delete">删除</a-menu-item>
</a-menu>
</template>
</a-dropdown>
@ -53,6 +54,20 @@ const treeData = ref<any>([
]);
const onContextMenuClick = (treeKey: string, menuKey: string) => {
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('');
const expandedKeys = ref<any[]>([]);
@ -60,6 +75,7 @@ const expandedKeys = ref<any[]>([]);
onMounted(() => {
loadTreeData()
})
//
watch(searchStr, (newVal, oldVal) => {
let expandedKeyArr: any[] = []
if (newVal.length == 0) return
@ -74,11 +90,13 @@ watch(searchStr, (newVal, oldVal) => {
});
expandedKeys.value = expandedKeyArr
})
//
function selectCamera(e: any) {
if (e.length && !isNaN(parseInt(e[0]))) {
piniaStore.updateCurSelectKey(e[0].toString())
}
}
//
function searchFn(newVal: string, arr: any[]): any {
let expandedKeyArr: any[] = []
arr.forEach(element => {

183
src/views/page/cameraCenter.vue

@ -9,54 +9,50 @@
</video>
<div v-for="item in labelList" class="labels" :key="item.id"
:style="`top:${canvasHeight * item.canvasTopRatio}px;left:${canvasWidth * item.canvasLeftRatio}px`">
<div class="labels-item" @click="test(item.id)" @contextmenu.prevent="mouseRightFn">
<!-- <div class="labels-item" v-if="item.inFlag"> -->
<img src="@/assets/images/dialog.png" width="80" height="50" alt="">
<span>{{ item.name }}</span>
</div>
<a-dropdown :trigger="['contextmenu']">
<div class="labels-item">
<!-- <div class="labels-item" v-if="item.inFlag"> -->
<img src="@/assets/images/dialog.png" alt="">
<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 class="labels" v-if="addLabel.isAddLabel"
:style="`position: fixed;transform: translate(-50%,-100%);top:${addLabelTop}px;left:${addLabelLeft}px`">
<div class="labels-item">
<img src="@/assets/images/dialog.png" width="80" height="50" alt="">
<span>1</span>
</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>
<CameraRightMenu></CameraRightMenu>
</div>
</template>
<script setup lang='ts'>
////@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 markSearchApi from '@/axios/core/markSearchApi';
import { useStore } from '@/store/index';
import { apiUrl } from "@/axios";
import { storeToRefs } from 'pinia';
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;
let piniaStore = useStore();
let player = <HTMLVideoElement>document.querySelector('#videoPlayer')
@ -85,6 +81,7 @@ onMounted(() => {
watch(curSelectKey, (newVal, oldVal) => {
labelList.value=[]
switchCamera(newVal)
})
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) => {
console.log(res.data);
@ -117,10 +114,6 @@ function test(id: number) {
})
}
function mouseRightFn(e: any) {
console.log(1111111111, e);
}
function loadVideoPlayer() {
let elmId = 'videoPlayer';
let url = apiUrl.WebRtcUrl;
@ -131,6 +124,46 @@ function loadVideoCanvas() {
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() {
canvasWidth.value = player.clientWidth;
canvasHeight.value = player.clientHeight;
@ -203,21 +236,14 @@ 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) {
console.log('camera switch.',cameraId,typeof cameraId);
console.log('camera switch.', cameraId, typeof cameraId);
// step1, get camera obj.
console.log('get camera obj.',cameraMap.value);
console.log('get camera obj.', cameraMap.value);
let cameraObj = cameraMap.value.get(cameraId);
console.log(cameraObj,'cameraObj');
console.log(cameraObj, 'cameraObj');
if (!cameraObj) {
console.log('camera obj not found.');
@ -283,8 +309,9 @@ function loadMarkLabelsByLoop(cameraObj: any, ms: number = 1000) {
return;
}
loadMarkLabels(cameraObj);
setTimeout(() => {
let timer = setTimeout(() => {
loadMarkLabelsByLoop(cameraObj, ms);
clearTimeout(timer)
}, ms);
}
function loadMarkLabels(cameraObj: any) {
@ -371,70 +398,20 @@ onUnmounted(() => {
position: absolute;
top: 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>

Loading…
Cancel
Save