Bläddra i källkod

算法反显:检测频率、电子围栏、是否生效

louhangfei 2 år sedan
förälder
incheckning
6f49262646

+ 19 - 10
src/api/camera/camera-preview.ts

@@ -32,9 +32,9 @@ export const getCameraTree = () => {
   });
 };
 
-interface AlgoStatus {
-  enabled: 1;
-  disabled: 0;
+export enum AlgoStatus {
+  enabled = 1,
+  disabled = 0,
 }
 
 interface AlgoItem {
@@ -51,28 +51,28 @@ interface AlgoItem {
   updatedAt: string;
 }
 /** 查询所有的算法 */
-export const getAllAlgosApi = (params: { pageNumber: number; pageSize: number }) => {
+export const getAllAlgosApi = () => {
   return http.request<AlgoItem[]>({
     url: '/cameraPreview/getAlgoList',
     method: 'get',
-    params,
   });
 };
 
 /** 相机关联的算法信息 */
-interface CameraAlgoItem {
+export interface CameraAlgoItem {
+  id?: number;
   algoId: number;
-  cameraId: number;
+  cameraId?: number;
   code: string;
   name: string;
   detectionFrequency: number;
   detectionTime: string;
-  electronicFence: string;
+  electronicFence: number;
   status: AlgoStatus;
   algoInfo: AlgoItem;
 }
 
-/** 查询某个camera下的所有算法算法 */
+/** 查询某个camera下的所有算法 */
 export const getCameraAlgoListApi = (cameraId: number) => {
   return http.request<CameraAlgoItem[]>({
     url: '/cameraPreview/getAlgo',
@@ -90,7 +90,7 @@ interface SaveCameraAlgoParam {
   status: 0 | 1;
 }
 /** 保存相机的某个算法 */
-export const saveCameraAlgoApi = (param: SaveCameraAlgoParam) => {
+export const createCameraAlgoApi = (param: SaveCameraAlgoParam) => {
   return http.request({
     url: '/cameraPreview/saveAlgo',
     data: param,
@@ -98,6 +98,15 @@ export const saveCameraAlgoApi = (param: SaveCameraAlgoParam) => {
   });
 };
 
+/** 更新相机的某个算法 */
+export const updateCameraAlgoApi = (param: SaveCameraAlgoParam & { id: number }) => {
+  return http.request({
+    url: '/cameraPreview/updateAlgo',
+    data: param,
+    method: 'put',
+  });
+};
+
 /** 删除相机的某个算法 */
 export const deleteCameraAlgoApi = (params: { cameraId: number; algoId: number }) => {
   const paramString = qs.stringify(params);

BIN
src/assets/icons/addTimeIcon.png


+ 50 - 55
src/views/cameras/preview/components/AlgorithmsSetting/AlgoSettingCard.vue

@@ -1,10 +1,10 @@
 <template>
   <div class="algoCardWrapper">
     <div style="display: flex; justify-content: space-between">
-      <ElSelect v-model="currentAlgoId" style="width: 150px">
-        <ElOption v-for="item in data" :key="item.id" :value="item.id" :label="item.name">
+      <ElSelect v-model="selectedAlgoId" style="width: 150px">
+        <ElOption v-for="item in allAlgoList" :key="item.id" :value="item.id" :label="item.name">
           {{ item.name }}
-          <span style="margin-left: 5px" v-if="isAlgoAdded(item.id)">√</span>
+          <span style="margin-left: 5px" v-if="isAlgoBind(item.id)">√</span>
         </ElOption>
       </ElSelect>
       <ElSwitch v-model="enableCard" />
@@ -39,13 +39,12 @@
               @change="handleTimeChange(x.id, $event)"
             />
             <span @click="removeTime(x.id)" v-if="timeRangeArr.length > 1">
-              <el-icon style="color: #8c8c8c"><CircleCloseFilled /></el-icon
+              <el-icon class="removeIcon"><CircleCloseFilled /></el-icon
             ></span>
           </div>
-          <div @click="handleAddTimeRange"
-            ><el-icon style="cursor: pointer; background-color: #f5f5f5; font-size: 20px"
-              ><CirclePlus /></el-icon
-          ></div>
+          <div @click="handleAddTimeRange" class="addTimeIcon">
+            <img :src="addTimeIcon" width="28" height="28" />
+          </div>
         </div>
       </div>
       <div class="algoRow" style="align-items: center">
@@ -56,6 +55,7 @@
           :min="0"
           size="small"
           style="width: 80px"
+          :precision="0"
         />
         <ElSelect size="small" style="width: 60px; margin-left: 10px" v-model="detectionUnit">
           <ElOption
@@ -68,7 +68,7 @@
         <span style="font-size: 12px; margin-left: 5px">/次</span>
       </div>
       <div style="display: flex; justify-content: flex-end">
-        <ElButton size="small" @click="emits('onRemove', currentAlgoId)">删除</ElButton>
+        <ElButton size="small" @click="handleRemoveAlgo">删除</ElButton>
         <ElButton size="small" type="primary" @click="handleSave">保存</ElButton>
       </div>
     </div>
@@ -76,21 +76,19 @@
 </template>
 <script lang="ts" setup>
   import { ElSelect, ElOption, ElSwitch, ElInputNumber, ElTimePicker } from 'element-plus';
-  import { CirclePlus, CircleCloseFilled } from '@element-plus/icons-vue';
-  import useAllAlgos from './useAllAlgos';
+  import { CircleCloseFilled } from '@element-plus/icons-vue';
   import { ref, watch } from 'vue';
-  import { uid } from 'uid';
   import { storeToRefs } from 'pinia';
+  import { Dayjs } from 'dayjs';
+  import addTimeIcon from '@/assets/icons/addTimeIcon.png';
   import useCameraAlgoStore from '../../store/useCameraAlgoStore';
   import { STATUS } from './types';
+  import { FrequencyEnum, createDefaultTime, frequencyOptions, getDetectionJSON } from './utils';
 
-  const { data, loading } = useAllAlgos();
-
+  // const { data: algoList, loading } = useAllAlgos();
   const cameraAlgoStore = useCameraAlgoStore();
-
-  const { data: cameraAlogList } = storeToRefs(cameraAlgoStore);
-
-  const props = defineProps<{ activeAlgoId: number | null }>();
+  const { isAlgoBind } = cameraAlgoStore;
+  const { allAlgoList, selectedAlgoId, selectedAlgoDetail } = storeToRefs(cameraAlgoStore);
 
   interface Param {
     /** 算法id */
@@ -110,43 +108,10 @@
     (e: 'onRemove', algoId: number): Promise<unknown>;
   }>();
 
-  enum FrequencyEnum {
-    second = 1,
-    miniute = 60,
-    hour = 3600,
-  }
-
-  watch(
-    () => props.activeAlgoId,
-    () => {
-      if (props.activeAlgoId) {
-        currentAlgoId.value = props.activeAlgoId;
-      }
-    },
-    {
-      immediate: true,
-    },
-  );
-
-  const frequencyOptions = [
-    { label: '秒', value: FrequencyEnum.second },
-    { label: '分钟', value: FrequencyEnum.miniute },
-    { label: '小时', value: FrequencyEnum.hour },
-  ];
-  const createDefaultTime = () => {
-    return { id: uid(), value: [new Date(), new Date()] as [Date, Date] };
-  };
-
-  const isAlgoAdded = (algoId: number) => {
-    return cameraAlogList.value?.some((x) => x.id === algoId);
-  };
-
   const timeRangeArr = ref([createDefaultTime()]);
 
   const detectionUnit = ref(FrequencyEnum.miniute);
 
-  const currentAlgoId = ref<number>(1);
-
   /** 电子围栏开关 */
   const electronicFence = ref(true);
 
@@ -154,6 +119,19 @@
 
   const enableCard = ref(true);
 
+  watch(
+    () => selectedAlgoDetail.value,
+    (detail) => {
+      console.log('detail change', detail);
+      const detectionJSON = getDetectionJSON(detail?.detectionFrequency);
+      enableCard.value = Boolean(detail?.status);
+      electronicFence.value = Boolean(detail?.electronicFence);
+      detectionNum.value = detectionJSON.detectionNum;
+      detectionUnit.value = detectionJSON.detectionUnit;
+    },
+    { deep: true, immediate: true },
+  );
+
   const handleAddTimeRange = () => {
     timeRangeArr.value.push(createDefaultTime());
   };
@@ -166,16 +144,19 @@
     timeRangeArr.value = timeRangeArr.value.filter((x) => x.id !== id);
   };
 
-  const getTimeStr = (d: Date) => {
-    return d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
+  const getTimeStr = (d: Dayjs) => {
+    return d.format('HH:mm:ss');
   };
-  const getTimeStrs = (d: [Date, Date]) => {
+  const getTimeStrs = (d: [Dayjs, Dayjs]) => {
     return getTimeStr(d[0]) + '-' + getTimeStr(d[1]);
   };
 
   const handleSave = () => {
+    const detail = selectedAlgoDetail.value;
+    if (!detail) return;
     const param = {
-      algoId: currentAlgoId.value,
+      id: detail.id,
+      algoId: detail.algoId,
       detectionFrequency: detectionNum.value * detectionUnit.value,
       detectionTime: timeRangeArr.value
         .map((x) => {
@@ -188,6 +169,11 @@
     emits('onSubmit', param);
     console.log('param', param);
   };
+
+  const handleRemoveAlgo = () => {
+    if (!selectedAlgoId.value) return;
+    emits('onRemove', selectedAlgoId.value);
+  };
 </script>
 <style scoped>
   .algoCardWrapper {
@@ -208,4 +194,13 @@
   .presetList {
     font-size: 12px;
   }
+  .removeIcon {
+    margin-left: 10px;
+    color: #8c8c8c;
+    cursor: pointer;
+  }
+
+  .addTimeIcon {
+    cursor: pointer;
+  }
 </style>

+ 27 - 21
src/views/cameras/preview/components/AlgorithmsSetting/AlgorithmsSetting.vue

@@ -4,19 +4,15 @@
     <div style="display: flex">
       <div style="width: 200px">
         <AlgoTag
-          v-for="item in data"
+          v-for="item in cameraAlgoList"
           :key="item.code"
           :label="item.algoInfo?.name"
-          :is-active="item.algoId === activeCameraAlgoId"
+          :is-active="item.algoId === selectedAlgoId"
           @click="handleSelectAlgo(item.algoId)"
         />
       </div>
       <div>
-        <AlgoSettingCard
-          @on-submit="handleSubmit"
-          @on-remove="handleRemove"
-          :activeAlgoId="activeCameraAlgoId"
-        />
+        <AlgoSettingCard @on-submit="handleSubmit" @on-remove="handleRemove" />
       </div>
     </div>
   </div>
@@ -26,48 +22,58 @@
   import useCameraAlgoStore from '../../store/useCameraAlgoStore';
   import AlgoSettingCard from './AlgoSettingCard.vue';
   import { storeToRefs } from 'pinia';
-  import { deleteCameraAlgoApi, saveCameraAlgoApi } from '@/api/camera/camera-preview';
+  import {
+    deleteCameraAlgoApi,
+    createCameraAlgoApi,
+    updateCameraAlgoApi,
+  } from '@/api/camera/camera-preview';
   import { useRouteQuery } from '@vueuse/router';
-  import { ElMessage, ElTag } from 'element-plus';
+  import { ElMessage } from 'element-plus';
   import AlgoTag from './AlgoTag.vue';
 
-  const bindAlgoList = defineProps<{ bindAlgoList: any }>();
   const cameraAlgoStore = useCameraAlgoStore();
 
-  const { getCameraAlgo } = cameraAlgoStore;
-  const { data, loading } = storeToRefs(cameraAlgoStore);
+  const { getCameraAlgoList, getAllAlgoList } = cameraAlgoStore;
+  const { cameraAlgoList, selectedAlgoId } = storeToRefs(cameraAlgoStore);
 
   const cameraId = useRouteQuery('cameraId', '', { transform: (str) => Number(str) });
-  const activeCameraAlgoId = ref<number | null>(null);
   onMounted(() => {
-    getCameraAlgo(cameraId.value);
+    getCameraAlgoList(cameraId.value);
+    getAllAlgoList();
   });
 
   const handleSelectAlgo = (id: number) => {
-    activeCameraAlgoId.value = id;
+    selectedAlgoId.value = id;
   };
 
   const handleSubmit = (param) => {
     console.log('submitParam', param);
     const newParam = {
       cameraId: cameraId.value,
-      electronicFence: '',
+      electronicFence: param.electronicFence,
       algoId: param.algoId,
       detectionFrequency: param.detectionFrequency,
       detectionTime: param.detectionTime,
       status: param.status,
     };
-    saveCameraAlgoApi(newParam).then(() => {
-      ElMessage.success('保存成功');
-      getCameraAlgo(cameraId.value);
-    });
+    if (param.id) {
+      updateCameraAlgoApi({ ...newParam, id: param.id }).then(() => {
+        ElMessage.success('更新成功');
+        getCameraAlgoList(cameraId.value);
+      });
+    } else {
+      createCameraAlgoApi(newParam).then(() => {
+        ElMessage.success('保存成功');
+        getCameraAlgoList(cameraId.value);
+      });
+    }
   };
 
   const handleRemove = (algoId: number) => {
     console.log('remove', algoId);
     deleteCameraAlgoApi({ algoId, cameraId: cameraId.value }).then(() => {
       ElMessage.success('删除成功');
-      getCameraAlgo(cameraId.value);
+      getCameraAlgoList(cameraId.value);
     });
   };
 </script>

+ 3 - 3
src/views/cameras/preview/components/AlgorithmsSetting/types.ts

@@ -1,4 +1,4 @@
 export enum STATUS {
-  enabled = 1;
-  disabled = 0;
-}
+  enabled = 1,
+  disabled = 0,
+}

+ 0 - 11
src/views/cameras/preview/components/AlgorithmsSetting/useAllAlgos.ts

@@ -1,11 +0,0 @@
-import { getAllAlgosApi } from '@/api/camera/camera-preview';
-import { useRequest } from 'vue-hooks-plus';
-
-/** 获取所有的算法列表 */
-const useAllAlgos = () => {
-  const { data, loading } = useRequest(getAllAlgosApi);
-
-  return { data, loading };
-};
-
-export default useAllAlgos;

+ 30 - 0
src/views/cameras/preview/components/AlgorithmsSetting/utils.ts

@@ -0,0 +1,30 @@
+import dayjs, { Dayjs } from 'dayjs';
+import { uid } from 'uid';
+
+export const createDefaultTime = () => {
+  return { id: uid(), value: [dayjs(), dayjs().add(1, 'hour')] as [Dayjs, Dayjs] };
+};
+
+export enum FrequencyEnum {
+  second = 1,
+  miniute = 60,
+  hour = 3600,
+}
+
+export const frequencyOptions = [
+  { label: '秒', value: FrequencyEnum.second },
+  { label: '分钟', value: FrequencyEnum.miniute },
+  { label: '小时', value: FrequencyEnum.hour },
+];
+/** 根据后端返回的时间,拆分成单位和数值 */
+export const getDetectionJSON = (time: number | undefined | null) => {
+  if (time && time > 0) {
+    for (let i = frequencyOptions.length - 1; i >= 0; i--) {
+      const unit = frequencyOptions[i].value;
+      if (time >= unit) {
+        return { detectionNum: Math.floor(time / unit), detectionUnit: unit };
+      }
+    }
+  }
+  return { detectionNum: 5, detectionUnit: FrequencyEnum.miniute };
+};

+ 52 - 5
src/views/cameras/preview/store/useCameraAlgoStore.ts

@@ -1,20 +1,67 @@
-import { getCameraAlgoListApi } from '@/api/camera/camera-preview';
+import {
+  getAllAlgosApi,
+  getCameraAlgoListApi,
+  CameraAlgoItem,
+  AlgoStatus,
+} from '@/api/camera/camera-preview';
 import { defineStore } from 'pinia';
+import { computed, ref } from 'vue';
 import { useRequest } from 'vue-hooks-plus';
 
 const useCameraAlgoStore = defineStore('cameraAlgo', () => {
-  const { data, loading, runAsync } = useRequest(
+  const { data: cameraAlgoList, runAsync: getCameraAlgoList } = useRequest(
     (cameraId: number) => {
       return getCameraAlgoListApi(cameraId);
     },
     { manual: true },
   );
 
-  const getAlgoDetail = (algoId: number) => {
-    return data.value?.find((x) => x.algoId === algoId);
+  const { data: allAlgoList, runAsync: getAllAlgoList } = useRequest(getAllAlgosApi, {
+    manual: true,
+  });
+
+  /** 所有算法列表中选定的算法id */
+  const selectedAlgoId = ref<number>();
+
+  const selectedAlgoDetail = computed(() => {
+    if (!selectedAlgoId.value) return null;
+    return getAlgoDetail(selectedAlgoId.value);
+  });
+
+  const getAlgoDetail = (algoId: number): null | CameraAlgoItem => {
+    const detailWithCamera = cameraAlgoList.value?.find((x) => x.algoId === algoId);
+    if (detailWithCamera) return detailWithCamera;
+    const algoDetail = allAlgoList.value?.find((x) => x.id === algoId);
+    if (!algoDetail) return null;
+    return {
+      algoInfo: algoDetail,
+      id: undefined,
+      algoId: algoDetail?.id,
+      status: AlgoStatus.disabled,
+      electronicFence: 0,
+      cameraId: undefined,
+      code: '',
+      name: '',
+      detectionFrequency: 0,
+      detectionTime: '',
+    };
   };
 
-  return { data, loading, getCameraAlgo: runAsync, getAlgoDetail };
+  /** 算法是否已经绑定到相机 */
+  const isAlgoBind = (algoId: number) => {
+    return cameraAlgoList.value?.find((x) => x.algoId === algoId);
+  };
+
+  return {
+    cameraAlgoList,
+    getCameraAlgoList,
+    selectedAlgoId,
+    allAlgoList,
+    getAllAlgoList,
+    getAlgoDetail,
+    selectedAlgoDetail,
+    isAlgoBind,
+  };
 });
 
 export default useCameraAlgoStore;