Browse Source

Merge branch 'master' of http://gitlab.pubdata.cn/liangyibo/CameraMachine

rambo 7 months ago
parent
commit
3076b9c7cd

+ 23 - 1
electron/api/setting.js

@@ -11,6 +11,12 @@ module.exports = {
       }
     })
   },
+  getDeviceTabs(data){
+    return get({
+      url: '/get_device_tabs',
+      data: data,
+    })
+  },
 
   getDeviceConfigDetail(data){
     return post({
@@ -84,6 +90,22 @@ module.exports = {
         'Content-Type':"application/json",
       }
     })
-  }
+  },
+  //更新左右脚配置
+  updateLeftRightConfig(data){
+    return post({
+      url: '/update_left_right_config',
+      data: data
+    })
+  },
+  //更新顶部tab名称
+  updateTabName(data){
+    return post({
+      url: '/update_tab_name',
+      data: data
+    })
+  },
+
+
 
 }

+ 1 - 2
electron/config/app.config.json

@@ -1,4 +1,3 @@
 {
-  "digiCamControl": "C:\\Program Files (x86)\\digiCamControl",
   "pyapp": "127.0.0.1"
-}
+}

+ 19 - 32
electron/controller/camera.js

@@ -8,31 +8,10 @@ const { liveShow, liveHide, setParams, capture, getParams,CMD,captureLive,closeO
 
 const { dialog } = require('electron'); // 引入 electron 的 dialog 模块
 const { windowManager } = require('node-window-manager');
-// 检查并读取配置文件
-function readConfigFile(configPath) {
-  try {
-    // 检查文件是否存在
-    if (!fs.existsSync(configPath)) {
-      // 创建默认配置文件
-      const defaultConfig = {};
-      fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
-      return defaultConfig;
-    }
-    // 读取配置文件
-    return JSON.parse(fs.readFileSync(configPath, 'utf8'));
-  } catch (error) {
-    console.error('读取配置文件时出错:', error);
-    throw error;
-  }
-}
-
-const configPath = path.join(__dirname, '..', 'config', 'app.config.json');
-const config = readConfigFile(configPath);
+const CoreWindow = require("ee-core/electron/window");
 
-async function checkCameraControlCmdExists() {
+async function checkCameraControlCmdExists(digiCamControlPath) {
   try {
-    // 获取 digiCamControl 文件夹路径
-    const digiCamControlPath = config.digiCamControl;
 
     // 拼接 CameraControlCmd.exe 的完整路径
     const exePath = path.join(digiCamControlPath, 'CameraControl.exe');
@@ -52,15 +31,24 @@ async function checkCameraControlCmdExists() {
       if (!canceled && filePaths.length > 0) {
         const selectedPath = filePaths[0];
         // 更新 app.config.json 中的 digiCamControl 值
-        config.digiCamControl = selectedPath;
-        fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
-        return true; // 重新检查文件是否存在
+       // config.digiCamControl = selectedPath;
+      //  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
+        digiCamControlPath = selectedPath
+        const win = CoreWindow.getMainWindow()
+        win.webContents.send('controller.camera.digiCamControlPath', {
+          code:0,
+          data:selectedPath,
+        });
+      //  return true; // 重新检查文件是否存在
       } else {
         console.error('用户未选择文件夹');
-        return false;
+        return {
+          status:-1,
+          msg:"无法找到或运行 CameraControlCmd.exe",
+        }
       }
     }
-    const res = await openCameraControlCmd();
+    const res = await openCameraControlCmd(digiCamControlPath);
     return res;
   } catch (error) {
     console.error('检查 CameraControlCmd.exe 是否存在时出错:', error);
@@ -69,11 +57,10 @@ async function checkCameraControlCmdExists() {
 }
 
 
-async function openCameraControlCmd() {
+async function openCameraControlCmd(digiCamControlPath) {
  return  new Promise(async (resolve, reject) => {
     try {
       // 获取 digiCamControl 文件夹路径
-      const digiCamControlPath = config.digiCamControl;
 
       // 拼接 CameraControlCmd.exe 的完整路径
       const exePath = path.join(digiCamControlPath, 'CameraControl.exe');
@@ -138,13 +125,13 @@ class CameraController extends Controller {
     super(ctx);
   }
 
-  async connect() {
+  async connect(digiCamControlPath) {
     try {
       await getParams('iso').catch(e=>{
         isOPen = false;
       })
       if(!isOPen){
-        await checkCameraControlCmdExists()
+        await checkCameraControlCmdExists(digiCamControlPath)
         await  CMD('All_Minimize')
         await closeCameraControlTips()
         isOPen = true

+ 51 - 1
electron/controller/setting.js

@@ -5,7 +5,19 @@ const Log = require('ee-core/log');
 const Services = require('ee-core/services');
 const path = require('path');
 const fs = require('fs');
-const { getDeviceConfigs, getDeviceConfigDetail,getDeviceConfigDetailQuery, removeConfig, saveDeviceConfig, resetDeviceConfig,updateSysConfigs,getSysConfig } = require('../api/setting');
+const {
+  getDeviceConfigs,
+  getDeviceConfigDetail,
+  getDeviceConfigDetailQuery,
+  removeConfig,
+  saveDeviceConfig,
+  resetDeviceConfig,
+  updateSysConfigs,
+  getSysConfig,
+  getDeviceTabs,
+  updateLeftRightConfig,
+  updateTabName
+} = require('../api/setting');
 
 const errData = {
   msg :'请求失败,请联系管理员',
@@ -38,6 +50,20 @@ class SettingController extends Controller {
   }
 
   /**
+   * 获取二级 设备配置列表
+   */
+  async getDeviceTabs(args) {
+    try {
+      const result = await getDeviceTabs(args);
+      if(result.data)  return result.data
+      return errData;
+    } catch (error) {
+      Log.error('获取设备配置二级列表失败:', error);
+      return errData;
+    }
+  }
+
+  /**
    * 获取设备配置详情
    * @param {Object} args - 配置ID
    */
@@ -85,6 +111,19 @@ class SettingController extends Controller {
     }
   }
 
+  async updateLeftRightConfig(args) {
+    try {
+      const result = await updateLeftRightConfig(args);
+      if(result.data)  return result.data
+      return errData;
+    } catch (error) {
+      Log.error('更新左右脚失败:', error);
+      return errData;
+    }
+  }
+
+
+
   /**
    * 重置设备配置
    * @param {Object} args - 配置ID
@@ -99,6 +138,17 @@ class SettingController extends Controller {
       return errData;
     }
   }
+  async updateTabName(args) {
+    try {
+      const result = await updateTabName(args);
+      if(result.data)  return result.data
+      return errData;
+    } catch (error) {
+      Log.error('重命名配置失败:', error);
+      return errData;
+    }
+  }
+
 
 
 

BIN
frontend/src/assets/images/home/bg.png


BIN
frontend/src/assets/images/home/left.jpg


BIN
frontend/src/assets/images/home/right.jpg


+ 1 - 1
frontend/src/components/check/index.vue

@@ -42,7 +42,7 @@
           <div class="step-content">
             <div class="step-title">自我检查</div>
             <div class="check-result">
-              <p>补光灯电源和接器是否正常连上。</p>
+              <p>补光灯电源和接器是否正常连上。</p>
               <p>请检查红外线器是否正常显示。</p>
             </div>
           </div>

+ 1 - 1
frontend/src/composables/userCheck.ts

@@ -13,7 +13,7 @@ export function useCheckInfo() {
         function ShowError(){
 
             ElMessageBox({
-                title:"接出错!",
+                title:"接出错!",
                 message:'设备连接出错,请在主窗口中重新连接设备后,在重新打开此窗口后进行操作',
                 showCancelButton:false,
                 showConfirmButton:false,

+ 3 - 1
frontend/src/router/index.ts

@@ -1,3 +1,5 @@
+
+
 import { createRouter, createWebHistory, createWebHashHistory, RouteRecordRaw } from "vue-router";
 
 import { authGuard } from './plugins/authGuard'
@@ -5,7 +7,7 @@ import { authGuard } from './plugins/authGuard'
 const routes: RouteRecordRaw[] = [
     {
         path: "/",
-        redirect: "/photography/check"
+        redirect: "/home"
     },
     {
         path: "/home",

+ 13 - 5
frontend/src/stores/modules/check.ts

@@ -4,6 +4,7 @@ import socket from "./socket";
 import icpList from "../../utils/ipc";
 import client from "./client";
 import {ElMessage} from "element-plus";
+import  configInfo  from '@/stores/modules/config';
 const socketStore = socket();
 const clientStore = client();
 
@@ -86,11 +87,19 @@ export const checkInfo = defineStore('checkInfo', () => {
         return null;
     });
 
+    const configInfoStore = configInfo();
     const checkcamControl = async ()=>{
 
 
               clientStore.ipc.removeAllListeners(icpList.camera.connect);
-              clientStore.ipc.send(icpList.camera.connect);
+              clientStore.ipc.send(icpList.camera.connect,configInfoStore.digiCamControlPath);
+              clientStore.ipc.on(icpList.camera.digiCamControlPath, async (event, result) => {
+                clientStore.ipc.removeAllListeners(icpList.camera.digiCamControlPath);
+                if(result.code === 0 && result.data){
+                    configInfoStore.updateDigiCamControlPath(result.data)
+                }
+
+              })
               clientStore.ipc.on(icpList.camera.connect, async (event, result) => {
 
 
@@ -134,7 +143,6 @@ export const checkInfo = defineStore('checkInfo', () => {
                 console.log(result);
                 if (result && checkTime.value > 0) {
                     if(deviceName === 'mcu'){
-                        console.log(result);
                         if(result.status === 2 ){
                             if(!mcu.isInitSend){
                                 socketStore.sendMessage({
@@ -157,14 +165,14 @@ export const checkInfo = defineStore('checkInfo', () => {
                             }
                         }
                         if([-1,0].includes(result.status)){
-                            if(result.status === -1 ){
+                   /*         if(result.status === -1 ){
                                 if(mcuErrorCount.value  === 0){
                                     mcuErrorCount.value++;
                                     return;
                                 }else{
                                     mcuErrorCount.value = 0
                                 }
-                            }
+                            }*/
                             devices[deviceName].status = result.status;
                             devices[deviceName].msg = result.msg;
                         }
@@ -226,7 +234,7 @@ export const checkInfo = defineStore('checkInfo', () => {
                 if( devices.mcu.status !== 2 || mcu.status !== 2 ){
                     devices.mcu.status = -1;
                     mcu.status = -1;
-                    devices.blue_tooth.msg = '拍照机接失败';
+                    devices.blue_tooth.msg = '拍照机接失败';
                 }
             }
         },1000)

+ 27 - 0
frontend/src/stores/modules/config.ts

@@ -0,0 +1,27 @@
+import { defineStore } from 'pinia';
+import { ref, computed } from 'vue';
+
+
+export const configInfo = defineStore('config',()=>{
+  const digiCamControlPath = ref("C:\\Program Files (x86)\\digiCamControl")
+  const updateDigiCamControlPath = (data:string)=>{
+    digiCamControlPath.value = data
+  }
+
+  //  1 为拍照并处理图像 2 为仅处理图像
+  const appModel = ref(1)
+  const updateAppModel = (data:number)=>{
+    appModel.value = data
+  }
+  return {
+    digiCamControlPath,
+    updateDigiCamControlPath,
+    appModel,
+    updateAppModel
+  }
+},{
+  persist:true,
+})
+
+
+export default configInfo;

+ 6 - 2
frontend/src/utils/ipc.ts

@@ -4,7 +4,8 @@ const icpList = {
         PreviewShow: 'controller.camera.liveShow',
         PreviewHide: 'controller.camera.liveHide',
         setParams:"controller.camera.setParams",
-        takePictures:"controller.camera.takePictures"
+        takePictures:"controller.camera.takePictures",
+        digiCamControlPath:"controller.camera.digiCamControlPath",
     },
     socket:{
         connect: 'controller.socket.connect',
@@ -25,9 +26,12 @@ const icpList = {
         removeDeviceConfig: 'controller.setting.removeDeviceConfig',
         saveDeviceConfig: 'controller.setting.saveDeviceConfig',
         getDeviceConfigList: 'controller.setting.getDeviceConfigList',
+        getDeviceTabs: 'controller.setting.getDeviceTabs',
         resetDeviceConfig: 'controller.setting.resetDeviceConfig',
+        updateLeftRightConfig:'controller.setting.updateLeftRightConfig',
         getSysConfig: 'controller.setting.getSysConfig',
-        updateSysConfigs: 'controller.setting.updateSysConfigs'
+        updateSysConfigs: 'controller.setting.updateSysConfigs',
+        updateTabName: 'controller.setting.updateTabName'
     },
     takePhoto:{
         getPhotoRecords: 'controller.takephoto.getPhotoRecords',

+ 117 - 323
frontend/src/views/Home/index.vue

@@ -1,353 +1,147 @@
 <template>
-
-
-  <headerBar
-    title="拍摄物体镜头矫正"
-    :menu="[
-        {
-          type:'setting'
-        },
-        {
-          type:'remoteControl'
-        },{
-            type: 'developer'
-        }
-    ]"
-  />
-  <div class="mb-4">
-
-    <template v-if="!show">
-      <div>{{useUserInfoStore.userInfo.account_name}}</div>
-      <div>{{useUserInfoStore.userInfo.brand_company_code}}</div>
-    </template>
-    <template v-else>
-      <img :src="src" width="500px" height="500px"/>
-      <img :src="preview" width="500px" height="500px"/>
-  </template>
-
-<!--
-    <el-button @click="showVideo">实时预览</el-button>
-    <el-button @click="hideVideo">关闭预览</el-button>
-    <el-button @click="takePictures">拍照</el-button>
-    <el-button @click="socketConnect">socket 连接</el-button>
-    <el-button @click="connect_mcu">发送设备连接检测请求</el-button>
-    <el-button @click="connect_bluetooth">发送遥控器请求</el-button>
-    <el-button @click="socketDisconnect">socket 断开</el-button>
-    <el-button @click="loginError">登录失败</el-button>
-    <el-button type="primary" @click="loginIn">登录成功</el-button>
-    <el-button type="success" @click="showLoginDialog">登录</el-button>
-    <el-button type="info" @click="checkVisible = true">软件检查</el-button>
-
-
--->
-
-    <el-button type="info"  @click="openSeeting">打开设置</el-button>
-    <el-button type="info"  @click="openTplSeeting">打开主图和详情设置</el-button>
-
-
-
-    <el-button type="info"  @click="connect_mcu">链接MCU</el-button>
-    <el-button type="info"  @click="connect_mcu__init">MCU初始化</el-button>
-    <el-button type="info"  @click="connect_bluetooth">连接蓝牙</el-button>
-    <el-button @click="socketDisconnect">socket 断开</el-button>
-    <el-button type="info"  @click="openFilePath">打开文件夹</el-button>
-    <router-link
-        class="mar-left-10"
-        :to="{
-          name:'PhotographyCheck'
-      }"
-    >
-      <el-button type="warning">拍摄物体</el-button>
-    </router-link>
-    <router-link
-        class="mar-left-10"
-      :to="{
-          name:'PhotographyShot'
-      }"
-  >
-    <el-button type="warning">拍摄商品</el-button>
-  </router-link>
-
-<!--    <hardware-check v-model="checkVisible" @confirm="onCheckComplete"></hardware-check>-->
-    <Login v-model:dialogVisible="dialogVisible" @login-success="handleLoginSuccess"/>
-    <el-button
-        class="mar-left-10"
-        type="primary"  @click="loginIn">登录成功</el-button>
+  <headerBar title="首页" />
+  <div class="home-container" v-loading="loading">
+    <!-- 背景图片 -->
+    <img src="@/assets/images/home/bg.png" alt="背景图片" class="background-image" />
+
+    <!-- 左侧图片区域 -->
+    <div class="image-container left-image" @click="goCheck">
+      <img src="@/assets/images/home/left.jpg" alt="拍摄产品并处理图像" class="zoom-on-hover" />
+      <div class="overlay-text">拍摄产品<br>并处理图像</div>
+    </div>
+
+    <!-- 右侧图片区域 -->
+    <div class="image-container right-image" @click="goShot">
+      <img src="@/assets/images/home/right.jpg" alt="仅处理图像" class="zoom-on-hover" />
+      <div class="overlay-text" style="line-height: 80px;">仅处理图像</div>
+    </div>
   </div>
-
-
-  <div class="mb-4">
-      <el-input v-model="paramsKey" placeholder="参数名称"></el-input>
-      <el-input v-model="paramsValue" placeholder="参数值"></el-input>
-      <el-button @click="setParams">保存</el-button>
-  </div>
-
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue'
-import useUserInfo from "@/stores/modules/user";
-import { login, getUserInfo } from '@/apis/user';
-import Login from '@/components/login/index.vue';
-import HardwareCheck from '@/components/check/index.vue'
-import headerBar from '@/components/header-bar/index.vue'
+import headerBar from "@/components/header-bar/index.vue";
+import { useRouter } from "vue-router";
+import configInfo from '@/stores/modules/config';
+import { ref, onMounted } from 'vue';
+import axios from 'axios';
 
-import { getFilePath,getRouterUrl } from '@/utils/appfun'
-import {useRouter} from "vue-router";
-const Router = useRouter()
+const configInfoStore = configInfo();
+const router = useRouter();
+const loading = ref(true);
 
 
-
-const useUserInfoStore = useUserInfo();
-const dialogVisible = ref(false);
-const checkVisible = ref(false)
-import client from "@/stores/modules/client";
-import  icpList from '@/utils/ipc'
 import socket from "@/stores/modules/socket";
-const clientStore = client();
-
-function showLoginDialog() {
-  dialogVisible.value = true;
-}
-
-function handleLoginSuccess() {
-  // 处理登录成功后的逻辑
-  console.log('登录成功');
-}
-function onCheckComplete(){
-
-}
-
-async function loginIn() {
-  console.log('aaa')
-  const res = await login({
-    "site":1,
-    "username":"13777879245",
-    "password":"753159",
-    "type":1,
-    "device":"aigc-photo"
-  })
-
-  const userRes = await getUserInfo({
-    "site":1,
-    "token":res.data.token
-  })
-
-  useUserInfoStore.updateUserInfo(userRes.data)
-}
-
-async function loginError() {
-  const res = await login({
-    "site":1,
-    "username":"18679381902",
-    "password":"123456",
-    "device":"aigc-photo"
-  })
-  console.log(res)
-}
-
-const show = ref(false)
-const imgKey = ref(0)
-const src = ref('http://localhost:5513/liveview.jpg')
-let interval:any = null
-function showVideo(){
-  if(clientStore.isClient){
-
-
-    clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);
-
-    clientStore.ipc.send(icpList.camera.PreviewShow);
-    clientStore.ipc.on(icpList.camera.PreviewShow, async (event, result) => {
-
-      show.value = true;
-      src.value = `http://localhost:5513/liveview.jpg?key=${imgKey.value}`
-      interval = setInterval(()=>{
-        imgKey.value++;
-        src.value = `http://localhost:5513/liveview.jpg?key=${imgKey.value}`
-      },100)
-
-    })
-  }
-
-}
-
-const preview = ref('http://localhost:5513/preview.jpg')
-const previewKey = ref(0)
-
-function hideVideo(){
-  if(clientStore.isClient){
-
-    clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
-
-    clientStore.ipc.send(icpList.camera.PreviewHide);
-    clientStore.ipc.on(icpList.camera.PreviewHide, async (event, result) => {
-      show.value = false;
-      if(interval) clearInterval(interval)
-    })
-  }
-
-}
-
-const paramsKey = ref('')
-const paramsValue = ref('')
-
-
-function setParams(){
-  if(clientStore.isClient){
-
-    clientStore.ipc.removeAllListeners(icpList.camera.setParams);
-
-    clientStore.ipc.send(icpList.camera.setParams,{
-      key:paramsKey.value,
-      value:paramsValue.value
-    });
-  }
-
-}
-
-
-function takePictures(){
-  if(clientStore.isClient){
-
-    clientStore.ipc.removeAllListeners(icpList.camera.takePictures);
-
-    clientStore.ipc.send(icpList.camera.takePictures);
-
-    clientStore.ipc.on(icpList.camera.takePictures, async (event, result) => {
-
-
-      setTimeout(()=>{
-        previewKey.value++;
-        preview.value = `http://localhost:5513/preview.jpg?key=${previewKey.value}`
-      },1000)
-    })
-  }
-}
-
 // 初始化 WebSocket 状态管理
-const socketStore = socket()
+const socketStore = socket();
 
 function socketConnect(){
-
-  if(clientStore.isClient){
-    socketStore.connectSocket()
-
-    clientStore.ipc.on(icpList.socket.message, async (event, result) => {
-      console.log(result)
-    })
-  }
-
+    socketStore.connectSocket();
 }
 
+const goCheck = () => {
+    configInfoStore.updateAppModel(1);
+    router.push({
+        name: 'PhotographyCheck'
+    });
+};
 
+const goShot = () => {
+    socketConnect();
+    configInfoStore.updateAppModel(2);
+    router.push({
+        name: 'PhotographyShot'
+    });
+};
+
+// 健康检查函数
+const checkHealth = async () => {
+    try {
+        const response = await axios.get('http://127.0.0.1:7074');
+        if (response.status === 200) {
+            loading.value = false; // 健康检查成功,关闭 loading
+        }
+    } catch (error) {
+        console.error('健康检查失败:', error);
+        setTimeout(() => {
+            checkHealth(); // 延迟检查
+        }, 2000);
+        // 可以在这里处理错误,例如显示错误提示
+    }
+};
 
-async function connect_mcu(){
-
-  if(clientStore.isClient){
-
-    await socketStore.connectSocket();
-    socketStore.sendMessage({
-      type: 'connect_mcu',
-      data:"connect_mcu"
-    })
-  }
-
-}
-
-async function connect_mcu__init(){
-
-  if(clientStore.isClient){
+// 在组件挂载时执行健康检查
+onMounted(() => {
+    checkHealth();
+});
+</script>
 
-    await socketStore.connectSocket();
 
-    socketStore.sendMessage({
-      type: 'init_mcu',
-      data:{
-        value:true
-      }
-    })
+<style lang="scss" scoped>
+.home-container {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+}
+
+.background-image {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  z-index: -1;
+}
+
+.image-container {
+  position: absolute;
+  cursor: pointer;
+  width: 400px; /* 设置宽度 */
+  height: 400px; /* 设置高度 */
+  overflow: hidden;
+  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.6); /* 添加阴影效果 */
+
+  .zoom-on-hover {
+    transition: transform 0.3s ease;
+    width: 100%; /* 确保图片充满容器 */
+    height: 100%; /* 确保图片充满容器 */
+    object-fit: cover; /* 裁剪图片以适应容器 */
   }
 
-}
-
-
-const openFilePath = () => {
-  // 这里可以添加打开目录的逻辑
-  /*
-  *
-  * E:\顶层\221
-  * */
-  clientStore.ipc.removeAllListeners(icpList.utils.shellFun);
-  let params = {
-    action: 'openPath',
-    params: paramsKey.value.replaceAll('/','\\')
+  &:hover .zoom-on-hover {
+    transform: scale(1.1);
   }
-  clientStore.ipc.send(icpList.utils.shellFun, params);
-}
-
-
-
-async function connect_bluetooth(){
-
-  await socketStore.connectSocket();
-     socketStore.sendMessage({type: 'connect_bluetooth',})
-
-      clientStore.ipc.on(icpList.socket.message+'_blue_tooth', (event, result) => {
-        console.log('4')
-        console.log(result)
-      });
 
 }
 
-
-
-function socketDisconnect(){
-
-  if(clientStore.isClient){
-
-    socketStore.disconnectSocket()
-  }
+.left-image {
+  top: 50%;
+  right: 50%;
+  transform: translateY(-50%);
+  margin-right: 50px;
 }
 
-
-
-function openSeeting(){
-  console.log('aaaaa')
-  clientStore.ipc.removeAllListeners(icpList.utils.openMain);
-  let params = {
-    title: '设置',
-    width: 900,
-    height: 630,
-    frame: true,
-    id:"seeting",
-    url:"http://localhost:3000/#/setting"
-  }
-  clientStore.ipc.send(icpList.utils.openMain,params);
+.right-image {
+  top: 50%;
+  left: 50%;
+  transform: translateY(-50%);
+  margin-left: 50px;
 }
-function openTplSeeting(){
 
-  const { href } = Router.resolve({
-    name: 'PhotographyDetail',
-    query:{
-      goods_art_nos:['ARN1411512'],
-    }
-  })
-  clientStore.ipc.removeAllListeners(icpList.utils.openMain);
-  let params = {
-    title: '主图和详情设置',
-    width: 900,
-    height: 650,
-    frame: true,
-    id:"photographyDetail",
-    url:getRouterUrl(href)
-  }
-  clientStore.ipc.send(icpList.utils.openMain,params);
+.overlay-text {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  color: white;
+  font-size: 24px;
+  text-align: center;
+  z-index: 1;
+  background-color: rgba(0, 0, 0, 0.5);
+  padding: 10px 40px;
+  line-height: 50px;
+  min-height: 80px;
+  min-width: 250px;
 }
-
-
-
-</script>
-
-<style scoped>
-
 </style>

+ 369 - 0
frontend/src/views/Home/index_old.vue

@@ -0,0 +1,369 @@
+<template>
+
+
+  <headerBar
+    title="拍摄物体镜头矫正"
+    :menu="[
+        {
+          type:'setting'
+        },
+        {
+          type:'remoteControl'
+        },{
+            type: 'developer'
+        }
+    ]"
+  />
+  <div class="mb-4">
+
+    <template v-if="!show">
+      <div>{{useUserInfoStore.userInfo.account_name}}</div>
+      <div>{{useUserInfoStore.userInfo.brand_company_code}}</div>
+    </template>
+    <template v-else>
+      <img :src="src" width="500px" height="500px"/>
+      <img :src="preview" width="500px" height="500px"/>
+  </template>
+
+<!--
+    <el-button @click="showVideo">实时预览</el-button>
+    <el-button @click="hideVideo">关闭预览</el-button>
+    <el-button @click="takePictures">拍照</el-button>
+    <el-button @click="socketConnect">socket 连接</el-button>
+    <el-button @click="connect_mcu">发送设备连接检测请求</el-button>
+    <el-button @click="connect_bluetooth">发送遥控器请求</el-button>
+    <el-button @click="socketDisconnect">socket 断开</el-button>
+    <el-button @click="loginError">登录失败</el-button>
+    <el-button type="primary" @click="loginIn">登录成功</el-button>
+    <el-button type="success" @click="showLoginDialog">登录</el-button>
+    <el-button type="info" @click="checkVisible = true">软件检查</el-button>
+
+
+-->
+
+    <el-button type="info"  @click="openSeeting">打开设置</el-button>
+    <el-button type="info"  @click="openTplSeeting">打开主图和详情设置</el-button>
+    <el-button type="info"  @click="opendigiCamControl">打开digiCamControl</el-button>
+
+
+
+    <el-button type="info"  @click="connect_mcu">连接MCU</el-button>
+    <el-button type="info"  @click="connect_mcu__init">MCU初始化</el-button>
+    <el-button type="info"  @click="connect_bluetooth">连接蓝牙</el-button>
+    <el-button @click="socketDisconnect">socket 断开</el-button>
+    <el-button type="info"  @click="openFilePath">打开文件夹</el-button>
+    <router-link
+        class="mar-left-10"
+        :to="{
+          name:'PhotographyCheck'
+      }"
+    >
+      <el-button type="warning">拍摄物体</el-button>
+    </router-link>
+    <router-link
+        class="mar-left-10"
+      :to="{
+          name:'PhotographyShot'
+      }"
+  >
+    <el-button type="warning">拍摄商品</el-button>
+  </router-link>
+
+<!--    <hardware-check v-model="checkVisible" @confirm="onCheckComplete"></hardware-check>-->
+    <Login v-model:dialogVisible="dialogVisible" @login-success="handleLoginSuccess"/>
+    <el-button
+        class="mar-left-10"
+        type="primary"  @click="loginIn">登录成功</el-button>
+  </div>
+
+
+  <div class="mb-4">
+      <el-input v-model="paramsKey" placeholder="参数名称"></el-input>
+      <el-input v-model="paramsValue" placeholder="参数值"></el-input>
+      <el-button @click="setParams">保存</el-button>
+  </div>
+
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import useUserInfo from "@/stores/modules/user";
+import { login, getUserInfo } from '@/apis/user';
+import Login from '@/components/login/index.vue';
+import HardwareCheck from '@/components/check/index.vue'
+import headerBar from '@/components/header-bar/index.vue'
+
+import { getFilePath,getRouterUrl } from '@/utils/appfun'
+import {useRouter} from "vue-router";
+const Router = useRouter()
+
+
+
+const useUserInfoStore = useUserInfo();
+const dialogVisible = ref(false);
+const checkVisible = ref(false)
+import client from "@/stores/modules/client";
+import  icpList from '@/utils/ipc'
+import socket from "@/stores/modules/socket";
+const clientStore = client();
+
+function showLoginDialog() {
+  dialogVisible.value = true;
+}
+
+function handleLoginSuccess() {
+  // 处理登录成功后的逻辑
+  console.log('登录成功');
+}
+function onCheckComplete(){
+
+}
+
+async function loginIn() {
+  console.log('aaa')
+  const res = await login({
+    "site":1,
+    "username":"13777879245",
+    "password":"753159",
+    "type":1,
+    "device":"aigc-photo"
+  })
+
+  const userRes = await getUserInfo({
+    "site":1,
+    "token":res.data.token
+  })
+
+  useUserInfoStore.updateUserInfo(userRes.data)
+}
+
+async function loginError() {
+  const res = await login({
+    "site":1,
+    "username":"18679381902",
+    "password":"123456",
+    "device":"aigc-photo"
+  })
+  console.log(res)
+}
+
+const show = ref(false)
+const imgKey = ref(0)
+const src = ref('http://localhost:5513/liveview.jpg')
+let interval:any = null
+function showVideo(){
+  if(clientStore.isClient){
+
+
+    clientStore.ipc.removeAllListeners(icpList.camera.PreviewShow);
+
+    clientStore.ipc.send(icpList.camera.PreviewShow);
+    clientStore.ipc.on(icpList.camera.PreviewShow, async (event, result) => {
+
+      show.value = true;
+      src.value = `http://localhost:5513/liveview.jpg?key=${imgKey.value}`
+      interval = setInterval(()=>{
+        imgKey.value++;
+        src.value = `http://localhost:5513/liveview.jpg?key=${imgKey.value}`
+      },100)
+
+    })
+  }
+
+}
+
+const preview = ref('http://localhost:5513/preview.jpg')
+const previewKey = ref(0)
+
+function hideVideo(){
+  if(clientStore.isClient){
+
+    clientStore.ipc.removeAllListeners(icpList.camera.PreviewHide);
+
+    clientStore.ipc.send(icpList.camera.PreviewHide);
+    clientStore.ipc.on(icpList.camera.PreviewHide, async (event, result) => {
+      show.value = false;
+      if(interval) clearInterval(interval)
+    })
+  }
+
+}
+
+const paramsKey = ref('')
+const paramsValue = ref('')
+
+
+function setParams(){
+  if(clientStore.isClient){
+
+    clientStore.ipc.removeAllListeners(icpList.camera.setParams);
+
+    clientStore.ipc.send(icpList.camera.setParams,{
+      key:paramsKey.value,
+      value:paramsValue.value
+    });
+  }
+
+}
+
+
+function takePictures(){
+  if(clientStore.isClient){
+
+    clientStore.ipc.removeAllListeners(icpList.camera.takePictures);
+
+    clientStore.ipc.send(icpList.camera.takePictures);
+
+    clientStore.ipc.on(icpList.camera.takePictures, async (event, result) => {
+
+
+      setTimeout(()=>{
+        previewKey.value++;
+        preview.value = `http://localhost:5513/preview.jpg?key=${previewKey.value}`
+      },1000)
+    })
+  }
+}
+
+// 初始化 WebSocket 状态管理
+const socketStore = socket()
+
+function socketConnect(){
+
+  if(clientStore.isClient){
+    socketStore.connectSocket()
+
+    clientStore.ipc.on(icpList.socket.message, async (event, result) => {
+      console.log(result)
+    })
+  }
+
+}
+
+
+
+async function connect_mcu(){
+
+  if(clientStore.isClient){
+
+    await socketStore.connectSocket();
+    socketStore.sendMessage({
+      type: 'connect_mcu',
+      data:"connect_mcu"
+    })
+  }
+
+}
+
+async function connect_mcu__init(){
+
+  if(clientStore.isClient){
+
+    await socketStore.connectSocket();
+
+    socketStore.sendMessage({
+      type: 'init_mcu',
+      data:{
+        value:true
+      }
+    })
+  }
+
+}
+
+
+const openFilePath = () => {
+  // 这里可以添加打开目录的逻辑
+  /*
+  *
+  * E:\顶层\221
+  * */
+  clientStore.ipc.removeAllListeners(icpList.utils.shellFun);
+  let params = {
+    action: 'openPath',
+    params: paramsKey.value.replaceAll('/','\\')
+  }
+  clientStore.ipc.send(icpList.utils.shellFun, params);
+}
+
+
+
+async function connect_bluetooth(){
+
+  await socketStore.connectSocket();
+     socketStore.sendMessage({type: 'connect_bluetooth',})
+
+      clientStore.ipc.on(icpList.socket.message+'_blue_tooth', (event, result) => {
+        console.log('4')
+        console.log(result)
+      });
+
+}
+
+
+
+function socketDisconnect(){
+
+  if(clientStore.isClient){
+
+    socketStore.disconnectSocket()
+  }
+}
+
+
+
+function openSeeting(){
+  console.log('aaaaa')
+  clientStore.ipc.removeAllListeners(icpList.utils.openMain);
+  let params = {
+    title: '设置',
+    width: 900,
+    height: 630,
+    frame: true,
+    id:"seeting",
+    url:"http://localhost:3000/#/setting"
+  }
+  clientStore.ipc.send(icpList.utils.openMain,params);
+}
+function openTplSeeting(){
+
+  const { href } = Router.resolve({
+    name: 'PhotographyDetail',
+    query:{
+      goods_art_nos:['ARN1411512'],
+    }
+  })
+  clientStore.ipc.removeAllListeners(icpList.utils.openMain);
+  let params = {
+    title: '主图和详情设置',
+    width: 900,
+    height: 650,
+    frame: true,
+    id:"photographyDetail",
+    url:getRouterUrl(href)
+  }
+  clientStore.ipc.send(icpList.utils.openMain,params);
+}
+
+
+import  configInfo  from '@/stores/modules/config';
+const configInfoStore = configInfo();
+const  opendigiCamControl = ()=>{
+
+  clientStore.ipc.removeAllListeners(icpList.camera.connect);
+  clientStore.ipc.send(icpList.camera.connect,configInfoStore.digiCamControlPath);
+  clientStore.ipc.on(icpList.camera.digiCamControlPath, async (event, result) => {
+    clientStore.ipc.removeAllListeners(icpList.camera.digiCamControlPath);
+    if(result.code === 0 && result.data){
+      configInfoStore.updateDigiCamControlPath(result.data)
+    }
+
+  })
+}
+
+
+</script>
+
+<style scoped>
+
+</style>

+ 13 - 9
frontend/src/views/Photography/check.vue

@@ -14,15 +14,15 @@
           <div class="left-panel flex-col justify-between">
             <div class="tips-container flex-row" v-if="show">
                 <spanc  v-if="isSetting" class="tips-tex">
-                  请在圆盘上摆上鞋子(注意左右脚),要求鞋外侧朝向拍照机,鞋子中轴线和红外线对齐,如果光亮不够,可以打开光源。
+                  请在圆盘上摆上鞋子(注意左右脚),要求鞋外侧朝向拍照机,鞋子中轴线和红外线对齐,如果光亮不够,可以打开环境光源,关闭闪光灯
                 </spanc>
                 <span v-else class="tips-tex">
-                  请在圆盘上摆上鞋子(注意左右脚),要求鞋外侧朝向拍照机,鞋子中轴线和红外线对齐,可以打开光源。
+                  请在圆盘上摆上鞋子(注意左右脚),要求鞋外侧朝向拍照机,鞋子中轴线和红外线对齐,如果光亮不够,可以打开环境光源,关闭闪光灯
                 </span>
             </div>
             <div class="camera-preview  flex col center ">
               <div class="camera-preview-img" v-if="step === 1">
-                <img v-if="previewKey" class="camera-img" :src="preview+'?key='+previewKey" />
+                <img v-if="previewKey" class="camera-img" :src="previewSrc" />
                 <div class="example-image flex-col" v-if="!isSetting && previewKey > 1"><img src="https://huilimaimg.cnhqt.com/frontend/zhihuiyin/demo.jpg?x-oss-process=image/resize,w_400"></div>
               </div>
               <template v-if="step === 2" >
@@ -122,6 +122,10 @@ import {ElMessage} from "element-plus";
 const previewKey = ref(0)
 const preview = ref(digiCamControlWEB+'liveview.jpg')
 
+const previewSrc = computed(()=>{
+  let time = new Date().getTime()
+  return preview.value+'?key='+previewKey.value+'&time='+time
+})
 const step = ref(1)
 function checkConfirm(init){
   step.value =1
@@ -129,9 +133,9 @@ function checkConfirm(init){
     menu.push({
       type:'developer'
     })
-  /*  if(useUserInfoStore.userInfo.brand_company_code === '1300'){
-
-    }*/
+    menu.push({
+      type:'toggleModel'
+    })
   }
   if(!init) previewKey.value++;
 
@@ -182,7 +186,7 @@ function takePictures() {
   if (clientStore.isClient) {
 
     loading.value = true;
-
+    hideVideo()
     socketStore.sendMessage({
       type: 'run_mcu_single',
       data: {
@@ -349,12 +353,12 @@ onBeforeUnmount(() => {
             right: 10px;
             bottom: 10px;
             background-color: rgba(216, 216, 216, 1);
-            height: 200px;
+            height: 135px;
             margin-top: 10px;
             width: 200px;
             img {
               width: 200px;
-              height: 200px;
+              height: 135px;
               display: block;
             }
           }

+ 2 - 0
frontend/src/views/Photography/components/editRow.vue

@@ -230,6 +230,8 @@ const saveRow = () => {
     ...editRowData.value
   });
   clientStore.ipc.on(icpList.setting.saveDeviceConfig, (event, result) => {
+    console.log('saveDeviceConfig');
+    console.log(editRowData.value);
     if (result.code == 0) {
       emit('confirm')
       ElMessage.success('保存成功');

+ 31 - 8
frontend/src/views/Photography/detail.vue

@@ -1,13 +1,29 @@
 <template>
 
-  <headerBar title="主图与详情生成" :menu="[
-    {
-      type: 'setting'
-    }
-  ]" />
+  <headerBar title="主图与详情生成" />
 
   <div class="detail-container">
     <div>
+      <!-- 处理模式 -->
+      <div class="logo-section flex left top" >
+        <div class="section-title" style="margin-bottom: 0px;">
+          <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
+          处理模式:
+
+            <el-checkbox v-model="form.is_only_cutout"
+                         true-value="1"
+                         false-value="0"
+                         true-label="1"
+                         false-label="0"
+                         label="仅抠图模式"/>
+        <span class="flex left" style="font-weight: normal; font-size: 12px; color: #666">
+          <el-icon><QuestionFilled /></el-icon>
+          如您勾选仅抠图模式,将只做抠图处理,不再自动生成详情页。
+        </span>
+        </div>
+      </div>
+
+      <template v-if="form.is_only_cutout == 0">
       <!-- 主图LOGO部分 -->
       <div class="logo-section flex left top" >
         <div class="section-title" style="margin-bottom: 0px;">
@@ -177,6 +193,7 @@
           </div>
         </div>
       </div>
+      </template>
     </div>
     <!-- 底部按钮 -->
     <div class="footer">
@@ -282,6 +299,7 @@ const form = reactive({
   dataType: '1', // 1: 选择excel文件 2: 系统对接
   logo_path: '', // 主图LOGO
   excel_path: '', // 商品基础资料EXCEL文件选择
+  is_only_cutout:0, //是否仅抠图模式
 })
 onMounted(() => {
   const goods_art_data = route.query.goods_art_nos
@@ -341,9 +359,12 @@ const onSizeChange = (data) => {
 
 // 开始生成操作
 const generate = async function () {
-  if ( form.dataType == '1'  && !form.excel_path) {
-    ElMessage.error('请上传商品基础资料')
-    return
+  if(form.is_only_cutout == 0 ){
+
+    if ( form.dataType == '1'  && !form.excel_path) {
+      ElMessage.error('请上传商品基础资料')
+      return
+    }
   }
   const tokenInfoStore = tokenInfo();
   const token = tokenInfoStore.getToken; // 使用 getToken() 获取 token
@@ -356,6 +377,7 @@ const generate = async function () {
   })
   const params = {
     goods_art_no: JSON.parse(JSON.stringify(goods_art_nos.value)),
+    is_only_cutout: form.is_only_cutout || '0',
     logo_path: form.logo_path || '',
     temp_name: form.selectTemplate.template_id || '',
     excel_path: form.dataType == '1' ? form.excel_path : '',
@@ -578,6 +600,7 @@ const selectFolder = () => {
   min-width: 600px;
   padding: 20px;
   overflow: hidden;
+  min-height: calc(100vh - 30px);
 
 }
 

+ 154 - 83
frontend/src/views/Photography/shot.vue

@@ -1,7 +1,7 @@
 <template>
 
   <headerBar
-      title="拍摄商品"
+      :title="configInfoStore.appModel === 1 ? '拍摄商品' : '处理图像'"
       showUser
       :menu="menu"
   />
@@ -10,67 +10,74 @@
 
   <div class="photography-page flex-col">
     <div class="main-container">
-      <div class="content-wrapper flex-row">
-<!--        <img class="camera-image" referrerpolicy="no-referrer" src="@/assets/images/Photography/camera-icon.png" />-->
-        <div class="step-number flex-col"><span class="text_22">1</span></div>
-        <div class="step-one flex-col justify-between">
-          <div class="step-header flex-row">
-            <span class="step-title">第一步:获取商品货号</span>
-            <img class="step-icon" referrerpolicy="no-referrer" src="@/assets/images/Photography/step1-icon.png" />
-            <img class="step-divider" referrerpolicy="no-referrer"
-              src="@/assets/images/Photography/step-divider-line.png" />
-          </div>
-          <div class="step-content flex-row justify-between">
-            <div class="method-container flex-col">
-              <div class="input-container flex-row">
-                <el-input class="input-item" v-model="goods_art_no" placeholder="请输入货号"> </el-input>
+      <template v-if="configInfoStore.appModel === 1 ">
+
+        <div class="content-wrapper flex-row">
+  <!--        <img class="camera-image" referrerpolicy="no-referrer" src="@/assets/images/Photography/camera-icon.png" />-->
+          <div class="step-number flex-col"><span class="text_22">1</span></div>
+          <div class="step-one flex-col justify-between">
+            <div class="step-header flex-row">
+              <span class="step-title">第一步:获取商品货号</span>
+              <img class="step-icon" referrerpolicy="no-referrer" src="@/assets/images/Photography/step1-icon.png" />
+              <img class="step-divider" referrerpolicy="no-referrer"
+                src="@/assets/images/Photography/step-divider-line.png" />
+            </div>
+            <div class="step-content flex-row justify-between">
+              <div class="method-container flex-col">
+                <div class="input-container flex-row">
+                  <el-input class="input-item" v-model="goods_art_no" placeholder="请输入货号"> </el-input>
 
-              </div>
-              <div class="auto-method flex-row justify-between">
-                <div class="text-method-tag flex-col"><span class="text_4">自动获取</span></div>
-                <span class="method-description">用遥控器扫描商品资料二维码</span>
-              </div>
-              <div class="scan-method flex-row justify-between">
-                <div class="remote-control flex-col">
                 </div>
-<!--                <span class="scan-label">遥控器扫描键</span>-->
+                <div class="auto-method flex-row justify-between">
+                  <div class="text-method-tag flex-col"><span class="text_4">自动获取</span></div>
+                  <span class="method-description">用遥控器扫描商品资料二维码</span>
+                </div>
+                <div class="scan-method flex-row justify-between">
+                  <div class="remote-control flex-col">
+                  </div>
+  <!--                <span class="scan-label">遥控器扫描键</span>-->
+                </div>
               </div>
+              <img class="remote-image" referrerpolicy="no-referrer"
+                src="@/assets/images/Photography/remote-control.png" />
             </div>
-            <img class="remote-image" referrerpolicy="no-referrer"
-              src="@/assets/images/Photography/remote-control.png" />
           </div>
-        </div>
-        <div class="step-number flex-col"><span class="text_22">2</span></div>
-        <div class="step-two flex-col justify-between">
-          <span class="step-title">第二步:启动拍摄(根据按遥控器左右键启动)</span>
-          <div class="shooting-container flex-col">
-            <div class="shooting-tips flex-row justify-between">
-              <img class="info-icon" referrerpolicy="no-referrer" src="@/assets/images/Photography/info-icon.png" />
-              <span class="tips-text">遥控左右按键可启动拍摄,中间按钮可在拍摄5张主图后解锁,用于拍摄自定义图</span>
-            </div>
-            <div class="wifi mar-top-20">
-              <img  referrerpolicy="no-referrer"
-                   src="@/assets/images/Photography/wifi.png" style="width: 60px" />
-            </div>
-            <div class="remote-control-wrap">
-              <RemoteControl
-                  @onRemoteControl="onRemoteControl"
-              />
-            </div>
+          <div class="step-number flex-col"><span class="text_22">2</span></div>
+          <div class="step-two flex-col justify-between">
+            <span class="step-title">第二步:启动拍摄(根据按遥控器左右键启动)</span>
+            <div class="shooting-container flex-col">
+              <div class="shooting-tips flex-row justify-between">
+                <img class="info-icon" referrerpolicy="no-referrer" src="@/assets/images/Photography/info-icon.png" />
+                <span class="tips-text">遥控左右按键可启动拍摄,中间按钮可在拍摄5张主图后解锁,用于拍摄自定义图</span>
+              </div>
+              <div class="wifi mar-top-20">
+                <img  referrerpolicy="no-referrer"
+                     src="@/assets/images/Photography/wifi.png" style="width: 60px" />
+              </div>
+              <div class="remote-control-wrap">
+                <RemoteControl
+                    @onRemoteControl="onRemoteControl"
+                />
+              </div>
 
+            </div>
           </div>
+
         </div>
 
-      </div>
+        <div class="last-photo" v-show="showlastPhoto" v-key="lastPhoto.file_path">
+          <div>{{lastPhoto.action_name || ''}}</div>
+          <el-image  :src="getFilePath(lastPhoto.file_path)"  fit="contain" ></el-image>
+        </div>
 
-      <div class="last-photo" v-show="showlastPhoto" v-key="lastPhoto.file_path">
-        <div>{{lastPhtotoName[lastPhoto.image_index] || ''}}</div>
-        <el-image  :src="getFilePath(lastPhoto.file_path)"  fit="contain" ></el-image>
-      </div>
-      <div class="history-section flex-col">
+      </template>
+      <div class="history-section flex-col"
+        :class="configInfoStore.appModel === 2 ? 'koutu-section' : ''"
+      >
           <span class="history-title flex between">
             <div>拍摄记录</div>
-            <div class="c-666 fs-12" v-if="goodsList.length">
+            <div class="c-666 fs-12" v-if="goodsList.length" >
+                    <el-button :disabled="!(runLoading || takePictureLoading)" @click="oneClickStop" v-if="configInfoStore.appModel === 1" class="input-button" type="primary" size="mini">一键停止</el-button>
                     <el-button :disabled="runLoading || takePictureLoading" @click="delAll" class="input-button" type="primary" size="mini">一键删除</el-button>
             </div>
           </span>
@@ -85,8 +92,8 @@
               <div v-else class="history-item clearfix"  v-for="item,index in goodsList" style="padding:10px;">
                 <div class="flex  between flex-item  c-333">
                   <div class="chaochu flex-item flex left">货号:{{ item.goods_art_no }}</div>
-                  <div>
-                    <el-button size="small" :disabled="runLoading || takePictureLoading"  type="primary"  @click="reTakePictureNos(item.goods_art_no,item)" plain>重拍</el-button>
+                  <div >
+                    <el-button size="small" :disabled="runLoading || takePictureLoading"  type="primary"  @click="reTakePictureNos(item.goods_art_no,item)" plain v-if="configInfoStore.appModel === 1">重拍</el-button>
                     <el-button size="small" :disabled="runLoading || takePictureLoading" @click="delGoods({goods_art_nos:[item.goods_art_no]})">删除</el-button>
                   </div>
                 </div>
@@ -95,30 +102,33 @@
                 </div>
                 <div class="mar-top-10 clearfix history-item_image_wrap" style="width: 100%" >
                     <component class="history-item_image"
-                         v-loading="!image.image_path && runAction.goods_art_no == item.goods_art_no"
-                         v-for="image in item.items"
-                               :is="image.image_path ? 'div' : 'p'"
+                         v-for="image,index in item.items"
+                               v-loading="!image.PhotoRecord.image_path && runAction.goods_art_no == item.goods_art_no"
+                               :is="image.PhotoRecord.image_path ? 'div' : 'p'"
 
                     >
+                      <span class="tag">{{ image.action_name }}</span>
                       <el-popover
-                          popper-class="shot-image-popper"
-                          placement="left"
+                          :popper-class="configInfoStore.appModel === 1  ? 'shot-image-popper' : 'koutu-image-popper'"
+                          :placement=" configInfoStore.appModel === 1  ? 'left' : 'right'"
                           :hide-after="0"
-                          v-if="image.image_path"
+                          width="50%"
+                          offset="20"
+                          v-if="image.PhotoRecord.image_path"
                       >
                         <template #reference>
                           <div class="flex el-image_view">
-                            <el-image  :src="getFilePath(image.image_path)"  fit="contain" >
+                            <el-image  :src="getFilePath(image.PhotoRecord.image_path)"  fit="contain" >
                               <template #error>
                                 <div class="image-slot"></div>
                               </template>
                             </el-image>
-                            <el-button :disabled="runLoading || takePictureLoading" class="reset-button" @click="reTakePicture(image)">重拍</el-button>
+                            <el-button :disabled="runLoading || takePictureLoading" class="reset-button" @click="reTakePicture(image.PhotoRecord)">重拍</el-button>
                           </div>
                         </template>
 
 
-                        <el-image  :src="getFilePath(image.image_path)"  fit="contain" >
+                        <el-image  :src="getFilePath(image.PhotoRecord.image_path)"  fit="contain" >
                           <template #error>
                             <div class="image-slot"></div>
                           </template>
@@ -127,14 +137,21 @@
 
 
                       <div class="flex el-image_view"  v-else>
-                      <el-image :src="getFilePath(image.image_path)"  fit="contain">
+                      <el-image :src="getFilePath(image.PhotoRecord.image_path)"  fit="contain">
                         <template #error>
                           <div class="image-slot"></div>
-                          <el-button :disabled="runLoading || takePictureLoading" class="reset-button" @click="reTakePicture(image)">重拍</el-button>
+                          <el-button :disabled="runLoading || takePictureLoading" class="reset-button" @click="reTakePicture(image.PhotoRecord)">重拍</el-button>
                         </template>
                       </el-image>
                       </div>
                     </component>
+                    <div v-if="item.items.length < 5"
+                      v-for="item in (5 - item.items.length)"
+                         class="history-item_image"
+                    >
+                      <span class="tag" style="font-size: 12px;">暂未配置</span>
+
+                    </div>
                 </div>
               </div>
 
@@ -150,7 +167,7 @@
             <span class="empty-text">暂无数据</span>
           </div>-->
           <div v-if="goodsList.length" class="next-step button--primary1 flex-col" @click="openPhotographyDetail"><span
-              class="next-step-text">拍摄完毕,进入下一步处理</span></div>
+              class="next-step-text">{{ configInfoStore.appModel === 1 ? '拍摄完毕,进入下一步处理' : '下一步'}}</span></div>
         </div>
 
     </div>
@@ -178,7 +195,26 @@ const takePictureLoading = ref(false)
 import useUserInfo from "@/stores/modules/user";
 const useUserInfoStore = useUserInfo();
 
+import  configInfo  from '@/stores/modules/config';
+const configInfoStore = configInfo();
+
 const menu = computed(()=>{
+  if(configInfoStore.appModel === 2){
+    return [
+      {
+        type:'setting'
+      },
+      {
+        name:'切换到拍摄模式',
+        click(){
+          configInfoStore.updateAppModel(1)
+          Router.push({
+            name:'PhotographyCheck'
+          })
+        }
+      }
+    ]
+  }
   if(useUserInfoStore.userInfo.brand_company_code === '1300'){
     return [
       {
@@ -322,7 +358,7 @@ async function runGoods(data) {
     console.log(result);
     if(result.code !== 0 && result.msg){
       ElMessage.error(result.msg)
-   //   runLoading.value = false
+      runLoading.value = false
       return;
     }
   })
@@ -456,6 +492,18 @@ const  next = async function(){
   }
 }
 
+const oneClickStop = ()=>{
+
+  if(!(runLoading.value || takePictureLoading.value)){
+    ElMessage.error('拍摄程序已结束,不需要单独停止!')
+    return
+  }else{
+
+    socketStore.sendMessage({
+      type: 'stop_action',
+    })
+  }
+}
 /**
  * 页面挂载时初始化事件监听器并获取初始数据。
  */
@@ -505,7 +553,22 @@ onMounted(async () => {
         getPhotoRecords()
       },3000)
       takePictureLoading.value = false;
+      return;
     }
+    if(result.code !== 0  && result.msg){
+      ElMessage.error(result.msg)
+      takePictureLoading.value = false;
+    }
+
+  })
+
+
+
+  // 监听一键停止
+  clientStore.ipc.on(icpList.socket.message + '_stop_action', (event, result) => {
+    console.log('_stop_action')
+    console.log(result)
+    oneClickStop()
 
   })
 
@@ -536,15 +599,18 @@ onMounted(async () => {
 
       ElMessage.success('正在拍摄中,请稍候')
 
+      takePictureLoading.value = true;
+/*      setTimeout(()=>{
+        takePictureLoading.value = false;
+      },3000)*/
       await socketStore.connectSocket();
       socketStore.sendMessage(result.data)
-      takePictureLoading.value = true;
 
-      getPhotoRecords()
-      // 延迟两秒再获取一遍数据
-      setTimeout(()=>{
-        getPhotoRecords()
-      },3000)
+           getPhotoRecords()
+         // 延迟两秒再获取一遍数据
+         setTimeout(()=>{
+           getPhotoRecords()
+         },3000)
 
     }
 
@@ -619,6 +685,7 @@ onBeforeUnmount(() => {
   clientStore.ipc.removeAllListeners(icpList.socket.message + '_photo_take');
   clientStore.ipc.removeAllListeners(icpList.socket.message + '_photo_take_finish');
   clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu_update');
+  clientStore.ipc.removeAllListeners(icpList.socket.message + '_stop_action');
 /*  window.removeEventListener('storage', handleStorageEvent);*/
 
 
@@ -629,13 +696,6 @@ onBeforeUnmount(() => {
 * */
 const lastPhoto = ref({})
 const showlastPhoto = ref(false)
-const lastPhtotoName = ref({
-  0:"俯视图",
-  1:"侧视图",
-  2:"后视图",
-  3:"鞋底",
-  4:"内里",
-})
 const  getLastPhotoRecord = async ()=>{
 
   return;
@@ -679,7 +739,11 @@ clientStore.ipc.on(icpList.socket.message + '_run_mcu_update', (event, result) =
           if(item.goods_art_no === result.data?.goods_art_no){
             console.log('========item');
             console.log(item);
-            item.items[result.data.image_index].image_path = result.data?.file_path
+            item.items[result.data.image_index].PhotoRecord.image_path = result.data?.file_path
+            result.data.action_name =  item.items[result.data.image_index].action_name
+            setTimeout(()=>{
+              item.items[result.data.image_index].PhotoRecord.image_path = result.data?.file_path
+            },1000)
             console.log(item);
             console.log( goodsList.value);
           }
@@ -1150,6 +1214,12 @@ function openPhotographyDetail() {
         width: 332px;
         height: calc(100vh - 30px);
 
+          &.koutu-section {
+            width: 100%;
+            .reset-button {
+              display: none  !important;
+            }
+          }
         .history-title {
           width: calc(100% - 20px);
           height: 22px;
@@ -1181,17 +1251,17 @@ function openPhotographyDetail() {
               border-bottom: 1px solid #CCCCCC;
             }
             .history-item_image {
-              &::before{
+              .tag {
                 color: #bbb;
                 position: absolute;
                 left: 0;
                 right: 0;
                 top:50%;
                 margin-top: -15px;
-                line-height: 30px;
+                line-height: 20px;
               }
 
-              &:nth-child(1)::before{
+             /* &:nth-child(1)::before{
                 content:"俯视图";
               }
               &:nth-child(2)::before{
@@ -1205,7 +1275,7 @@ function openPhotographyDetail() {
               }
               &:nth-child(5)::before{
                 content:"内里";
-              }
+              }*/
 
               position: relative;
               width: 70px;
@@ -1309,6 +1379,7 @@ function openPhotographyDetail() {
 
           }
         }
+
       }
 .last-photo{
   position: fixed;

+ 432 - 0
frontend/src/views/Setting/components/action_config.vue

@@ -0,0 +1,432 @@
+<template>
+
+  <el-tabs v-model="topsTab" type="card" class="top_tabs">
+    <el-tab-pane label="执行左脚程序" name="left">
+    </el-tab-pane>
+    <el-tab-pane label="执行右脚程序" name="right"></el-tab-pane>
+  </el-tabs>
+
+  <div class="two_tabs">
+      <div class="item"
+           :class="item.id === activeTab.id ? 'active' : ''"
+           v-for="item in tabs" :key="item.id"
+           @click="toggleTab(item)"
+      >{{item.mode_name}}</div>
+  </div>
+  <div class="form-table">
+    <div class="btnBox">
+      <div class="primary-btn" @click="addRow">新增一行</div>
+      <div class="primary-btn" @click="resetConfig">重新初始化</div>
+      <div class="primary-btn" @click="reName">重命名配置</div>
+      <el-radio-group style="margin-left: 10px" v-model="selectID" @click="changeSelectId(activeTab.id)">
+        <el-radio :label="activeTab.id">切换成执行配置</el-radio>
+      </el-radio-group>
+    </div>
+    <el-table max-height="700" :data="tableData" style="width: 100%" border>
+<!--      <el-table-column prop="id" label="id" />-->
+      <el-table-column prop="action_name" label="步骤" >
+        <template #default="scope">
+          {{ scope.row.action_name }}
+          <el-tag type="success" size="small" v-if="calibrationId === scope.row.id">校准位</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="take_picture" label="是否拍照" width="200px">
+        <template #default="scope">
+          <div v-if="!scope.row.is_system">
+            {{ scope.row.take_picture ? '拍照' : '不拍照' }}
+          </div>
+          <span v-else></span>
+
+        </template>
+      </el-table-column>
+      <el-table-column prop="value" label="操作" >
+        <template #default="{row, $index}">
+          <a class="mar-right-10 cursor-pointer" @click="editRow(row, $index)">编辑</a>
+          <a class="cursor-pointer" v-if="!row.is_system" @click="deleteRow(row, $index)">删除</a>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+
+
+
+
+  <EditDialog
+      v-if="dialogVisible"
+      v-model="dialogVisible"
+      :id="editId"
+      :addRowData="addRowData"
+      @confirm="getList"
+  />
+</template>
+
+<script setup lang="ts">
+import { ref, defineProps, defineEmits , watch,onMounted, reactive } from 'vue'
+import EditDialog from "./EditDialog.vue";
+import { ElMessage, ElMessageBox } from 'element-plus';import client from "@/stores/modules/client";
+import icpList from '@/utils/ipc';
+const clientStore = client();
+import socket from "@/stores/modules/socket";
+const socketStore = socket(); // WebSocket状态管理实例
+
+
+// 表格数据和对话框状态
+const tableData = ref([]); // 配置表格数据
+const dialogVisible = ref(false); // 编辑对话框可见状态
+const editTitle = ref(''); // 编辑对话框标题
+const addRowData = ref({}); // 新增行
+const topsTab = ref('left'); // 顶部tab
+const activeTab = ref({}); // 当前激活的标签页
+const tabs = ref([]); // 所有标签页
+const editId = ref(0); // 当前编辑行的索引
+const selectID = ref(0) //当前默认的ID
+
+onMounted(()=>{
+  topsTab.value = 'left';
+  getTopList()
+})
+
+/**
+ * 监听topsTab变化,获取对应标签页的设备配置列表。
+ */
+watch(() => topsTab.value, (newTab) => {
+  getTopList();
+});
+
+const getTopList = ()=>{
+      clientStore.ipc.removeAllListeners(icpList.setting.getDeviceTabs);
+      clientStore.ipc.send(icpList.setting.getDeviceTabs, {
+        type: topsTab.value == 'left' ? 0 :1
+      })
+      clientStore.ipc.on(icpList.setting.getDeviceTabs, (event, result) => {
+        console.log('getDeviceTabs')
+        console.log(topsTab.value)
+        console.log(result)
+        if(result.code == 0 && result.data){
+          tabs.value = result.data.tabs
+          tabs.value.some(item=>{
+            console.log('=======' )
+            console.log(item.id )
+            console.log(result.data.select_configs[topsTab.value] )
+            if(item.id === result.data.select_configs[topsTab.value]){
+              selectID.value = item.id
+              activeTab.value =  item
+              return true;
+            }
+          })
+
+          getList()
+        }
+        clientStore.ipc.removeAllListeners(icpList.setting.getDeviceTabs);
+      });
+
+}
+
+//切换tab
+const toggleTab = (item) => {
+  activeTab.value = item
+  getList()
+};
+
+
+const calibrationId = ref(null) //校准位
+/**
+ * 获取设备配置列表。
+ */
+const getList = () => {
+  clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
+  let params = {
+    tab_id: activeTab.value.id
+  }
+  clientStore.ipc.send(icpList.setting.getDeviceConfigList, params);
+  clientStore.ipc.on(icpList.setting.getDeviceConfigList, (event, result) => {
+    console.log('getDeviceConfigList')
+    console.log(params)
+    console.log(result)
+    if (result.code == 0) {
+      tableData.value = result.data.list;
+      const calibration =  result.data.list.filter(item=>(item.action_name === '侧视'))
+      if(calibration.length >= 1){
+        calibrationId.value = calibration[0].id
+      }else{
+
+        calibrationId.value = tableData.value[0].id
+      }
+    } else {
+      ElMessage.error('获取列表失败');
+    }
+    clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
+  });
+};
+
+
+const changeSelectId = (id)=>{
+  if(id === selectID.value) return;
+  clientStore.ipc.removeAllListeners(icpList.setting.updateLeftRightConfig);
+  let params = {
+    type: topsTab.value,
+    id,
+  }
+  clientStore.ipc.send(icpList.setting.updateLeftRightConfig, params);
+  clientStore.ipc.on(icpList.setting.updateLeftRightConfig, (event, result) => {
+    console.log('updateLeftRightConfig')
+    console.log(params)
+    console.log(result)
+    if (result.code == 0) {
+      selectID.value = id;
+    } else if(result.mssg){
+      ElMessage.error(result.mssg);
+    }else{
+      ElMessage.error('切换失败');
+    }
+    clientStore.ipc.removeAllListeners(icpList.setting.updateLeftRightConfig);
+  });
+}
+
+/**
+ * 编辑指定行的配置。
+ * @param {Object} row - 当前行的数据
+ * @param {number} index - 当前行的索引
+ */
+const editRow = (row, index) => {
+  addRowData.value = {}
+  dialogVisible.value = true;
+  editId.value = row.id
+};
+
+/**
+ * 删除指定行的配置。
+ * @param {Object} row - 当前行的数据
+ * @param {number} index - 当前行的索引
+ */
+const deleteRow = (row, index) => {
+  ElMessageBox.confirm('确定删除该步骤吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    clientStore.ipc.send(icpList.setting.removeDeviceConfig, {
+      id: row.id
+    });
+    clientStore.ipc.on(icpList.setting.removeDeviceConfig, (event, result) => {
+      if (result.code == 0) {
+        getList();
+        ElMessage.success('删除成功');
+      }  else if(result.mssg){
+        ElMessage.error(result.mssg);
+      }else {
+        ElMessage.error('删除失败');
+      }
+      clientStore.ipc.removeAllListeners(icpList.setting.removeDeviceConfig);
+    });
+  });
+};
+
+/**
+ * 重置设备配置。
+ */
+const resetConfig = () => {
+  console.log(activeTab.value);
+  ElMessageBox.confirm(`确定初始化${activeTab.value.mode_name}吗?`, '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    clientStore.ipc.removeAllListeners(icpList.setting.resetDeviceConfig);
+    clientStore.ipc.send(icpList.setting.resetDeviceConfig, {
+      tab_id: activeTab.value.id
+    });
+    clientStore.ipc.on(icpList.setting.resetDeviceConfig, (event, result) => {
+      if (result.code == 0) {
+        getList();
+        ElMessage.success('重置成功');
+      } else if(result.mssg){
+        ElMessage.error(result.mssg);
+      } else {
+        ElMessage.error('重置失败');
+      }
+      clientStore.ipc.removeAllListeners(icpList.setting.resetDeviceConfig);
+    });
+  });
+};
+
+const reName = ()=>{
+  ElMessageBox.prompt('', '重命名配置', {
+    confirmButtonText: '保存',
+    cancelButtonText: '取消',
+    inputValue:  activeTab.value.mode_name,
+    inputPlaceholder:'请输入配置名称',
+    inputValidator: (value) => {
+      if (value === '') {
+        return '请输入配置名称';
+      }
+      return true;
+    },
+  })
+      .then(({ value }) => {
+        clientStore.ipc.removeAllListeners(icpList.setting.updateTabName);
+        clientStore.ipc.send(icpList.setting.updateTabName, {
+          id: activeTab.value.id,
+          mode_name:value,
+        });
+        clientStore.ipc.on(icpList.setting.updateTabName, (event, result) => {
+          if (result.code == 0) {
+            activeTab.value.mode_name = value
+            tabs.value.some(item=>{
+              if(item.id ===  activeTab.value.id){
+                item.mode_name   =  activeTab.value.mode_name
+              }
+            })
+            ElMessage.success('重命名成功');
+          }  else if(result.mssg){
+            ElMessage.error(result.mssg);
+          }else {
+            ElMessage.error('重命名失败');
+          }
+          clientStore.ipc.removeAllListeners(icpList.setting.updateTabName);
+        });
+      })
+}
+
+/**
+ * 新增一行配置。
+ */
+const addRow = () => {
+  editId.value = -1
+  let length = Number(tableData.value.length)+1
+  addRowData.value =   {
+    mode_type: topsTab.value === 'left' ? '执行左脚程序' : '执行右脚程序',
+    tab_id: activeTab.value.id,
+    action_name: '新增步骤'+length,
+    take_picture: false,
+    camera_height: 0,
+    camera_angle: 0,
+    turntable_position: 0,
+    turntable_angle: 0,
+    shoe_upturn: false,
+    led_switch: false,
+    number_focus: 0,
+    pre_delay: 0,
+    after_delay: 0,
+  }
+  dialogVisible.value = true;
+  editTitle.value = '新增步骤';
+};
+
+</script>
+
+<style lang="scss" scoped>
+.top_tabs {
+  height: 30px;
+  overflow: hidden;
+  border: 1px solid #c8c8c8;
+  border-bottom: none;
+}
+.two_tabs {
+  width: 100%;
+  height: 30px;
+  background: #fff;
+  border: 1px solid #c8c8c8;
+  border-top: none;
+  .item {
+    float: left;
+    padding: 0 15px;
+    font-size: 14px;
+    height: 30px;
+    line-height: 30px;
+    cursor: pointer;
+    &.active {
+      color: #2957FF;
+    }
+  }
+}
+.form-table{
+  margin-top: 10px;
+  .btnBox{
+    display: flex;
+    align-items: center;
+    margin-bottom: 12px;
+  }
+  :deep(.el-table .el-table__header){
+    padding: 0;
+    height: 30px;
+    .el-table__cell{
+      background: #F1F4FF;
+    }
+  }
+  :deep(.el-table .el-table__cell){
+    padding: 0;
+    text-align: center;
+  }
+  :deep(.el-table__row) {
+    height: 30px;
+    padding: 0;
+    &:nth-child(even) {
+      background: #F1F4FF;
+    }
+    &:nth-child(odd) {
+      background: #FFFFFF;
+    }
+  }
+  .primary-btn{
+    width: 80px;
+    height: 30px;
+    background: linear-gradient( 135deg, #2FB0FF 0%, #B863FB 100%);
+    border-radius: 4px;
+    color: #fff;
+    font-size: 14px;
+    text-align: center;
+    cursor: pointer;
+    line-height: 30px;
+    margin-right: 10px;
+  }
+  .normal-btn{
+    width: 80px;
+    height: 30px;
+    background: #fff;
+    border: 1px solid #CCCCCC;
+    border-radius: 4px;
+    font-size: 14px;
+    text-align: center;
+    line-height: 30px;
+    cursor: pointer;
+  }
+  .cursor-pointer{
+    cursor: pointer;
+  }
+}
+.editDialog{
+  .el-dialog__body{
+    padding: 0 !important;
+  }
+  .btn-row{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    gap: 10px;
+  }
+  .primary-btn{
+    width: 100px;
+    height: 30px;
+    background: linear-gradient( 135deg, #2FB0FF 0%, #B863FB 100%);
+    border-radius: 4px;
+    color: #fff;
+    font-size: 14px;
+    text-align: center;
+    line-height: 30px;
+    cursor: pointer;
+  }
+  .normal-btn{
+    width: 100px;
+    height: 30px;
+    background: #fff;
+    border: 1px solid #CCCCCC;
+    border-radius: 4px;
+    font-size: 14px;
+    text-align: center;
+    line-height: 30px;
+    cursor: pointer;
+  }
+}
+
+</style>

+ 30 - 328
frontend/src/views/Setting/index.vue

@@ -14,7 +14,7 @@
         <img src="@/assets/images/setting/icon3a.png" class="nav-icon" v-else/>
         <span>其他设置</span>
       </div>
-      <div class="nav-item" :class="{'active': activeIndex === 4}" @click="activeIndex = 4">
+      <div class="nav-item" v-if="configInfoStore.appModel === 1" :class="{'active': activeIndex === 4}" @click="activeIndex = 4">
         <img src="@/assets/images/setting/icon4.png" class="nav-icon" v-if="activeIndex !== 4"/>
         <img src="@/assets/images/setting/icon4a.png" class="nav-icon" v-else/>
         <span>左右脚程序设置</span>
@@ -27,7 +27,10 @@
                 <div class="form-item">
                     <label>主图尺寸:</label>
                     <div class="select-wrapper">
-                    <el-select v-model="formData.basic_configs.main_image_size" placeholder="请选择">
+                    <el-select multiple
+                               collapse-tags
+                               multiple-limit="3"
+                               v-model="formData.basic_configs.main_image_size" placeholder="请选择">
                       <el-option v-for="item in mainImageSizeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
                     </el-select>
                     </div>
@@ -87,42 +90,8 @@
           </div>
       <!--其他设置-->
           <div class="selectBox" style="padding-top: 0px;padding-left: 0;" v-if="activeIndex === 4">
-            <el-tabs v-model="activeTab" type="card">
-              <el-tab-pane label="执行左脚程序" name="left">
-              </el-tab-pane>
-              <el-tab-pane label="执行右脚程序" name="right"></el-tab-pane>
-            </el-tabs>
-            <div class="form-table">
-              <div class="btnBox">
-                <div class="primary-btn" @click="addRow">新增一行</div>
-                <div class="normal-btn" @click="resetConfig">重新初始化</div>
-              </div>
-              <el-table max-height="700" :data="activeTab === 'left' ? lefttableData : righttableData" style="width: 100%" border>
-                <el-table-column prop="id" label="id" />
-                <el-table-column prop="action_name" label="步骤" />
-                <el-table-column prop="take_picture" label="是否拍照" width="200px">
-                  <template #default="scope">
-                    <el-radio-group v-model="scope.row.take_picture" v-if="!scope.row.is_system">
-                      <el-radio :label="true">拍照</el-radio>
-                      <el-radio :label="false">不拍照</el-radio>
-                    </el-radio-group>
-                    <span v-else></span>
-                  </template>
-                </el-table-column>
-<!--                <el-table-column prop="action_index" label="排序" >
-                  <template #default="{row, $index}">
-                    <a v-if="$index !== 0" class="cursor-pointer" @click="upRow(row)">上移</a>
-                    <a class="mar-left-10 cursor-pointer" v-if="$index !== activeTab === 'left' ? lefttableData.length - 1 : righttableData.length - 1" @click="downRow(row)">下移</a>
-                  </template>
-                </el-table-column>-->
-                <el-table-column prop="value" label="操作" >
-                  <template #default="{row, $index}">
-                    <a class="mar-right-10 cursor-pointer" @click="editRow(row, $index)">编辑</a>
-                    <a class="cursor-pointer" v-if="!row.is_system" @click="deleteRow(row, $index)">删除</a>
-                  </template>
-                </el-table-column>
-              </el-table>
-            </div>
+            <actionConfig/>
+
           </div>
     </div>
       <div class="text-center mt-8">
@@ -131,13 +100,6 @@
         </button>
       </div>
 
-    <EditDialog
-        v-if="dialogVisible"
-        v-model="dialogVisible"
-        :id="editId"
-        :addRowData="addRowData"
-        @confirm="getList"
-    />
   </div>
 </template>
 
@@ -153,7 +115,6 @@ import { useRoute, useRouter } from 'vue-router';
 import { onMounted, watch } from 'vue';
 import socket from "@/stores/modules/socket";
 import headerBar from '@/components/header-bar/index.vue';
-import EditDialog from './components/EditDialog'
 import client from "@/stores/modules/client";
 import icpList from '@/utils/ipc';
 const clientStore = client();
@@ -161,6 +122,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
 import { digiCamControlWEB } from  '@/utils/appconfig'
 import { useCheckInfo } from '@/composables/userCheck';
 import { preview } from '@planckdev/element-plus/utils'
+import actionConfig from './components/action_config.vue'
 useCheckInfo();
 
 // 路由和状态管理初始化
@@ -172,13 +134,17 @@ const folderPath = ref(''); // 文件夹路径
 const activeIndex = ref(0); // 当前激活的索引
 const socketStore = socket(); // WebSocket状态管理实例
 
+
+import  configInfo  from '@/stores/modules/config';
+const configInfoStore = configInfo();
+
 /**
  * 表单数据对象,用于存储设备配置信息。
  */
 const formData = reactive({
   //基础配置
   basic_configs:{
-    "main_image_size": "",//主图尺寸
+    "main_image_size": [],//主图尺寸
     "image_out_format": "",//图片输出格式
     "image_sharpening": "" //图片锐化
   },
@@ -217,10 +183,13 @@ const formData = reactive({
 
 // 配置选项列表
 const mainImageSizeList = ref([
-  { label: '800', value: '800' },
-  { label: '1024', value: '1024' },
-  { label: '1200', value: '1200' },
-  { label: '1600', value: '1600' },
+  { label: '320*320', value: 320 },
+  { label: '512*512', value: 512 },
+  { label: '768*768', value: 768 },
+  { label: '800*800', value: 800 },
+  { label: '1024*1024', value: 1024 },
+  { label: '1400*1400', value: 1400 },
+  { label: '1600*1600', value: 1600 },
 ]);
 const imageFormatList = ref([
   { label: 'jpg', value: 'jpg' },
@@ -261,6 +230,7 @@ const deviceSpeedList = ref([
   { label: '二档', value: '2' },
   { label: '三档', value: '3' },
 ]);
+/*
 const runModeList = ref([
   { label: '普通模式', value: '普通模式' },
   { label: '待用户确认模式', value: '待用户确认模式' }
@@ -290,16 +260,7 @@ const downList = ref([
   { label: '下移', value: '2' },
   { label: '左右移', value: '3' },
 ]);
-
-// 表格数据和对话框状态
-const lefttableData = ref([]); // 左脚配置表格数据
-const righttableData = ref([]); // 右脚配置表格数据
-const dialogVisible = ref(false); // 编辑对话框可见状态
-const editTitle = ref(''); // 编辑对话框标题
-const addRowData = ref({}); // 新增行
-const activeTab = ref('left'); // 当前激活的标签页
-const editId = ref(0); // 当前编辑行的索引
-const isDefault = ref(false); // 是否为默认配置
+*/
 
 const indexKey  ={
   0:"basic_configs",
@@ -316,20 +277,8 @@ watch(() => route.query.type, async (newType,oldType) => {
     await  saveSetting(oldType)
   }
   const typeValue = parseInt(newType) || 0;
+  if(typeValue === 4) return;
   switch (typeValue) {
-      case 4:
-        activeTab.value = 'left';
-        clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-        clientStore.ipc.send(icpList.setting.getDeviceConfigList, {
-          mode_type: '执行左脚程序'
-        });
-        clientStore.ipc.on(icpList.setting.getDeviceConfigList, (event, result) => {
-          if (result?.data?.list) {
-            lefttableData.value = result.data.list;
-          }
-          clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-        });
-        break;
       default:
         clientStore.ipc.removeAllListeners(icpList.setting.getSysConfig);
         clientStore.ipc.send(icpList.setting.getSysConfig,{
@@ -347,34 +296,6 @@ watch(() => route.query.type, async (newType,oldType) => {
     }
 }, { immediate: true });
 
-/**
- * 监听activeTab变化,获取对应标签页的设备配置列表。
- */
-watch(() => activeTab.value, (newTab) => {
-  if (newTab === 'left') {
-    clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-    clientStore.ipc.send(icpList.setting.getDeviceConfigList, {
-      mode_type: '执行左脚程序'
-    });
-    clientStore.ipc.on(icpList.setting.getDeviceConfigList, (event, result) => {
-      if (result?.data?.list) {
-        lefttableData.value = result.data.list;
-      }
-      clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-    });
-  } else {
-    clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-    clientStore.ipc.send(icpList.setting.getDeviceConfigList, {
-      mode_type: '执行右脚程序'
-    });
-    clientStore.ipc.on(icpList.setting.getDeviceConfigList, (event, result) => {
-      if (result?.data?.list) {
-        righttableData.value = result.data.list;
-      }
-      clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-    });
-  }
-});
 
 /**
  * 监听activeIndex变化,更新URL中的查询参数。
@@ -403,22 +324,17 @@ onMounted(() => {
 });
 
 /**
- * 打开文件夹选择对话框并更新表单数据。
- */
-const selectFolder = () => {
-  clientStore.ipc.removeAllListeners(icpList.utils.openDirectory);
-  clientStore.ipc.send(icpList.utils.openDirectory);
-  clientStore.ipc.on(icpList.utils.openDirectory, async (event, result) => {
-    formData.captureOneFolder = result;
-    clientStore.ipc.removeAllListeners(icpList.utils.openDirectory);
-  });
-};
-
-/**
  * 保存当前表单配置。
  */
 const saveSetting = async (index) => {
 
+  if(index === 0){
+    if(formData.basic_configs.main_image_size.length === 0){
+
+      ElMessage.error('请选择主图尺寸!');
+      return;
+    }
+  }
   await new Promise((resolve, reject) => {
 
     clientStore.ipc.removeAllListeners(icpList.setting.updateSysConfigs);
@@ -440,132 +356,6 @@ const saveSetting = async (index) => {
 
 };
 
-/**
- * 新增一行配置。
- */
-const addRow = () => {
-  if (activeTab.value === 'left') {
-    editId.value = -1
-    addRowData.value = {
-      mode_type: '执行左脚程序',
-      action_name: '',
-      take_picture: false,
-      camera_height: 0,
-      camera_angle: 0,
-      turntable_position: 0,
-      turntable_angle: 0,
-      shoe_upturn: false,
-      led_switch: false,
-      number_focus: 0,
-      pre_delay: 0,
-      after_delay: 0,
-    };
-    dialogVisible.value = true;
-    editTitle.value = '新增步骤';
-  } else {
-    editId.value = -1
-    addRowData.value = {
-      mode_type: '执行右脚程序',
-      action_name: '',
-      take_picture: false,
-      camera_height: 0,
-      camera_angle: 0,
-      turntable_position: 0,
-      turntable_angle: 0,
-      shoe_upturn: false,
-      led_switch: false,
-      number_focus: 0,
-      pre_delay: 0,
-      after_delay: 0,
-    };
-    dialogVisible.value = true;
-    editTitle.value = '新增步骤';
-  }
-};
-
-/**
- * 获取设备配置列表。
- */
-const getList = () => {
-  clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-  clientStore.ipc.send(icpList.setting.getDeviceConfigList, {
-    mode_type: activeTab.value === 'left' ? '执行左脚程序' : '执行右脚程序'
-  });
-  clientStore.ipc.on(icpList.setting.getDeviceConfigList, (event, result) => {
-    if (result.code == 0) {
-      if (activeTab.value === 'left') {
-        lefttableData.value = result.data.list;
-      } else {
-        righttableData.value = result.data.list;
-      }
-    } else {
-      ElMessage.error('获取列表失败');
-    }
-    clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigList);
-  });
-};
-
-/**
- * 编辑指定行的配置。
- * @param {Object} row - 当前行的数据
- * @param {number} index - 当前行的索引
- */
-const editRow = (row, index) => {
-  dialogVisible.value = true;
-  editId.value = row.id
-};
-
-/**
- * 删除指定行的配置。
- * @param {Object} row - 当前行的数据
- * @param {number} index - 当前行的索引
- */
-const deleteRow = (row, index) => {
-  ElMessageBox.confirm('确定删除该步骤吗?', '提示', {
-    confirmButtonText: '确定',
-    cancelButtonText: '取消',
-    type: 'warning'
-  }).then(() => {
-    clientStore.ipc.send(icpList.setting.removeDeviceConfig, {
-      id: row.id
-    });
-    clientStore.ipc.on(icpList.setting.removeDeviceConfig, (event, result) => {
-      if (result.code == 0) {
-        getList();
-        ElMessage.success('删除成功');
-      } else {
-        ElMessage.error('删除失败');
-      }
-      clientStore.ipc.removeAllListeners(icpList.setting.removeDeviceConfig);
-    });
-  });
-};
-
-/**
- * 重置设备配置。
- */
-const resetConfig = () => {
-  ElMessageBox.confirm(`确定初始化执行${activeTab.value === 'left' ? '左脚' : '右脚'}程序吗?`, '提示', {
-    confirmButtonText: '确定',
-    cancelButtonText: '取消',
-    type: 'warning'
-  }).then(() => {
-    clientStore.ipc.send(icpList.setting.resetDeviceConfig, {
-      mode_type: activeTab.value === 'left' ? '执行左脚程序' : '执行右脚程序'
-    });
-    clientStore.ipc.on(icpList.setting.resetDeviceConfig, (event, result) => {
-      if (result.code == 0) {
-        getList();
-        ElMessage.success('重置成功');
-      } else {
-        ElMessage.error('重置失败');
-      }
-      clientStore.ipc.removeAllListeners(icpList.setting.resetDeviceConfig);
-    });
-  });
-};
-
-
 
 
 </script>
@@ -726,94 +516,6 @@ body {
   padding: 30px 0;
   height: 100px;
 }
-.form-table{
-  margin-top: 10px;
-  .btnBox{
-    display: flex;
-    align-items: center;
-    margin-bottom: 12px;
-  }
-  :deep(.el-table .el-table__header){
-    padding: 0;
-    height: 30px;
-    .el-table__cell{
-      background: #F1F4FF;
-    }
-  }
-  :deep(.el-table .el-table__cell){
-    padding: 0;
-    text-align: center;
-  }
-  :deep(.el-table__row) {
-    height: 30px;
-    padding: 0;
-    &:nth-child(even) {
-      background: #F1F4FF;
-    }
-    &:nth-child(odd) {
-      background: #FFFFFF;
-    }
-  }
-  .primary-btn{
-    width: 80px;
-    height: 30px;
-    background: linear-gradient( 135deg, #2FB0FF 0%, #B863FB 100%);
-    border-radius: 4px;
-    color: #fff;
-    font-size: 14px;
-    text-align: center;
-    cursor: pointer;
-    line-height: 30px;
-    margin-right: 10px;
-  }
-  .normal-btn{
-    width: 80px;
-    height: 30px;
-    background: #fff;
-    border: 1px solid #CCCCCC;
-    border-radius: 4px;
-    font-size: 14px;
-    text-align: center;
-    line-height: 30px;
-    cursor: pointer;
-  }
-  .cursor-pointer{
-    cursor: pointer;
-  }
-}
-.editDialog{
-  .el-dialog__body{
-    padding: 0 !important;
-  }
-  .btn-row{
-    display: flex;
-    align-items: center;
-    justify-content: flex-end;
-    gap: 10px;
-  }
-  .primary-btn{
-    width: 100px;
-    height: 30px;
-    background: linear-gradient( 135deg, #2FB0FF 0%, #B863FB 100%);
-    border-radius: 4px;
-    color: #fff;
-    font-size: 14px;
-    text-align: center;
-    line-height: 30px;
-    cursor: pointer;
-  }
-  .normal-btn{
-    width: 100px;
-    height: 30px;
-    background: #fff;
-    border: 1px solid #CCCCCC;
-    border-radius: 4px;
-    font-size: 14px;
-    text-align: center;
-    line-height: 30px;
-    cursor: pointer;
-  }
-}
   .config-type{
     font-size: 14px;
     color: #333333;

+ 12 - 0
hlm/aigc/CameraMachine/frontend/src/views/Home/index.vue

@@ -0,0 +1,12 @@
+<!-- ... existing code ... -->
+<div class="image-container left-image" @click="goCheck">
+    <img src="@/assets/images/home/left.jpg" alt="拍摄产品并处理图像" class="zoom-on-hover" />
+    <div class="overlay-text">拍摄产品<br>并处理图像</div>
+</div>
+
+<!-- 右侧图片区域 -->
+<div class="image-container right-image" @click="goShot">
+    <img src="@/assets/images/home/right.jpg" alt="仅处理图像" class="zoom-on-hover" />
+    <div class="overlay-text">仅处理图像</div>
+</div>
+<!-- ... existing code ... -->

+ 2 - 2
public/dist/index.html

@@ -5,8 +5,8 @@
     <link rel="icon" type="image/svg+xml" href="./vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>智惠映AI自动拍照机</title>
-    <script type="module" crossorigin src="./assets/index-CW4uQ-aR.js"></script>
-    <link rel="stylesheet" crossorigin href="./assets/index-CL_4evXq.css">
+    <script type="module" crossorigin src="./assets/index-CnxFcUMX.js"></script>
+    <link rel="stylesheet" crossorigin href="./assets/index-BAP24IE0.css">
   </head>
   <body>
     <div id="app"></div>