Просмотр исходного кода

feat: 相机配置-单相机&批量操作功能

bxy 1 год назад
Родитель
Сommit
4a536fadae

+ 17 - 10
src/api/camera/camera-config.ts

@@ -43,36 +43,43 @@ export interface AlgoStruct {
   algoName: string; // 算法名称
 }
 export interface QueryAlgoStatusByCameraIdRes {
-  enabledAlgoList: Array<AlgoStruct>; // 已开启算法列表(已添加)
-  notEnabledAlgoList: Array<AlgoStruct>; // 未开启算法列表(已添加)
-  savedAlgoList: Array<AlgoStruct>; // 已添加算法列表(共同算法
-  notSavedAlgoList: Array<AlgoStruct>; // 未添加算法列表
+  enabledAlgoBingjiList: Array<AlgoStruct>; // 已开启算法列表(已添加)
+  notEnabledAlgoBingjiList: Array<AlgoStruct>; // 未开启算法列表(已添加)
+  savedAlgoBingjiList: Array<AlgoStruct>; // 已添加算法列表(全部
+  savedAlgoJiaojiList: Array<AlgoStruct>; // 已添加算法列表(共同算法)
 }
 
 // 根据相机id查询算法状态
-export function getAlgoStatusByCameraIds(params: { cameraIdList: number[] }) {
+export function getAlgoStatusByCameraIds(data: { cameraIdList: number[] }) {
   return http.request({
     url: '/admin/algo/queryAlgoStatusByCameraId',
     method: 'post',
-    params,
+    data,
   });
 }
 
 // 相机算法批量添加
-export function addAlgosByBatch(params: { cameraIdList: number[]; algoIdList: number[] }) {
+export function addAlgosByBatch(data: { cameraIdList: number[]; algoIdList: number[] }) {
   return http.request({
     url: '/admin/algo/batchSaveCameraAlgoRel',
     method: 'post',
-    params,
+    data,
   });
 }
 
+export interface BatchUpdateCameraAlgoRelParams {
+  cameraIdList?: number[]; //相机id列表
+  algoId?: number; //算法id
+  extra?: string; //扩展数据
+  detectionTime?: string; //检测时间段
+  detectionFrequency?: number; //检测频率
+}
 // 相机算法参数批量设置
-export function updateAlgosByBatch(params: { cameraIdList: number[]; algoId: number; algoParam: string }) {
+export function updateAlgosByBatch(data: BatchUpdateCameraAlgoRelParams) {
   return http.request({
     url: '/admin/algo/batchUpdateCameraAlgoRelParam',
     method: 'post',
-    params,
+    data,
   });
 }
 

+ 1 - 1
src/modules/algo/algo-params-edit/AlgoParamsCard.vue

@@ -166,7 +166,7 @@
 
       //先定form字段集合,如果有nextobj,添加子字段
       const meta = metaObjList.value.find((item) => item.label === val);
-      const nexts = meta.nextObjs;
+      const nexts = meta?.nextObjs;
       if (nexts) {
         for (let i = 0; i < nexts.length; i++) {
           const item = nexts[i];

+ 2 - 2
src/modules/algo/algo-params-edit/index.vue

@@ -11,7 +11,7 @@
             <div
               class="timeAdd"
               :class="{ addDisable: unEmptyLabels.length >= metaObjList.length }"
-              @click="handleAddMetaObj"
+              @click="unEmptyLabels.length >= metaObjList.length ? null : handleAddMetaObj"
             >
               <el-icon color="#d0d0d0"><Plus /></el-icon>
             </div>
@@ -322,7 +322,7 @@
         min_height: meta['min_height'],
       } as any;
       const nextValues = [] as any[];
-      obj.nextObjs.forEach((next) => {
+      obj?.nextObjs?.forEach((next) => {
         if (meta[`${next.label}.confidence`]) {
           nextValues.push({
             label: next.label,

+ 2 - 0
src/modules/algo/algo-params-edit/utils.ts

@@ -241,6 +241,8 @@ export const algoDetailToJSON = (detail) => {
 
   return {
     ...detail,
+    algoId: detail?.id, // 兼容算法默认参数
+    algoInfo: detail, // 兼容算法默认参数
     inferCode: getInferCode(detail?.extra),
     // detectionJSON,
     enableCardBool: enableCard,

+ 11 - 11
src/views/cameras/preview/components/CameraConfigSingle/BatchOperationDialog.vue

@@ -14,10 +14,11 @@
         class="algo-item"
         :class="{
           'active-item': chooseAlgos.find((obj) => obj.algoId === item.algoId),
-          'added-item': type === 'add' && algoStatusList?.savedAlgoList?.find((obj) => obj.algoId === item.algoId),
+          'added-item':
+            type === 'add' && algoStatusList?.savedAlgoJiaojiList?.find((obj) => obj.algoId === item.algoId),
         }"
         @click="
-          type === 'add' && algoStatusList?.savedAlgoList?.find((obj) => obj.algoId === item.algoId)
+          type === 'add' && algoStatusList?.savedAlgoJiaojiList?.find((obj) => obj.algoId === item.algoId)
             ? null
             : handleChangeChooseAlgos(item)
         "
@@ -87,13 +88,13 @@
   const hasAlgosOfType = computed(() => {
     switch (props.type) {
       case 'set':
-        if (algoStatusList.value) return algoStatusList.value?.savedAlgoList?.length > 0;
+        if (algoStatusList.value) return algoStatusList.value?.savedAlgoJiaojiList?.length > 0;
       case 'open':
-        if (algoStatusList.value) return algoStatusList.value?.notEnabledAlgoList?.length > 0;
+        if (algoStatusList.value) return algoStatusList.value?.notEnabledAlgoBingjiList?.length > 0;
       case 'close':
-        if (algoStatusList.value) return algoStatusList.value?.enabledAlgoList?.length > 0;
+        if (algoStatusList.value) return algoStatusList.value?.enabledAlgoBingjiList?.length > 0;
       case 'delete':
-        if (algoStatusList.value) return algoStatusList.value?.savedAlgoList?.length > 0;
+        if (algoStatusList.value) return algoStatusList.value?.savedAlgoBingjiList?.length > 0;
       default:
         return true;
     }
@@ -116,25 +117,25 @@
 
   const getAlgoListByType = () => {
     if (props.type === 'set') {
-      algosList.value = algoStatusList.value?.savedAlgoList.map((item) => ({
+      algosList.value = algoStatusList.value?.savedAlgoJiaojiList.map((item) => ({
         algoName: item.algoName,
         algoId: item.algoId,
       }));
     }
     if (props.type === 'open') {
-      algosList.value = algoStatusList.value?.notEnabledAlgoList.map((item) => ({
+      algosList.value = algoStatusList.value?.notEnabledAlgoBingjiList.map((item) => ({
         algoName: item.algoName,
         algoId: item.algoId,
       }));
     }
     if (props.type === 'close') {
-      algosList.value = algoStatusList.value?.enabledAlgoList.map((item) => ({
+      algosList.value = algoStatusList.value?.enabledAlgoBingjiList.map((item) => ({
         algoName: item.algoName,
         algoId: item.algoId,
       }));
     }
     if (props.type === 'delete') {
-      algosList.value = algoStatusList.value?.savedAlgoList.map((item) => ({
+      algosList.value = algoStatusList.value?.savedAlgoBingjiList.map((item) => ({
         algoName: item.algoName,
         algoId: item.algoId,
       }));
@@ -168,7 +169,6 @@
   // 全选
   const handleChooseAllAlgos = () => {
     chooseAlgos.value = algosList.value || [];
-    console.log('chooseAlgos.value', chooseAlgos.value);
   };
   // 重置
   const resetChooseAlgos = () => {

+ 141 - 94
src/views/cameras/preview/components/CameraConfigSingle/CameraConfigSingle.vue

@@ -1,58 +1,84 @@
 <template>
-  <QueryForm :algos-info="algosInfo" @on-search="handleQueryTableData" @on-reset="handleResetTableData" />
-  <div v-if="showActionBar" class="action-bar">
-    <span class="num-text">已选{{ chooseNum }}项</span>
-    <el-button :class="isAlgoAdd ? 'btn-active' : 'btn-normal'" @click="handleAlgosAdd">算法添加</el-button>
-    <el-button :class="isParamsSet ? 'btn-active' : 'btn-normal'" @click="handleParamsSet">参数设置</el-button>
-    <el-button :class="isAlgoOpen ? 'btn-active' : 'btn-normal'" @click="handleAlgosOpen">算法开启</el-button>
-    <el-button :class="isAlgoClose ? 'btn-active' : 'btn-normal'" @click="handleAlgosClose">算法关闭</el-button>
-    <el-button :class="isAlgoDelete ? 'btn-active' : 'btn-normal'" @click="handleAlgosDel">算法删除</el-button>
-    <span class="close-btn" @click="handleSelectNone"></span>
-  </div>
-  <SingleCameraTable
-    ref="singleCameraTableRef"
-    class="table-bar"
-    :table-data="tableData"
-    @on-filter="handleFilterTable"
-    @on-reset="handleResetTable"
-    @on-refresh="getTableData"
-    @update:selection="handlePop"
-  />
-  <Pagination
-    v-model:page="tableQueryParams.pageNumber"
-    v-model:size="tableQueryParams.pageSize"
-    :total="total"
-    @update:page="handlePageChange"
-    @update:size="handleSizeChange"
-    style="margin-bottom: 0"
-  />
-  <BatchOperationDialog
-    v-if="batchOperationVisible"
-    :type="batchOperationType"
-    :camera-ids="chooseId"
-    :all-algo-list="algosInfo"
-    @on-confirm="handleConfirmBatchOperation"
-    @on-close="handleCloseBatchOperation"
-  />
-  <div class="batch-param-set" v-if="isBatchParamSetVisible">
-    <div class="batch-param-set-header">
-      <div class="algo-title">气密人员隔离</div>
-      <div class="set-tips">
-        <el-icon :size="15"><InfoFilled /></el-icon>
-        <div class="tip"
-          >当前为默认参数值,请选择具体参数进行修改,提交后,新参数值将对所选相机全部生效,覆盖原有参数值</div
-        >
-      </div>
-      <el-icon class="set-close" :size="24" @click="isBatchParamSetVisible = false"><Close /></el-icon>
+  <div>
+    <QueryForm :algos-info="algosInfo" @on-search="handleQueryTableData" @on-reset="handleResetTableData" />
+    <div v-if="showActionBar" class="action-bar">
+      <span class="num-text">已选{{ chooseNum }}项</span>
+      <el-button :class="isAlgoAdd ? 'btn-active' : 'btn-normal'" @click="handleAlgosAdd" v-if="hasAddPermission()"
+        >算法添加</el-button
+      >
+      <el-button
+        :class="isParamsSet ? 'btn-active' : 'btn-normal'"
+        @click="handleParamsSet"
+        v-if="hasParamSetPermission()"
+        >参数设置</el-button
+      >
+      <el-button :class="isAlgoOpen ? 'btn-active' : 'btn-normal'" @click="handleAlgosOpen">算法开启</el-button>
+      <el-button :class="isAlgoClose ? 'btn-active' : 'btn-normal'" @click="handleAlgosClose">算法关闭</el-button>
+      <el-button
+        :class="isAlgoDelete ? 'btn-active' : 'btn-normal'"
+        @click="handleAlgosDel"
+        v-if="hasDeletePermission()"
+        >算法删除</el-button
+      >
+      <span class="close-btn" @click="handleSelectNone"></span>
     </div>
-    <AlgoParamsSetting :algo-detail="selectedAlgoDetail" @on-submit="handleSubmit" @on-cancel="handleCancel" />
+    <SingleCameraTable
+      ref="singleCameraTableRef"
+      class="table-bar"
+      :table-data="tableData"
+      @on-filter="handleFilterTable"
+      @on-reset="handleResetTable"
+      @on-refresh="getTableData"
+      @update:selection="handlePop"
+    />
+    <Pagination
+      v-model:page="tableQueryParams.pageNumber"
+      v-model:size="tableQueryParams.pageSize"
+      :total="total"
+      @update:page="handlePageChange"
+      @update:size="handleSizeChange"
+      style="margin-bottom: 0"
+    />
+    <BatchOperationDialog
+      v-if="batchOperationVisible"
+      :type="batchOperationType"
+      :camera-ids="chooseId"
+      :all-algo-list="algosInfo"
+      @on-confirm="handleConfirmBatchOperation"
+      @on-close="handleCloseBatchOperation"
+    />
+    <el-dialog
+      v-model="isBatchParamSetVisible"
+      width="1022"
+      align-center
+      :close-on-click-modal="false"
+      @close="handleCancel"
+    >
+      <template #header>
+        <div class="batch-param-set-header">
+          <div class="algo-title">{{ selectedAlgoDetail?.name }}</div>
+          <div class="set-tips">
+            <el-icon :size="15"><InfoFilled /></el-icon>
+            <div class="tip"
+              >当前显示默认参数值,请选择具体参数进行修改,提交后新参数值将对所选全部相机生效,覆盖原有参数值</div
+            >
+          </div>
+        </div>
+      </template>
+      <AlgoParamsSetting
+        v-if="selectedAlgoDetail"
+        :algo-detail="selectedAlgoDetail"
+        @on-submit="handleSubmit"
+        @on-cancel="handleCancel"
+      />
+    </el-dialog>
   </div>
 </template>
 
 <script lang="ts" setup>
   import { onMounted, ref } from 'vue';
-  import { ElButton, ElIcon } from 'element-plus';
-  import { InfoFilled, Close } from '@element-plus/icons-vue';
+  import { ElButton, ElIcon, ElMessage, ElDialog } from 'element-plus';
+  import { InfoFilled } from '@element-plus/icons-vue';
   import {
     QueryCameraPageByAlgoParams,
     QueryCameraPageByAlgoRes,
@@ -62,12 +88,30 @@
     addAlgosByBatch,
     deleteAlgosByBatch,
     updateAlgosStatusByBatch,
+    updateAlgosByBatch,
   } from '@/api/camera/camera-config';
   import QueryForm from './QueryForm.vue';
   import SingleCameraTable from './SingleCameraTable.vue';
   import Pagination from '@/components/Pagination/Pagination.vue';
   import BatchOperationDialog from './BatchOperationDialog.vue';
-  import AlgoParamsSetting from '@/modules/algo/algo-params-edit/index.vue'; // 多相机共同算法配置组件
+  import AlgoParamsSetting from '@/modules/algo/algo-params-edit/index.vue';
+  import { CameraAlgoItemInCard } from '@/modules/algo/algo-params-edit/types';
+  import { createAlgoSubmitParams, algoDetailToJSON } from '@/modules/algo/algo-params-edit/utils';
+  import { useUserStore } from '@/store/modules/user';
+  import { PERM_ALGO } from '@/types/permission/constants';
+
+  const userStore = useUserStore();
+
+  // 权限设置
+  const hasAddPermission = () => {
+    return userStore.checkPermission(PERM_ALGO.CONFIG_ADD);
+  };
+  const hasDeletePermission = () => {
+    return userStore.checkPermission(PERM_ALGO.CONFIG_DELETE);
+  };
+  const hasParamSetPermission = () => {
+    return userStore.checkPermission(PERM_ALGO.CONFIG_PARAM);
+  };
 
   const tableQueryParams = ref<QueryCameraPageByAlgoParams>({
     pageNumber: 1,
@@ -93,7 +137,8 @@
   const batchOperationType = ref('');
   const batchOperationVisible = ref(false);
   // 批量参数设置
-  const isBatchParamSetVisible = ref(true);
+  const isBatchParamSetVisible = ref(false);
+  const selectedAlgoDetail = ref<CameraAlgoItemInCard>(); // 批量参数设置组件的参数
 
   // 查询
   const handleQueryTableData = (queryParams) => {
@@ -209,30 +254,37 @@
   };
   // 批量操作弹窗
   const handleConfirmBatchOperation = (algoIds) => {
-    console.log('algoIds', algoIds);
-    console.log('batchOperationType.value', batchOperationType.value);
-    // 这里可以根据不同的操作类型,调用不同的接口
     if (batchOperationType.value === 'add') {
       addAlgosByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds }).then(() => {
+        ElMessage({ type: 'success', message: '算法添加成功' });
         handleCloseBatchOperation();
+        getTableData();
       });
     }
     if (batchOperationType.value === 'set') {
       isBatchParamSetVisible.value = true;
+      const algoDetail = algosInfo.value.find((item) => item.id === algoIds[0]);
+      selectedAlgoDetail.value = algoDetailToJSON(algoDetail);
     }
     if (batchOperationType.value === 'open') {
       updateAlgosStatusByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds, isEnabled: true }).then(() => {
+        ElMessage({ type: 'success', message: '算法开启成功' });
         handleCloseBatchOperation();
+        getTableData();
       });
     }
     if (batchOperationType.value === 'close') {
       updateAlgosStatusByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds, isEnabled: false }).then(() => {
+        ElMessage({ type: 'success', message: '算法关闭成功' });
         handleCloseBatchOperation();
+        getTableData();
       });
     }
     if (batchOperationType.value === 'delete') {
       deleteAlgosByBatch({ cameraIdList: chooseId.value, algoIdList: algoIds }).then(() => {
+        ElMessage({ type: 'success', message: '算法删除成功' });
         handleCloseBatchOperation();
+        getTableData();
       });
     }
   };
@@ -240,7 +292,21 @@
     batchOperationType.value = '';
     batchOperationVisible.value = false;
     handleResetBtnStatus();
-    getTableData();
+  };
+
+  // 批量参数设置提交
+  const handleSubmit = (param) => {
+    const newParam = createAlgoSubmitParams(param, selectedAlgoDetail.value);
+    updateAlgosByBatch({
+      cameraIdList: chooseId.value,
+      ...newParam,
+    }).then(() => {
+      ElMessage({ type: 'success', message: '参数设置成功' });
+      isBatchParamSetVisible.value = false;
+    });
+  };
+  const handleCancel = () => {
+    isBatchParamSetVisible.value = false;
   };
 
   // 换页,重新获取表格
@@ -264,7 +330,6 @@
     getTableData();
     getAlgosInfo().then((res) => {
       algosInfo.value = res;
-      console.log('algosInfo', algosInfo.value);
     });
   });
 </script>
@@ -315,49 +380,31 @@
     position: relative;
   }
 
-  .batch-param-set {
-    width: 1030px;
-    height: 550px;
-    padding: 20px;
-    border-radius: 4px;
-    box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
-    background-color: #ffffff;
-    z-index: 20;
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    transform: translate(-50%, -50%);
-
-    .batch-param-set-header {
-      width: 100%;
-      height: 80px;
-      border-bottom: 1px solid #e4e7ec;
-      margin-bottom: 20px;
-      position: relative;
-
-      .algo-title {
-        font-size: 20px;
-        font-weight: 600;
-        color: #000000;
-      }
+  .batch-param-set-header {
+    width: 100%;
+    height: 80px;
+    border-bottom: 1px solid #e4e7ec;
+    position: relative;
 
-      .set-tips {
-        display: flex;
-        align-items: center;
-        margin-top: 10px;
-        color: #66abeb;
+    .algo-title {
+      font-size: 20px;
+      font-weight: 600;
+      color: #000000;
+    }
 
-        .tip {
-          margin-left: 2px;
-        }
-      }
+    .set-tips {
+      display: flex;
+      align-items: center;
+      margin-top: 10px;
+      color: #66abeb;
 
-      .set-close {
-        position: absolute;
-        top: 0;
-        right: 0;
-        cursor: pointer;
+      .tip {
+        margin-left: 2px;
       }
     }
   }
+
+  :deep(.el-dialog__header) {
+    padding-right: 0px;
+  }
 </style>