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

feat(camera): 添加多点位相机预览功能

- 在 liveShow 和 liveHide 方法中添加 point_name 参数支持
- 修改相机控制器以传递点位名称参数并返回操作结果
- 更新前端相机配置界面支持多点位切换和相机绑定
- 实现预览点位切换时自动隐藏当前预览并显示新点位预览
- 添加多相机模式判断逻辑和相机数量限制
- 在摄影检查页面集成点位预览切换功能
- 优化相机配置界面样式和布局结构
panqiuyao 9 часов назад
Родитель
Сommit
fb80eb6bf2

+ 6 - 4
electron/api/camera.js

@@ -61,7 +61,7 @@ const { readConfigFile } = require('../utils/config');
 
 
 
 
 module.exports = {
 module.exports = {
-  async liveShow(){
+  async liveShow(point_name = 'A'){
     if(readConfigFile().controlType === 'digiCamControl'){
     if(readConfigFile().controlType === 'digiCamControl'){
       return get({
       return get({
         url: '?CMD=LiveViewWnd_Show'
         url: '?CMD=LiveViewWnd_Show'
@@ -71,7 +71,8 @@ module.exports = {
       await pySocket.sendMessage(JSON.stringify({
       await pySocket.sendMessage(JSON.stringify({
         type: 'smart_shooter_enable_preview',
         type: 'smart_shooter_enable_preview',
         data:{
         data:{
-          value:true
+          value:true,
+          point_name: point_name
         }
         }
       }))
       }))
       return  new Promise(async (resolve, reject) => {
       return  new Promise(async (resolve, reject) => {
@@ -82,7 +83,7 @@ module.exports = {
       })
       })
     }
     }
   },
   },
-  async liveHide(){
+  async liveHide(point_name = 'A'){
     if(readConfigFile().controlType === 'digiCamControl'){
     if(readConfigFile().controlType === 'digiCamControl'){
       return get({
       return get({
         url: '?CMD=LiveViewWnd_Hide'
         url: '?CMD=LiveViewWnd_Hide'
@@ -92,7 +93,8 @@ module.exports = {
       await pySocket.sendMessage(JSON.stringify({
       await pySocket.sendMessage(JSON.stringify({
         type: 'smart_shooter_enable_preview',
         type: 'smart_shooter_enable_preview',
         data:{
         data:{
-          value:false
+          value:false,
+          point_name: point_name
         }
         }
       }))
       }))
       return  new Promise(async (resolve, reject) => {
       return  new Promise(async (resolve, reject) => {

+ 10 - 8
electron/controller/camera.js

@@ -4,7 +4,7 @@ const Log = require('ee-core/log');
 const { checkCameraControlCmdExists, closeCameraControlTips, isProcessRunning, onProcessClosed, removeProcessClosedListener } = require('../utils/camera');
 const { checkCameraControlCmdExists, closeCameraControlTips, isProcessRunning, onProcessClosed, removeProcessClosedListener } = require('../utils/camera');
 const {
 const {
   checkCamera,
   checkCamera,
-  liveShow, liveHide, setParams, capture, getParams,CMD,captureLive,closeOtherWindow } = require('../api/camera');
+  liveShow: liveShowApi, liveHide: liveHideApi, setParams, capture, getParams,CMD,captureLive,closeOtherWindow } = require('../api/camera');
 
 
 const { readConfigFile } = require('../utils/config');
 const { readConfigFile } = require('../utils/config');
 
 
@@ -127,15 +127,16 @@ class CameraController extends Controller {
   /**
   /**
    * 启动预览
    * 启动预览
    */
    */
-  async liveShow() {
+  async liveShow(data) {
     try {
     try {
-      await liveShow();
+      const point_name = data?.point_name || 'A';
+      await liveShowApi(point_name);
       if(readConfigFile().controlType === 'digiCamControl'){
       if(readConfigFile().controlType === 'digiCamControl'){
         await  CMD('All_Minimize')
         await  CMD('All_Minimize')
       }
       }
-      return true;
+      return { success: true, point_name };
     } catch (error) {
     } catch (error) {
-      console.error('eeee启动直播失败:', error);
+      console.error('启动预览失败:', error);
       throw error;
       throw error;
     }
     }
   }
   }
@@ -143,10 +144,11 @@ class CameraController extends Controller {
   /**
   /**
    * 结束预览
    * 结束预览
    */
    */
-  async liveHide() {
+  async liveHide(data) {
     try {
     try {
-      await liveHide();
-      return true;
+      const point_name = data?.point_name || 'A';
+      await liveHideApi(point_name);
+      return { success: true, point_name };
     } catch (error) {
     } catch (error) {
       throw error;
       throw error;
     }
     }

+ 9 - 5
frontend/src/stores/modules/user.ts

@@ -15,17 +15,16 @@ export const useUserInfo = defineStore('userInfo', () => {
   const userInfo = ref({}); // 用户的详细信息
   const userInfo = ref({}); // 用户的详细信息
   const isExpired = ref(false); // 企业账户是否过期
   const isExpired = ref(false); // 企业账户是否过期
   const expiredMessage = ref(''); // 过期提示消息
   const expiredMessage = ref(''); // 过期提示消息
+  const supportCameraCounts = ref(1); // 支持的相机数量
 
 
   // 多相机模式判断
   // 多相机模式判断
-  // zhihuiyinType: 1 = 单相机, 2 = 多相机
+  // support_camera_counts > 1 则为多相机模式
   const isMultiCameraMode = computed(() => {
   const isMultiCameraMode = computed(() => {
-    return  true;
-    return userInfo.value.zhihuiyinType === 2
+    return supportCameraCounts.value > 1
   })
   })
 
 
   const cameraMode = computed(() => {
   const cameraMode = computed(() => {
-    return  'multi';
-    return userInfo.value.zhihuiyinType === 2 ? 'multi' : 'single'
+    return supportCameraCounts.value > 1 ? 'multi' : 'single'
   })
   })
 
 
   // 定时检查相关
   // 定时检查相关
@@ -157,6 +156,10 @@ export const useUserInfo = defineStore('userInfo', () => {
         // 未过期,重置状态
         // 未过期,重置状态
         isExpired.value = false;
         isExpired.value = false;
         expiredMessage.value = '';
         expiredMessage.value = '';
+        // 保存支持的相机数量
+        if (statusData?.support_camera_counts) {
+          supportCameraCounts.value = statusData.support_camera_counts;
+        }
         return false;
         return false;
       }
       }
     } catch (statusError) {
     } catch (statusError) {
@@ -236,6 +239,7 @@ export const useUserInfo = defineStore('userInfo', () => {
     userInfo,
     userInfo,
     isExpired,
     isExpired,
     expiredMessage,
     expiredMessage,
+    supportCameraCounts,
     isMultiCameraMode,
     isMultiCameraMode,
     cameraMode,
     cameraMode,
     updateUserInfo,
     updateUserInfo,

+ 39 - 24
frontend/src/views/Photography/check.vue

@@ -67,6 +67,8 @@
       ref="editData"
       ref="editData"
       @onClose="onClose"
       @onClose="onClose"
       @onRunMcuSingle="onRunMcuSingle"
       @onRunMcuSingle="onRunMcuSingle"
+      @onReady="onEditRowReady"
+      @onPointChange="switchPreviewPoint"
       :addRowData="addRowData"
       :addRowData="addRowData"
       :disablePointConfig="!isSetting"
       :disablePointConfig="!isSetting"
     />
     />
@@ -95,11 +97,11 @@ import  configInfo  from '@/stores/modules/config';
 const configInfoStore = configInfo();
 const configInfoStore = configInfo();
 
 
 const confirm = ()=>{
 const confirm = ()=>{
-  hideVideo()
+  hideVideo(currentPointName.value)
   emit('confirm')
   emit('confirm')
 }
 }
 const onClose = ()=>{
 const onClose = ()=>{
-  hideVideo()
+  hideVideo(currentPointName.value)
   emit('onClose')
   emit('onClose')
 }
 }
 // 定义 props
 // 定义 props
@@ -150,11 +152,15 @@ async function checkConfirm(init){
   }
   }
   if(!init) previewKey.value++;
   if(!init) previewKey.value++;
 
 
-  showVideo()
   showrEditRow.value = true
   showrEditRow.value = true
   loading.value = false;
   loading.value = false;
 }
 }
 
 
+// editRow 数据加载完成后调用 showVideo
+function onEditRowReady(point_name) {
+  showVideo(point_name)
+}
+
 const init = ref(true)
 const init = ref(true)
 function onRunMcuSingle (){
 function onRunMcuSingle (){
   if(init.value) {
   if(init.value) {
@@ -168,31 +174,40 @@ const showrEditRow = ref(false)
 
 
 
 
 let interval:any = null
 let interval:any = null
-function showVideo(){
+let currentPointName = ref('A')
 
 
-    clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);
+function showVideo(point_name = 'A'){
+  currentPointName.value = point_name
 
 
-    clientStore.ipc.send(icpList.camera.PreviewShow);
-    clientStore.ipc.on(icpList.camera.PreviewShow, async (event, result) => {
+  clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);
 
 
-      setTimeout(()=>{
-        interval = setInterval(()=>{
-          previewKey.value++;
-        },200)
-      },500)
+  clientStore.ipc.send(icpList.camera.PreviewShow, { point_name });
+  clientStore.ipc.on(icpList.camera.PreviewShow, async (event, result) => {
 
 
-    })
+    setTimeout(()=>{
+      interval = setInterval(()=>{
+        previewKey.value++;
+      },200)
+    },500)
 
 
-}
+  })
 
 
-function hideVideo(){
+}
 
 
+function hideVideo(point_name = 'A'){
+  return new Promise((resolve) => {
     clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
     clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
-    clientStore.ipc.send(icpList.camera.PreviewHide);
+    clientStore.ipc.send(icpList.camera.PreviewHide, { point_name });
     clientStore.ipc.on(icpList.camera.PreviewHide, async (event, result) => {
     clientStore.ipc.on(icpList.camera.PreviewHide, async (event, result) => {
       if(interval) clearInterval(interval)
       if(interval) clearInterval(interval)
+      resolve(true)
     })
     })
+  })
+}
 
 
+async function switchPreviewPoint(point_name = 'A') {
+  await hideVideo(currentPointName.value)
+  showVideo(point_name)
 }
 }
 
 
 function goArts(){
 function goArts(){
@@ -209,7 +224,7 @@ function takePictures() {
   if (clientStore.isClient) {
   if (clientStore.isClient) {
 
 
     loading.value = true;
     loading.value = true;
-    hideVideo()
+    hideVideo(currentPointName.value)
     socketStore.sendMessage({
     socketStore.sendMessage({
       type: 'run_mcu_single',
       type: 'run_mcu_single',
       data: {
       data: {
@@ -246,12 +261,12 @@ function  createMainImage (file_path){
   clientStore.ipc.on(icpList.takePhoto.createMainImage, async (event, result) => {
   clientStore.ipc.on(icpList.takePhoto.createMainImage, async (event, result) => {
     if(result.code === 0 && result.data?.main_out_path){
     if(result.code === 0 && result.data?.main_out_path){
       imageTplPath.value  = result.data?.main_out_path
       imageTplPath.value  = result.data?.main_out_path
-      hideVideo()
+      hideVideo(currentPointName.value)
       step.value = 2
       step.value = 2
       loading.value = false;
       loading.value = false;
     }else if(result.msg){
     }else if(result.msg){
       loading.value = false;
       loading.value = false;
-      showVideo()
+      showVideo(currentPointName.value)
       if(result.code !== 0) ElMessage.error(result.msg)
       if(result.code !== 0) ElMessage.error(result.msg)
     }
     }
     clientStore.ipc.removeAllListeners(icpList.takePhoto.createMainImage);
     clientStore.ipc.removeAllListeners(icpList.takePhoto.createMainImage);
@@ -267,12 +282,12 @@ clientStore.ipc.on(icpList.socket.message+'_smart_shooter_photo_take', async (ev
   console.log(result);
   console.log(result);
   if(result.code === 0 && result.data?.photo_file_name){
   if(result.code === 0 && result.data?.photo_file_name){
     imageTplPath.value  = result.data?.photo_file_name
     imageTplPath.value  = result.data?.photo_file_name
-    hideVideo()
+    hideVideo(currentPointName.value)
     step.value = 2
     step.value = 2
     loading.value = false;
     loading.value = false;
   }else {
   }else {
     loading.value = false;
     loading.value = false;
-    showVideo()
+    showVideo(currentPointName.value)
     if(result.code !== 0 && result.msg) ElMessage.error(result.msg)
     if(result.code !== 0 && result.msg) ElMessage.error(result.msg)
   }
   }
 
 
@@ -286,12 +301,12 @@ clientStore.ipc.on(icpList.socket.message+'_run_mcu_single', async (event, resul
 
 
   if(result.code === 0 && result.data?.file_path){
   if(result.code === 0 && result.data?.file_path){
     imageTplPath.value  = result.data?.file_path
     imageTplPath.value  = result.data?.file_path
-    hideVideo()
+    hideVideo(currentPointName.value)
     step.value = 2
     step.value = 2
     loading.value = false;
     loading.value = false;
   }else {
   }else {
     loading.value = false;
     loading.value = false;
-    showVideo()
+    showVideo(currentPointName.value)
     if(result.code !== 0 && result.msg) ElMessage.error(result.msg)
     if(result.code !== 0 && result.msg) ElMessage.error(result.msg)
   }
   }
 
 
@@ -326,7 +341,7 @@ onMounted(async ()=>{
  * 页面卸载时移除所有事件监听器。
  * 页面卸载时移除所有事件监听器。
  */
  */
 onBeforeUnmount(() => {
 onBeforeUnmount(() => {
-  hideVideo()
+  hideVideo(currentPointName.value)
   clientStore.ipc.removeAllListeners(icpList.camera.takePictures);
   clientStore.ipc.removeAllListeners(icpList.camera.takePictures);
   clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
   clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
   clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);
   clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);

+ 11 - 1
frontend/src/views/Photography/components/editRow.vue

@@ -137,6 +137,14 @@ const props = defineProps({
 const initStatus = ref(false)
 const initStatus = ref(false)
 const isDefault = ref(true); // 是否为默认配置
 const isDefault = ref(true); // 是否为默认配置
 const editRowData = ref({}); // 当前编辑行的数据
 const editRowData = ref({}); // 当前编辑行的数据
+
+// 监听点位变化,切换预览
+watch(() => editRowData.value.point_name, (newPoint, oldPoint) => {
+  if (initStatus.value && newPoint && newPoint !== oldPoint) {
+    emit('onPointChange', newPoint)
+  }
+})
+
 onMounted(async ()=>{
 onMounted(async ()=>{
   console.log('editrow')
   console.log('editrow')
   if(props.addRowData.mode_type){
   if(props.addRowData.mode_type){
@@ -149,6 +157,7 @@ onMounted(async ()=>{
       editRowData.value.is_move_device = editRowData.value.is_move_device ?? 1
       editRowData.value.is_move_device = editRowData.value.is_move_device ?? 1
     }
     }
     testShoesFlip()
     testShoesFlip()
+    emit('onReady', editRowData.value.point_name || 'A')
     return
     return
   }
   }
   let fun = getDeviceConfigDetail;
   let fun = getDeviceConfigDetail;
@@ -176,6 +185,7 @@ onMounted(async ()=>{
     }
     }
     initStatus.value = true;
     initStatus.value = true;
     testShoesFlip()
     testShoesFlip()
+    emit('onReady', editRowData.value.point_name || 'A')
   }
   }
 
 
 })
 })
@@ -261,7 +271,7 @@ function testShoesFlip(){
   }
   }
 }
 }
 
 
-const emit = defineEmits([ 'confirm','onClose','onRunMcuSingle']);
+const emit = defineEmits([ 'confirm','onClose','onRunMcuSingle','onReady','onPointChange']);
 const close = ()=>{
 const close = ()=>{
   console.log('onClose')
   console.log('onClose')
   emit('onClose')
   emit('onClose')

+ 12 - 13
frontend/src/views/Setting/components/CameraConfig.vue

@@ -1,14 +1,12 @@
 <template>
 <template>
   <div class="camera-config-container">
   <div class="camera-config-container">
     <!-- 统一使用多点位配置界面 -->
     <!-- 统一使用多点位配置界面 -->
-    <div class="flex left fw-b fs-16 mar-top-20" style="padding-left: 100px">
-      {{ isMultiCameraMode ? '多点位相机配置' : '相机配置' }}<span style="color: #FD5E1A">(<el-icon style="position: relative; top:2px; margin: 0 3px"><WarningFilled /></el-icon>{{ isMultiCameraMode ? '每个点位绑定独立相机' : '点击点位切换相机配置' }})</span>
-    </div>
+
 
 
     <!-- 点位切换Tab -->
     <!-- 点位切换Tab -->
-    <div class="selectBox multi-camera-config">
+    <div class="selectBox multi-camera-config" v-id>
       <!-- 点位切换按钮 -->
       <!-- 点位切换按钮 -->
-      <div class="point-tabs">
+      <div class="point-tabs" v-if="isMultiCameraMode">
         <div
         <div
           v-for="point in displayPointList"
           v-for="point in displayPointList"
           :key="point.key"
           :key="point.key"
@@ -25,14 +23,14 @@
 
 
       <!-- 当前点位配置 -->
       <!-- 当前点位配置 -->
       <div class="current-point-config">
       <div class="current-point-config">
-        <div class="config-header">
+<!--        <div class="config-header" v-if="isMultiCameraMode">
           <span class="config-title">点位 {{ activePoint }} 配置</span>
           <span class="config-title">点位 {{ activePoint }} 配置</span>
-        </div>
+        </div>-->
 
 
         <div class="config-body">
         <div class="config-body">
           <!-- 多相机模式下显示相机绑定 -->
           <!-- 多相机模式下显示相机绑定 -->
           <div v-if="isMultiCameraMode" class="form-item">
           <div v-if="isMultiCameraMode" class="form-item">
-            <label>绑定相机:</label>
+            <label class="iso-label">绑定相机:</label>
             <div class="camera-select-wrapper">
             <div class="camera-select-wrapper">
               <el-select
               <el-select
                 v-model="multiConfig[activePoint].CameraKey"
                 v-model="multiConfig[activePoint].CameraKey"
@@ -357,6 +355,7 @@ defineExpose({ save })
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 .selectBox {
 .selectBox {
   padding-top: 10px;
   padding-top: 10px;
+  padding-bottom: 50px;
 }
 }
 
 
 .multi-camera-config {
 .multi-camera-config {
@@ -399,9 +398,9 @@ defineExpose({ save })
 
 
 // 当前点位配置卡片
 // 当前点位配置卡片
 .current-point-config {
 .current-point-config {
-  background: #fff;
-  border: 1px solid #E4E7ED;
-  border-radius: 12px;
+  // background: #fff;
+  // border: 1px solid #E4E7ED;
+ // border-radius: 12px;
   overflow: hidden;
   overflow: hidden;
   max-width: 500px;
   max-width: 500px;
 
 
@@ -427,7 +426,7 @@ defineExpose({ save })
         display: block;
         display: block;
         margin-bottom: 8px;
         margin-bottom: 8px;
         font-size: 14px;
         font-size: 14px;
-        color: #606266;
+       // color: #606266;
       }
       }
 
 
       .camera-select-wrapper {
       .camera-select-wrapper {
@@ -447,7 +446,7 @@ defineExpose({ save })
       gap: 12px;
       gap: 12px;
 
 
       .iso-label {
       .iso-label {
-        min-width: 70px;
+        min-width: 125px;
         font-size: 14px;
         font-size: 14px;
         color: #1A1A1A;
         color: #1A1A1A;
       }
       }