Explorar o código

fix: 增加标签删除功能

louhangfei hai 1 ano
pai
achega
49a4856264

+ 27 - 7
src/api/camera/camera-preview.ts

@@ -257,6 +257,26 @@ export const saveFenceApi = (data: SaveFenceParams) => {
   });
 };
 
+export interface DeleteFenceParams {
+  /*相机id */
+  cameraId: number;
+
+  /*算法id */
+  algoId: number;
+
+  /*摄像头预置位token */
+  presetToken: string;
+  fenceId: number;
+}
+/** 删除单个电子围栏 */
+export const deleteFenceApi = (data: DeleteFenceParams) => {
+  return http.request({
+    url: '/admin/algo/deleteFence',
+    method: 'post',
+    data,
+  });
+};
+
 export interface UpdateFenceParams {
   /*相机id */
   cameraId: number;
@@ -291,13 +311,13 @@ export const editFenceApi = (data: UpdateFenceParams) => {
   });
 };
 
-/** 删除电子围栏 */
-export const deleteFenceApi = (cameraAlgoPresetRelId: number) => {
-  return http.request({
-    url: `/cameraPreview/deleteFence?cameraAlgoPresetRelId=${cameraAlgoPresetRelId}`,
-    method: 'delete',
-  });
-};
+// /** 删除电子围栏 */
+// export const deleteFenceApi = (cameraAlgoPresetRelId: number) => {
+//   return http.request({
+//     url: `/cameraPreview/deleteFence?cameraAlgoPresetRelId=${cameraAlgoPresetRelId}`,
+//     method: 'delete',
+//   });
+// };
 
 interface CreatePresetParam {
   presetName: string;

BIN=BIN
src/assets/icons/more-dot-icon.png


+ 16 - 4
src/views/cameras/algo-params-setting/components/CameraViewSetting/CameraViewSetting.vue

@@ -19,7 +19,7 @@
             :canvas-size="{ width: canvasWidth, height: canvasHeight }"
             :line-points="fenceStore.allFences"
             @save="handleSaveFence"
-            @select="handleSelectFence"
+            @select="handleSelectFencePolygon"
           />
         </div>
 
@@ -44,11 +44,12 @@
   <div class="presetWrapper">
     <FenceToolbar
       :style="{ display: drawable ? 'block' : 'none' }"
+      :is-edit="isEdit"
       @remove="handleRemove"
       @save="handleSave"
       @toggle-editable="toggleEditable"
       @toggle-range="toggleRange"
-      :is-edit="isEdit"
+      @select="handleSelectFenceList"
     />
   </div>
 
@@ -131,6 +132,11 @@
     fenceEditorRef.value?.remove();
   };
 
+  /** 选中电子围栏多边形 */
+  const selectFencePolygon = (fenceId: number) => {
+    fenceEditorRef.value?.selectFence(fenceId);
+  };
+
   const isEdit = ref(false);
 
   /** 退出编辑模式 */
@@ -143,9 +149,15 @@
     }
   };
 
-  /** 校验参数 */
-  const handleSelectFence = (nextFenceId: number) => {
+  /** 从图中选中电子围栏多边形 */
+  const handleSelectFencePolygon = (nextFenceId: number) => {
+    fenceStore.currentFenceId = nextFenceId;
+  };
+
+  // 选中电子围栏列表时
+  const handleSelectFenceList = (nextFenceId: number) => {
     fenceStore.currentFenceId = nextFenceId;
+    fenceEditorRef.value?.selectFence(nextFenceId);
   };
 
   const handleSaveFence = (data: { fenceId?: number; polygon: FencePolygonPoints }) => {

+ 12 - 1
src/views/cameras/algo-params-setting/components/FenceEditorV2/FenceEditor.vue

@@ -49,7 +49,7 @@
   // 保存修改后的电子围栏, fenceId为空表示新建的,否则表示编辑已存在的
   interface EmitsEvents {
     (e: 'save', data: { fenceId?: number; polygon: FencePolygonPoints }): unknown;
-    (e: 'select', fenceId: number): unknown;
+    (e: 'select', fenceId: number | null): unknown;
   }
   const emits = defineEmits<EmitsEvents>();
 
@@ -134,6 +134,8 @@
       currentGroupId.value = groupConfig.uid;
       groupConfig._temp.points = point;
       fenceGroups.value.push(groupConfig);
+      // 创建新点时,要把之前选中的电子围栏取消高亮
+      emits('select', null);
     } else {
       /** 右键点击,取消最后一个点 */
       if (e.evt.button === 2) {
@@ -264,12 +266,21 @@
     isEdit.value = true;
   };
 
+  const selectFence = (fenceId: number) => {
+    const currentGroup = fenceGroups.value.find((x) => x.fenceId === fenceId);
+    const groupId = currentGroup?.uid;
+    if (groupId) {
+      currentGroupId.value = groupId;
+    }
+  };
+
   defineExpose({
     clear,
     remove,
     toObject,
     exitEditMode,
     setEditMode,
+    selectFence,
   });
 </script>
 

+ 50 - 3
src/views/cameras/algo-params-setting/components/FenceToolbar/FenceNameItem.vue

@@ -1,27 +1,74 @@
 <!-- 电子围栏名称的一项 -->
 <template>
-  <div :class="props.active ? 'active' : ''">
+  <div :class="props.active ? 'active' : ''" class="fenceItem">
     <div>
       {{ props.detail.name }}
     </div>
 
-    <ElTag type="primary" v-if="props.detail.label">{{ props.detail.label }}</ElTag>
+    <ElTag type="success" size="small" class="fenceLabel" v-if="props.detail.label">{{ props.detail.label }}</ElTag>
+    <el-popover placement="bottom" trigger="click" popper-style="min-width: 80px;width: 80px">
+      <template #reference>
+        <img :src="moreDotIcon" alt="菜单" class="moreDot" />
+      </template>
+      <template #default>
+        <div class="popoverMenu" @click="handleEdit">编辑</div>
+        <div class="popoverMenu" @click="handleDelete">删除</div>
+      </template>
+    </el-popover>
   </div>
 </template>
 
 <script lang="ts" setup>
   import { ElTag } from 'element-plus';
+  import moreDotIcon from '@/assets/icons/more-dot-icon.png';
   interface FenceDetail {
     name: string;
     id: number;
     label: string;
   }
   const props = defineProps<{ detail: FenceDetail; active: boolean }>();
+
+  const emits = defineEmits<{ (e: 'edit', id: number): unknown; (e: 'delete', id: number): unknown }>();
+
+  const handleDelete = () => {
+    emits('delete', props.detail.id);
+  };
+  const handleEdit = () => {
+    emits('edit', props.detail.id);
+  };
 </script>
 
 <style>
-  .active {
+  .fenceItem.active {
     background: #409eff;
     color: #fff;
+    border-color: transparent;
+  }
+  .moreDot {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    right: 0;
+    top: 0;
+    margin: auto;
+    bottom: 0;
+  }
+  .fenceItem {
+    position: relative;
+    padding: 15px;
+    border: 1px solid #ccc;
+    margin: 5px 0;
+    cursor: pointer;
+  }
+  .popoverMenu {
+    text-align: center;
+    margin: 10px 0px;
+    cursor: pointer;
+  }
+  .fenceLabel {
+    position: absolute;
+    bottom: 2px;
+    right: 20px;
+    height: 14px;
   }
 </style>

+ 30 - 6
src/views/cameras/algo-params-setting/components/FenceToolbar/FenceToolbar.vue

@@ -7,13 +7,17 @@
     <PresetSelect />
 
     <div style="display: flex"> <ElCheckbox label="检测围栏外部" /> <ElCheckbox label="前台画面显示" /> </div>
-    <div
-      ><FenceNameItem
+    <div class="fenceListWrapper">
+      <FenceNameItem
         :active="item.id === fenceStore.currentFenceId"
         v-for="item in fenceStore.allFences"
         :detail="item"
         :key="item.id"
-    /></div>
+        @click="handleSelectFence(item.id)"
+        @delete="handleDeleteFence"
+        @edit="handleEditFenceInfo"
+      />
+    </div>
 
     <div class="toolbar">
       <!-- <div class="fenceDrawingTip" v-if="isEdit">
@@ -48,11 +52,13 @@
   import PresetSelect from '../PresetSelect/PresetSelect.vue';
   import FenceNameItem from './FenceNameItem.vue';
   import useFenceStore from '../../store/useFenceStore';
-
+  import useCameraDetailStore from '../../store/useCameraDetailStore';
+  import usePresetListStore from '../../store/usePresetListStore';
   const cameraAlgoStore = useCameraAlgoStore();
 
   const fenceStore = useFenceStore();
-
+  const cameraDetailStore = useCameraDetailStore();
+  const presetStore = usePresetListStore();
   const props = defineProps<{ isEdit: boolean }>();
 
   const emits = defineEmits<{
@@ -60,11 +66,25 @@
     (e: 'toggleRange'): unknown;
     (e: 'remove'): unknown;
     (e: 'save'): unknown;
+    (e: 'select', fenceId: number): unknown;
   }>();
 
   const toggleEdit = () => {
     emits('toggleEditable', !props.isEdit);
   };
+
+  const handleSelectFence = (nextFenceId: number) => {
+    emits('select', nextFenceId);
+  };
+
+  const handleEditFenceInfo = (fenceId: number) => {};
+
+  const handleDeleteFence = (fenceId: number) => {
+    const cameraId = cameraDetailStore.cameraId;
+    const algoId = cameraAlgoStore.selectedAlgoId!;
+    const presetToken = presetStore.currentPresetToken;
+    fenceStore.deleteFence({ cameraId, algoId, presetToken, fenceId });
+  };
 </script>
 
 <style scoped>
@@ -94,6 +114,10 @@
   }
 
   .fenceWrapper {
-    padding: 15px;
+    padding: 10px;
+  }
+  .fenceListWrapper {
+    max-height: 435px;
+    overflow-y: auto;
   }
 </style>

+ 17 - 6
src/views/cameras/algo-params-setting/store/useFenceStore.ts

@@ -5,6 +5,8 @@ import {
   SaveFenceParams,
   editFenceApi,
   UpdateFenceParams,
+  deleteFenceApi,
+  DeleteFenceParams,
 } from '@/api/camera/camera-preview';
 import { defineStore } from 'pinia';
 import { ref } from 'vue';
@@ -12,11 +14,11 @@ import { ServerLine, ServerLines } from '../components/FenceEditor/constants';
 import safeParse from '@/utils/safeParse';
 
 /** 当前电子围栏的store */
-export const useFenceStore = defineStore('electronicFencePolygonStore', () => {
+export const useFenceStore = defineStore('fencePolygonStore', () => {
   /** 当前相机-预置位-算法对应的所有的电子围栏 */
   const allFences = ref<ServerLines>([]);
   /** 当前正在操作的电子围栏id */
-  const currentFenceId = ref<number>();
+  const currentFenceId = ref<number | null>(null);
   const loading = ref(false);
 
   /** 获取电子围栏 */
@@ -33,7 +35,7 @@ export const useFenceStore = defineStore('electronicFencePolygonStore', () => {
         allFences.value = newFence;
       })
       .catch(() => {
-        currentFenceId.value = undefined;
+        currentFenceId.value = null;
         allFences.value = [];
       })
       .finally(() => {
@@ -54,15 +56,24 @@ export const useFenceStore = defineStore('electronicFencePolygonStore', () => {
 
   /** 修改电子围栏信息 */
   const editFence = (param: UpdateFenceParams) => {
-    return editFenceApi(param).then(() => getFence(param));
+    return editFenceApi(param);
+  };
+
+  const deleteFence = (param: DeleteFenceParams) => {
+    const { fenceId } = param;
+    if (currentFenceId.value === fenceId) {
+      currentFenceId.value = null;
+    }
+    allFences.value = allFences.value.filter((x) => x.id !== fenceId);
+    return deleteFenceApi(param);
   };
 
   const clear = () => {
     allFences.value = [];
-    currentFenceId.value = undefined;
+    currentFenceId.value = null;
   };
 
-  return { allFences, currentFenceId, getFence, createFence, editFence, clear };
+  return { allFences, currentFenceId, getFence, createFence, editFence, deleteFence, clear };
 });
 
 export default useFenceStore;