Browse Source

1、将2d绘图组件canvas-select集成到项目中,并正常编辑、保存标注、画图数据

2、弃用组件内置删除回退方法,添加页面键盘事件监听,实现删除和回退
master
Fuyuu 9 months ago
parent
commit
24c134de88
  1. 15
      src/views/earthMap/edit/EarthComp.vue
  2. 73
      src/views/military/modules/ai/aiModel/DtAiModel.data.ts
  3. 21
      src/views/military/modules/ai/aiModel/components/DtAiModelForm.vue
  4. 107
      src/views/military/modules/ai/aiMonitorArea/DtAiMonitorArea.data.ts
  5. 20
      src/views/military/modules/ai/aiMonitorArea/DtAiMonitorAreaList.vue
  6. 72
      src/views/military/modules/ai/aiMonitorArea/checkCom/CheckCom.vue
  7. 161
      src/views/military/modules/ai/aiMonitorArea/components/DtAiMonitorAreaForm.vue
  8. 360
      src/views/military/modules/ai/aiMonitorArea/selectCom/SelectCom.vue
  9. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/circle_icon.png
  10. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/hide.png
  11. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/line_icon.png
  12. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/point_icon.png
  13. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/polo_icon.png
  14. BIN
      src/views/military/modules/ai/aiMonitorArea/selectCom/assets/rect_icon.png
  15. 5
      src/views/military/modules/ai/monitorArea/components/DtMonitorAreaForm.vue
  16. 11
      src/views/system/loginmini/CanvasVideoPage.vue

15
src/views/earthMap/edit/EarthComp.vue

@ -627,9 +627,6 @@
this.clearAlarmModel(eventSerialNum)
}
})
$mitt.on('fly', function (callback) {
that.fly(callback)
})
}
@ -844,7 +841,7 @@
});
}
async fly(callback:any = null) {
async fly() {
let position, rotation, viewDistance, duration;
//
let parentData =
@ -869,11 +866,6 @@
rotation = [data.rotationX, data.rotationY, data.rotationZ];
viewDistance = data.viewDistance;
duration = data.duration ? data.duration : 0;
// mitt
if(callback){
callback(position,rotation,viewDistance,duration);
return
}
this._earth.camera.flyTo(position, viewDistance, rotation, duration);
//
window.$flyTo = this.flyTo = () => {
@ -885,11 +877,6 @@
rotation = [parentData[0].rotationX, parentData[0].rotationY, parentData[0].rotationZ];
viewDistance = parentData[0].viewDistance;
duration = parentData[0].duration;
// mitt
if(callback){
callback(position,rotation,viewDistance,duration);
return
}
//
this._earth.camera.flyTo(position, viewDistance, rotation, duration);
//

73
src/views/military/modules/ai/aiModel/DtAiModel.data.ts

@ -1,54 +1,53 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '模型编号',
align: "center",
dataIndex: 'modelCode'
align: 'center',
dataIndex: 'modelCode',
},
{
title: '模型名称',
align: "center",
dataIndex: 'modelName'
align: 'center',
dataIndex: 'modelName',
},
{
title: '备注',
align: "center",
dataIndex: 'remark'
},
{
title: '备用1',
align: "center",
dataIndex: 'field1'
},
{
title: '备用2',
align: "center",
dataIndex: 'field2'
},
{
title: '备用3',
align: "center",
dataIndex: 'field3'
},
{
title: '所属区域',
align: "center",
dataIndex: 'sysAreaCode'
},
{
title: '所属单位',
align: "center",
dataIndex: 'sysUnitCode'
},
align: 'center',
dataIndex: 'remark',
},
// {
// title: '备用1',
// align: "center",
// dataIndex: 'field1'
// },
// {
// title: '备用2',
// align: "center",
// dataIndex: 'field2'
// },
// {
// title: '备用3',
// align: "center",
// dataIndex: 'field3'
// },
// {
// title: '所属区域',
// align: "center",
// dataIndex: 'sysAreaCode'
// },
// {
// title: '所属单位',
// align: "center",
// dataIndex: 'sysUnitCode'
// },
];
//查询数据
export const searchFormSchema: FormSchema[] = [
];
export const searchFormSchema: FormSchema[] = [];
//表单数据
export const formSchema: FormSchema[] = [

21
src/views/military/modules/ai/aiModel/components/DtAiModelForm.vue

@ -17,7 +17,7 @@
<a-input v-model:value="formData.remark" placeholder="请输入备注" :disabled="disabled"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<!-- <a-col :span="24">
<a-form-item label="备用1" v-bind="validateInfos.field1">
<a-input v-model:value="formData.field1" placeholder="请输入备用1" :disabled="disabled"></a-input>
</a-form-item>
@ -41,7 +41,7 @@
<a-form-item label="所属单位" v-bind="validateInfos.sysUnitCode">
<a-input v-model:value="formData.sysUnitCode" placeholder="请输入所属单位" :disabled="disabled"></a-input>
</a-form-item>
</a-col>
</a-col> -->
</a-row>
</a-form>
</a-spin>
@ -57,8 +57,8 @@
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: ()=>{} },
formBpm: { type: Boolean, default: true }
formData: { type: Object, default: () => {} },
formBpm: { type: Boolean, default: true },
});
const formRef = ref();
const useForm = Form.useForm;
@ -79,23 +79,21 @@
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//
const validatorRules = {
};
const validatorRules = {};
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });
//
const disabled = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
}else{
} else {
return true;
}
}
return props.formDisabled;
});
/**
* 新增
*/
@ -152,7 +150,6 @@
});
}
defineExpose({
add,
edit,

107
src/views/military/modules/ai/aiMonitorArea/DtAiMonitorArea.data.ts

@ -1,69 +1,70 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '模型编号',
align: "center",
dataIndex: 'modelCode'
align: 'center',
dataIndex: 'modelCode',
width: 100,
},
{
title: '模型名称',
align: "center",
dataIndex: 'modelName'
align: 'center',
dataIndex: 'modelName',
},
{
title: '模型范围数据',
align: "center",
dataIndex: 'areaData'
},
{
title: '画图数据',
align: "center",
dataIndex: 'drawdata'
},
{
title: '相机id',
align: "center",
dataIndex: 'cameraId'
},
{
title: '备注',
align: "center",
dataIndex: 'remark'
},
{
title: '备用1',
align: "center",
dataIndex: 'field1'
title: 'rtsp地址',
align: 'center',
dataIndex: 'rtspUrl',
},
{
title: '备用2',
align: "center",
dataIndex: 'field2'
title: 'webrtc地址',
align: 'center',
dataIndex: 'webrtcUrl',
},
{
title: '备用3',
align: "center",
dataIndex: 'field3'
},
{
title: '所属区域',
align: "center",
dataIndex: 'sysAreaCode'
title: '模型范围数据',
align: 'center',
dataIndex: 'areaData',
},
{
title: '所属单位',
align: "center",
dataIndex: 'sysUnitCode'
},
title: '画图数据',
align: 'center',
dataIndex: 'drawdata',
},
// ,
// {
// title: '备注',
// align: 'center',
// dataIndex: 'remark',
// },
// {
// title: '备用2',
// align: "center",
// dataIndex: 'field2'
// },
// {
// title: '备用3',
// align: "center",
// dataIndex: 'field3'
// },
// {
// title: '所属区域',
// align: "center",
// dataIndex: 'sysAreaCode'
// },
// {
// title: '所属单位',
// align: "center",
// dataIndex: 'sysUnitCode'
// },
];
//查询数据
export const searchFormSchema: FormSchema[] = [
];
export const searchFormSchema: FormSchema[] = [];
//表单数据
export const formSchema: FormSchema[] = [
@ -88,18 +89,18 @@ export const formSchema: FormSchema[] = [
component: 'Input',
},
{
label: '相机id',
field: 'cameraId',
label: 'rtsp地址',
field: 'rtspUrl',
component: 'Input',
},
{
label: '备注',
field: 'remark',
label: 'webrtc地址',
field: 'webrtcUrl',
component: 'Input',
},
{
label: '备用1',
field: 'field1',
label: '备',
field: 'remark',
component: 'Input',
},
{

20
src/views/military/modules/ai/aiMonitorArea/DtAiMonitorAreaList.vue

@ -53,6 +53,8 @@
</BasicTable>
<!-- 表单区域 -->
<DtAiMonitorAreaModal ref="registerModal" @success="handleSuccess"></DtAiMonitorAreaModal>
<!-- 查看监控 -->
<CheckCom v-if="videoVisible"></CheckCom>
</div>
</template>
@ -64,7 +66,13 @@
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './DtAiMonitorArea.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import DtAiMonitorAreaModal from './components/DtAiMonitorAreaModal.vue';
import CheckCom from './checkCom/CheckCom.vue';
//
const videoVisible = ref(false);
//
function videoCheck(record) {
videoVisible.value = true;
}
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
@ -78,7 +86,7 @@
canResize: false,
useSearchForm: false,
actionColumn: {
width: 120,
width: 180,
fixed: 'right',
},
beforeFetch: (params) => {
@ -156,6 +164,10 @@
*/
function getTableAction(record) {
return [
{
label: '查看监控',
onClick: videoCheck.bind(null, record),
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
@ -198,6 +210,10 @@
//
reload();
}
defineExpose({
videoVisible,
});
</script>
<style lang="less" scoped>

72
src/views/military/modules/ai/aiMonitorArea/checkCom/CheckCom.vue

@ -0,0 +1,72 @@
<template>
<a-modal :visible="visible" :title="title" width="1080px" @cancel="handleCancel" destroyOnClose>
<a-row>
<div class="mpegPlayer" ref="mpegPlayer"></div>
</a-row>
<template #footer="">
<a-button @click="handleCancel">关闭</a-button>
</template>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, getCurrentInstance, onMounted, nextTick } from 'vue';
const { proxy }: any = getCurrentInstance();
const props = defineProps({
title: {
type: String,
default: '查看监控',
},
visible: {
type: Boolean,
default: true,
},
// rtsp
videoUrl: {
type: String,
default: 'rtsp://admin:hk123456@192.168.1.71:554/',
},
});
/* 播放rtsp视频相关 */
import MpegPlayer from 'jsmpeg-player';
const { ipcRenderer } = require('electron');
// DOM
const mpegPlayer = ref();
//
const msg = ref('');
//
let player: any = ref(null);
//
const open = () => {
const res = ipcRenderer.sendSync('openRtsp', props.videoUrl);
if (res.code === 200) {
player.value = new MpegPlayer.VideoElement(mpegPlayer.value, res.ws);
}
msg.value = res.msg;
};
//
const close = () => {
const res = ipcRenderer.sendSync('closeRtsp', props.videoUrl);
msg.value = res.msg;
};
function handleCancel() {
nextTick(() => {
//
proxy.$parent.videoVisible = false;
//
close();
});
}
onMounted(() => {
open();
});
</script>
<style lang="less" scoped>
.mpegPlayer {
width: 100%;
height: 580px;
background: #000;
}
</style>

161
src/views/military/modules/ai/aiMonitorArea/components/DtAiMonitorAreaForm.vue

@ -12,31 +12,53 @@
<a-input v-model:value="formData.modelName" placeholder="请输入模型名称" :disabled="disabled"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="模型范围数据" v-bind="validateInfos.areaData">
<a-textarea v-model:value="formData.areaData" rows="4" placeholder="请输入模型范围数据" :disabled="disabled"/>
<a-col :span="24" v-show="!disabled">
<a-form-item label="标注区域">
<img :src="locationPng" @click="videoShow" class="dwImg" alt="绘制标注数据" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="画图数据" v-bind="validateInfos.drawdata">
<a-input v-model:value="formData.drawdata" placeholder="请输入画图数据" :disabled="disabled"></a-input>
<a-form-item label="rtsp地址" v-bind="validateInfos.rtspUrl">
<a-tree-select
v-model:value="formData.rtspUrl"
@change="getvideoUrl($event, 'rtsp')"
allow-clear
:treeData="cameraList"
:disabled="disabled"
placeholder="请选择rtsp地址"
>
</a-tree-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="相机id" v-bind="validateInfos.cameraId">
<a-input v-model:value="formData.cameraId" placeholder="请输入相机id" :disabled="disabled"></a-input>
<a-form-item label="webrtc地址" v-bind="validateInfos.webrtcUrl">
<a-tree-select
v-model:value="formData.webrtcUrl"
@change="getvideoUrl($event, 'webrtc')"
allow-clear
:treeData="cameraList"
:disabled="disabled"
placeholder="请选择webrtc地址"
>
</a-tree-select>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备注" v-bind="validateInfos.remark">
<a-input v-model:value="formData.remark" placeholder="请输入备注" :disabled="disabled"></a-input>
<a-form-item label="模型范围数据" v-bind="validateInfos.areaData">
<a-textarea v-model:value="formData.areaData" rows="4" placeholder="请输入模型范围数据" :disabled="disabled" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备用1" v-bind="validateInfos.field1">
<a-input v-model:value="formData.field1" placeholder="请输入备用1" :disabled="disabled"></a-input>
<a-form-item label="画图数据" v-bind="validateInfos.drawdata">
<a-textarea v-model:value="formData.drawdata" rows="4" placeholder="请输入画图数据" :disabled="disabled"></a-textarea>
</a-form-item>
</a-col>
<!-- <a-col :span="24">
<a-form-item label="备注" v-bind="validateInfos.remark">
<a-input v-model:value="formData.remark" placeholder="请输入备注" :disabled="disabled"></a-input>
</a-form-item>
</a-col> -->
<!--
<a-col :span="24">
<a-form-item label="备用2" v-bind="validateInfos.field2">
<a-input v-model:value="formData.field2" placeholder="请输入备用2" :disabled="disabled"></a-input>
@ -56,10 +78,16 @@
<a-form-item label="所属单位" v-bind="validateInfos.sysUnitCode">
<a-input v-model:value="formData.sysUnitCode" placeholder="请输入所属单位" :disabled="disabled"></a-input>
</a-form-item>
</a-col>
</a-col> -->
</a-row>
</a-form>
</a-spin>
<SelectCom
v-if="videoVisible"
:videoUrl="formData.rtspUrl"
v-model:labelData="formData.drawdata"
v-model:locationData="formData.areaData"
></SelectCom>
</template>
<script lang="ts" setup>
@ -69,11 +97,17 @@
import { getValueType } from '/@/utils';
import { saveOrUpdate } from '../DtAiMonitorArea.api';
import { Form } from 'ant-design-vue';
import locationPng from '@/assets/images/getLocation.png';
//
import SelectCom from '../selectCom/SelectCom.vue';
//
const cameraList: any = ref([]);
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: ()=>{} },
formBpm: { type: Boolean, default: true }
formData: { type: Object, default: () => {} },
formBpm: { type: Boolean, default: true },
});
const formRef = ref();
const useForm = Form.useForm;
@ -84,9 +118,9 @@
modelName: '',
areaData: '',
drawdata: '',
cameraId: '',
rtspUrl: '',
webrtcUrl: '',
remark: '',
field1: '',
field2: '',
field3: '',
sysAreaCode: '',
@ -97,23 +131,96 @@
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//
const validatorRules = {
};
const validatorRules = {};
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });
onMounted(() => {
getCameraList();
});
//
function getCameraList() {
defHttp
.get(
{
url: '/military/camera/site/getSiteCameraInfo',
params: { pageNo: 1, pageSize: 9999 },
},
{
isTransformResponse: false,
}
)
.then((res) => {
if (res.success) {
cameraList.value = handleCameraTree(res.result);
}
});
}
//
function handleCameraTree(data, index = undefined) {
let arr: any = [];
for (let i = 0; i < data.length; i++) {
let obj: any = {};
let item = data[i];
obj.title = item.name;
obj.value = obj.key = item.id;
// obj.selectable = false;
if (item.children && item.children.length > 0) {
obj.children = [];
// obj.key = i + 1;
let indexValue: any = index ? index + '-' + (i + 1) : i + 1;
obj.children = handleCameraTree(item.children, indexValue);
} else {
// obj.key = index !== undefined ? index + '-' + (i + 1) : (i + 1) + '';
// let tmp = (obj.key + '').split('-').length;
// obj.selectable = tmp >= 3;
}
// obj.key = index !== undefined ? index + '-' + (i + 1) : (i + 1) + '';
arr.push(obj);
}
return arr;
}
// rtspUrl - id
function getvideoUrl(event, urlType) {
defHttp
.get(
{
url: '/military/camera/setting/queryById',
params: { id: event },
},
{ isTransformResponse: false }
)
.then((res) => {
if (urlType == 'rtsp') {
formData.rtspUrl = res.result.preRtsp;
formData.webrtcUrl = '';
} else {
formData.webrtcUrl = res.result.webcastAddress;
formData.rtspUrl = '';
}
});
}
//
const videoVisible = ref(false);
//
function videoShow() {
videoVisible.value = true;
}
//
const disabled = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
}else{
} else {
return true;
}
}
return props.formDisabled;
});
/**
* 新增
*/
@ -170,11 +277,11 @@
});
}
defineExpose({
add,
edit,
submitForm,
videoVisible,
});
</script>
@ -184,4 +291,10 @@
overflow-y: auto;
padding: 24px 24px 24px 24px;
}
.dwImg {
width: 10%;
height: 10%;
margin-left: 3%;
cursor: pointer !important;
}
</style>

360
src/views/military/modules/ai/aiMonitorArea/selectCom/SelectCom.vue

@ -0,0 +1,360 @@
<!--
标注组件1.0
目录位置AI智能化区域监控 -> 视频智能监控范围 -> 标注区域
功能概述引入轻量级图片2d标注组件canvas-select,通过添加透明图层,与rtsp视频流结合,实现视频监控区域标注
-->
<template>
<a-modal
:keyboard="false"
:maskClosable="false"
:mask="false"
:forceRender="true"
:visible="visible"
:title="title"
width="1080px"
@cancel="handleCancel"
destroyOnClose
>
<a-row class="video_area">
<canvas ref="canvas" class="container"></canvas>
<div class="mpegPlayer" ref="mpegPlayer"></div>
</a-row>
<a-row class="operate_area">
<div class="area_box">
<a-space :size="18">
<a-button shape="round" size="middle" @click="change(0)"> <ApiOutlined /> 退出创建</a-button>
<a-button type="primary" shape="circle" size="large" @click="change(1)" title="创建矩形">
<img class="icon_style" src="./assets/rect_icon.png" />
</a-button>
<a-button type="primary" shape="circle" size="large" @click="change(2)" title="创建多边形">
<img class="icon_style" src="./assets/polo_icon.png" />
</a-button>
<a-button type="primary" shape="circle" size="large" @click="change(3)" title="创建标记点">
<img class="icon_style" src="./assets/point_icon.png" />
</a-button>
<a-button type="primary" shape="circle" size="large" @click="change(4)" title="创建线">
<img class="icon_style" src="./assets/line_icon.png" />
</a-button>
<a-button type="primary" shape="circle" size="large" @click="change(5)" title="创建圆">
<img class="icon_style" src="./assets/circle_icon.png" />
</a-button>
<a-button type="primary" shape="round" danger size="middle" @click="clear()"> <FormatPainterOutlined />清除标注 </a-button>
</a-space>
</div>
</a-row>
<template #footer="">
<a-popconfirm title="是否保存标注?" ok-text="确认" cancel-text="取消" @confirm="handleOk()" @cancel="handleCancel">
<a-button type="primary">保存</a-button>
</a-popconfirm>
</template>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, getCurrentInstance, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { ApiOutlined, FormatPainterOutlined } from '@ant-design/icons-vue';
const { proxy }: any = getCurrentInstance();
const props = defineProps({
title: {
type: String,
default: '区域标注',
},
visible: {
type: Boolean,
default: true,
},
// rtsp
videoUrl: {
type: String,
default: 'rtsp://admin:hk123456@192.168.1.71:554/',
},
//
labelData: {
type: String,
default: '',
},
//
locationData: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:label-data', 'update:location-data']);
/* 播放rtsp视频相关 */
import MpegPlayer from 'jsmpeg-player';
const { ipcRenderer } = require('electron');
// DOM
const mpegPlayer = ref();
//
const msg = ref('');
//
let player: any = ref(null);
//
const open = () => {
const res = ipcRenderer.sendSync('openRtsp', props.videoUrl);
if (res.code === 200) {
player.value = new MpegPlayer.VideoElement(mpegPlayer.value, res.ws);
}
msg.value = res.msg;
};
//
const close = () => {
const res = ipcRenderer.sendSync('closeRtsp', props.videoUrl);
msg.value = res.msg;
};
/* 标注区域相关 */
// 2dcanvas-Select
import CanvasSelect from 'canvas-select';
// canvas
const canvas = ref(null);
//
const hideUrl = new URL('./assets/hide.png', import.meta.url).href;
//
let instance: any = ref(null);
//
const option: any = ref([]);
//
function change(num: any) {
instance.createType = num;
}
//
function clear() {
instance.setData([]);
}
//
function save() {
/* 保存绘制数据,用于回显 */
//
instance.dataset.forEach((item) => {
item.active = false;
});
//
emit('update:label-data', JSON.stringify(instance.dataset));
/* 保存区域界限节点数据,用于后端分析 */
//
const newData = instance.dataset.map((item) => {
let typeString;
switch (item.type) {
case 1:
typeString = 'rect';
break;
case 2:
typeString = 'polygon';
break;
case 3:
typeString = 'dot';
break;
case 4:
typeString = 'line';
break;
case 5:
typeString = 'circle';
break;
default:
typeString = '';
}
const newShape: any = {
type: typeString,
coor: item.coor,
};
if (item.type === 5) {
// type5circleradius
newShape.radius = item.radius;
}
return newShape;
});
//
emit('update:location-data', JSON.stringify(newData));
}
// backspace / 退 esc
function changeSelect(event) {
if (event.keyCode == 8) {
//
instance.dataset = instance.dataset.filter((item) => !item.active);
//
instance.update();
} else if (event.keyCode == 27) {
//
let delete_status = 0;
// 退
instance.dataset.forEach((item) => {
if (item.active === true && item.creating === true) {
//
if (item.type == 1) {
if (item.coor.length > 1) {
// 退
item.coor = [];
//
delete_status = 1;
}
}
//
else if (item.type == 5) {
if (item.coor.length > 1) {
// 退
item.coor = [];
item.radius = 0;
//
delete_status = 1;
}
}
//
else {
if (item.coor.length > 1) {
// 退
item.coor.pop();
} else {
//
delete_status = 1;
}
}
//
instance.update();
}
});
if (delete_status === 1) {
//
instance.dataset = instance.dataset.filter((item) => !item.active);
//
instance.update();
}
}
}
onMounted(() => {
//
document.addEventListener('keydown', changeSelect);
//
open();
//
if (props.labelData == '') {
option.value = [];
} else {
option.value = JSON.parse(props.labelData);
}
//
instance = new CanvasSelect('.container', hideUrl);
//
instance.labelMaxLen = 10;
//
instance.scrollZoom = false;
//
instance.setData(option.value);
// 线
instance.lineWidth = 2;
//
instance.labelFont = '12px Arial';
//
instance.labelFillStyle = '#fa4545';
//
instance.textFillStyle = '#fff';
//
instance.ctrlRadius = 4;
//
instance.on('load', (src: any) => {
console.log('image load', src);
});
//
instance.on('add', (info: any) => {
//
switch (instance.createType) {
case 1:
info.label = '矩形防区';
break;
case 2:
info.label = '多边形防区';
break;
case 3:
info.label = '标记点位';
break;
case 4:
info.label = '报警界线';
break;
case 5:
info.label = '圆形防区';
break;
default:
info.label = '未定义';
}
//
instance.update();
});
// -
// instance.on('delete', (info: any) => {
// console.log('', info);
// });
//
instance.on('select', (shape: any) => {
console.log('选中', shape);
});
//
instance.on('updated', (result: any) => {
console.log('更新', result);
});
});
//
// 使`beforeUnmount`
// 使`onUnmounted`
onBeforeUnmount(() => {
document.removeEventListener('keydown', changeSelect);
});
//
async function handleOk() {
//
save();
//
handleCancel();
}
//
function handleCancel() {
nextTick(() => {
//
proxy.$parent.videoVisible = false;
//
close();
});
}
</script>
<style lang="less" scoped>
.video_area {
width: 100%;
height: 580px;
margin: 0 auto;
position: relative;
.container {
width: 1080px;
height: 580px;
position: absolute;
z-index: 9999;
left: 0;
top: 0;
}
.mpegPlayer {
width: 100%;
height: 100%;
background: #000;
}
}
.operate_area {
width: 100%;
margin: 10px auto;
.area_box {
margin: 0 auto;
}
.icon_style {
width: 24px;
height: 24px;
margin: 0 auto;
}
}
</style>

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/circle_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/hide.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/line_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/point_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/polo_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/views/military/modules/ai/aiMonitorArea/selectCom/assets/rect_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

5
src/views/military/modules/ai/monitorArea/components/DtMonitorAreaForm.vue

@ -75,6 +75,9 @@
</a-spin>
<!-- <Area v-if="mapVisible" v-model:areaData="formData.areaData" v-model:drawData="formData.drawData" ></Area> -->
<!-- <AreaByXbsjEarthUI :visible="mapVisible" v-model:areaData="formData.areaData" v-model:drawData="formData.drawData"></AreaByXbsjEarthUI> -->
<!-- <EarthMapModal v-model:areaData="formData.areaData" v-model:drawData="formData.drawData" :visible="mapVisible"
:enableTile="false" :enablePointer="true" @closeWin="() => { mapVisible = false }" @clearAreaData="clearAreaData">
</EarthMapModal> -->
<VCEarthViewer v-if="mapVisible" v-model:areaData="formData.areaData" v-model:drawData="formData.drawData"> </VCEarthViewer>
</template>
@ -91,7 +94,7 @@
import VCEarthViewer from './VCEarthViewer.vue';
import Area from '@/views/military/modules/ai/MonitorArea/components/Area.vue';
import AreaByXbsjEarthUI from '@/views/military/modules/ai/MonitorArea/components/AreaByXbsjEarthUI.vue';
import EarthMapModal from '/@/views/military/modules/earthMap/scene/model/mapModel/EarthMapModal.vue';
import locationPng from '@/assets/images/getLocation.png';
import { FormatPainterOutlined } from '@ant-design/icons-vue';

11
src/views/system/loginmini/CanvasVideoPage.vue

@ -45,7 +45,7 @@
<a-button type="primary" @click="save()"><FileDoneOutlined />保存</a-button>
</div>
</div>
<div class="right">
<!-- <div class="right">
<pre>
1.设置 instance.createType 指定需要创建形状类型
@ -60,9 +60,8 @@
6.鼠标滚轮缩放画布
7.选中形状Backspace删除
</pre
>
</div>
</pre>
</div> -->
</div>
</template>
@ -95,7 +94,7 @@
const mouseX = ref(0);
const mouseY = ref(0);
const isRightMouseDown = ref(false);
//
// rtsp
const open = () => {
const res = ipcRenderer.sendSync('openRtsp', rtspUrl.value);
@ -252,7 +251,7 @@
width: 800px;
height: 480px;
position: absolute;
z-index: 999;
z-index: 999999;
left: 0;
top: 0;
}

Loading…
Cancel
Save