diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/src/router/modules/alarm.ts b/src/router/modules/alarm.ts index f8109ab..908735c 100644 --- a/src/router/modules/alarm.ts +++ b/src/router/modules/alarm.ts @@ -71,7 +71,7 @@ { path: 'videoPreviewList', name: 'PolicyConfigVideoPreviewList', - component: () => import('@/views/alarm/policyConfig/videoPreview/index-media-single.vue'), + component: () => import('@/views/alarm/policyConfig/videoPreview/videoPreview.vue'), meta: { title: '视频预览', icon: 'ep:key', diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/src/router/modules/alarm.ts b/src/router/modules/alarm.ts index f8109ab..908735c 100644 --- a/src/router/modules/alarm.ts +++ b/src/router/modules/alarm.ts @@ -71,7 +71,7 @@ { path: 'videoPreviewList', name: 'PolicyConfigVideoPreviewList', - component: () => import('@/views/alarm/policyConfig/videoPreview/index-media-single.vue'), + component: () => import('@/views/alarm/policyConfig/videoPreview/videoPreview.vue'), meta: { title: '视频预览', icon: 'ep:key', diff --git a/src/utils/useCheckList.ts b/src/utils/useCheckList.ts index fb5f8ac..608bb98 100644 --- a/src/utils/useCheckList.ts +++ b/src/utils/useCheckList.ts @@ -13,7 +13,7 @@ // 检查必填 if (prop.required && !item[prop.value]) { // ElMessage.warning(`请先完善${tableTitle}第${index + 1}行中${prop.text}`) - ElMessage.warning(`请先完善${tableTitle}中【${item.typeName}】的${prop.text}`) + ElMessage.warning(`请先完善${tableTitle}中【${item.typeName || item.recognitionTypeName}】的${prop.text}`) return false } // 验证正则 diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/src/router/modules/alarm.ts b/src/router/modules/alarm.ts index f8109ab..908735c 100644 --- a/src/router/modules/alarm.ts +++ b/src/router/modules/alarm.ts @@ -71,7 +71,7 @@ { path: 'videoPreviewList', name: 'PolicyConfigVideoPreviewList', - component: () => import('@/views/alarm/policyConfig/videoPreview/index-media-single.vue'), + component: () => import('@/views/alarm/policyConfig/videoPreview/videoPreview.vue'), meta: { title: '视频预览', icon: 'ep:key', diff --git a/src/utils/useCheckList.ts b/src/utils/useCheckList.ts index fb5f8ac..608bb98 100644 --- a/src/utils/useCheckList.ts +++ b/src/utils/useCheckList.ts @@ -13,7 +13,7 @@ // 检查必填 if (prop.required && !item[prop.value]) { // ElMessage.warning(`请先完善${tableTitle}第${index + 1}行中${prop.text}`) - ElMessage.warning(`请先完善${tableTitle}中【${item.typeName}】的${prop.text}`) + ElMessage.warning(`请先完善${tableTitle}中【${item.typeName || item.recognitionTypeName}】的${prop.text}`) return false } // 验证正则 diff --git a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue index 6e72273..9346cbc 100644 --- a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue +++ b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue @@ -3,29 +3,48 @@ dialogStatus: { type: String, }, + points: { + type: Array, + default: () => [], + }, }) -const emits = defineEmits(['givePoints']) -const points = ref([ // 标记点初始 - { x: 50, y: 50 }, // 左上 - { x: 150, y: 50 }, - { x: 150, y: 150 }, - { x: 50, y: 150 }, -]) -onMounted(() => { - const canvas: any = document.getElementById('myCanvas') - const container: any = document.getElementById('draw-area') - const ctx = canvas.getContext('2d') - ctx.clearRect(0, 0, container.clientWidth, container.clientHeight) +const emits = defineEmits(['givepointsInfo']) +const baseurl = ref(window.location.href.split('/#')[0]) +const canvas = ref(null) as any +const myCtx = ref(null) as any +const container = ref([]) as any +const style = ref([]) as any // 点的位置 +const pointsInfo = ref([]) as any // 标记位置信息 +const initDraw = () => { + if (!pointsInfo.value.length) { + return + } + const ctx = myCtx.value // 初始位置 function draw() { - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.beginPath() - ctx.moveTo(points.value[0].x, points.value[0].y) - ctx.lineTo(points.value[1].x, points.value[1].y) - ctx.lineTo(points.value[2].x, points.value[2].y) - ctx.lineTo(points.value[3].x, points.value[3].y) - ctx.closePath() - ctx.strokeStyle = 'red' + ctx.clearRect(0, 0, canvas.value.width, canvas.value.height) + if (pointsInfo.value && pointsInfo.value.length) { + ctx.beginPath() + pointsInfo.value.forEach((e: any) => { + if (e.boundary && e.boundary.length) { // 画线 + ctx.moveTo(e.boundary[0].x, e.boundary[0].y) + ctx.lineTo(e.boundary[1].x, e.boundary[1].y) + ctx.lineTo(e.boundary[2].x, e.boundary[2].y) + ctx.lineTo(e.boundary[3].x, e.boundary[3].y) + } + // ctx.strokeStyle = e.pointColor + ctx.strokeStyle = '#ff0000' + ctx.closePath() + ctx.font = '13px Arial' + // ctx.fillStyle = e.pointColor + ctx.fillStyle = '#ff0000' + // const minY = Math.min(e.boundary[0].y, e.boundary[1].y, e.boundary[2].y, e.boundary[3].y) + // const minX = Math.min(e.boundary[0].x, e.boundary[1].x, e.boundary[2].x, e.boundary[3].x) + const textX = e.boundary[0].x === 0 ? 0 : e.boundary[0].x + 3 > 540 ? 540 : e.boundary[0].x + 3 + const textY = e.boundary[0].y < 12 ? 12 : e.boundary[0].y > 438 ? 438 : e.boundary[0].y - 5 + ctx.fillText(e.recognitionTypeName, textX, textY) + }) + } ctx.lineWidth = 1 ctx.stroke() } @@ -36,26 +55,36 @@ } e = e || window.event e.preventDefault() - var mousePos = { x: e.clientX - canvas.getBoundingClientRect().left, y: e.clientY - canvas.getBoundingClientRect().top } - console.log(mousePos, 'mousePos') + var mousePos = { x: e.clientX - canvas.value.getBoundingClientRect().left, y: e.clientY - canvas.value.getBoundingClientRect().top } // 限制在指定区域内 if (mousePos.x < 0) { mousePos.x = 0 } - else if (mousePos.x > container.clientWidth) { - mousePos.x = container.clientWidth + else if (mousePos.x > 600) { + mousePos.x = 600 } if (mousePos.y < 0) { mousePos.y = 0 } - else if (mousePos.y > container.clientHeight) { - mousePos.y = container.clientHeight + else if (mousePos.y > 450) { + mousePos.y = 450 } - points.value[pointIndex].x = mousePos.x - points.value[pointIndex].y = mousePos.y + const { quotient, remainder } = divideAndModulo(pointIndex, 4) + console.log(`移动的是第${quotient + 1}条数据,第${remainder + 1}个点`) + pointsInfo.value[quotient].boundary[remainder].x = mousePos.x + pointsInfo.value[quotient].boundary[remainder].y = mousePos.y draw() } + function divideAndModulo(dividend: number, divisor: number) { + const quotient = Math.floor(dividend / divisor) // 求商 + const remainder = dividend % divisor // 求余数 + return { + quotient, + remainder, + } + } + function addDragEvents() { if (props.dialogStatus === 'detail') { return @@ -76,10 +105,10 @@ }, } - var pointsElements = document.getElementsByClassName('point') - for (var i = 0; i < pointsElements.length; i++) { - pointsElements[i].addEventListener('mousedown', dragEvents.dragStart) - pointsElements[i].setAttribute('data-point-index', `${i}`) + var pointsInfoElements = document.getElementsByClassName('point') + for (var i = 0; i < pointsInfoElements.length; i++) { + pointsInfoElements[i].addEventListener('mousedown', dragEvents.dragStart) + pointsInfoElements[i].setAttribute('data-point-index', `${i}`) } } @@ -88,56 +117,65 @@ addDragEvents() } init() +} + +onMounted(() => { + canvas.value = document.getElementById('myCanvas') + myCtx.value = canvas.value.getContext('2d') }) -const style = ref([ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, -]) +const removeCanvas = () => { + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + pointsInfo.value = [] +} -watch(() => points.value, () => { - emits('givePoints', points.value) - style.value = [ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, - ] +watch(() => props.points, (newValue: any) => { + console.log('监听点位信息', newValue) + if (newValue && newValue.length) { + pointsInfo.value = newValue + nextTick(() => { + initDraw() + }) + } + else { + pointsInfo.value = newValue + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + } }, { deep: true, + immediate: true, }) + +watch(() => pointsInfo.value, (newValue: any) => { + emits('givepointsInfo', newValue) +}, { + deep: true, + immediate: true, +}) + +defineExpose({ removeCanvas }) diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/src/router/modules/alarm.ts b/src/router/modules/alarm.ts index f8109ab..908735c 100644 --- a/src/router/modules/alarm.ts +++ b/src/router/modules/alarm.ts @@ -71,7 +71,7 @@ { path: 'videoPreviewList', name: 'PolicyConfigVideoPreviewList', - component: () => import('@/views/alarm/policyConfig/videoPreview/index-media-single.vue'), + component: () => import('@/views/alarm/policyConfig/videoPreview/videoPreview.vue'), meta: { title: '视频预览', icon: 'ep:key', diff --git a/src/utils/useCheckList.ts b/src/utils/useCheckList.ts index fb5f8ac..608bb98 100644 --- a/src/utils/useCheckList.ts +++ b/src/utils/useCheckList.ts @@ -13,7 +13,7 @@ // 检查必填 if (prop.required && !item[prop.value]) { // ElMessage.warning(`请先完善${tableTitle}第${index + 1}行中${prop.text}`) - ElMessage.warning(`请先完善${tableTitle}中【${item.typeName}】的${prop.text}`) + ElMessage.warning(`请先完善${tableTitle}中【${item.typeName || item.recognitionTypeName}】的${prop.text}`) return false } // 验证正则 diff --git a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue index 6e72273..9346cbc 100644 --- a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue +++ b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue @@ -3,29 +3,48 @@ dialogStatus: { type: String, }, + points: { + type: Array, + default: () => [], + }, }) -const emits = defineEmits(['givePoints']) -const points = ref([ // 标记点初始 - { x: 50, y: 50 }, // 左上 - { x: 150, y: 50 }, - { x: 150, y: 150 }, - { x: 50, y: 150 }, -]) -onMounted(() => { - const canvas: any = document.getElementById('myCanvas') - const container: any = document.getElementById('draw-area') - const ctx = canvas.getContext('2d') - ctx.clearRect(0, 0, container.clientWidth, container.clientHeight) +const emits = defineEmits(['givepointsInfo']) +const baseurl = ref(window.location.href.split('/#')[0]) +const canvas = ref(null) as any +const myCtx = ref(null) as any +const container = ref([]) as any +const style = ref([]) as any // 点的位置 +const pointsInfo = ref([]) as any // 标记位置信息 +const initDraw = () => { + if (!pointsInfo.value.length) { + return + } + const ctx = myCtx.value // 初始位置 function draw() { - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.beginPath() - ctx.moveTo(points.value[0].x, points.value[0].y) - ctx.lineTo(points.value[1].x, points.value[1].y) - ctx.lineTo(points.value[2].x, points.value[2].y) - ctx.lineTo(points.value[3].x, points.value[3].y) - ctx.closePath() - ctx.strokeStyle = 'red' + ctx.clearRect(0, 0, canvas.value.width, canvas.value.height) + if (pointsInfo.value && pointsInfo.value.length) { + ctx.beginPath() + pointsInfo.value.forEach((e: any) => { + if (e.boundary && e.boundary.length) { // 画线 + ctx.moveTo(e.boundary[0].x, e.boundary[0].y) + ctx.lineTo(e.boundary[1].x, e.boundary[1].y) + ctx.lineTo(e.boundary[2].x, e.boundary[2].y) + ctx.lineTo(e.boundary[3].x, e.boundary[3].y) + } + // ctx.strokeStyle = e.pointColor + ctx.strokeStyle = '#ff0000' + ctx.closePath() + ctx.font = '13px Arial' + // ctx.fillStyle = e.pointColor + ctx.fillStyle = '#ff0000' + // const minY = Math.min(e.boundary[0].y, e.boundary[1].y, e.boundary[2].y, e.boundary[3].y) + // const minX = Math.min(e.boundary[0].x, e.boundary[1].x, e.boundary[2].x, e.boundary[3].x) + const textX = e.boundary[0].x === 0 ? 0 : e.boundary[0].x + 3 > 540 ? 540 : e.boundary[0].x + 3 + const textY = e.boundary[0].y < 12 ? 12 : e.boundary[0].y > 438 ? 438 : e.boundary[0].y - 5 + ctx.fillText(e.recognitionTypeName, textX, textY) + }) + } ctx.lineWidth = 1 ctx.stroke() } @@ -36,26 +55,36 @@ } e = e || window.event e.preventDefault() - var mousePos = { x: e.clientX - canvas.getBoundingClientRect().left, y: e.clientY - canvas.getBoundingClientRect().top } - console.log(mousePos, 'mousePos') + var mousePos = { x: e.clientX - canvas.value.getBoundingClientRect().left, y: e.clientY - canvas.value.getBoundingClientRect().top } // 限制在指定区域内 if (mousePos.x < 0) { mousePos.x = 0 } - else if (mousePos.x > container.clientWidth) { - mousePos.x = container.clientWidth + else if (mousePos.x > 600) { + mousePos.x = 600 } if (mousePos.y < 0) { mousePos.y = 0 } - else if (mousePos.y > container.clientHeight) { - mousePos.y = container.clientHeight + else if (mousePos.y > 450) { + mousePos.y = 450 } - points.value[pointIndex].x = mousePos.x - points.value[pointIndex].y = mousePos.y + const { quotient, remainder } = divideAndModulo(pointIndex, 4) + console.log(`移动的是第${quotient + 1}条数据,第${remainder + 1}个点`) + pointsInfo.value[quotient].boundary[remainder].x = mousePos.x + pointsInfo.value[quotient].boundary[remainder].y = mousePos.y draw() } + function divideAndModulo(dividend: number, divisor: number) { + const quotient = Math.floor(dividend / divisor) // 求商 + const remainder = dividend % divisor // 求余数 + return { + quotient, + remainder, + } + } + function addDragEvents() { if (props.dialogStatus === 'detail') { return @@ -76,10 +105,10 @@ }, } - var pointsElements = document.getElementsByClassName('point') - for (var i = 0; i < pointsElements.length; i++) { - pointsElements[i].addEventListener('mousedown', dragEvents.dragStart) - pointsElements[i].setAttribute('data-point-index', `${i}`) + var pointsInfoElements = document.getElementsByClassName('point') + for (var i = 0; i < pointsInfoElements.length; i++) { + pointsInfoElements[i].addEventListener('mousedown', dragEvents.dragStart) + pointsInfoElements[i].setAttribute('data-point-index', `${i}`) } } @@ -88,56 +117,65 @@ addDragEvents() } init() +} + +onMounted(() => { + canvas.value = document.getElementById('myCanvas') + myCtx.value = canvas.value.getContext('2d') }) -const style = ref([ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, -]) +const removeCanvas = () => { + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + pointsInfo.value = [] +} -watch(() => points.value, () => { - emits('givePoints', points.value) - style.value = [ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, - ] +watch(() => props.points, (newValue: any) => { + console.log('监听点位信息', newValue) + if (newValue && newValue.length) { + pointsInfo.value = newValue + nextTick(() => { + initDraw() + }) + } + else { + pointsInfo.value = newValue + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + } }, { deep: true, + immediate: true, }) + +watch(() => pointsInfo.value, (newValue: any) => { + emits('givepointsInfo', newValue) +}, { + deep: true, + immediate: true, +}) + +defineExpose({ removeCanvas }) diff --git a/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue b/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue new file mode 100644 index 0000000..919cc3b --- /dev/null +++ b/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/public/player/player.html b/public/player/player.html index dcc534b..93ffb30 100644 --- a/public/player/player.html +++ b/public/player/player.html @@ -13,6 +13,7 @@ height: 100vh; background: rgba(13, 14, 27, 0.7); overflow: hidden; + padding: 0px !important; } diff --git a/src/assets/styles/globals.scss b/src/assets/styles/globals.scss index eff72d0..a49b40f 100644 --- a/src/assets/styles/globals.scss +++ b/src/assets/styles/globals.scss @@ -9,7 +9,8 @@ --g-header-height: 60px; // 侧边栏宽度 --g-main-sidebar-width: 70px; - --g-sub-sidebar-width: 180px; + // --g-sub-sidebar-width: 180px; + --g-sub-sidebar-width: 220px; // 侧边栏Logo高度 --g-sidebar-logo-height: 50px; // 顶栏高度 diff --git a/src/main.ts b/src/main.ts index f91e0d9..ef31da6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -31,6 +31,7 @@ .then((result) => { console.log('get config') console.log(result) + if (Object.prototype.toString.call(result.data) !== '[object Object]') { return } window.localStorage.setItem('baseurl-safe', result.data.baseUrl) request.defaults.baseURL = result.data.baseUrl // 设置默认请求网址 window.localStorage.setItem('baseURL', result.data.baseUrl) diff --git a/src/router/modules/alarm.ts b/src/router/modules/alarm.ts index f8109ab..908735c 100644 --- a/src/router/modules/alarm.ts +++ b/src/router/modules/alarm.ts @@ -71,7 +71,7 @@ { path: 'videoPreviewList', name: 'PolicyConfigVideoPreviewList', - component: () => import('@/views/alarm/policyConfig/videoPreview/index-media-single.vue'), + component: () => import('@/views/alarm/policyConfig/videoPreview/videoPreview.vue'), meta: { title: '视频预览', icon: 'ep:key', diff --git a/src/utils/useCheckList.ts b/src/utils/useCheckList.ts index fb5f8ac..608bb98 100644 --- a/src/utils/useCheckList.ts +++ b/src/utils/useCheckList.ts @@ -13,7 +13,7 @@ // 检查必填 if (prop.required && !item[prop.value]) { // ElMessage.warning(`请先完善${tableTitle}第${index + 1}行中${prop.text}`) - ElMessage.warning(`请先完善${tableTitle}中【${item.typeName}】的${prop.text}`) + ElMessage.warning(`请先完善${tableTitle}中【${item.typeName || item.recognitionTypeName}】的${prop.text}`) return false } // 验证正则 diff --git a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue index 6e72273..9346cbc 100644 --- a/src/views/alarm/policyConfig/monitorPoint/drawArea.vue +++ b/src/views/alarm/policyConfig/monitorPoint/drawArea.vue @@ -3,29 +3,48 @@ dialogStatus: { type: String, }, + points: { + type: Array, + default: () => [], + }, }) -const emits = defineEmits(['givePoints']) -const points = ref([ // 标记点初始 - { x: 50, y: 50 }, // 左上 - { x: 150, y: 50 }, - { x: 150, y: 150 }, - { x: 50, y: 150 }, -]) -onMounted(() => { - const canvas: any = document.getElementById('myCanvas') - const container: any = document.getElementById('draw-area') - const ctx = canvas.getContext('2d') - ctx.clearRect(0, 0, container.clientWidth, container.clientHeight) +const emits = defineEmits(['givepointsInfo']) +const baseurl = ref(window.location.href.split('/#')[0]) +const canvas = ref(null) as any +const myCtx = ref(null) as any +const container = ref([]) as any +const style = ref([]) as any // 点的位置 +const pointsInfo = ref([]) as any // 标记位置信息 +const initDraw = () => { + if (!pointsInfo.value.length) { + return + } + const ctx = myCtx.value // 初始位置 function draw() { - ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.beginPath() - ctx.moveTo(points.value[0].x, points.value[0].y) - ctx.lineTo(points.value[1].x, points.value[1].y) - ctx.lineTo(points.value[2].x, points.value[2].y) - ctx.lineTo(points.value[3].x, points.value[3].y) - ctx.closePath() - ctx.strokeStyle = 'red' + ctx.clearRect(0, 0, canvas.value.width, canvas.value.height) + if (pointsInfo.value && pointsInfo.value.length) { + ctx.beginPath() + pointsInfo.value.forEach((e: any) => { + if (e.boundary && e.boundary.length) { // 画线 + ctx.moveTo(e.boundary[0].x, e.boundary[0].y) + ctx.lineTo(e.boundary[1].x, e.boundary[1].y) + ctx.lineTo(e.boundary[2].x, e.boundary[2].y) + ctx.lineTo(e.boundary[3].x, e.boundary[3].y) + } + // ctx.strokeStyle = e.pointColor + ctx.strokeStyle = '#ff0000' + ctx.closePath() + ctx.font = '13px Arial' + // ctx.fillStyle = e.pointColor + ctx.fillStyle = '#ff0000' + // const minY = Math.min(e.boundary[0].y, e.boundary[1].y, e.boundary[2].y, e.boundary[3].y) + // const minX = Math.min(e.boundary[0].x, e.boundary[1].x, e.boundary[2].x, e.boundary[3].x) + const textX = e.boundary[0].x === 0 ? 0 : e.boundary[0].x + 3 > 540 ? 540 : e.boundary[0].x + 3 + const textY = e.boundary[0].y < 12 ? 12 : e.boundary[0].y > 438 ? 438 : e.boundary[0].y - 5 + ctx.fillText(e.recognitionTypeName, textX, textY) + }) + } ctx.lineWidth = 1 ctx.stroke() } @@ -36,26 +55,36 @@ } e = e || window.event e.preventDefault() - var mousePos = { x: e.clientX - canvas.getBoundingClientRect().left, y: e.clientY - canvas.getBoundingClientRect().top } - console.log(mousePos, 'mousePos') + var mousePos = { x: e.clientX - canvas.value.getBoundingClientRect().left, y: e.clientY - canvas.value.getBoundingClientRect().top } // 限制在指定区域内 if (mousePos.x < 0) { mousePos.x = 0 } - else if (mousePos.x > container.clientWidth) { - mousePos.x = container.clientWidth + else if (mousePos.x > 600) { + mousePos.x = 600 } if (mousePos.y < 0) { mousePos.y = 0 } - else if (mousePos.y > container.clientHeight) { - mousePos.y = container.clientHeight + else if (mousePos.y > 450) { + mousePos.y = 450 } - points.value[pointIndex].x = mousePos.x - points.value[pointIndex].y = mousePos.y + const { quotient, remainder } = divideAndModulo(pointIndex, 4) + console.log(`移动的是第${quotient + 1}条数据,第${remainder + 1}个点`) + pointsInfo.value[quotient].boundary[remainder].x = mousePos.x + pointsInfo.value[quotient].boundary[remainder].y = mousePos.y draw() } + function divideAndModulo(dividend: number, divisor: number) { + const quotient = Math.floor(dividend / divisor) // 求商 + const remainder = dividend % divisor // 求余数 + return { + quotient, + remainder, + } + } + function addDragEvents() { if (props.dialogStatus === 'detail') { return @@ -76,10 +105,10 @@ }, } - var pointsElements = document.getElementsByClassName('point') - for (var i = 0; i < pointsElements.length; i++) { - pointsElements[i].addEventListener('mousedown', dragEvents.dragStart) - pointsElements[i].setAttribute('data-point-index', `${i}`) + var pointsInfoElements = document.getElementsByClassName('point') + for (var i = 0; i < pointsInfoElements.length; i++) { + pointsInfoElements[i].addEventListener('mousedown', dragEvents.dragStart) + pointsInfoElements[i].setAttribute('data-point-index', `${i}`) } } @@ -88,56 +117,65 @@ addDragEvents() } init() +} + +onMounted(() => { + canvas.value = document.getElementById('myCanvas') + myCtx.value = canvas.value.getContext('2d') }) -const style = ref([ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, -]) +const removeCanvas = () => { + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + pointsInfo.value = [] +} -watch(() => points.value, () => { - emits('givePoints', points.value) - style.value = [ - { - top: `${points.value[0].y - 5}px`, - left: `${points.value[0].x - 5}px`, - }, - { - top: `${points.value[1].y - 5}px`, - left: `${points.value[1].x - 5}px`, - }, - { - top: `${points.value[2].y - 5}px`, - left: `${points.value[2].x - 5}px`, - }, - { - top: `${points.value[3].y - 5}px`, - left: `${points.value[3].x - 5}px`, - }, - ] +watch(() => props.points, (newValue: any) => { + console.log('监听点位信息', newValue) + if (newValue && newValue.length) { + pointsInfo.value = newValue + nextTick(() => { + initDraw() + }) + } + else { + pointsInfo.value = newValue + if (myCtx.value) { + myCtx.value.clearRect(0, 0, canvas.value.width, canvas.value.height) + } + } }, { deep: true, + immediate: true, }) + +watch(() => pointsInfo.value, (newValue: any) => { + emits('givepointsInfo', newValue) +}, { + deep: true, + immediate: true, +}) + +defineExpose({ removeCanvas }) diff --git a/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue b/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue new file mode 100644 index 0000000..919cc3b --- /dev/null +++ b/src/views/alarm/policyConfig/monitorPoint/drawAreaBak.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/src/views/alarm/policyConfig/monitorPoint/editDialog.vue b/src/views/alarm/policyConfig/monitorPoint/editDialog.vue index 36618a7..d60f330 100644 --- a/src/views/alarm/policyConfig/monitorPoint/editDialog.vue +++ b/src/views/alarm/policyConfig/monitorPoint/editDialog.vue @@ -8,18 +8,24 @@ import drawArea from './drawArea.vue' import type { TableColumn } from '@/components/NormalTable/table_interface' import { isIp } from '@/utils/validate' +import { getMediaStream, getMediaToken } from '@/api/monitor/media' import { useCheckList } from '@/utils/useCheckList' import { getBoxList, getModelList, getRecognitionList, getSceneList, updateMonitorPoint } from '@/api/alarm/policyConfig/monitorPoint' const emits = defineEmits(['closeRefresh']) const dialogStatus = ref('add') +const baseurl = ref(window.location.href.split('/#')[0]) const dialogVisible = ref(false) // 弹窗显示隐藏 +const mediaToken = ref('') // 流媒体token +const mediaUrl = ref('') // 流媒体url +const cameraIndexCode = ref('') // 设备国标号 +const nvrIndexCode = ref('') // nvr国标号 // 显示标题 const textMap: { [key: string]: string } = { detail: '详情', edit: '编辑', add: '新增', } - +const menu = ref([]) // 表单数据对象 const formData: Ref = ref({ id: '', @@ -37,6 +43,8 @@ boundary: '', // 识别边界 }) const selectModelList = ref([]) // 选择的算法 +const drawAreaRef = ref() +const points = ref([]) as any // 标记点位置信息 const algorithmTableRef = ref() const btnLoading = ref(false) // 保存按钮加载状态 const formDataRef = ref() // 表单对象 @@ -108,36 +116,54 @@ ElMessage.warning('请选择报警对象') return false } - if (!useCheckList(selectModelList.value, columns.value, '报警对象')) { + const checkList = [] as any + selectModelList.value.forEach((item: { id: string }) => { + const index = recognitionList.value.findIndex((i: { id: string }) => i.id === item.id) + if (index !== -1) { + checkList.push(recognitionList.value[index]) + } + }) + if (!useCheckList(checkList, columns.value, '报警对象')) { return false } } if (formDataRef.value) { formDataRef.value?.validate((valid: boolean) => { if (valid) { - selectModelList.value.forEach((item: any) => { - const index = recognitionList.value.findIndex((i: { id: string }) => i.id === item.id) - if (index !== -1) { - recognitionList.value.splice(index, 1, { ...item, isUse: '1' }) - } - else { - recognitionList.value.splice(index, 1, { ...item, isUse: '0' }) - } - }) - const params = { - ...formData.value, - sceneRelation: formData.value.type === 1 ? { id: formData.value.id, sceneId: formData.value.sceneId } : null, - // eslint-disable-next-line multiline-ternary - deviceModelRelations: formData.value.type === 0 ? recognitionList.value.map((item: any) => { + let tempList = [] as any + if (formData.value.type === 0) { // 算法 + // 把是否使用全都置为0 + recognitionList.value = recognitionList.value.map((e: { isUse: string }) => { + return { + ...e, + isUse: '0', + } + }) + // 把画点的是否使用置为1 + points.value.forEach((itemOut: any) => { + const index = recognitionList.value.findIndex((itemIn: any) => itemOut.recognitionTypeId === itemIn.recognitionTypeId) + if (index !== -1) { + recognitionList.value[index] = { ...itemOut, isUse: '1' } + } + }) + tempList = recognitionList.value.map((item: any) => { return { ...item, algoModelId: formData.value.algoModelId, // 算法模型id confidenceLevel: item.confidenceLevel, // 置信度 - isUse: item.isUse, recognitionTypeId: item.recognitionTypeId, // 模型识别类型 threshold: item.threshold, // 阈值 + remark: item.recognitionTypeName, // 危险因素描述 + boundary: item.boundary ? JSON.stringify(item.boundary) : item.boundary, } - }) : [], + }) + } + + const params = { + ...formData.value, + sceneRelation: formData.value.type === 1 ? { id: formData.value.id, sceneId: formData.value.sceneId } : null, + // eslint-disable-next-line multiline-ternary + deviceModelRelations: tempList, } console.log('要传的参数', params) updateMonitorPoint(params).then(() => { @@ -172,8 +198,57 @@ recognitionList.value = [] // 报警对象列表 } +// 取随机颜色 +function getRandomColor() { + const r = Math.floor(Math.random() * 256) // 0-255 + const g = Math.floor(Math.random() * 256) // 0-255 + const b = Math.floor(Math.random() * 256) // 0-255 + // const a = Math.random().toFixed(2) // 0-1 + const a = 1 // 0-1 + return `rgba(${r}, ${g}, ${b}, ${a})` +} +// 多选 const selectModel = (value: any) => { - selectModelList.value = value + // console.log('监听算法报警对象的变化,更新区域绘制', value) + selectModelList.value = value.map((item: any) => { + return { + ...item, + pointColor: getRandomColor(), + } + }) + if (formData.value.type === 0) { // 算法模式 + let tempList = [] + console.log('----------------------', points.value) + console.log('[[[[[[[[[[[[[[[]]]]]]]', value) + tempList = value.map((i: any, index: number) => { + const findIndex = points.value.findIndex((item: { recognitionTypeId: string }) => { + console.log(item.recognitionTypeId) + console.log(i.recognitionTypeId) + console.log(i.recognitionTypeId === item.recognitionTypeId) + + return i.recognitionTypeId === item.recognitionTypeId + }) + if (findIndex === -1) { + console.log('没找到', i.recognitionTypeName) + return { + ...i, + remark: i.recognitionTypeName, + boundary: [ // 标记点位置 + { x: 50 + index * 30, y: 50 + index * 30 }, + { x: 150 + index * 30, y: 50 + index * 30 }, + { x: 150 + index * 30, y: 150 + index * 30 }, + { x: 50 + index * 30, y: 150 + index * 30 }, + ], + } + } + else { + console.log('找到了', i.recognitionTypeName) + return { ...i, ...points.value[findIndex] } + } + }) + points.value = tempList + console.log('多选制作的数据', points.value) + } } // -----------------------------------初始化、关闭对话框相关----------------------------------------- @@ -191,82 +266,123 @@ formData.value.deviceId = row.deviceId // 设备id formData.value.recognitionUrl = row.recognitionUrl || 'http://192.168.83.42/recognitionUrl'// 识别流地址 formData.value.rtspUrl = row.rtspUrl || 'http://192.168.83.42/rtsp' // rtsp地址 - // formData.value.boundary = formData.value.boundary ? JSON.parse(formData.value.boundary) : formData.value.boundary // 识别边界 + if (`${row.type}` === '0') { // 算法关联 formData.value.algoModelId = row.deviceModelRelations && row.deviceModelRelations.length && row.deviceModelRelations[0].algoModelId // 模型id - recognitionList.value = row.deviceModelRelations.map((item: any) => { + // 处理一下返回的数据格式 + const resultList = row.deviceModelRelations.map((item: any) => { return { ...item, confidenceLevel: `${item.confidenceLevel}` ? Number(item.confidenceLevel) : undefined, threshold: `${item.threshold}` ? Number(item.threshold) : undefined, + boundary: item.boundary ? JSON.parse(item.boundary) : item.boundary, } }) - - // 恢复选中状态 - const selectedRows = recognitionList.value.filter((item: any) => `${item.isUse}` === '1') - if (selectedRows && Array.isArray(selectedRows) && selectedRows.length) { - nextTick(() => { - selectedRows.forEach((row: any) => { - algorithmTableRef.value?.toggleRowSelection(row, true) - }) + // 先请求所有的数据,因为场景有可能变化 + changeAlgoModelId(formData.value.algoModelId).then((res: any) => { + // 把其余的没有添加的报警对象给添加上 + resultList.forEach((itemOut: any) => { + const index = recognitionList.value.findIndex((itemIn: any) => itemOut.recognitionTypeId === itemIn.recognitionTypeId) + if (index !== -1) { + recognitionList.value[index] = { ...itemOut } + } }) - } + + // 原来选中的数据:进行默认选中 + const selectedRows = recognitionList.value.filter((e: { isUse: string }) => e.isUse === '1') // 把选中的找出来 + if (selectedRows && Array.isArray(selectedRows) && selectedRows.length) { + nextTick(() => { + // 默认选中 + selectedRows.forEach((row: any) => { + algorithmTableRef.value?.toggleRowSelection(row, true) + }) + points.value = selectedRows // 画图 + }) + } + }) } else if (`${row.type}` === '1') { // 业务场景 formData.value.sceneId = row.sceneRelation.sceneId } } - if (dialogstatus === 'detail') { formDataRef.value?.clearValidate() } dialogStatus.value = dialogstatus // 类型 新建add 编辑edit 详情detail + cameraIndexCode.value = row.cameraIndexCode || '' // 设备国标号 + nvrIndexCode.value = row.nvrIndexCode || '' // nvr国标号 + if (cameraIndexCode.value && nvrIndexCode.value) { + fetchMediaStream(cameraIndexCode.value, nvrIndexCode.value) + } btnLoading.value = false } // 关闭并刷新 function closeRefresh() { + drawAreaRef.value.removeCanvas() dialogVisible.value = false + mediaToken.value = '' // 流媒体token + mediaToken.value = '' // 流媒体url + mediaToken.value = '' // 设备国标号 + mediaToken.value = '' // nvr国标号 resetForm() emits('closeRefresh') } // 监听算法变化,查询算法报警对象 -const changeAlgoModelId = (newValue: string) => { - if (newValue) { +async function changeAlgoModelId(modelId: string) { + if (modelId) { // 获取场景对象 const params = { - modelId: newValue, // 模型ID + modelId, // 模型ID typeCode: '', // 类型编码 typeName: '', // 类型名称 } - getRecognitionList(params).then((res) => { - recognitionList.value = res.data.map((item: { id: string; typeName: string }) => { - return { - ...item, - recognitionTypeName: item.typeName, - recognitionTypeId: item.id, - id: '', - } - }) + const res = await getRecognitionList(params) + recognitionList.value = res.data.map((item: { id: string; typeName: string }) => { + return { + ...item, + recognitionTypeName: item.typeName, + recognitionTypeId: item.id, + id: '', + } }) } } +// -------------------------------------------区域绘制相关----------------------------------------------- const givePoints = (value: any) => { - formData.value.boundary = JSON.stringify(value) + console.log('监听到子组件数据变化', value) + points.value = value } -// ----------------------- 以下是暴露的方法内容 ---------------------------- + +// ----------------------------------------------取流--------------------------------------------------------- +// 拉取流--普通流 +async function fetchMediaStream(deviceId: string, channelId: string) { + // 获取流媒体token + const response = await getMediaToken() + mediaToken.value = response.data + // 取流 + const res = await getMediaStream(deviceId, channelId, mediaToken.value) + if (res && res.data) { + mediaUrl.value = res.data.flv + } + else { + ElMessage.warning('设备未注册') + } +} + +// ---------------------------------------------- 以下是暴露的方法内容 --------------------------------------------------------- defineExpose({ initDialog })