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

feat: 设备管理-相机管理功能迁移与新增

bxy 1 год назад
Родитель
Сommit
6737ea683f
30 измененных файлов с 932 добавлено и 488 удалено
  1. 21 20
      src/api/camera/camera-nvr.ts
  2. 126 107
      src/api/camera/camera-overview.ts
  3. 0 0
      src/types/camera/constant.ts
  4. 53 7
      src/views/cameras/overview/type.ts
  5. 16 5
      src/views/cameras/overview/CamerasOverview.vue
  6. 75 67
      src/views/cameras/overview/components/AddCameraByIP.vue
  7. 76 79
      src/views/cameras/overview/components/AddCameraByNVR.vue
  8. 3 3
      src/views/cameras/overview/components/AddCameraByRange.vue
  9. 159 110
      src/views/cameras/overview/components/AddCameraBySRS.vue
  10. 10 4
      src/views/cameras/overview/components/CameraAddPopover.vue
  11. 15 14
      src/views/cameras/overview/components/CameraEditNVRPopover.vue
  12. 15 16
      src/views/cameras/overview/components/CameraEditPopover.vue
  13. 15 9
      src/views/cameras/overview/components/CameraEditSRSPopover.vue
  14. 6 2
      src/views/cameras/overview/components/CameraEditshared.vue
  15. 8 4
      src/views/cameras/overview/components/CameraSharePopover.vue
  16. 6 2
      src/views/cameras/overview/components/CameraSharedEdit.vue
  17. 1 1
      src/views/cameras/overview/components/ConditionQuery.vue
  18. 2 2
      src/views/cameras/overview/components/EditSharedCamera.vue
  19. 7 3
      src/views/cameras/overview/components/ShareCameraDetail.vue
  20. 2 2
      src/views/cameras/overview/components/SharedTable.vue
  21. 115 0
      src/views/cameras/overview/components/sysConfigItemOfAddCamera.vue
  22. 42 9
      src/views/cameras/overview/overviewColumns.ts
  23. 0 0
      src/views/cameras/overview/hooks/searchRangeColumns.ts
  24. 1 1
      src/views/cameras/overview/sharedColumns.ts
  25. 0 0
      src/views/cameras/overview/hooks/useCameraShare.ts
  26. 34 0
      src/views/cameras/overview/hooks/useNvrDevice.ts
  27. 56 0
      src/views/cameras/overview/hooks/useTreeWorkspaceInfo.ts
  28. 29 20
      src/views/cameras/overview/stores/useCameraOverview.ts
  29. 38 0
      src/views/cameras/overview/stores/useSceneTemplateList.ts
  30. 1 1
      src/views/cameras/overview/stores/useSharedCamera.ts

+ 21 - 20
src/api/camera/camera-nvr.ts

@@ -1,31 +1,31 @@
 import { http } from '@/utils/http/axios';
 
 export interface NVRListItem {
-  code: string;           // 编码
-  name: string;           // NVR名称
-  nvrIp: string;          // NVR的IP地址
-  nvrPort: string;        // NVR端口号
-  nvrType: string;        // NVR品牌
-  password: string;       // NVR登录密码
-  principal?: string;     // 设备安装负责人
-  remark?: string;        // 备注
-  username: string;       // NVR登录用户名
+  code: string; // 编码
+  name: string; // NVR名称
+  nvrIp: string; // NVR的IP地址
+  nvrPort: string; // NVR端口号
+  nvrType: string; // NVR品牌
+  password: string; // NVR登录密码
+  principal?: string; // 设备安装负责人
+  remark?: string; // 备注
+  username: string; // NVR登录用户名
   workshopList: number[]; // NVR使用车间列表
-};
+}
 
 export interface NVRListItemAll extends NVRListItem {
   id: number;
-  tenantId: number;     // 租户ID
+  tenantId: number; // 租户ID
   createdAt: string;
   updatedAt: string;
-  isDeleted: number;    // 0-未删除,>0-已删除
+  isDeleted: number; // 0-未删除,>0-已删除
   workshopName: string; // NVR绑定车间名称展示
 }
 
 export interface NVRQueryItem {
   pageNumber: number;
   pageSize: number;
-};
+}
 
 // 添加NVR
 export const addNVRListItem = (data: NVRListItem) => {
@@ -60,10 +60,11 @@ export const getNVRList = (query: NVRQueryItem) => {
     method: 'get',
   });
 };
-// export const getNVRList = (data: NVRQueryItem) => {
-//   return http.request({
-//     url: '/nvrOption/getNvr',
-//     method: 'get',
-//     data,
-//   });
-// };
+
+// 不分页,获取nvr列表所有信息
+export const getAllNVRList = () => {
+  return http.request({
+    url: '/admin/nvr/queryNvrList',
+    method: 'get',
+  });
+};

+ 126 - 107
src/api/camera/camera-overview.ts

@@ -1,11 +1,12 @@
 import { http } from '@/utils/http/axios';
 import {
-  CameraIPItem,
+  CameraAddType,
+  // CameraIPItem,
   CameraShowItem,
   CameraRangeItem,
-  CameraSRS,
-  CameraNVRItem,
-} from '@/views/cameras/overview/type';
+  // CameraSRS,
+  // CameraNVRItem,
+} from '@/types/camera/type';
 
 export type PaginationArrayData<T> = {
   records: T[];
@@ -15,23 +16,21 @@ export type PaginationArrayData<T> = {
   totalRow: number;
 };
 
+export type CameraQueryParamDetails = {
+  ip?: string; // 相机IP
+  code?: string; // 相机code
+  cameraType?: string; // 相机协议类型
+  sceneCode?: string; // 场景编码
+  sourceType?: string; // 添加方式:IP,NVR,RTSP
+  integrationState?: number; // 是否接入平台
+  networkingState?: number; // 联网状态
+  openEagle?: number; // 是否开启鹰眼追踪
+};
+
 export type CameraQueryParams = {
-  /** 相机协议类型 */
-  cameraType?: string;
-  /** 设备ID */
-  code?: string;
-  /** 相机IP */
-  ip?: string;
-  /** 场景 */
-  sceneCode?: string;
-  /** 是否接入平台 */
-  integrationState?: number;
-  /** 联网状态 */
-  networkingState?: number;
   pageNumber?: number;
   pageSize?: number;
-  sourceType?: string;
-  openEagle?: number;
+  queryParam: CameraQueryParamDetails;
 };
 
 export enum IsPtz {
@@ -39,68 +38,74 @@ export enum IsPtz {
   enbaled = 1,
 }
 
+export interface CameraUrlInfoDTO {
+  pushstreamIp: string; // 推流地址(前端播放的地址)
+  pushstreamRenderUrl: string; // 渲染推流地址(前端播放的渲染地址)
+  m3u8PushstreamIp: string; // ios推流地址(前端播放的地址)
+  m3u8PushstreamRenderIp: string; // ios推流地址(前端播放的地址)
+  pushstreamIpAbs: string; // 推流地址(前端播放的地址)
+  pushstreamRenderUrlAbs: string; //渲染推流地址(前端播放的渲染地址)
+  m3u8PushstreamIpAbs: string; //ios推流地址(前端播放的地址)
+  m3u8PushstreamRenderIpAbs: string; //ios推流地址(前端播放的地址)
+}
+
+export interface PushStreamDTOType {
+  videoUrls: CameraUrlInfoDTO;
+  imageUrl: string; // 摄像头实时记录的画面
+}
+
 /** 根据后端返回的相机详情 */
 export interface CameraDetailServer {
-  /** 相机IP */
-  cameraIp: string;
-  /**	相机协议类型 */
-  cameraType: string;
-  /** 相机端口 */
-  cameraPort: string;
-  /** 相机ID */
-  code: string;
-  /** 工位场景Id */
-  workspaceId: string;
-  /** 车间id */
-  workshopId: string;
-  /** 工位负责人 */
-  principal?: string;
-  /** 描述 */
-  remark?: string;
-  /** 相机名称 */
-  name: string;
-  /** id */
-  id?: number;
-  /** 用户名 */
-  username?: string;
-  /** 密码 */
-  password?: string;
-  /** 相机MAC地址 */
-  cameraMac: string;
-  /** 车间场景名称 */
-  workshopName: string;
-  /** 工位场景名称 */
-  workspaceName: string;
-  /** 联网状态: 0-启用, 1-禁用 */
-  networkingState: number;
-  /** 平台状态: 0-启用, 1-禁用 */
-  integrationState: number;
-  /** 状态: 0-启用, 1-禁用 */
-  status: number;
-  pushstreamIp: string;
-  // 视频流绝对地址
-  pushstreamIpAbs: string;
-  /** 渲染框的视频流相对地址 */
-  pushstreamRenderUrl: string;
-  /** 渲染框的视频流绝对地址 */
-  pushstreamRenderUrlAbs: string;
-  /** 工位code */
-  workspaceCode: string;
-
-  /** 是否支持设置相机转动,比如设置预置位,调整视角等 */
-  isPtz: IsPtz;
-  /** 录制周期 */
-  nvrPeriod: number;
-  /** 录制开始时间 */
-  nvrStartAt: string;
-  /** 录制结束时间 */
-  nvrEndAt: string;
-  /** 分辨率 */
-  resolution: number;
-  //渲染
-  render: number | string;
-  // 平台是否显示电子围栏
-  fenceDisplayStatus: FenceDisplayStatus;
+  id?: number; // 自增主键;
+  workshopId: string; // 车间id
+  workspaceId: string; // 工位id
+  name: string; // 相机名称
+  code: string; // 相机ID
+  cameraIp: string; // 相机IP
+  cameraPort: string; // 相机端口
+  username?: string; // 用户名
+  password?: string; // 密码
+  cameraType: string; // 相机协议类型
+  remark?: string; // 描述
+  isPtz: IsPtz; // 是否支持设置相机转动,比如设置预置位,调整视角等,0-不支持,1-支持
+  onvifPort: string; // 相机的ONVIF端口号
+  sourceType: string; // 相机的添加方式:IP,NVR,RTSP
+  rtspUrl: string; // rtsp地址
+  nvrId: number; // NVRid
+  nvrChannel: string; // NVR通道号
+  videoStandard: string; //视频编码标准,H264, H265
+  videoServiceType: string; // 视频服务类型,TCP, UDP, AUTO
+  isDisabled: number; // 状态: 0-启用, 1-禁用
+  createdBy: number; //创建人
+  updatedBy: number; // 更新人
+  createdAt: string; // 创建时间
+  updatedAt: string; // 更新时间
+  isDeleted: number; //0-未删除,大于0(时间戳)-已删除
+  tenantId: number; // 租户ID
+  networkingState: number; // 联网状态: 0-启用, 1-禁用
+  integrationState: number; // 接入状态: 0-启用, 1-禁用
+  render: number | string; // 渲染选择,无渲染/某个算法
+  version: number; // 版本
+  extra: string; // 扩展数据
+  pushStreamDTO: PushStreamDTOType;
+  companyName: string; // 公司名称
+  workshopName: string; // 车间场景名称
+  workspaceName: string; // 工位名称
+  workspaceCode: string; // 工位code
+  principal?: string; // 工位负责人
+
+  // /** 相机MAC地址 */
+  // cameraMac: string;
+  // /** 录制周期 */
+  // nvrPeriod: number;
+  // /** 录制开始时间 */
+  // nvrStartAt: string;
+  // /** 录制结束时间 */
+  // nvrEndAt: string;
+  // /** 分辨率 */
+  // resolution: number;
+  // // 平台是否显示电子围栏
+  // fenceDisplayStatus: FenceDisplayStatus;
 }
 
 // 是否启用
@@ -111,18 +116,24 @@ export enum FenceDisplayStatus {
   disabled = 1,
 }
 
-export const getCameraList = (params: CameraQueryParams) => {
+export interface CameraStatus {
+  cameraCode: string;
+  integrationState: number;
+  networkingState: number;
+}
+
+export const getCameraList = (data: CameraQueryParams) => {
   return http.request<PaginationArrayData<CameraDetailServer>>({
-    url: '/cameraConfig/findCamera',
-    method: 'get',
-    params,
-    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    url: '/admin/cameraConfig/queryCameraPageByFilters',
+    method: 'post',
+    data: data,
   });
 };
 
-export const addCameraItem = (data: CameraIPItem) => {
+// 添加相机,三种方式,共用此接口
+export const addCameraItem = (data: CameraAddType) => {
   return http.request({
-    url: '/cameraConfig/saveCamera',
+    url: '/admin/cameraConfig/saveCamera',
     method: 'post',
     data: data,
   });
@@ -136,10 +147,10 @@ export const getCamerasByIPRange = (params: CameraRangeItem) => {
   });
 };
 
-export const updateCameraItem = (data: Partial<CameraIPItem>) => {
+export const updateCameraItem = (data: CameraAddType) => {
   return http.request(
     {
-      url: '/cameraConfig/updateCamera',
+      url: '/admin/cameraConfig/updateCamera',
       method: 'put',
       data,
     },
@@ -165,7 +176,7 @@ export const stopCameraStream = (cameraId: number) => {
 
 export const deleteCameraItem = (params: { cameraId: number }) => {
   return http.request({
-    url: `/cameraConfig/deleteCamera?cameraId=${params.cameraId}`,
+    url: `/admin/cameraConfig/deleteCamera?cameraId=${params.cameraId}`,
     method: 'delete',
     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
   });
@@ -182,30 +193,30 @@ export const deleteCameraItems = (data: number[]) => {
 
 /** 获取相机状态 */
 export const getCameraState = (data: { cameraCodeList: string[] }) => {
-  return http.request<{ cameraCode: string; status: 0 | 1 }[]>({
-    url: '/cameraConfig/getCameraStatusList',
+  return http.request<CameraStatus[]>({
+    url: '/admin/cameraConfig/queryCameraStatusList',
     method: 'post',
     data,
   });
 };
 
-/** 添加流媒体相机 */
-export const addSRSCameraItem = (data: CameraSRS) => {
-  return http.request({
-    url: '/cameraConfig/saveRstp',
-    method: 'post',
-    data,
-  });
-};
-
-/** 添加NVR相机 */
-export const addNVRCameraItem = (data: CameraNVRItem) => {
-  return http.request({
-    url: '/cameraConfig/saveByNVR',
-    method: 'post',
-    data,
-  });
-};
+// /** 添加流媒体相机 */
+// export const addSRSCameraItem = (data: CameraSRS) => {
+//   return http.request({
+//     url: '/cameraConfig/saveRstp',
+//     method: 'post',
+//     data,
+//   });
+// };
+
+// /** 添加NVR相机 */
+// export const addNVRCameraItem = (data: CameraNVRItem) => {
+//   return http.request({
+//     url: '/cameraConfig/saveByNVR',
+//     method: 'post',
+//     data,
+//   });
+// };
 
 // 批量添加相机 - 下载场景code
 export function downloadSpaceCode() {
@@ -230,3 +241,11 @@ export function downloadBatchTemplate() {
     { urlPrefix: '/skyeye-file-upload', isShowErrorMessage: false, isTransformResponse: false },
   );
 }
+
+export function getTreeWorkspaceInfo() {
+  return http.request({
+    url: '/admin/workshop/queryCompanyShopSpaceList',
+    method: 'get',
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+  });
+}

src/views/cameras/overview/constant.ts → src/types/camera/constant.ts


+ 53 - 7
src/views/cameras/overview/type.ts

@@ -1,3 +1,32 @@
+export interface CheckedSceneTemplate {
+  sceneId: number;
+  templateId: number;
+}
+
+export interface CameraAddType {
+  id?: number; //相机id:编辑时必传
+  name: string; // 相机名称
+  code: string; // 相机编号、设备ID
+  cameraIp?: string; // 相机IP
+  cameraPort?: string; //	相机端口
+  username?: string; // 用户名
+  password?: string; // 密码
+  cameraType: string; // 协议类型: haikang/dahua/anxus/huawei
+  workshopId: number; // 车间id
+  workspaceId: number; // 工位id
+  remark?: string; // 描述、备注
+  isPtz?: number; // 相机是否支持移动缩放:0-不支持;1-支持
+  onvifPort?: string; // 相机的ONVIF端口号
+  sourceType: string; // 添加方式: IP,NVR,RTSP1
+  rtspUrl?: string; // rtsp地址
+  nvrId?: number; // NVR id
+  nvrChannel?: string; // NVR通道号
+  videoStandard: string; // 视频编码标准,H264, H265
+  videoServiceType?: string; // 视频服务类型,TCP, UDP, AUTO
+  sceneTemplateList: CheckedSceneTemplate[]; // 场景-模板列表
+  version?: number; // 版本
+}
+
 export interface CameraIPItem {
   /** 相机IP */
   cameraIp: string;
@@ -26,10 +55,16 @@ export interface CameraIPItem {
   /** 推流地址 */
   pushstreamIp: string;
   rtspurl: string;
-  //服务类型
+  // 服务类型
   videoServiceType: VideoServiceType;
-  //视频编码类型
+  // 视频编码类型
   videoStandard: VideoStandardType;
+  // 业务场景信息
+  sceneTemplateList: CheckedSceneTemplate[];
+  // 添加方式
+  sourceType: string;
+  // 车间信息
+  workshopId: number;
 }
 
 export interface CameraShowItem extends CameraIPItem {
@@ -45,8 +80,6 @@ export interface CameraShowItem extends CameraIPItem {
   status: number;
   /** 工位code */
   workspaceCode: string;
-  //添加方式
-  sourceType: string;
 }
 
 export interface CameraRangeItem {
@@ -95,15 +128,21 @@ export interface CameraSRS {
   /** 相机工位code */
   workspaceCode?: string;
   /** 流媒体地址 */
-  rtspurl: string;
+  rtspUrl: string;
   /** 工位负责人 */
   principal?: string;
   /** 描述 */
   remark?: string;
-  //服务类型
+  // 服务类型
   videoServiceType: VideoServiceType;
-  //视频编码类型
+  // 视频编码类型
   videoStandard: VideoStandardType;
+  // 业务场景信息
+  sceneTemplateList: CheckedSceneTemplate[];
+  // 添加方式
+  sourceType: string;
+  // 车间信息
+  workshopId: number;
 }
 
 export enum VideoServiceType {
@@ -118,6 +157,7 @@ export enum VideoStandardType {
 }
 
 export interface CameraNVRItem {
+  nvrId?: number; // NVR id
   //名称
   name: string;
   //ip地址
@@ -145,4 +185,10 @@ export interface CameraNVRItem {
   videoServiceType: VideoServiceType;
   //视频编码类型
   videoStandard: VideoStandardType;
+  // 业务场景信息
+  sceneTemplateList: CheckedSceneTemplate[];
+  // 添加方式
+  sourceType: string;
+  // 车间信息
+  workshopId: number;
 }

+ 16 - 5
src/views/cameras/overview/CamerasOverview.vue

@@ -92,7 +92,11 @@
       @close="handleCloseBatchEdit"
     />
     <EditCamera class="add-popover" v-model="showEditPopover" :edit-data="editCameraData" />
-    <EditSRSCamera class="add-popover" v-model="showEditSRSPopover" :edit-data="editCameraData!" />
+    <EditSRSCamera
+      class="add-popover"
+      v-model="showEditSRSPopover"
+      :edit-data="editCameraData! as any as CameraSRS"
+    />
     <EditNVRCamera
       class="add-popover"
       v-model="showEditNVRPopover"
@@ -111,7 +115,7 @@
   import { h, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
   import { BasicTable, TableActionIcons } from '@/components/Table';
   import { BasicColumn } from '@/components/Table';
-  import { columns } from './overviewColumns';
+  import { columns } from './hooks/overviewColumns';
   import ConditionQuery from './components/ConditionQuery.vue';
   import AddCamera from './components/CameraAddPopover.vue';
   import BatchImportCamera from './components/BatchImportCamera.vue';
@@ -129,15 +133,20 @@
   import deleteIcon from '@/assets/images/table/table-delete.png';
   import useCameraOverview from './stores/useCameraOverview';
   import { storeToRefs } from 'pinia';
-  import { CameraIPItem, CameraNVRItem, CameraShowItem } from './type';
+  import { CameraIPItem, CameraNVRItem, CameraShowItem, CameraSRS } from '@/types/camera/type';
   import { deleteCameraItem, deleteCameraItems } from '@/api/camera/camera-overview';
   import { ElMessage, ElMessageBox } from 'element-plus';
-  import useCameraShare from './stores/useCameraShare';
+  import useCameraShare from './hooks/useCameraShare';
   import router from '@/router';
-  import { AddType } from './constant';
+  import { AddType } from '@/types/camera/constant';
   import axios, { AxiosRequestConfig } from 'axios';
   import { getHeaders } from '@/utils/http/axios';
   import { useGlobSetting } from '@/hooks/setting';
+  import { useSceneTemplateList } from './stores/useSceneTemplateList';
+
+  const sceneTemplateListInfo = useSceneTemplateList();
+  const { sceneTemplateList } = storeToRefs(sceneTemplateListInfo);
+  const { getSceneTemplateList } = sceneTemplateListInfo;
 
   const { urlPrefix } = useGlobSetting();
 
@@ -378,6 +387,8 @@
   onMounted(() => {
     getCameraItems();
     openInterval();
+    getSceneTemplateList();
+    console.log('--------------', sceneTemplateList.value);
   });
 
   onBeforeUnmount(() => {

+ 75 - 67
src/views/cameras/overview/components/AddCameraByIP.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div style="margin-bottom: 60px">
+    <div>
       <el-form
         ref="IPFormRef"
         class="ip-form"
@@ -13,6 +13,13 @@
         <el-form-item label="名称:" prop="name">
           <el-input v-model="cameraIPData.name" placeholder="请输入名称" style="width: 200px" />
         </el-form-item>
+        <el-form-item label="设备ID:" prop="code">
+          <el-input
+            v-model="cameraIPData.code"
+            placeholder="自定义ID,不能重复"
+            style="width: 200px"
+          />
+        </el-form-item>
         <el-form-item label="IP地址:" prop="cameraIp">
           <el-input
             v-model="cameraIPData.cameraIp"
@@ -27,10 +34,24 @@
             style="width: 200px"
           />
         </el-form-item>
+        <el-form-item label="用户名:" prop="username">
+          <el-input
+            v-model="cameraIPData.username"
+            placeholder="请输入用户名"
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="密码:" prop="password">
+          <el-input
+            v-model="cameraIPData.password"
+            placeholder="请输入用户名密码"
+            style="width: 200px"
+          />
+        </el-form-item>
         <el-form-item label="协议类型:" prop="cameraType">
           <el-select
             v-model="cameraIPData.cameraType"
-            placeholder="请输入协议类型"
+            placeholder="请选择协议类型"
             style="width: 200px"
           >
             <el-option
@@ -41,69 +62,50 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="用户名:" prop="username">
-          <el-input
-            v-model="cameraIPData.username"
-            placeholder="请输入用户名"
+        <el-form-item label="服务类型:" prop="videoServiceType">
+          <el-select
+            v-model="cameraIPData.videoServiceType"
+            placeholder="请选择服务类型"
             style="width: 200px"
+          >
+            <el-option
+              v-for="protocal in serviceTypeSelect"
+              :key="protocal.value"
+              :label="protocal.label"
+              :value="protocal.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
+          <sysConfigItemOfAddCamera
+            :origin-scene-checked-list="cameraIPData.sceneTemplateList"
+            @update:scene-checked-list="handleUpdateSceneTemplateList"
           />
         </el-form-item>
-        <el-form-item label="场景:" prop="workspaceCode">
+        <el-form-item label="所属工位:" prop="workspaceId">
           <el-tree-select
-            v-model="cameraIPData.workspaceCode"
-            :data="scenesTree"
+            v-model="cameraIPData.workspaceId"
+            :data="workspaceInfo"
             :render-after-expand="false"
             :default-expand-all="props.formData ? true : false"
             check-strictly
-            placeholder="请输入场景名称"
+            placeholder="请选择工位"
             style="width: 200px"
             @node-click="handleTreeSelect"
           />
         </el-form-item>
-        <el-form-item label="密码:" prop="password">
-          <el-input
-            v-model="cameraIPData.password"
-            placeholder="请输入用户名密码"
-            style="width: 200px"
-          />
-        </el-form-item>
         <el-form-item label="工位负责人:" prop="principal">
           <el-input
             v-model="cameraIPData.principal"
-            placeholder="请输入工位负责人"
+            placeholder="请选择工位,该项自动填充"
             disabled
             style="width: 200px"
           />
         </el-form-item>
-
-        <el-form-item label="设备ID号:" prop="code">
-          <el-input
-            v-model="cameraIPData.code"
-            placeholder="自定义ID,不能重复"
-            style="width: 200px"
-          />
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input v-model="cameraIPData.remark" placeholder="请输入备注" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="服务类型:" prop="videoServiceType">
-          <el-select
-            v-model="cameraIPData.videoServiceType"
-            placeholder="请输入服务类型"
-            style="width: 200px"
-          >
-            <el-option
-              v-for="protocal in serviceTypeSelect"
-              :key="protocal.value"
-              :label="protocal.label"
-              :value="protocal.value"
-            />
-          </el-select>
-        </el-form-item>
         <el-form-item label="视频编码标准:" prop="videoStandard">
           <el-select
             v-model="cameraIPData.videoStandard"
-            placeholder="请输入视频编码标准"
+            placeholder="请选择视频编码标准"
             style="width: 200px"
           >
             <el-option
@@ -114,6 +116,9 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="备注:" prop="remark">
+          <el-input v-model="cameraIPData.remark" placeholder="请输入备注" style="width: 200px" />
+        </el-form-item>
       </el-form>
     </div>
     <span class="pop-footer">
@@ -125,36 +130,42 @@
 
 <script setup lang="ts">
   import { onBeforeMount, ref } from 'vue';
-  import { CameraIPItem } from '../type';
-  import { protocalTypeSelect, serviceTypeSelect, standardTypeSelect } from '../constant';
-  import useSceneInfos from '@/hooks/useSceneInfos';
+  import { CameraIPItem } from '@/types/camera/type';
+  import {
+    protocalTypeSelect,
+    serviceTypeSelect,
+    standardTypeSelect,
+  } from '@/types/camera/constant';
+  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
   import { cloneDeep } from 'lodash-es';
   import { ElMessage } from 'element-plus';
+  import sysConfigItemOfAddCamera from './sysConfigItemOfAddCamera.vue';
 
   const props = defineProps<{ formData?: CameraIPItem | null }>();
-
   const emits = defineEmits(['cancel-execute', 'confirm-execute']);
 
-  const sceneInfos = useSceneInfos();
-  const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
+  const treeWorkspaceInfo = useTreeWorkspaceInfo();
+  const { workspaceInfo, getWorkspaceFromTreeInfo } = treeWorkspaceInfo;
 
   const IPFormRef = ref();
-
   const cameraIPData = ref<CameraIPItem>({} as CameraIPItem);
 
   const rules = {
     name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
     cameraIp: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
     cameraPort: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
-    cameraType: [{ required: true, message: '请输入协议类型', trigger: 'blur' }],
     username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
-    workspaceCode: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
     password: [{ required: true, message: '请输入用户名密码', trigger: 'blur' }],
-    principal: [{ required: false }],
-    code: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
-    remark: [{ required: false }],
-    videoServiceType: [{ required: false }],
-    videoStandard: [{ required: true, message: '请输入视频编码标准', trigger: 'blur' }],
+    cameraType: [{ required: true, message: '请选择协议类型', trigger: 'blur' }],
+    sceneTemplateList: [{ required: true, message: '请选择至少一个业务场景', trigger: 'blur' }],
+    workspaceId: [{ required: true, message: '请选择工位', trigger: 'blur' }],
+    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
+  };
+
+  const handleUpdateSceneTemplateList = (data) => {
+    console.log('接收到的信息', data);
+    cameraIPData.value.sceneTemplateList = data;
   };
 
   const handleCancel = () => {
@@ -165,30 +176,27 @@
     IPFormRef.value.validate((valid) => {
       if (valid) {
         const copyData = cloneDeep(cameraIPData.value);
-        copyData.workspaceId = flattendWorkspaces.value.find(
-          (item) => item.code === cameraIPData.value.workspaceCode,
-        ).id;
-        delete (copyData as any).workspaceCode;
         delete (copyData as any).principal;
+        copyData.sourceType = 'IP';
         emits('confirm-execute', copyData);
       }
     });
   };
 
   const handleTreeSelect = (node) => {
-    const space = flattendWorkspaces.value.find((item) => item.code === node.value);
-    cameraIPData.value.workspaceId = space?.id;
-    cameraIPData.value.principal = space?.principal;
+    console.log('点击选择车间', node);
+    cameraIPData.value.workspaceId = node.value;
+    cameraIPData.value.principal = node.principalName;
+    cameraIPData.value.workshopId = node.workshopId;
     if (node.disabled && node.children.length < 1) {
       ElMessage.error('请先添加工位');
     }
   };
 
   onBeforeMount(() => {
-    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
+    getWorkspaceFromTreeInfo();
     if (props.formData) {
       console.log('props.formData', props.formData);
-
       cameraIPData.value = props.formData;
     }
   });

+ 76 - 79
src/views/cameras/overview/components/AddCameraByNVR.vue

@@ -10,97 +10,85 @@
         label-width="124px"
         label-position="left"
       >
+        <el-form-item label="NVR设备:" prop="nvrId" style="width: 766px">
+          <el-select v-model="cameraNVRData.nvrId" placeholder="请选择NVR设备" style="width: 200px">
+            <el-option
+              v-for="item in nvrDevice"
+              :key="item.id"
+              :label="item.label"
+              :value="item.id"
+            />
+          </el-select>
+          <div>
+            <el-icon><InfoFilled /></el-icon>
+            选择已添加在【NVR设备管理】中的设备编号
+          </div>
+        </el-form-item>
         <el-form-item label="名称:" prop="name">
           <el-input v-model="cameraNVRData.name" placeholder="请输入名称" style="width: 200px" />
         </el-form-item>
-        <el-form-item label="NVR平台IP地址:" prop="nvrIp">
+        <el-form-item label="设备ID:" prop="code">
           <el-input
-            v-model="cameraNVRData.nvrIp"
-            placeholder="请输入NVR平台地址"
+            v-model="cameraNVRData.code"
+            placeholder="自定义ID,不能重复"
             style="width: 200px"
           />
         </el-form-item>
-        <el-form-item label="端口:" prop="cameraPort">
+        <el-form-item label="NVR平台通道号:" prop="nvrChannel">
           <el-input
-            v-model="cameraNVRData.cameraPort"
-            placeholder="请输入端口号"
+            v-model="cameraNVRData.nvrChannel"
+            placeholder="请输入NVR平台通道号"
             style="width: 200px"
           />
         </el-form-item>
-        <el-form-item label="协议类型:" prop="cameraType">
+        <el-form-item label="服务类型:" prop="videoServiceType">
           <el-select
-            v-model="cameraNVRData.cameraType"
-            placeholder="请输入协议类型"
+            v-model="cameraNVRData.videoServiceType"
+            placeholder="请选择服务类型"
             style="width: 200px"
           >
             <el-option
-              v-for="protocal in protocalTypeSelect"
+              v-for="protocal in serviceTypeSelect"
               :key="protocal.value"
               :label="protocal.label"
               :value="protocal.value"
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="NVR平台用户名:" prop="nvrUsername">
-          <el-input
-            v-model="cameraNVRData.nvrUsername"
-            placeholder="请输入NVR平台用户名"
-            style="width: 200px"
+        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
+          <sysConfigItemOfAddCamera
+            :origin-scene-checked-list="cameraNVRData.sceneTemplateList"
+            @update:scene-checked-list="handleUpdateSceneTemplateList"
           />
         </el-form-item>
-        <el-form-item label="场景:" prop="workspaceCode">
+        <el-form-item label="所属工位:" prop="workspaceId">
           <el-tree-select
-            v-model="cameraNVRData.workspaceCode"
-            :data="scenesTree"
+            v-model="cameraNVRData.workspaceId"
+            :data="workspaceInfo"
             :render-after-expand="false"
             :default-expand-all="props.formData ? true : false"
             check-strictly
-            placeholder="请输入场景名称"
+            placeholder="请选择工位"
             style="width: 200px"
             @node-click="handleTreeSelect"
           />
         </el-form-item>
-        <el-form-item label="NVR平台密码:" prop="nvrPassword">
-          <el-input
-            v-model="cameraNVRData.nvrPassword"
-            placeholder="请输入NVR平台密码"
-            style="width: 200px"
-          />
-        </el-form-item>
         <el-form-item label="工位负责人:" prop="principal">
           <el-input
             v-model="cameraNVRData.principal"
-            placeholder="请输入工位负责人"
+            placeholder="请选择工位,该项自动填充"
             disabled
             style="width: 200px"
           />
         </el-form-item>
-
-        <el-form-item label="设备ID号:" prop="code">
-          <el-input
-            v-model="cameraNVRData.code"
-            placeholder="自定义ID,不能重复"
-            style="width: 200px"
-          />
-        </el-form-item>
-        <el-form-item label="备注:" prop="remark">
-          <el-input v-model="cameraNVRData.remark" placeholder="请输入备注" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="NVR平台通道号:" prop="nvrChannel">
-          <el-input
-            v-model="cameraNVRData.nvrChannel"
-            placeholder="请输入NVR平台通道号"
-            style="width: 200px"
-          />
-        </el-form-item>
-        <el-form-item label="服务类型:" prop="videoServiceType">
+        <el-form-item label="协议类型:" prop="cameraType">
           <el-select
-            v-model="cameraNVRData.videoServiceType"
-            placeholder="请输入服务类型"
+            v-model="cameraNVRData.cameraType"
+            placeholder="请选择协议类型"
             style="width: 200px"
           >
             <el-option
-              v-for="protocal in serviceTypeSelect"
+              v-for="protocal in protocalTypeSelect"
               :key="protocal.value"
               :label="protocal.label"
               :value="protocal.value"
@@ -110,7 +98,7 @@
         <el-form-item label="视频编码标准:" prop="videoStandard">
           <el-select
             v-model="cameraNVRData.videoStandard"
-            placeholder="请输入视频编码标准"
+            placeholder="请选择视频编码标准"
             style="width: 200px"
           >
             <el-option
@@ -121,6 +109,9 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="备注:" prop="remark">
+          <el-input v-model="cameraNVRData.remark" placeholder="请输入备注" style="width: 200px" />
+        </el-form-item>
       </el-form>
     </div>
     <span class="pop-footer">
@@ -132,37 +123,45 @@
 
 <script setup lang="ts">
   import { onBeforeMount, ref } from 'vue';
-  import { CameraNVRItem } from '../type';
-  import { protocalTypeSelect, serviceTypeSelect, standardTypeSelect } from '../constant';
-  import useSceneInfos from '@/hooks/useSceneInfos';
   import { cloneDeep } from 'lodash-es';
-  import { ElMessage } from 'element-plus';
+  import { ElMessage, ElIcon } from 'element-plus';
+  import { InfoFilled } from '@element-plus/icons-vue';
+  import { CameraNVRItem } from '@/types/camera/type';
+  import {
+    protocalTypeSelect,
+    serviceTypeSelect,
+    standardTypeSelect,
+  } from '@/types/camera/constant';
+  import useNvrDevice from '../hooks/useNvrDevice';
+  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
+  import sysConfigItemOfAddCamera from './sysConfigItemOfAddCamera.vue';
 
   const props = defineProps<{ formData?: CameraNVRItem | null }>();
-
   const emits = defineEmits(['cancel-execute', 'confirm-execute']);
 
-  const sceneInfos = useSceneInfos();
-  const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
+  const nvrDeviceInfo = useNvrDevice();
+  const { nvrDevice, getNvrDevice } = nvrDeviceInfo;
 
-  const NVRFormRef = ref();
+  const treeWorkspaceInfo = useTreeWorkspaceInfo();
+  const { workspaceInfo, getWorkspaceFromTreeInfo } = treeWorkspaceInfo;
 
+  const NVRFormRef = ref();
   const cameraNVRData = ref<CameraNVRItem>({} as CameraNVRItem);
 
   const rules = {
+    nvrId: [{ required: true, message: '请选择NVR设备', trigger: 'blur' }],
     name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    nvrIp: [{ required: true, message: '请输入NVR平台地址', trigger: 'blur' }],
-    cameraPort: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
-    cameraType: [{ required: true, message: '请输入协议类型', trigger: 'blur' }],
-    nvrUsername: [{ required: true, message: '请输入NVR平台用户名', trigger: 'blur' }],
-    workspaceCode: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
-    nvrPassword: [{ required: true, message: '请输入NVR平台密码', trigger: 'blur' }],
-    principal: [{ required: false }],
-    code: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
-    remark: [{ required: false }],
+    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
     nvrChannel: [{ required: true, message: '请输入NVR平台通道号', trigger: 'blur' }],
-    videoServiceType: [{ required: false }],
-    videoStandard: [{ required: true, message: '请输入视频编码标准', trigger: 'blur' }],
+    sceneTemplateList: [{ required: true, message: '请选择至少一个业务场景', trigger: 'blur' }],
+    workspaceId: [{ required: true, message: '请选择工位', trigger: 'blur' }],
+    cameraType: [{ required: true, message: '请选择协议类型', trigger: 'blur' }],
+    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
+  };
+
+  const handleUpdateSceneTemplateList = (data) => {
+    console.log('接收到的信息', data);
+    cameraNVRData.value.sceneTemplateList = data;
   };
 
   const handleCancel = () => {
@@ -173,30 +172,28 @@
     NVRFormRef.value.validate((valid) => {
       if (valid) {
         const copyData = cloneDeep(cameraNVRData.value);
-        console.log();
-
-        copyData.workspaceId = flattendWorkspaces.value.find(
-          (item) => item.code === cameraNVRData.value.workspaceCode,
-        ).id;
-        delete (copyData as any).workspaceCode;
         delete (copyData as any).principal;
+        copyData.sourceType = 'NVR';
         emits('confirm-execute', copyData);
       }
     });
   };
 
   const handleTreeSelect = (node) => {
-    const space = flattendWorkspaces.value.find((item) => item.code === node.value);
-    cameraNVRData.value.workspaceId = space?.id;
-    cameraNVRData.value.principal = space?.principal;
+    console.log('点击选择车间', node);
+    cameraNVRData.value.workspaceId = node.value;
+    cameraNVRData.value.principal = node.principalName;
+    cameraNVRData.value.workshopId = node.workshopId;
     if (node.disabled && node.children.length < 1) {
       ElMessage.error('请先添加工位');
     }
   };
 
   onBeforeMount(() => {
-    getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
+    getNvrDevice();
+    getWorkspaceFromTreeInfo();
     if (props.formData) {
+      console.log('props.formData', props.formData);
       cameraNVRData.value = props.formData;
     }
   });

+ 3 - 3
src/views/cameras/overview/components/AddCameraByRange.vue

@@ -79,12 +79,12 @@
 
 <script setup lang="ts">
   import { computed, h, reactive, ref } from 'vue';
-  import { CameraRangeItem, CameraIPItem } from '../type';
-  import { cameraRangeAddForm } from '../constant';
+  import { CameraRangeItem, CameraIPItem } from '../../../../types/camera/type';
+  import { cameraRangeAddForm } from '../../../../types/camera/constant';
   import SearchCamerasAction from './SearchCamerasAction.vue';
   import { BasicTable } from '@/components/Table';
   import { BasicColumn } from '@/components/Table';
-  import { columns } from '../searchRangeColumns';
+  import { columns } from '../hooks/searchRangeColumns';
   import emptyImg from '@/assets/images/table/table-empty.png';
   import editIcon from '@/assets/images/table/table-edit.png';
   import deleteIcon from '@/assets/images/table/table-delete.png';

+ 159 - 110
src/views/cameras/overview/components/AddCameraBySRS.vue

@@ -1,39 +1,91 @@
 <template>
   <div>
-    <div style="margin-bottom: 120px">
-      <el-form ref="IPFormRef" class="ip-form" :inline="true" :model="CameraSRSData" :rules="rules" label-width="114px"
-        label-position="left">
+    <div>
+      <el-form
+        ref="IPFormRef"
+        class="ip-form"
+        :inline="true"
+        :model="CameraSRSData"
+        :rules="rules"
+        label-width="114px"
+        label-position="left"
+      >
         <el-form-item label="名称:" prop="name">
           <el-input v-model="CameraSRSData.name" placeholder="请输入名称" style="width: 200px" />
         </el-form-item>
-        <el-form-item label="场景:" prop="workspaceCode">
-          <el-tree-select v-model="CameraSRSData.workspaceCode" :data="scenesTree" :render-after-expand="false"
-            :default-expand-all="props.formData ? true : false" check-strictly placeholder="请输入场景名称"
-            style="width: 200px" @node-click="handleTreeSelect" />
+        <el-form-item label="设备ID:" prop="code">
+          <el-input
+            v-model="CameraSRSData.code"
+            placeholder="自定义ID,不能重复"
+            style="width: 200px"
+          />
         </el-form-item>
-        <el-form-item label="设备ID号:" prop="code">
-          <el-input v-model="CameraSRSData.code" placeholder="自定义ID,不能重复" style="width: 200px" />
-        </el-form-item>
-        <el-form-item label="工位负责人:" prop="principal">
-          <el-input v-model="CameraSRSData.principal" placeholder="请输入工位负责人" style="width: 200px" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="rtsp地址:" prop="rtspurl">
-          <el-input v-model="CameraSRSData.rtspurl" placeholder="rtsp://192.168.0.249:557/34020000000_00000000000001"
-            style="width: 685px" />
+        <el-form-item label="rtsp地址:" prop="rtspUrl">
+          <el-input
+            v-model="CameraSRSData.rtspUrl"
+            placeholder="rtsp://192.168.0.249:557/34020000000_00000000000001"
+            style="width: 655px"
+          />
         </el-form-item>
         <el-form-item label="相机IP地址:" prop="cameraIp">
-          <el-input v-model="CameraSRSData.cameraIp" placeholder="请输入IP地址" style="width: 200px" />
+          <el-input
+            v-model="CameraSRSData.cameraIp"
+            placeholder="请输入IP地址"
+            style="width: 200px"
+          />
         </el-form-item>
         <el-form-item label="服务类型:" prop="videoServiceType">
-          <el-select v-model="CameraSRSData.videoServiceType" placeholder="请输入服务类型" style="width: 200px">
-            <el-option v-for="protocal in serviceTypeSelect" :key="protocal.value" :label="protocal.label"
-              :value="protocal.value" />
+          <el-select
+            v-model="CameraSRSData.videoServiceType"
+            placeholder="请选择服务类型"
+            style="width: 200px"
+          >
+            <el-option
+              v-for="protocal in serviceTypeSelect"
+              :key="protocal.value"
+              :label="protocal.label"
+              :value="protocal.value"
+            />
           </el-select>
         </el-form-item>
+        <el-form-item label="业务场景:" prop="sceneTemplateList" style="width: 766px">
+          <sysConfigItemOfAddCamera
+            :origin-scene-checked-list="CameraSRSData.sceneTemplateList"
+            @update:scene-checked-list="handleUpdateSceneTemplateList"
+          />
+        </el-form-item>
+        <el-form-item label="所属工位:" prop="workspaceId">
+          <el-tree-select
+            v-model="CameraSRSData.workspaceId"
+            :data="workspaceInfo"
+            :render-after-expand="false"
+            :default-expand-all="props.formData ? true : false"
+            check-strictly
+            placeholder="请选择工位"
+            style="width: 200px"
+            @node-click="handleTreeSelect"
+          />
+        </el-form-item>
+        <el-form-item label="工位负责人:" prop="principal">
+          <el-input
+            v-model="CameraSRSData.principal"
+            placeholder="请选择工位,该项自动填充"
+            style="width: 200px"
+            :disabled="true"
+          />
+        </el-form-item>
         <el-form-item label="视频编码标准:" prop="videoStandard">
-          <el-select v-model="CameraSRSData.videoStandard" placeholder="请输入视频编码标准" style="width: 200px">
-            <el-option v-for="protocal in standardTypeSelect" :key="protocal.value" :label="protocal.label"
-              :value="protocal.value" />
+          <el-select
+            v-model="CameraSRSData.videoStandard"
+            placeholder="请选择视频编码标准"
+            style="width: 200px"
+          >
+            <el-option
+              v-for="protocal in standardTypeSelect"
+              :key="protocal.value"
+              :label="protocal.label"
+              :value="protocal.value"
+            />
           </el-select>
         </el-form-item>
         <el-form-item label="备注:" prop="remark">
@@ -49,100 +101,97 @@
 </template>
 
 <script setup lang="ts">
-import { onBeforeMount, ref } from 'vue';
-import { CameraSRS } from '../type';
-import useSceneInfos from '@/hooks/useSceneInfos';
-import { cloneDeep } from 'lodash-es';
-import { serviceTypeSelect, standardTypeSelect } from '../constant';
-import { ElMessage } from 'element-plus';
-
-const props = defineProps<{ formData?: CameraSRS | null }>();
-
-const emits = defineEmits(['cancel-execute', 'confirm-execute']);
-
-const sceneInfos = useSceneInfos();
-const { scenesTree, flattendWorkspaces, getScenesTree } = sceneInfos;
-
-const IPFormRef = ref();
-
-const CameraSRSData = ref<CameraSRS>({} as CameraSRS);
-
-const rules = {
-  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-  workspaceCode: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
-  code: [{ required: true, message: '请输入设备ID号', trigger: 'blur' }],
-  rtspurl: [{ required: true, message: '请输入流媒体地址', trigger: 'blur' }],
-  videoServiceType: [{ required: false }],
-  videoStandard: [{ required: true, message: '请输入视频编码标准', trigger: 'blur' }],
-};
-
-const handleCancel = () => {
-  emits('cancel-execute');
-};
+  import { onBeforeMount, ref } from 'vue';
+  import { CameraSRS } from '@/types/camera/type';
+  import { cloneDeep } from 'lodash-es';
+  import { serviceTypeSelect, standardTypeSelect } from '../../../../types/camera/constant';
+  import { ElMessage } from 'element-plus';
+  import useTreeWorkspaceInfo from '../hooks/useTreeWorkspaceInfo';
+  import sysConfigItemOfAddCamera from './sysConfigItemOfAddCamera.vue';
+
+  const props = defineProps<{ formData?: CameraSRS | null }>();
+  const emits = defineEmits(['cancel-execute', 'confirm-execute']);
+
+  const treeWorkspaceInfo = useTreeWorkspaceInfo();
+  const { workspaceInfo, getWorkspaceFromTreeInfo } = treeWorkspaceInfo;
+
+  const IPFormRef = ref();
+  const CameraSRSData = ref<CameraSRS>({} as CameraSRS);
+
+  const rules = {
+    name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+    code: [{ required: true, message: '请输入设备ID', trigger: 'blur' }],
+    rtspUrl: [{ required: true, message: '请输入流媒体地址', trigger: 'blur' }],
+    sceneTemplateList: [{ required: true, message: '请选择至少一个业务场景', trigger: 'blur' }],
+    workspaceId: [{ required: true, message: '请选择工位', trigger: 'blur' }],
+    videoStandard: [{ required: true, message: '请选择视频编码标准', trigger: 'blur' }],
+  };
+
+  const handleUpdateSceneTemplateList = (data) => {
+    console.log('接收到的信息', data);
+    CameraSRSData.value.sceneTemplateList = data;
+  };
+
+  const handleCancel = () => {
+    emits('cancel-execute');
+  };
+
+  const handleConfirm = () => {
+    IPFormRef.value.validate((valid) => {
+      if (valid) {
+        const copyData = cloneDeep(CameraSRSData.value);
+        delete (copyData as any).principal;
+        copyData.sourceType = 'RTSP';
+        emits('confirm-execute', copyData);
+      }
+    });
+  };
+
+  const handleTreeSelect = (node) => {
+    console.log('点击选择车间', node);
+    CameraSRSData.value.workspaceId = node.value;
+    CameraSRSData.value.principal = node.principalName;
+    CameraSRSData.value.workshopId = node.workshopId;
+    if (node.disabled && node.children.length < 1) {
+      ElMessage.error('请先添加工位');
+    }
+  };
 
-const handleConfirm = () => {
-  IPFormRef.value.validate((valid) => {
-    if (valid) {
-      const copyData = cloneDeep(CameraSRSData.value);
-      copyData.workspaceId = flattendWorkspaces.value.find(
-        (item) => item.code === CameraSRSData.value.workspaceCode,
-      ).id;
-      delete (copyData as any).workspaceCode;
-      delete (copyData as any).principal;
-      emits('confirm-execute', copyData);
+  onBeforeMount(() => {
+    getWorkspaceFromTreeInfo();
+    if (props.formData) {
+      console.log('props.formData', props.formData);
+      CameraSRSData.value = props.formData;
     }
   });
-};
-
-// const handleTreeSelect = (code: string) => {
-//   const space = flattendWorkspaces.value.find((item) => item.code === code);
-//   CameraSRSData.value.workspaceId = space?.id;
-//   CameraSRSData.value.principal = space?.principal;
-// };
-
-const handleTreeSelect = (node) => {
-  const space = flattendWorkspaces.value.find((item) => item.code === node.value);
-  CameraSRSData.value.workspaceId = space?.id;
-  CameraSRSData.value.principal = space?.principal;
-  if (node.disabled && node.children.length < 1) {
-    ElMessage.error('请先添加工位');
-  }
-};
-
-onBeforeMount(() => {
-  getScenesTree({ level: 3, valueKey: 'code', labelKey: 'name', disabled: true });
-  if (props.formData) {
-    CameraSRSData.value = props.formData;
-  }
-});
 </script>
 
 <style scoped>
-.ip-form {
-  width: 768px;
-  display: flex;
-  flex-wrap: wrap;
-  justify-content: space-between;
-  align-content: space-around;
-}
+  .ip-form {
+    width: 768px;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    align-content: space-around;
+  }
 
-.pop-footer {
-  position: absolute;
-  right: 24px;
-  bottom: 27px;
-  display: flex;
-  justify-content: flex-end;
-}
+  .pop-footer {
+    position: absolute;
+    right: 24px;
+    bottom: 27px;
+    display: flex;
+    justify-content: flex-end;
+  }
 
-:deep(.el-form-item__label) {
-  font-size: 14px;
-  color: #363636;
-  padding: 0;
-}
+  :deep(.el-form-item__label) {
+    font-size: 14px;
+    color: #363636;
+    padding: 0;
+  }
 
-:deep(.el-form--inline .el-form-item) {
-  display: flex;
-  margin-right: 0;
-  margin-bottom: 28px;
-}
+  :deep(.el-form--inline .el-form-item) {
+    display: flex;
+    margin-right: 0;
+    margin-bottom: 28px;
+  }
 </style>

+ 10 - 4
src/views/cameras/overview/components/CameraAddPopover.vue

@@ -14,10 +14,12 @@
             {{ item.label }}
           </div>
         </div>
-        <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
+        <el-icon :size="16" class="mr-5" @click="updateValue(false)" style="cursor: pointer"
+          ><Close
+        /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <IPAddCamera
         v-if="addType === 'ip'"
         @cancel-execute="updateValue(false)"
@@ -40,7 +42,7 @@
 
 <script setup lang="ts">
   import { ref } from 'vue';
-  import { cameraAddType } from '../constant';
+  import { cameraAddType } from '../../../../types/camera/constant';
   import { Close } from '@element-plus/icons-vue';
   import IPAddCamera from './AddCameraByIP.vue';
   import SRSAddCamera from './AddCameraBySRS.vue';
@@ -124,7 +126,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 15 - 14
src/views/cameras/overview/components/CameraEditNVRPopover.vue

@@ -6,7 +6,7 @@
         <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <NVRAddCamera
         :form-data="props.editData"
         @cancel-execute="updateValue(false)"
@@ -17,11 +17,11 @@
 </template>
 
 <script setup lang="ts">
+  import { ElMessage } from 'element-plus';
   import { Close } from '@element-plus/icons-vue';
-  import NVRAddCamera from './AddCameraByNVR.vue';
-  import { CameraNVRItem } from '../type';
+  import { CameraNVRItem } from '@/types/camera/type';
   import useCameraOverview from '../stores/useCameraOverview';
-  import { ElMessage } from 'element-plus';
+  import NVRAddCamera from './AddCameraByNVR.vue';
 
   const props = defineProps<{
     modelValue: boolean;
@@ -41,18 +41,17 @@
   const onEditCamera = (data) => {
     const temp = {
       id: data.id,
+      nvrId: data.nvrId,
       name: data.name,
-      nvrIp: data.nvrIp,
-      cameraPort: data.cameraPort,
-      cameraType: data.cameraType,
-      nvrUsername: data.nvrUsername,
-      nvrPassword: data.nvrPassword,
-      workspaceId: data.workspaceId,
       code: data.code,
-      remark: data.remark,
       nvrChannel: data.nvrChannel,
       videoServiceType: data.videoServiceType,
+      sceneTemplateList: data.sceneTemplateList,
+      workshopId: data.workshopId,
+      workspaceId: data.workspaceId,
+      cameraType: data.cameraType,
       videoStandard: data.videoStandard,
+      remark: data.remark,
       sourceType: data.sourceType,
     };
     editCamera(temp)
@@ -71,8 +70,6 @@
       .catch((error) => {
         ElMessage.error(error);
       });
-    // props.confirmEvent && props.confirmEvent(data);
-    // updateValue(false);
   };
 </script>
 
@@ -97,7 +94,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 15 - 16
src/views/cameras/overview/components/CameraEditPopover.vue

@@ -6,7 +6,7 @@
         <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <IPAddCamera
         :form-data="props.editData"
         @cancel-execute="updateValue(false)"
@@ -17,11 +17,11 @@
 </template>
 
 <script setup lang="ts">
+  import { ElMessage } from 'element-plus';
   import { Close } from '@element-plus/icons-vue';
-  import IPAddCamera from './AddCameraByIP.vue';
-  import { CameraIPItem } from '../type';
+  import { CameraIPItem } from '@/types/camera/type';
   import useCameraOverview from '../stores/useCameraOverview';
-  import { ElMessage } from 'element-plus';
+  import IPAddCamera from './AddCameraByIP.vue';
 
   const props = defineProps<{
     modelValue: boolean;
@@ -39,28 +39,23 @@
   };
 
   const onEditCamera = (data) => {
-    // const temp = cloneDeep(data) as any;
-    // delete temp.workshopName;
-    // delete temp.workspaceName;
-    // delete temp.principal;
     const temp = {
       id: data.id,
       name: data.name,
+      code: data.code,
       cameraIp: data.cameraIp,
       cameraPort: data.cameraPort,
-      cameraType: data.cameraType,
       username: data.username,
       password: data.password,
-      workspaceId: data.workspaceId,
-      code: data.code,
-      remark: data.remark,
+      cameraType: data.cameraType,
       videoServiceType: data.videoServiceType,
+      sceneTemplateList: data.sceneTemplateList,
+      workshopId: data.workshopId,
+      workspaceId: data.workspaceId,
       videoStandard: data.videoStandard,
+      remark: data.remark,
       sourceType: data.sourceType,
     };
-    // editCamera(temp);
-    // props.confirmEvent && props.confirmEvent(data);
-    // updateValue(false);
     editCamera(temp)
       .then((res) => {
         if (res.code === 200) {
@@ -101,7 +96,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 15 - 9
src/views/cameras/overview/components/CameraEditSRSPopover.vue

@@ -7,11 +7,11 @@
         <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <SRSAddCamera
+        :form-data="props.editData!"
         @cancel-execute="updateValue(false)"
         @confirm-execute="onUpdateSRSCamera"
-        :form-data="props.editData!"
       />
     </div>
   </el-card>
@@ -21,10 +21,10 @@
   import { Close } from '@element-plus/icons-vue';
   import SRSAddCamera from './AddCameraBySRS.vue';
   import useCameraOverview from '../stores/useCameraOverview';
-  import { CameraIPItem } from '../type';
+  import { CameraSRS } from '@/types/camera/type';
   import { ElMessage } from 'element-plus';
 
-  const props = defineProps<{ modelValue: boolean; editData?: CameraIPItem }>();
+  const props = defineProps<{ modelValue: boolean; editData?: CameraSRS }>();
 
   const emits = defineEmits(['update:modelValue']);
 
@@ -37,15 +37,17 @@
 
   const onUpdateSRSCamera = (data) => {
     const temp = {
-      cameraIp: data.cameraIp,
       id: data.id,
       name: data.name,
-      workspaceId: data.workspaceId,
       code: data.code,
-      rtspurl: data.rtspurl,
-      remark: data.remark,
+      rtspUrl: data.rtspUrl,
+      cameraIp: data.cameraIp,
       videoServiceType: data.videoServiceType,
+      sceneTemplateList: data.sceneTemplateList,
+      workshopId: data.workshopId,
+      workspaceId: data.workspaceId,
       videoStandard: data.videoStandard,
+      remark: data.remark,
       sourceType: data.sourceType,
     };
     editCamera(temp)
@@ -110,7 +112,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 6 - 2
src/views/cameras/overview/components/CameraEditshared.vue

@@ -6,7 +6,7 @@
         <el-icon :size="16" class="mr-3" @click="updateValue"><Close /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <EditSharedCamera @close-edit="updateValue" :form-data="props.editData" />
     </div>
   </el-card>
@@ -69,7 +69,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 8 - 4
src/views/cameras/overview/components/CameraSharePopover.vue

@@ -6,7 +6,7 @@
         <el-icon :size="16" class="mr-3" @click="updateValue(false)"><Close /></el-icon>
       </div>
     </template>
-    <div class="pop-content flex justify-center items-center">
+    <div class="pop-content">
       <ShareCameraDetail :form-data="props.shareData" />
     </div>
   </el-card>
@@ -14,10 +14,10 @@
 
 <script setup lang="ts">
   import { ref } from 'vue';
-  import { cameraAddType } from '../constant';
+  import { cameraAddType } from '../../../../types/camera/constant';
   import { Close } from '@element-plus/icons-vue';
   import ShareCameraDetail from './ShareCameraDetail.vue';
-  import { CameraShowItem } from '../type';
+  import { CameraShowItem } from '../../../../types/camera/type';
 
   const props = defineProps<{ modelValue: boolean; shareData?: CameraShowItem | null }>();
 
@@ -74,7 +74,11 @@
   }
 
   .pop-content {
-    // height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 6 - 2
src/views/cameras/overview/components/CameraSharedEdit.vue

@@ -23,7 +23,7 @@
 
 <script setup lang="ts">
   import { ref } from 'vue';
-  import { sharedCaremaType } from '../constant';
+  import { sharedCaremaType } from '../../../../types/camera/constant';
   import { Close } from '@element-plus/icons-vue';
   import SharedTable from './SharedTable.vue';
 
@@ -86,7 +86,11 @@
   }
 
   .pop-content {
-    height: 566px;
+    height: 480px;
+    display: flex;
+    justify-content: center;
+    padding: 35px;
+    overflow: auto;
   }
 
   :deep(.el-card__header) {

+ 1 - 1
src/views/cameras/overview/components/ConditionQuery.vue

@@ -74,7 +74,7 @@
 
 <script setup lang="ts">
   import { onMounted } from 'vue';
-  import { queryTypeSelect, cameraAddType, AddType } from '../constant';
+  import { queryTypeSelect, cameraAddType, AddType } from '../../../../types/camera/constant';
   import useCameraOverview from '../stores/useCameraOverview';
   import useSceneInfos from '@/hooks/useSceneInfos';
   import { storeToRefs } from 'pinia';

+ 2 - 2
src/views/cameras/overview/components/EditSharedCamera.vue

@@ -47,10 +47,10 @@
 
 <script setup lang="ts">
   import { computed, onBeforeMount, ref } from 'vue';
-  import { cameraSharedForm } from '../constant';
+  import { cameraSharedForm } from '../../../../types/camera/constant';
 
   import useSceneInfos from '@/hooks/useSceneInfos';
-  import useCameraShare from '../stores/useCameraShare';
+  import useCameraShare from '../hooks/useCameraShare';
   import { CameraShareType } from '@/api/camera/camera-share';
 
   const useShare = useCameraShare();

+ 7 - 3
src/views/cameras/overview/components/ShareCameraDetail.vue

@@ -94,10 +94,14 @@
 <script setup lang="ts">
   import { h, reactive, ref, onMounted } from 'vue';
   import { BasicColumn, BasicTable, TableActionIcons } from '@/components/Table';
-  import { CameraShareItem, CameraShowItem } from '../type';
+  import { CameraShareItem, CameraShowItem } from '../../../../types/camera/type';
   import deleteIcon from '@/assets/images/table/table-delete.png';
-  import { authorityTypeSelect, timeTypeSelect, getColumns } from '../constant';
-  import useCameraShare from '../stores/useCameraShare';
+  import {
+    authorityTypeSelect,
+    timeTypeSelect,
+    getColumns,
+  } from '../../../../types/camera/constant';
+  import useCameraShare from '../hooks/useCameraShare';
   import { getVerify } from '@/api/camera/camera-share';
   import dayjs from 'dayjs';
   import { ElMessage, FormInstance, FormRules } from 'element-plus';

+ 2 - 2
src/views/cameras/overview/components/SharedTable.vue

@@ -53,12 +53,12 @@
 
 <script setup lang="ts">
   import { h, reactive, ref, onMounted, watch, onBeforeMount } from 'vue';
-  import { getColumns } from '../sharedColumns';
+  import { getColumns } from '../hooks/sharedColumns';
   import editIcon from '@/assets/images/table/table-edit.png';
   import deleteIcon from '@/assets/images/table/table-delete.png';
   import { BasicColumn, TableActionIconsWords, BasicTable } from '@/components/Table';
   import CameraEditshared from '../components/CameraEditshared.vue';
-  import useCameraShare from '../stores/useCameraShare';
+  import useCameraShare from '../hooks/useCameraShare';
   import useSceneInfos from '@/hooks/useSceneInfos';
   import { CameraShareType } from '@/api/camera/camera-share';
   import { ElMessageBox } from 'element-plus';

+ 115 - 0
src/views/cameras/overview/components/sysConfigItemOfAddCamera.vue

@@ -0,0 +1,115 @@
+<template>
+  <div class="scene-template-item" v-for="item in sceneTemplateList" :key="item.id">
+    <el-checkbox
+      v-model="sceneCheckedValues[item.id!]"
+      :label="item.name"
+      @change="handleSceneIdChange(item.id)"
+    />
+    <div class="template-item">
+      <div class="template-item-tip"><span style="color: red"> * </span> 应用模版:</div>
+      <el-radio-group
+        class="template-item-list"
+        v-model="templateCheckedValues[item.id!]"
+        @change="handleTemplateIdChange"
+      >
+        <el-radio
+          v-for="subItem in item.viewTemplateList"
+          :key="subItem.id"
+          :value="subItem.id"
+          :disabled="!sceneCheckedValues[item.id!]"
+          >{{ subItem.name }}</el-radio
+        >
+      </el-radio-group>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { onMounted, ref } from 'vue';
+  import { CheckedSceneTemplate } from '@/types/camera/type';
+  import { useSceneTemplateList } from '../stores/useSceneTemplateList';
+  import { storeToRefs } from 'pinia';
+
+  const sceneTemplateListInfo = useSceneTemplateList();
+  const { sceneTemplateList } = storeToRefs(sceneTemplateListInfo);
+  // const { sceneTemplateList, getSceneTemplateList } = sceneTemplateListInfo;
+
+  const props = defineProps<{ originSceneCheckedList: CheckedSceneTemplate[] }>();
+  const emits = defineEmits(['update:sceneCheckedList']);
+
+  const sceneCheckedValues = ref({} as Record<number, boolean>);
+  const templateCheckedValues = ref({} as Record<number, number | null>);
+  const sceneCheckedList = ref<CheckedSceneTemplate[]>([]);
+
+  // Object 转换为 CheckedSceneTemplate
+  function getSceneCheckedList(obj: Record<number, number | null>): CheckedSceneTemplate[] {
+    return Object.entries(obj).map(([sceneId, templateId]) => ({
+      sceneId: Number(sceneId),
+      templateId: Number(templateId),
+    }));
+  }
+
+  // CheckedSceneTemplate 转换为 Object
+  function getSceneCheckedValues(arr: CheckedSceneTemplate[]): Record<number, boolean> {
+    const result: Record<number, boolean> = {};
+    arr.forEach(({ sceneId }) => {
+      result[sceneId] = true;
+    });
+    return result;
+  }
+  function getTemplateCheckedValues(arr: CheckedSceneTemplate[]): Record<number, number | null> {
+    const result: Record<number, number | null> = {};
+    arr.forEach(({ sceneId, templateId }) => {
+      result[sceneId] = templateId;
+    });
+    return result;
+  }
+
+  function updateSceneCheckedList() {
+    sceneCheckedList.value = getSceneCheckedList(templateCheckedValues.value);
+    emits('update:sceneCheckedList', sceneCheckedList.value);
+  }
+
+  const handleSceneIdChange = (id) => {
+    if (!sceneCheckedValues.value[id]) delete templateCheckedValues.value[id];
+    updateSceneCheckedList();
+  };
+
+  const handleTemplateIdChange = () => {
+    updateSceneCheckedList();
+  };
+
+  onMounted(() => {
+    // getSceneTemplateList();
+    console.log('props', props.originSceneCheckedList);
+    if (props.originSceneCheckedList?.length) {
+      sceneCheckedValues.value = getSceneCheckedValues(props.originSceneCheckedList);
+      templateCheckedValues.value = getTemplateCheckedValues(props.originSceneCheckedList);
+    }
+  });
+</script>
+
+<style scoped lang="less">
+  .scene-template-item {
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    margin-bottom: 10px;
+  }
+
+  .template-item {
+    padding: 5px 20px;
+    border-radius: 5px;
+    background: rgba(170, 170, 170, 0.1);
+    display: flex;
+
+    .template-item-tip {
+      width: 100px;
+      color: rgba(0, 0, 0, 0.4);
+    }
+
+    .template-item-list {
+      flex: 1;
+    }
+  }
+</style>

+ 42 - 9
src/views/cameras/overview/overviewColumns.ts

@@ -1,11 +1,18 @@
 import { h } from 'vue';
-import { ElSwitch } from 'element-plus';
+import { ElSwitch, ElTag } from 'element-plus';
 import type { BasicColumn } from '@/components/Table';
 import connectedIcon from '@/assets/images/table/camera-netConnect.png';
 import unConnectedIcon from '@/assets/images/table/camera-netUnconnect.png';
-import { protocalTypeSelect } from './constant';
-import useCameraOverview from './stores/useCameraOverview';
+// import { protocalTypeSelect } from '@/types/camera/constant';
+import useCameraOverview from '../stores/useCameraOverview';
 import { startCameraStream, stopCameraStream } from '@/api/camera/camera-overview';
+import { useSceneTemplateList } from '../stores/useSceneTemplateList';
+import { storeToRefs } from 'pinia';
+
+const sceneTemplateListInfo = useSceneTemplateList();
+const { sceneTemplateList } = storeToRefs(sceneTemplateListInfo);
+
+const { getLabelById } = sceneTemplateListInfo;
 
 const cameraOverview = useCameraOverview();
 const { getState, getCameraItems } = cameraOverview;
@@ -14,28 +21,33 @@ export const columns: BasicColumn[] = [
   {
     minWidth: 30,
     type: 'selection',
-    fixed: 'left',
+    // fixed: 'left',
+    align: 'center',
   },
   {
     label: '序号',
     minWidth: 60,
     type: 'index',
-    fixed: 'left',
+    // fixed: 'left',
+    align: 'center',
   },
   {
     label: '公司名称',
     prop: 'companyName',
     minWidth: 100,
+    align: 'center',
   },
   {
     label: '名称',
     prop: 'name',
-    minWidth: 100,
+    minWidth: 140,
+    align: 'center',
   },
   {
     label: '添加方式',
     prop: 'sourceType',
-    minWidth: 140,
+    minWidth: 100,
+    align: 'center',
   },
   // {
   //   label: 'IP地址',
@@ -70,17 +82,37 @@ export const columns: BasicColumn[] = [
   {
     label: '设备ID',
     prop: 'code',
-    minWidth: 150,
+    minWidth: 120,
+    align: 'center',
   },
   {
     label: '车间场景',
     prop: 'workshopName',
     minWidth: 140,
+    align: 'center',
   },
   {
     label: '工位场景',
     prop: 'workspaceName',
     minWidth: 140,
+    align: 'center',
+  },
+  {
+    label: '业务场景',
+    prop: 'sceneTemplateList',
+    minWidth: 160,
+    align: 'center',
+    render(record) {
+      const tags = getLabelById(record.row.sceneTemplateList, sceneTemplateList.value);
+      const tag = tags.map((item) => h(ElTag, item));
+      return h(
+        'span',
+        {
+          style: 'display: flex; justify-content: center; flex-wrap: wrap; gap: 5px;',
+        },
+        tag,
+      );
+    },
   },
   {
     label: '联网状态',
@@ -135,6 +167,7 @@ export const columns: BasicColumn[] = [
   {
     label: '备注',
     prop: 'remark',
-    minWidth: 60,
+    minWidth: 140,
+    align: 'center',
   },
 ];

src/views/cameras/overview/searchRangeColumns.ts → src/views/cameras/overview/hooks/searchRangeColumns.ts


+ 1 - 1
src/views/cameras/overview/sharedColumns.ts

@@ -1,6 +1,6 @@
 import { h } from 'vue';
 import type { BasicColumn } from '@/components/Table';
-import { protocalTypeSelect } from './constant';
+import { protocalTypeSelect } from '@/types/camera/constant';
 import useSceneInfos from '@/hooks/useSceneInfos';
 
 // export const columns: BasicColumn[] = [

src/views/cameras/overview/stores/useCameraShare.ts → src/views/cameras/overview/hooks/useCameraShare.ts


+ 34 - 0
src/views/cameras/overview/hooks/useNvrDevice.ts

@@ -0,0 +1,34 @@
+/**
+ * description: NVR方式添加相机时,选择的NVR设备列表
+ */
+
+import { ref } from 'vue';
+import { getAllNVRList } from '@/api/camera/camera-nvr';
+
+interface NvrDevice {
+  id: number; // nvrId
+  label: string; // Nvr展示格式
+}
+
+export function useNvrDevice() {
+  const nvrDevice = ref<NvrDevice[]>([]);
+
+  const getNvrDevice = async () => {
+    await getAllNVRList().then((res) => {
+      nvrDevice.value = res.map((item) => {
+        return {
+          id: item.id,
+          label: `${item.name}(${item.code})`,
+        };
+      });
+      console.log('nvrdevice', nvrDevice.value);
+    });
+  };
+
+  return {
+    nvrDevice,
+    getNvrDevice,
+  };
+}
+
+export default useNvrDevice;

+ 56 - 0
src/views/cameras/overview/hooks/useTreeWorkspaceInfo.ts

@@ -0,0 +1,56 @@
+/**
+ * description:
+ * 获取公司-车间-工位(树结构)信息,适用于添加相机(三种方式)- 所属工位下拉框选项
+ */
+import { ref } from 'vue';
+import { getTreeWorkspaceInfo } from '@/api/camera/camera-overview';
+
+interface TreeWorkspaceInfoType {
+  id: number; // 自增主键
+  name: string; // 公司名称
+  code?: string; // 公司编号
+  nodeType: string; // 节点类型
+  workshopId?: number; // nodeType=workspace时携带车间Id
+  principalName?: string; // nodeType=workspace时携带负责人name
+  children?: TreeWorkspaceInfoType[];
+}
+
+interface ElTreeItem {
+  value: any;
+  label: string;
+  children?: ElTreeItem[];
+  disabled?: boolean;
+  workshopId?: number;
+  principalName?: string;
+}
+
+export function useTreeWorkspaceInfo() {
+  const workspaceInfo = ref<ElTreeItem[]>([]);
+
+  const setTreeWorkspaceInfo = (infos: TreeWorkspaceInfoType[]): ElTreeItem[] => {
+    return infos.map((item) => {
+      return {
+        value: item.id,
+        label: item.name,
+        workshopId: item.workshopId,
+        principalName: item.principalName,
+        disabled: item.nodeType === 'workspace' ? false : true,
+        children:
+          item.children && item.children.length > 0 ? setTreeWorkspaceInfo(item.children) : [],
+      };
+    });
+  };
+
+  const getWorkspaceFromTreeInfo = async () => {
+    await getTreeWorkspaceInfo().then((res) => {
+      workspaceInfo.value = setTreeWorkspaceInfo(res);
+    });
+  };
+
+  return {
+    workspaceInfo,
+    getWorkspaceFromTreeInfo,
+  };
+}
+
+export default useTreeWorkspaceInfo;

+ 29 - 20
src/views/cameras/overview/stores/useCameraOverview.ts

@@ -1,15 +1,22 @@
 import { ref } from 'vue';
 import { defineStore } from 'pinia';
 import {
+  CameraQueryParamDetails,
   CameraQueryParams,
   getCameraList,
   addCameraItem,
   updateCameraItem,
   getCameraState,
-  addSRSCameraItem,
-  addNVRCameraItem,
+  // addSRSCameraItem,
+  // addNVRCameraItem,
 } from '@/api/camera/camera-overview';
-import { CameraIPItem, CameraNVRItem, CameraSRS, CameraShowItem } from '../type';
+import {
+  CameraAddType,
+  // CameraIPItem,
+  // CameraNVRItem,
+  // CameraSRS,
+  CameraShowItem,
+} from '@/types/camera/type';
 import { useRequest } from 'vue-hooks-plus';
 
 const ALL = -1;
@@ -33,39 +40,41 @@ export const useCameraOverview = defineStore('camera-overview', () => {
 
   // 条件查询事件
   const conditionSearch = () => {
+    const paramDetails = ref({} as CameraQueryParamDetails);
     const params: CameraQueryParams = {
       pageNumber: page.value,
       pageSize: size.value,
+      queryParam: paramDetails.value,
     };
     if (queryType.value) {
       switch (queryType.value) {
         case 'cameraIp':
-          params.ip = queryTypeContent.value;
+          paramDetails.value.ip = queryTypeContent.value;
           break;
 
         case 'name':
-          params.code = queryTypeContent.value;
+          paramDetails.value.code = queryTypeContent.value;
           break;
       }
     }
     if (queryCameraType.value) {
-      params.cameraType = queryCameraType.value;
+      paramDetails.value.cameraType = queryCameraType.value;
     }
     if (queryWorkSpace.value) {
-      params.sceneCode = queryWorkSpace.value;
+      paramDetails.value.sceneCode = queryWorkSpace.value;
     }
     if (querySourceType.value) {
       console.log('queryCameraType.value', querySourceType.value);
-      params.sourceType = querySourceType.value;
+      paramDetails.value.sourceType = querySourceType.value;
     }
     if (networkingState.value != ALL) {
-      params.networkingState = networkingState.value;
+      paramDetails.value.networkingState = networkingState.value;
     }
     if (integrationState.value != ALL) {
-      params.integrationState = integrationState.value;
+      paramDetails.value.integrationState = integrationState.value;
     }
     if (openEagle.value != ALL) {
-      params.openEagle = openEagle.value;
+      paramDetails.value.openEagle = openEagle.value;
     }
     return getCameraList(params).then((res) => {
       return res;
@@ -80,27 +89,27 @@ export const useCameraOverview = defineStore('camera-overview', () => {
     },
   });
 
-  const addCamera = (data: CameraIPItem) => {
-    console.log(data);
+  const addCamera = (data: CameraAddType) => {
+    console.log('添加相机,相机信息————————', data);
 
     return addCameraItem(data).then(() => {
       getCameraItems();
     });
   };
 
-  const addSRSCamera = (data: CameraSRS) => {
-    return addSRSCameraItem(data).then(() => {
+  const addSRSCamera = (data) => {
+    return addCameraItem(data).then(() => {
       getCameraItems();
     });
   };
 
-  const addNVRCamera = (data: CameraNVRItem) => {
-    return addNVRCameraItem(data).then(() => {
+  const addNVRCamera = (data) => {
+    return addCameraItem(data).then(() => {
       getCameraItems();
     });
   };
 
-  const editCamera = (data: Partial<CameraShowItem>) => {
+  const editCamera = (data) => {
     return updateCameraItem(data);
     // .then(() => {
     //   getCameraItems();
@@ -111,8 +120,8 @@ export const useCameraOverview = defineStore('camera-overview', () => {
     getCameraState({ cameraCodeList: cameraItems.value.map((camera) => camera.code) }).then(
       (res) => {
         res.forEach((item) => {
-          cameraItems.value.find((camera) => camera.code === item.cameraCode)!.networkingState =
-            item.status;
+          const targetObj = cameraItems.value.find((camera) => camera.code === item.cameraCode);
+          if (targetObj) targetObj.networkingState = Number(item.networkingState);
         });
       },
     );

+ 38 - 0
src/views/cameras/overview/stores/useSceneTemplateList.ts

@@ -0,0 +1,38 @@
+/**
+ * description:
+ * 1. 获取业务场景模版信息
+ * 2. 反显列表显示信息
+ */
+
+import { ref } from 'vue';
+import { SceneListInfo } from '@/types/business-scene/type';
+import { CheckedSceneTemplate } from '@/types/camera/type';
+import { getSceneList } from '@/api/sys-config/business-scene';
+import { defineStore } from 'pinia';
+
+export const useSceneTemplateList = defineStore('scene-template', () => {
+  const sceneTemplateList = ref<SceneListInfo[]>([]);
+
+  const getSceneTemplateList = async () => {
+    await getSceneList().then((res) => {
+      sceneTemplateList.value = res;
+    });
+  };
+
+  const getLabelById = (arr: CheckedSceneTemplate[], list: SceneListInfo[]): string[] => {
+    const result = [] as string[];
+    arr.forEach((item) => {
+      const targetObj = list.find((obj) => obj.id === item.sceneId);
+      if (targetObj) result.push(targetObj.name);
+    });
+    return result;
+  };
+
+  return {
+    sceneTemplateList,
+    getSceneTemplateList,
+    getLabelById,
+  };
+});
+
+export default useSceneTemplateList;

+ 1 - 1
src/views/cameras/overview/stores/useSharedCamera.ts

@@ -1,6 +1,6 @@
 import { computed, ref } from 'vue';
 import { defineStore } from 'pinia';
-import { CameraSharedItem } from '../constant';
+import { CameraSharedItem } from '../../../../types/camera/constant';
 import { ElMessage } from 'element-plus';
 
 export const useCameraShare = defineStore('camera-share', () => {