From 79b8268ff801b1477b6cb4b33818bd16291f1f49 Mon Sep 17 00:00:00 2001 From: root <13910913995@163.com> Date: Wed, 10 Dec 2025 15:35:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A3=80=E6=B5=8B=E9=A1=B5=E9=9D=A2=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/Log/OrbbecSDK.log.txt | Bin 25672 -> 15334 bytes backend/config.ini | 4 +- backend/main.py | 2 +- frontend/src/renderer/main/main.js | 3 +- frontend/src/renderer/main/preload.js | 2 +- frontend/src/renderer/src/views/Detection.vue | 41 ++++---- frontend/src/renderer/src/views/model.vue | 4 +- frontend/src/renderer/src/views/viewPDF.vue | 96 +++++++----------- frontend/src/renderer/vite.config.js | 2 +- 9 files changed, 70 insertions(+), 84 deletions(-) diff --git a/backend/Log/OrbbecSDK.log.txt b/backend/Log/OrbbecSDK.log.txt index a44ce616d4e2b7a2fd29f60886ebc4096c55e1c1..0079a34330193624ce1fba0da0e63c83d58561cc 100644 GIT binary patch literal 15334 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 diff --git a/backend/config.ini b/backend/config.ini index 08a01276..f718726e 100644 --- a/backend/config.ini +++ b/backend/config.ini @@ -50,12 +50,12 @@ synchronized_images_only = False [DEVICES] imu_enabled = True -imu_device_type = ble +imu_device_type = mock imu_port = COM9 imu_mac_address = ef:3c:1a:0a:fe:02 imu_baudrate = 9600 pressure_enabled = True -pressure_device_type = real +pressure_device_type = mock pressure_use_mock = False pressure_port = COM5 pressure_baudrate = 115200 diff --git a/backend/main.py b/backend/main.py index 96c92dd5..663d4906 100644 --- a/backend/main.py +++ b/backend/main.py @@ -2077,7 +2077,7 @@ def main(): """主函数""" # 解析命令行参数 parser = argparse.ArgumentParser(description='Body Balance Evaluation System Backend') - parser.add_argument('--host', default='0.0.0.0', help='Host address to bind to') + parser.add_argument('--host', default='localhost', help='Host address to bind to') parser.add_argument('--port', type=int, default=5000, help='Port number to bind to') parser.add_argument('--debug', action='store_true', help='Enable debug mode') args = parser.parse_args() diff --git a/frontend/src/renderer/main/main.js b/frontend/src/renderer/main/main.js index 6fa0f75d..fc338ea0 100644 --- a/frontend/src/renderer/main/main.js +++ b/frontend/src/renderer/main/main.js @@ -192,7 +192,8 @@ function createWindow() { webPreferences: { nodeIntegration: false, contextIsolation: true, - sandbox: false, // 显式关闭沙盒,避免 preload 加载问题 + // sandbox: false, // 显式关闭沙盒,避免 preload 加载问题 + // backgroundThrottling: false, preload: path.join(__dirname, 'preload.js') }, icon: path.join(__dirname, '../public/logo.png'), diff --git a/frontend/src/renderer/main/preload.js b/frontend/src/renderer/main/preload.js index 8990560c..511db204 100644 --- a/frontend/src/renderer/main/preload.js +++ b/frontend/src/renderer/main/preload.js @@ -2,5 +2,5 @@ const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { generateReportPdf: (payload) => ipcRenderer.invoke('generate-report-pdf', payload), - getBackendUrl: () => 'http://localhost:5000' + getBackendUrl: () => process.env.BACKEND_URL || 'http://localhost:5000', }); diff --git a/frontend/src/renderer/src/views/Detection.vue b/frontend/src/renderer/src/views/Detection.vue index 02842cfa..d7ff8e68 100644 --- a/frontend/src/renderer/src/views/Detection.vue +++ b/frontend/src/renderer/src/views/Detection.vue @@ -932,7 +932,7 @@ function connectWebSocket() { // 创建主Socket.IO连接 socket = io(BACKEND_URL, { - transports: ['websocket', 'polling'], // 只使用polling,与后端保持一致 + transports: ['websocket'], timeout: 10000, forceNew: true, reconnection: true, @@ -942,7 +942,7 @@ function connectWebSocket() { // 创建统一设备命名空间连接 devicesSocket = io(BACKEND_URL + '/devices', { - transports: ['websocket', 'polling'], // 只使用polling,与后端保持一致 + transports: ['websocket'], timeout: 10000, forceNew: true }) @@ -995,9 +995,16 @@ function connectWebSocket() { devicesSocket.on('connect', () => { console.log('🔗 设备命名空间连接成功') - // 连接成功后订阅所有设备数据 - devicesSocket.emit('subscribe_device', { device_type: 'camera1' }) - devicesSocket.emit('subscribe_device', { device_type: 'camera2' }) + const enabledCameras = (() => { + const list = [] + const idx1 = String((cameraForm.value && cameraForm.value.camera1 && cameraForm.value.camera1.device_index) || '').trim() + const idx2 = String((cameraForm.value && cameraForm.value.camera2 && cameraForm.value.camera2.device_index) || '').trim() + if (idx1 !== '') list.push('camera1') + if (idx2 !== '') list.push('camera2') + if (list.length === 0) list.push('camera1') + return list + })() + enabledCameras.forEach(t => devicesSocket.emit('subscribe_device', { device_type: t })) devicesSocket.emit('subscribe_device', { device_type: 'femtobolt' }) devicesSocket.emit('subscribe_device', { device_type: 'imu' }) devicesSocket.emit('subscribe_device', { device_type: 'pressure' }) @@ -1033,9 +1040,9 @@ function connectWebSocket() { frameCount++ // 区分 camera1 / camera2 帧 const devId = (data && data.device_id) ? String(data.device_id).toLowerCase() : '' - if (!tempInfo.value.camera_frames) { - tempInfo.value.camera_frames = {} - } + if (!tempInfo.value.camera_frames) { + tempInfo.value.camera_frames = {} + } if (devId === 'camera1') { tempInfo.value.camera_frames['camera1'] = data tempInfo.value.camera1_frame = data @@ -1080,15 +1087,15 @@ function connectWebSocket() { const { device_type, status } = data const statusText = status ? '已连接' : '未连接' - switch (device_type) { - case 'camera1': - camera1Status.value = statusText - console.log(`📷 相机1状态: ${statusText}`) - break - case 'camera2': - camera2Status.value = statusText - console.log(`📷 相机2状态: ${statusText}`) - break + switch (device_type) { + case 'camera1': + camera1Status.value = statusText + console.log(`📷 相机1状态: ${statusText}`) + break + case 'camera2': + camera2Status.value = statusText + console.log(`📷 相机2状态: ${statusText}`) + break case 'femtobolt': femtoboltStatus.value = statusText console.log(`🔍 深度相机状态: ${statusText}`) diff --git a/frontend/src/renderer/src/views/model.vue b/frontend/src/renderer/src/views/model.vue index d0479f48..b515cd65 100644 --- a/frontend/src/renderer/src/views/model.vue +++ b/frontend/src/renderer/src/views/model.vue @@ -41,9 +41,9 @@ function initThreeJS() { camera.lookAt(0, 0, 0); // 创建渲染器 - renderer = new THREE.WebGLRenderer({ antialias: true,alpha: true }); + renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false, powerPreference: 'high-performance' }); scene.background = null; // 置空场景背景 - renderer.setClearColor(0x000000, 0); // 设置透明度为0(完全透明) + renderer.setClearColor(0x000000, 0.02); renderer.setSize(containermodel.offsetWidth, containermodel.offsetHeight); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; diff --git a/frontend/src/renderer/src/views/viewPDF.vue b/frontend/src/renderer/src/views/viewPDF.vue index fc822feb..58ab0e74 100644 --- a/frontend/src/renderer/src/views/viewPDF.vue +++ b/frontend/src/renderer/src/views/viewPDF.vue @@ -20,7 +20,7 @@ import { patientAPI, detectionAPI,historyAPI,getBackendUrl } from '@/services/api.js' import { ref, onMounted } from 'vue' -import * as pdfjsLib from 'pdfjs-dist' +// import * as pdfjsLib from 'pdfjs-dist' const emit = defineEmits([ 'closeViewPDF' ]); const props = defineProps({ pdfUrl: { @@ -32,7 +32,7 @@ const props = defineProps({ const pdfUrl = ref(props.pdfUrl) const pdfContainer = ref(null) // 容器用于挂载多个 canvas // 设置 worker 路径(重要) -pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.js' +// pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.js' const BACKEND_URL = getBackendUrl() const pdfCanvas = ref(null) function handleCancel(){ @@ -66,64 +66,42 @@ const pdfCanvas = ref(null) // console.error('Error rendering PDF:', error) // } // } -const renderPDF = async (url) => { - try { - // 1️⃣ 加载 PDF 文档 - const loadingTask = pdfjsLib.getDocument(url) - const pdf = await loadingTask.promise - console.log(`PDF loaded: ${pdf.numPages} pages`) - - // 2️⃣ 清空旧内容 - if (pdfContainer.value) { - pdfContainer.value.innerHTML = '' - } - - const scale = 1.5 // 可根据设备 DPR 动态调整 - const pagePromises = [] - - // 3️⃣ 预处理:循环加载每一页(不立即渲染) - for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) { - pagePromises.push(renderPage(pdf, pageNum, scale)) - } - - // 4️⃣ 并行渲染所有页面(注意:大量页面时需节流) - await Promise.all(pagePromises) - console.log('✅ All PDF pages rendered successfully') - } catch (error) { - console.error('❌ Error rendering PDF:', error) - } -} +// const renderPDF = async (url) => { +// try { +// const pdfjsLib = await import('pdfjs-dist/legacy/build/pdf') +// if (pdfjsLib && pdfjsLib.GlobalWorkerOptions) { +// pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.11.174/build/pdf.worker.min.js' +// } +// const loadingTask = pdfjsLib.getDocument(url) +// const pdf = await loadingTask.promise +// if (pdfContainer.value) { +// pdfContainer.value.innerHTML = '' +// } +// const scale = 1.5 +// const pagePromises = [] +// for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) { +// pagePromises.push(renderPage(pdf, pageNum, scale)) +// } +// await Promise.all(pagePromises) +// } catch (error) { +// console.error('Error rendering PDF:', error) +// } +// } // 单独封装 renderPage 函数便于复用与控制并发 -const renderPage = async (pdf, pageNum, scale) => { - const page = await pdf.getPage(pageNum) - - // 获取视口(viewport) - const viewport = page.getViewport({ scale }) - - // 创建 canvas - const canvas = document.createElement('canvas') - const context = canvas.getContext('2d') - canvas.height = viewport.height - canvas.width = viewport.width - - - // 添加页码标识(可选) - const pageNumberDiv = document.createElement('div') - // 插入到容器 - if (pdfContainer.value) { - pdfContainer.value.appendChild(canvas) - } - - // 渲染上下文 - const renderContext = { - canvasContext: context, - viewport, - } - - // 执行渲染 - await page.render(renderContext).promise -} +// const renderPage = async (pdf, pageNum, scale) => { +// const page = await pdf.getPage(pageNum) +// const viewport = page.getViewport({ scale }) +// const canvas = document.createElement('canvas') +// const context = canvas.getContext('2d') +// canvas.height = viewport.height +// canvas.width = viewport.width +// if (pdfContainer.value) { +// pdfContainer.value.appendChild(canvas) +// } +// const renderContext = { canvasContext: context, viewport } +// await page.render(renderContext).promise +// } onMounted(() => { // 替换为你的 PDF 文件路径或 URL // renderPDF(`${BACKEND_URL}/202512070001/20251209141628/report_142802459.pdf`) // 可以是本地文件或远程链接 @@ -167,4 +145,4 @@ canvas { align-items: center; padding-right: 20px; } - \ No newline at end of file + diff --git a/frontend/src/renderer/vite.config.js b/frontend/src/renderer/vite.config.js index c6b9c5d7..5236fae8 100644 --- a/frontend/src/renderer/vite.config.js +++ b/frontend/src/renderer/vite.config.js @@ -24,7 +24,7 @@ export default defineConfig({ }, server: { port: 3000, - host: '0.0.0.0', + host: 'localhost', // 开发服务器配置 cors: true, strictPort: false