import { ref, onMounted, onBeforeUnmount, watchEffect, computed } from 'vue' import icpList from '@/utils/ipc' import client from "@/stores/modules/client"; import socket from "@/stores/modules/socket"; import { ElMessage, ElMessageBox } from 'element-plus' import { getFilePath, getRouterUrl } from '@/utils/appfun' import { useRouter, useRoute } from "vue-router"; import checkInfo from "@/stores/modules/check"; import generate from '@/utils/menus/generate' import { clickLog, setLogInfo } from '@/utils/log' import { useUuidStore } from '@/stores/modules/uuid' import useUserInfo from "@/stores/modules/user"; import configInfo from '@/stores/modules/config'; import tokenInfo from "@/stores/modules/token"; import { getAllUserConfigs, getTopTabs } from '@/apis/setting'; export default function usePhotography() { const loading = ref(false) const runLoading = ref(false) const takePictureLoading = ref(false) // pagination const pageSize = ref(10) const currentPage = ref(1) const totalPages = ref(1) const goodsList = ref([]) const goods_art_no_tpl = ref('') const goods_art_no = ref('') const runAction = ref({ "action": "", "goods_art_no": "" }) const lastPhoto = ref({}) const showlastPhoto = ref(false) const isDelGoodsGetList = ref(false) const reNosObj = ref({ goods_art_no: null, action: null, }) const goodsArtNo = ref() const searchGoodsArtNo = ref('') let smartShooterTimeout: ReturnType | null = null // ==================== 演示模式 ==================== const isDemoMode = ref(false) // 是否处于演示模式 const demoGoodsArtNo = ref('演示货号1') // 演示货号 const demoProgramType = ref('执行左脚程序') // 演示程序类型 const demoConfigList = ref<{id: number, mode_name: string}[]>([]) // 演示配置列表 const demoSelectedConfigId = ref(null) // 选中的演示配置ID const demoDialogVisible = ref(false) // 演示配置对话框 // ==================== 演示模式 END ==================== // 初始化 WebSocket 状态管理 const socketStore = socket() const uuidStore = useUuidStore(); const clientStore = client(); const Router = useRouter() const route = useRoute(); const useUserInfoStore = useUserInfo(); const configInfoStore = configInfo(); const tokenInfoStore = tokenInfo(); const checkInfoStore = checkInfo() // 拍照点位配置 const STORAGE_KEY = 'photo_point_name' // 获取已配置相机的点位列表(从 getAllUserConfigs API 获取,仅返回已绑定相机的点位) const getPointList = async (): Promise => { try { const result = await getAllUserConfigs({}) if (result.code == 0 && result.data?.configs?.camera_configs?.iso_config) { const isoConfig = result.data.configs.camera_configs.iso_config const points = Object.keys(isoConfig).filter(key => { const config = isoConfig[key] return config && config.CameraKey && config.CameraKey !== '' }) return points.length > 0 ? points : ['A'] } } catch (err) { console.error('获取点位配置失败:', err) } return ['A'] } // 获取保存的点位(单相机模式默认A,多相机模式验证点位合法性) const getPhotoPointName = async (): Promise => { if (!useUserInfoStore.isMultiCameraMode) { return 'A' } const pointList = await getPointList() const savedPoint = localStorage.getItem(STORAGE_KEY) if (savedPoint && pointList.includes(savedPoint)) { return savedPoint } return pointList[0] || 'A' } // 抠图请求去重与延迟队列(key: goods_art_no, value: timeoutId) const segmentQueue = new Map>() function isGoodsStillInList(goodsArtNo: string): boolean { return goodsList.value?.some((g: any) => g.goods_art_no === goodsArtNo) || false } function scheduleSegment(goodsArtNo: string) { if (!goodsArtNo) return // 若已存在,则重置计时(重新插入) if (segmentQueue.has(goodsArtNo)) { const t = segmentQueue.get(goodsArtNo) if (t) clearTimeout(t) segmentQueue.delete(goodsArtNo) } const timeoutId = setTimeout(async () => { segmentQueue.delete(goodsArtNo) // if (!isGoodsStillInList(goodsArtNo)) return try { await socketStore.connectSocket(); socketStore.sendMessage({ type: 'segment_progress', data: { token: tokenInfoStore.getToken, uuid: uuidStore?.getUuid || '', goods_art_no: [goodsArtNo], } }) } catch (e) { // 忽略发送异常,避免打断主流程 } }, 20000) segmentQueue.set(goodsArtNo, timeoutId) } /** * 保存货号模板到货号变量中。 */ function saveGoodsArtNo() { if (goods_art_no_tpl.value) { goods_art_no.value = goods_art_no_tpl.value ElMessage.success('商品货号' + goods_art_no.value + '获取成功,请在遥控器上按下左或右脚按键,启动拍摄') } } /** * 获取拍照记录。 * @param params - 可选参数,用于分页或其他筛选条件。 */ async function getPhotoRecords(params?: { page?: number; size?: number; goods_art_no?: string }) { if (loading.value) return; loading.value = true; const page = params?.page ?? currentPage.value ?? 1 const size = params?.size ?? pageSize.value ?? 10 console.log('params' , { ...params, page, size, }) clientStore.ipc.send(icpList.takePhoto.getPhotoRecords, { ...params, page, size, }); clientStore.ipc.on(icpList.takePhoto.getPhotoRecords, (event, result) => { loading.value = false; if (result.code === 0) { clientStore.ipc.removeAllListeners(icpList.takePhoto.getPhotoRecords); //console.log('getPhotoRecords print_time:' + new Date().toLocaleString()) // console.log('getPhotoRecords print_time:' + JSON.stringify(result.data.list)) console.log(result.data) // 在设置 goodsList.value 之前,检查 items 数组中的 action_name 是否为 null const modifiedList = result.data.list.map(item => { // 检查 items 数组中是否有 action_name 为 null 的情况 const hasNullActionName = item.items && Array.isArray(item.items) && item.items.some(image => image.action_name === null || image.action_name === undefined); // 根据检查结果设置 syncConfig return { ...item, syncConfig: hasNullActionName ? false : true }; }); goodsList.value = modifiedList; // update pagination info if provided by API if (result.data) { currentPage.value = result.data.current_page || page totalPages.value = result.data.total_pages || 1 } if (isDelGoodsGetList.value) { isDelGoodsGetList.value = false; return; } getLastPhotoRecord() } else if (result.msg) { ElMessage.error(result.msg) } }); } /** * 执行拍照操作。 * @param data - 包含拍摄所需的数据对象。 */ async function runGoods(data) { if (runLoading.value || takePictureLoading.value) { ElMessage.error('拍摄程序正在运行,请稍候') return } await socketStore.connectSocket(); socketStore.sendMessage({ type: 'run_mcu', data, }) runLoading.value = true; runAction.value.action = data.action runAction.value.goods_art_no = data.goods_art_no // goods_art_no.value = '' goods_art_no_tpl.value = '' reNosObj.value.goods_art_no = null; reNosObj.value.action = null; searchGoodsArtNo.value = '' clientStore.ipc.on(icpList.socket.message + '_run_mcu', (event, result) => { clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu'); console.log('_run_mcu'); console.log(result); if (result.code !== 0 && result.msg) { ElMessage.error(result.msg) runLoading.value = false return; } else { ElMessage.success('开始拍摄,请稍后') } }) } /** * 格式化时间字符串。 * @param time - 原始时间字符串。 * @returns 格式化后的时间字符串,若输入为空则返回 null。 */ const getTime = function (time) { if (!time) return null return time.replace('T', ' ').substr(5, 11) } /** * 删除所有商品货号的历史记录。 */ async function delAll() { let params = goodsList.value.map(item => item.goods_art_no) try { await ElMessageBox.confirm('确定要删除当下的历史记录吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', }) await clickLog({ describe: { action: '点击确认一键删除', goods_art_nos: params } }, route) del({ goods_art_nos: params }) } catch (e) { await clickLog({ describe: { action: '点击取消一键删除' } }, route) } } /** * 删除指定的商品货号。 * @param params - 包含需要删除的货号列表的对象。 */ const delGoods = async function (params) { try { await ElMessageBox.confirm('确定要删除货号:' + params.goods_art_nos[0] + '的拍摄数据吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', }) await clickLog({ describe: { action: '点击确认删除货号', goods_art_no: params.goods_art_nos?.[0] } }, route) del(params) } catch (e) { await clickLog({ describe: { action: '点击取消删除货号', goods_art_no: params.goods_art_nos?.[0] } }, route) } } /** * 删除指定的商品货号。 * @param params - 包含需要删除的货号列表的对象。 */ const del = async function (params) { console.log(icpList.takePhoto.delectGoodsArts, params); clientStore.ipc.removeAllListeners(icpList.takePhoto.delectGoodsArts); clientStore.ipc.send(icpList.takePhoto.delectGoodsArts, params); clientStore.ipc.on(icpList.takePhoto.delectGoodsArts, (event, result) => { clientStore.ipc.removeAllListeners(icpList.takePhoto.delectGoodsArts); console.log("icpList.takePhoto.delectGoodsArts", params); if (result.code === 0) { isDelGoodsGetList.value = true ElMessage.info('货号删除成功') getPhotoRecords() if (reNosObj.value.goods_art_no) { runGoods( { "action": reNosObj.value.action, "goods_art_no": reNosObj.value.goods_art_no }) } } else if (result.msg) { ElMessage.error(result.msg) } }); } //单个重拍 const reTakePicture = async (img) => { if (!img.id) return; if (img.image_path) { try { await ElMessageBox.confirm('此操作会先删除此数据,需要继续吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', }) await clickLog({ describe: { action: '点击确认单张重拍', goods_art_no: img.goods_art_no, action_name: img.action_name } }, route) } catch (e) { await clickLog({ describe: { action: '点击取消单张重拍', goods_art_no: img.goods_art_no, action_name: img.action_name } }, route) return } } runLoading.value = true; reNosObj.value.goods_art_no = img.goods_art_no reNosObj.value.action = 're_take_picture' let params = { id: img.action_id } clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigDetail); clientStore.ipc.send(icpList.setting.getDeviceConfigDetail, params); clientStore.ipc.on(icpList.setting.getDeviceConfigDetail, (event, result) => { console.log('getDeviceConfigDetail') console.log(result) if (result.code == 0 && result.data) { clientStore.ipc.removeAllListeners(icpList.setting.getDeviceConfigDetail); this_run_mcu_single(result.data) } else if (result.msg) { runLoading.value = false; reNosObj.value.goods_art_no = '' reNosObj.value.action = '' ElMessage.error(result.msg) } }); function this_run_mcu_single(data) { clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu_single'); socketStore.sendMessage({ type: 'run_mcu_single', data: { camera_height: Number(data.camera_height), camera_angle: Number(data.camera_angle), led_switch: data.led_switch, id: 0, mode_type: data.mode_type, turntable_position: Number(data.turntable_position), action_name: data.action_name || '测试', turntable_angle: Number(data.turntable_angle), shoe_upturn: Number(data.shoe_upturn), camera_focal_distance: Number(data.camera_focal_distance), action_index: 1, number_focus: 0, take_picture: false, point_name:data.point_name, is_move_device: data.is_move_device, pre_delay: 0, after_delay: 0, } }); clientStore.ipc.on(icpList.socket.message + '_run_mcu_single', async (event, result) => { console.log('_run_mcu_single_row') clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu_single'); this_re_take_picture(data) }) } async function this_re_take_picture(data) { await ElMessageBox.alert('已复位到该视图下,请把鞋子摆放完毕之后,点击按钮开始重拍', '提示', { confirmButtonText: "开始重拍", showClose: false, closeOnClickModal: false, closeOnPressEscape: false }) await clickLog({ describe: { action: '点击开始重拍', goods_art_no: img.goods_art_no } }, route) socketStore.sendMessage({ type: 'smart_shooter_photo_take', "data": { "id": img.id, "goods_art_no": img.goods_art_no, point_name:data.point_name, is_move_device: data.is_move_device }, }) } } // 删除单张图片 const deletePhotoRecord = async (img) => { if (!img?.id) return try { await ElMessageBox.confirm('确定要删除这张图片吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', }) await clickLog({ describe: { action: '点击确认删除单张图片', goods_art_no: img.goods_art_no, record_id: img.id, action_name: img.action_name } }, route) } catch (e) { await clickLog({ describe: { action: '点击取消删除单张图片', goods_art_no: img.goods_art_no, record_id: img.id, action_name: img.action_name } }, route) return } const channel = icpList.socket.message + '_delete_photo_record' clientStore.ipc.removeAllListeners(channel) socketStore.sendMessage({ type: 'delete_photo_record', data: { record_id: img.id, }, }) clientStore.ipc.on(channel, (event, result) => { clientStore.ipc.removeAllListeners(channel) console.log('_delete_photo_record', result) if (result.code === 0) { ElMessage.success(result.msg || '图片删除成功') getPhotoRecords() if (img.goods_art_no) { scheduleSegment(img.goods_art_no) } } else if (result.msg) { ElMessage.error(result.msg) } else { ElMessage.error('图片删除失败') } }) } const resetStatus = () => { runLoading.value = false; takePictureLoading.value = false; reNosObj.value.goods_art_no = '' reNosObj.value.action = '' runAction.value.goods_art_no = ''; runAction.value.action = ''; } //货号重拍 const reTakePictureNos = async (goods_art_no, item) => { try { await ElMessageBox.confirm('此操作会先删除删除货号:' + goods_art_no + '的拍摄数据吗,需要继续吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', }) await clickLog({ describe: { action: '点击确认重拍货号', goods_art_no } }, route) } catch (e) { await clickLog({ describe: { action: '点击取消重拍货号', goods_art_no } }, route) return } reNosObj.value.goods_art_no = goods_art_no reNosObj.value.action = '执行左脚程序' console.log(item); if (item.items && typeof item.items === 'object' && item.items[0].PhotoRecord.image_deal_mode) { reNosObj.value.action = '执行右脚程序' } del({ goods_art_nos: [goods_art_no] }) } /** * 检查是否可以进入下一步操作。 */ const next = async function () { if (runLoading.value) { ElMessage.error('正在拍摄中,请稍候') return; } if (goodsList.length) { ElMessage.error('请先拍摄商品。') return; } } const oneClickStop = () => { if (!(runLoading.value || takePictureLoading.value)) { ElMessage.error('拍摄程序已结束,不需要单独停止!') return } else { socketStore.sendMessage({ type: 'stop_action', }) } } /** * 打开最近一张拍摄图 */ const getLastPhotoRecord = async () => { return; if (goodsList.value && goodsList.value.length === 0) return; clientStore.ipc.removeAllListeners(icpList.takePhoto.getLastPhotoRecord); clientStore.ipc.send(icpList.takePhoto.getLastPhotoRecord,); clientStore.ipc.on(icpList.takePhoto.getLastPhotoRecord, (event, result) => { console.log('getLastPhotoRecord'); console.log(result.data?.goods_art_no); clientStore.ipc.removeAllListeners(icpList.takePhoto.getLastPhotoRecord); if (result.code === 0) { if (lastPhoto.value?.photo_file_name) { // if( lastPhoto.value?.image_path == result.data?.image_path) return; if (runAction.value.goods_art_no === result.data?.goods_art_no) { showlastPhoto.value = true } } lastPhoto.value = result.data } else if (result.msg) { ElMessage.error(result.msg) } }); } /** * 打开主图详情页面。 */ function openPhotographyDetail() { // 埋点:开始生成 clickLog({ describe: { action: '开始生成', goods_count: goodsList.value.length, goods_art_nos: goodsList.value.map(item => item.goods_art_no) } }, route); if (runLoading.value || takePictureLoading.value) { ElMessage.error('正在拍摄中,请稍候') return; } const { href } = Router.resolve({ name: 'PhotographyDetail', query: { goods_art_nos: goodsList.value.map(item => item.goods_art_no), } }) clientStore.ipc.removeAllListeners(icpList.utils.openMain); let params = { title: '主图与详情生成', width: 3840, height: 2160, frame: true, id: "PhotographyDetail", url: getRouterUrl(href) } clientStore.ipc.send(icpList.utils.openMain, params); } /*高级生成*/ const onGenerateCLick = (menu, item) => { if (menu.name === '历史记录') { menu.click() return } const firstWithImagePath = item.items.find( (image) => image.PhotoRecord.image_path ); if (firstWithImagePath) { menu.click({ query: { image_path: firstWithImagePath.PhotoRecord.image_path } }) } else { menu.click() } } // 打开输出目录:appConfig.appPath + '/build/extraResources/py/output' const openOutputDir = () => { try { const appPath = configInfoStore?.appConfig?.appPath || '' if (!appPath) { ElMessage.error('未获取到应用目录 appPath') return } const fullPath = `${appPath}\\output` clientStore.ipc.removeAllListeners(icpList.utils.shellFun); clientStore.ipc.send(icpList.utils.shellFun, { action: 'openMkPath', params: fullPath.replace(/\//g, '\\') }); } catch (e) { console.error(e) ElMessage.error('打开目录失败') } } const menu = computed(() => { // 生成图目录(独立菜单项,点击直接打开目录) const outputDirMenu = { name: '生成图目录', click() { openOutputDir() } } // 快捷操作菜单子项(不含生成图目录) const quickActionsChildren = [ { type: 'OneClickRelease' }, { type: 'OneKeyDown' } ] // 一级导航:高级生成下拉 const generateMenu = { ...generate } if (configInfoStore.appModel === 2) { return [ { type: 'setting' }, { name: '快捷操作', children: [ ...quickActionsChildren, { name: '切换模式', click() { configInfoStore.updateAppModel(1) Router.push({ name: 'PhotographyCheck' }) } } ] }, generateMenu, outputDirMenu ] } if (useUserInfoStore.isHLM || configInfoStore.appConfig.debug) { return [ { type: 'setting' }, { name: '快捷操作', children: quickActionsChildren }, { name: '开发工具', children: [ { type: 'developer' } ] }, generateMenu, outputDirMenu ] } return [ { type: 'setting' }, { name: '快捷操作', children: quickActionsChildren }, generateMenu, outputDirMenu ] }) const onRemoteControl = async (type) => { const pointName = await getPhotoPointName() if (type == 'take_picture') { // 埋点:手动拍照 clickLog({ describe: { action: '点击遥控器拍照按钮', point_name: pointName } }, route); if (runLoading.value || takePictureLoading.value) { ElMessage.error('拍摄程序正在运行,请稍候') return } ElMessage.success('正在拍摄中,请稍候') takePictureLoading.value = true; socketStore.sendMessage({ type: 'handler_take_picture', data: { point_name: pointName } }) return; } if (!goods_art_no.value) { ElMessage.error('请在左侧第一步中,先扫描货号或者手动输入货号!') goodsArtNo.value?.focus() // 聚焦输入框 return; } let action = '执行左脚程序' if (type === 'right') action = '执行右脚程序' // 埋点:遥控器启动拍摄 clickLog({ describe: { action: `点击遥控器${type === 'left' ? '左脚' : '右脚'}按钮`, goods_art_no: goods_art_no.value, point_name: pointName } }, route); runGoods({ "action": action, "goods_art_no": goods_art_no.value }) } // 初始化事件监听 const initEventListeners = () => { // 监听蓝牙扫描事件 clientStore.ipc.on(icpList.socket.message + '_blue_tooth_scan', (event, result) => { console.log('_blue_tooth_scan') if (result.code === 0 && result.data?.data) { console.log(goods_art_no.value); if (!goods_art_no.value) { ElMessage.error('请在左侧第一步中,先扫描货号或者手动输入货号!') goodsArtNo.value?.focus() // 聚焦输入框 return; } runGoods({ ...result.data?.data, goods_art_no: goods_art_no.value }) } }); // 监听图片处理完成事件 clientStore.ipc.on(icpList.socket.message + '_image_process', (event, result) => { console.log('_image_process') console.log(result) getPhotoRecords() // 延迟两秒再获取一遍数据 setTimeout(() => { getPhotoRecords() }, 3000) }) // 监听拍照完成事件 clientStore.ipc.on(icpList.socket.message + '_photo_take', (event, result) => { console.log('_photo_take') console.log(result) if (result.status === 2 && result.msg.includes('执行完成')) { getPhotoRecords() searchGoodsArtNo.value = '' // 延迟两秒再获取一遍数据 setTimeout(() => { searchGoodsArtNo.value = '' 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() }) // 监听一键停止结束 clientStore.ipc.on(icpList.socket.message + '_run_mcu_stop', (event, result) => { console.log('_run_mcu_stop') resetStatus() }) // 监听拍照完成后的最终状态事件 clientStore.ipc.on(icpList.socket.message + '_photo_take_finish', (event, result) => { console.log('_photo_take_finish') console.log(result) if (result.code === 0) { setLogInfo(route, { action: '全部拍摄完成', goods_art_no: runAction.value.goods_art_no }); // 全部拍摄完成后,触发抠图队列 if (runAction.value.goods_art_no) { scheduleSegment(runAction.value.goods_art_no) } // 演示模式:拍摄完成后自动删除货号 if (isDemoMode.value) { const demoGoodsNo = demoGoodsArtNo.value setTimeout(async () => { try { await del({ goods_art_nos: [demoGoodsNo] }) ElMessage.info('演示拍摄完成,货号已自动删除') } catch (e) { console.error('自动删除演示货号失败:', e) } }, 2000) } runLoading.value = false; runAction.value.goods_art_no = ''; runAction.value.action = ''; setTimeout(() => { showlastPhoto.value = false }, 3000) } }) // 监听手动触发拍照事件 clientStore.ipc.on(icpList.socket.message + '_handler_take_picture', async (event, result) => { console.log('_handler_take_picture') console.log(result) if (result.code === 0) { if(result.msg === '处理单拍消息'){ const pointName = await getPhotoPointName() clickLog({ describe: { action: '实体遥控器拍照按钮', point_name: pointName } }, route); if (runLoading.value || takePictureLoading.value) { ElMessage.error('拍摄程序正在运行,请稍候') return } ElMessage.success('正在拍摄中,请稍候') takePictureLoading.value = true; socketStore.sendMessage({ type: 'handler_take_picture', data: { point_name: pointName } }) return; } /* if (runLoading.value || takePictureLoading.value) { ElMessage.error('拍摄程序正在运行,请稍候') return }*/ /* ElMessage.success('正在拍摄中,请稍候') */ takePictureLoading.value = true; // await socketStore.connectSocket(); // socketStore.sendMessage(result.data) getPhotoRecords() // 延迟两秒再获取一遍数据 setTimeout(() => { searchGoodsArtNo.value = '' getPhotoRecords() }, 3000) } else if (result.msg) { ElMessage.error(result.msg) } }) //拍照成功 SmartShooter clientStore.ipc.on(icpList.socket.message + '_smart_shooter_photo_take', async (event, result) => { console.log('_smart_shooter_photo_take'); console.log(result); if (result.code === 0) { if (!result.data.goods_art_no) return; setLogInfo(route, { action: '单张拍摄完成', goods_art_no: result.data.goods_art_no }); if (reNosObj.value?.goods_art_no === result.data.goods_art_no) { runLoading.value = false; reNosObj.value.goods_art_no = '' reNosObj.value.action = '' } // 单张重拍完成且存在重拍货号时,触发抠图队列 scheduleSegment(result.data.goods_art_no) if (smartShooterTimeout) { clearTimeout(smartShooterTimeout); } setTimeout(() => { showlastPhoto.value = true; lastPhoto.value = { file_path: result.data.photo_file_name, action_name: result.data.action_name }; setTimeout(() => { if (!runAction.value.goods_art_no) { showlastPhoto.value = false; } }, 3000) }, 100); smartShooterTimeout = setTimeout(() => { getPhotoRecords(); if (!runAction.value.goods_art_no) { showlastPhoto.value = false; } }, 2000); } else if (result.msg) { runLoading.value = false; reNosObj.value.goods_art_no = '' reNosObj.value.action = '' ElMessage.error(result.msg) } }) // 监听拍照完成后的最终状态事件 clientStore.ipc.on(icpList.socket.message + '_run_mcu_update', (event, result) => { console.log('run_mcu_updat print_time:' + new Date().toLocaleString()) console.log('run_mcu_update print_time:' + JSON.stringify(result)) if (result.code === 0) { if (result.data?.file_path) { if (lastPhoto.value?.file_path == result.data?.file_path) return; let goods_art_no = runAction.value.goods_art_no || reNosObj.value.goods_art_no if (goods_art_no === result.data?.goods_art_no) { showlastPhoto.value = true goodsList.value.map(item => { if (item.goods_art_no === result.data?.goods_art_no) { 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) setTimeout(() => { showlastPhoto.value = false }, 3000) } }) setTimeout(() => { getPhotoRecords() }, 2000) } lastPhoto.value = result.data } } else if (result.msg) { ElMessage.error(result.msg) } if (reNosObj.value.goods_art_no) { resetStatus() } }) } // 清理事件监听 const cleanupEventListeners = () => { clientStore.ipc.removeAllListeners(icpList.socket.message + '_blue_tooth_scan'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_image_process'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu'); 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'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_smart_shooter_photo_take'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_run_mcu_stop'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_digicam_take_picture'); clientStore.ipc.removeAllListeners(icpList.socket.message + '_segment_progress'); // 清理抠图队列的定时器 try { segmentQueue.forEach((t) => { if (t) clearTimeout(t) }) segmentQueue.clear() } catch (e) { } } // 监听蓝牙扫描 checkInfoStore.set_blue_tooth_scan_NO('') watchEffect(async () => { if (checkInfoStore.blue_tooth_scan_NO) { ElMessage.success('商品货号' + checkInfoStore.blue_tooth_scan_NO + '获取成功,请在遥控器上按下左或右脚按键,启动拍摄') goods_art_no.value = checkInfoStore.blue_tooth_scan_NO checkInfoStore.set_blue_tooth_scan_NO('') } }) /** * 导入图片目录。 * @param dirPath - 需要导入的目录路径。 */ const importDirs = function (dirPath: string) { clientStore.ipc.removeAllListeners(icpList.takePhoto.import_dirs); clientStore.ipc.send(icpList.takePhoto.import_dirs, { dir_path: dirPath }); clientStore.ipc.on(icpList.takePhoto.import_dirs, (event, result) => { clientStore.ipc.removeAllListeners(icpList.takePhoto.import_dirs); if (result.code === 0) { getPhotoRecords() } else { ElMessage.error(result.msg || '导入图片失败') } }); } /** * 演示模式:获取配置列表 * @param type 0-左脚程序, 1-右脚程序 */ const fetchDemoConfigList = async (type: number) => { demoConfigList.value = [] demoSelectedConfigId.value = null const result = await getTopTabs({ type }) if (result.code == 0 && result.data?.tabs) { demoConfigList.value = result.data.tabs if (demoConfigList.value.length > 0) { demoSelectedConfigId.value = demoConfigList.value[0].id } } } /** * 演示模式:打开配置选择对话框 */ const openDemoMode = async () => { demoGoodsArtNo.value = '演示货号1' demoProgramType.value = '执行左脚程序' demoSelectedConfigId.value = null demoConfigList.value = [] // 获取左脚程序配置列表 await fetchDemoConfigList(0) demoDialogVisible.value = true } /** * 演示模式:监听程序类型变化,重新获取配置列表 */ const onDemoProgramTypeChange = async () => { const type = demoProgramType.value === '执行左脚程序' ? 0 : 1 await fetchDemoConfigList(type) } /** * 演示模式:开始演示 */ const startDemoMode = async () => { if (!demoGoodsArtNo.value.trim()) { ElMessage.error('请输入货号') return } if (!demoSelectedConfigId.value) { ElMessage.error('请选择配置') return } // 设置演示模式标记 isDemoMode.value = true // 设置货号 goods_art_no.value = demoGoodsArtNo.value goods_art_no_tpl.value = demoGoodsArtNo.value demoDialogVisible.value = false // 直接启动拍摄 runGoods({ action: demoProgramType.value, goods_art_no: demoGoodsArtNo.value }) } /** * 演示模式:停止演示 * 执行完成后删除货号,然后退出演示模式 */ const stopDemoMode = async () => { if (!isDemoMode.value) return // 停止当前运行 if (runLoading.value || takePictureLoading.value) { socketStore.sendMessage({ type: 'stop_action', }) } // 等待拍摄停止,然后删除货号 const demoGoodsNo = demoGoodsArtNo.value // 延迟等待设备停止 setTimeout(async () => { // 重置状态 resetStatus() // 删除演示货号 try { await del({ goods_art_nos: [demoGoodsNo] }) } catch (e) { console.error('删除演示货号失败:', e) } // 退出演示模式 isDemoMode.value = false goods_art_no.value = '' goods_art_no_tpl.value = '' ElMessage.success('已退出演示模式') }, 500) } /** * 演示模式:监听拍摄完成事件 * 演示模式下拍摄完成后自动删除货号 */ const handlePhotoTakeFinishForDemo = (goodsArtNo: string) => { if (isDemoMode.value && goodsArtNo === demoGoodsArtNo.value) { // 延迟删除,等待数据写入完成 setTimeout(async () => { try { await del({ goods_art_nos: [demoGoodsArtNo.value] }) ElMessage.info('演示拍摄完成,货号已自动删除') } catch (e) { console.error('自动删除演示货号失败:', e) } }, 2000) } } /** * 删除所有货号。 */ const deleteAllGoods = function () { clientStore.ipc.removeAllListeners(icpList.takePhoto.delete_all_goods_arts); clientStore.ipc.send(icpList.takePhoto.delete_all_goods_arts); clientStore.ipc.on(icpList.takePhoto.delete_all_goods_arts, (event, result) => { clientStore.ipc.removeAllListeners(icpList.takePhoto.delete_all_goods_arts); if (result.code === 0) { ElMessage.success('删除所有货号成功') getPhotoRecords() } else { ElMessage.error(result.msg || '删除所有货号失败') } }); } return { loading, runLoading, takePictureLoading, goodsList, pageSize, currentPage, totalPages, goods_art_no_tpl, goods_art_no, runAction, lastPhoto, showlastPhoto, goodsArtNo, searchGoodsArtNo, menu, configInfoStore, getTime, getFilePath, getPhotoRecords, delAll, delGoods, del, importDirs, deleteAllGoods, reTakePicture, reTakePictureNos, deletePhotoRecord, oneClickStop, onRemoteControl, openPhotographyDetail, onGenerateCLick, initEventListeners, cleanupEventListeners, resetStatus, // 演示模式 isDemoMode, demoGoodsArtNo, demoProgramType, demoConfigList, demoSelectedConfigId, demoDialogVisible, openDemoMode, startDemoMode, stopDemoMode, onDemoProgramTypeChange, } }