From 9f2ecf02c454d4ac6ccc6aa307116231498c529b Mon Sep 17 00:00:00 2001 From: root <13910913995@163.com> Date: Sat, 10 Jan 2026 22:28:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=8F=8A=E7=9B=B8=E5=85=B3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tivation_request_W10-F5AC32003C0A160B.json | 15 -- backend/config.ini | 22 +- backend/database.py | 122 ++------- backend/devices/device_coordinator.py | 20 +- backend/devices/remote_control_manager.py | 2 +- backend/devices/screen_recorder.py | 19 +- backend/devices/utils/config_manager.py | 253 ++---------------- backend/main.py | 15 +- document/串口遥控器遥控界面操作说明.md | 2 +- frontend/src/renderer/src/views/Detection.vue | 93 ++----- .../src/renderer/src/views/PatientProfile.vue | 24 +- 11 files changed, 120 insertions(+), 467 deletions(-) delete mode 100644 backend/activation_request_W10-F5AC32003C0A160B.json diff --git a/backend/activation_request_W10-F5AC32003C0A160B.json b/backend/activation_request_W10-F5AC32003C0A160B.json deleted file mode 100644 index 1a1a650a..00000000 --- a/backend/activation_request_W10-F5AC32003C0A160B.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "product": "BodyBalanceEvaluation", - "version": "1.5.0", - "machine_id": "W10-F5AC32003C0A160B", - "platform": "Windows", - "request_time": "2026-01-09T02:40:10.695573+00:00", - "hardware_info": { - "system": "Windows", - "machine": "AMD64", - "processor": "Intel64 Family 6 Model 165 Stepping 3, GenuineIntel", - "node": "PS2020LTDYIFOO" - }, - "company_name": "北京天宏博科技有限公司", - "contact_info": "thb@163.com" -} \ No newline at end of file diff --git a/backend/config.ini b/backend/config.ini index 0771b414..885eb287 100644 --- a/backend/config.ini +++ b/backend/config.ini @@ -19,7 +19,7 @@ max_backups = 7 path = D:/BodyCheck/file/ [CAMERA1] -enabled = True +enable = True device_index = 0 width = 1280 height = 720 @@ -29,8 +29,8 @@ fourcc = MJPG backend = directshow [CAMERA2] -enabled = False -device_index = 3 +enable = True +device_index = 1 width = 1280 height = 720 fps = 30 @@ -39,7 +39,7 @@ fourcc = MJPG backend = directshow [FEMTOBOLT] -enabled = False +enable = True algorithm_type = plt color_resolution = 1080P depth_mode = NFOV_2X2BINNED @@ -50,19 +50,19 @@ fps = 15 synchronized_images_only = False [DEVICES] -imu_enabled = False +imu_enable = False imu_device_type = ble imu_port = COM9 imu_mac_address = ef:3c:1a:0a:fe:02 imu_baudrate = 9600 -pressure_enabled = False +pressure_enable = False pressure_device_type = real pressure_use_mock = False pressure_port = COM5 pressure_baudrate = 115200 [REMOTE] -enable = False +enable = True port = COM6 baudrate = 115200 timeout = 0.1 @@ -97,20 +97,12 @@ grace_days = 7 dev_mode = False [SCREEN_RECORDING] -# 录屏策略:ffmpeg(外部进程录制)或 threaded(内部线程录制) strategy = ffmpeg -# ffmpeg可执行文件绝对路径(Windows示例:D:/BodyCheck/ffmpeg/bin/ffmpeg.exe) ffmpeg_path = D:/BodyCheck/ffmpeg/bin/ffmpeg.exe -# 编码器:libx264(CPU)或 h264_nvenc(GPU,CPU占用更低,需显卡支持) ffmpeg_codec = libx264 -# 编码预设:ultrafast(CPU更低、文件更大);NVENC用 p1/p2 更快 ffmpeg_preset = ultrafast -# 编码线程数:限制CPU占用,按机器性能调整 ffmpeg_threads = 2 -# B帧数量:0可降低编码复杂度与CPU占用 ffmpeg_bframes = 0 -# 关键帧间隔(GOP,单位:帧):数值越大CPU越低,seek精度下降 ffmpeg_gop = 50 -# 是否录制鼠标:0关闭,1开启 ffmpeg_draw_mouse = 0 diff --git a/backend/database.py b/backend/database.py index 7fc55324..d456ecb9 100644 --- a/backend/database.py +++ b/backend/database.py @@ -619,90 +619,7 @@ class DatabaseManager: except Exception as e: conn.rollback() logger.error(f'更新会话状态失败: {e}') - return False - - - def update_session_endcheck(self, session_id: str, diagnosis_info: Optional[str] = None, - treatment_info: Optional[str] = None, - suggestion_info: Optional[str] = None) -> bool: - """结束检测:根据 start_time 与当前时间计算持续时长并写入结束信息 - - 行为: - - 计算并保存 `duration` - - 保存 `end_time` 为当前中国时区时间 - - 可选更新 `diagnosis_info`、`treatment_info`、`suggestion_info` - - 设置 `status = 'checked'` - - 同步更新患者 `updated_at` - """ - conn = self.get_connection() - cursor = conn.cursor() - - try: - # 读取会话的开始时间与患者ID - cursor.execute('SELECT start_time, patient_id FROM detection_sessions WHERE id = ?', (session_id,)) - row = cursor.fetchone() - if not row: - logger.error(f'会话不存在: {session_id}') - return False - - start_time_str, patient_id = row - if not start_time_str: - logger.error(f'会话缺少开始时间: {session_id}') - return False - - # 计算持续时间(秒) - now_str = self.get_china_time() - try: - start_dt = datetime.strptime(start_time_str, '%Y-%m-%d %H:%M:%S') - now_dt = datetime.strptime(now_str, '%Y-%m-%d %H:%M:%S') - duration_seconds = max(0, int((now_dt - start_dt).total_seconds())) - except Exception as e: - logger.error(f'解析时间失败: start_time={start_time_str}, now={now_str}, error={e}') - return False - - # 构造更新语句 - update_fields = [ - 'duration = ?', - 'end_time = ?' - - ] - update_values = [duration_seconds, now_str] - - if diagnosis_info is not None: - update_fields.append('diagnosis_info = ?') - update_values.append(diagnosis_info) - - if suggestion_info is not None: - update_fields.append('suggestion_info = ?') - update_values.append(suggestion_info) - - status='checked' #默认状态为checked:已完成检查 - if treatment_info is not None: #处理信息不为空时,状态设为completed:已诊断处理 - update_fields.append('treatment_info = ?') - update_values.append(treatment_info) - status='completed' - - update_fields.append('status = ?') - update_values.append(status) - - # 添加会话ID到参数列表 - update_values.append(session_id) - - sql = f'''UPDATE detection_sessions SET {', '.join(update_fields)} WHERE id = ?''' - cursor.execute(sql, update_values) - - # 同步更新患者表的updated_at时间 - cursor.execute('''UPDATE patients SET updated_at = ? WHERE id = ?''', (now_str, patient_id)) - self._sync_patient_medical_history_from_session(cursor, session_id) - conn.commit() - logger.info(f'结束检测并更新会话: {session_id}, duration={duration_seconds}s, status={status}') - return True - - except Exception as e: - conn.rollback() - logger.error(f'结束检测更新失败: {e}') return False - def update_session_all_info(self, session_id: str, diagnosis_info: str = None, treatment_info: str = None, suggestion_info: str = None): """同时更新会话的诊断信息、处理信息、建议信息和状态""" @@ -714,18 +631,21 @@ class DatabaseManager: update_fields = [] update_values = [] - if diagnosis_info is not None: + if diagnosis_info is not None and diagnosis_info.strip() != '': update_fields.append('diagnosis_info = ?') update_values.append(diagnosis_info) status='checked' #默认状态为checked:已完成检查 - if treatment_info is not None: + if treatment_info is not None and treatment_info.strip() != '': update_fields.append('treatment_info = ?') update_values.append(treatment_info) status='completed' #处理信息不为空时,状态设为completed:已诊断处理 - if suggestion_info is not None: + if suggestion_info is not None and suggestion_info.strip() != '': update_fields.append('suggestion_info = ?') - update_values.append(suggestion_info) + update_values.append(suggestion_info) + + update_fields.append('status = ?') + update_values.append(status) if not update_fields: logger.warning(f'没有提供要更新的信息: {session_id}') @@ -754,11 +674,11 @@ class DatabaseManager: updated_info.append(f'状态({status})') logger.info(f'批量更新会话信息成功: {session_id}, 更新字段: {", ".join(updated_info)}') - + return True except Exception as e: conn.rollback() logger.error(f'批量更新会话信息失败: {e}') - raise + return False def _sync_patient_medical_history_from_session(self, cursor, session_id: str) -> None: """根据会话信息同步患者 medical_history 的 doctor/status/lastcheck_time 字段""" @@ -806,7 +726,8 @@ class DatabaseManager: try: offset = (page - 1) * size cursor.execute(''' - SELECT s.id, s.status, s.start_time, u.name as creator_name,s.detection_report as detection_report,s.data_ids as data_ids + SELECT s.id, s.status, s.start_time, u.name as creator_name,s.detection_report as detection_report,s.data_ids as data_ids, + (SELECT COUNT(*) FROM detection_data WHERE session_id = s.id) as data_count FROM detection_sessions s LEFT JOIN users u ON s.creator_id = u.id WHERE s.patient_id = ? and s.status in ('checked','completed','reported') @@ -827,7 +748,8 @@ class DatabaseManager: 'start_time': r[2], 'creator_name': r[3], 'detection_report': r[4], - 'data_ids': r[5] + 'data_ids': r[5], + 'data_count': r[6] } sessions.append({ 'id': item.get('id'), @@ -835,7 +757,8 @@ class DatabaseManager: 'start_time': item.get('start_time'), 'creator_name': item.get('creator_name'), 'detection_report': item.get('detection_report'), - 'data_ids': item.get('data_ids') + 'data_ids': item.get('data_ids'), + 'data_count': item.get('data_count', 0) }) return sessions @@ -1118,15 +1041,22 @@ class DatabaseManager: return False def has_session_detection_data(self, session_id: str) -> bool: - """检查指定会话是否存在检测数据,用于判断单次检测是否有效""" + """检查指定会话是否存在检测数据或视频数据,用于判断单次检测是否有效""" conn = self.get_connection() cursor = conn.cursor() try: + # 检查检测数据 cursor.execute('SELECT COUNT(1) FROM detection_data WHERE session_id = ?', (session_id,)) row = cursor.fetchone() - count = row[0] if row else 0 - exists = count > 0 - logger.info(f'会话 {session_id} 检测数据存在: {exists} (count={count})') + data_count = row[0] if row else 0 + + # 检查视频数据 + cursor.execute('SELECT COUNT(1) FROM detection_video WHERE session_id = ?', (session_id,)) + video_row = cursor.fetchone() + video_count = video_row[0] if video_row else 0 + + exists = (data_count > 0) or (video_count > 0) + logger.info(f'会话 {session_id} 数据检查: data_count={data_count}, video_count={video_count}, exists={exists}') return exists except Exception as e: logger.error(f'检查会话检测数据存在失败: {e}') diff --git a/backend/devices/device_coordinator.py b/backend/devices/device_coordinator.py index 5eb4f852..df73b117 100644 --- a/backend/devices/device_coordinator.py +++ b/backend/devices/device_coordinator.py @@ -159,29 +159,29 @@ class DeviceCoordinator: futures = [] # FemtoBolt深度相机 - if self.device_configs.get('femtobolt', {}).get('enabled', False): + if self.device_configs.get('femtobolt', {}).get('enable', False): future = self.executor.submit(self._init_femtobolt) futures.append(('femtobolt', future)) # 普通相机:初始化两个实例(camera1 与 camera2) # camera1 使用 [CAMERA1] 配置;camera2 使用 [CAMERA2](若不存在则回退为 device_index+1) - if self.device_configs.get('camera1', {}).get('enabled', False): + if self.device_configs.get('camera1', {}).get('enable', False): futures.append(('camera1', self.executor.submit(self._init_camera_by_name, 'camera1', 'CAMERA1'))) - if self.device_configs.get('camera2', {}).get('enabled', False): + if self.device_configs.get('camera2', {}).get('enable', False): futures.append(('camera2', self.executor.submit(self._init_camera_by_name, 'camera2', 'CAMERA2'))) # IMU传感器 - if self.device_configs.get('imu', {}).get('enabled', False): + if self.device_configs.get('imu', {}).get('enable', False): future = self.executor.submit(self._init_imu) futures.append(('imu', future)) # 压力传感器 - if self.device_configs.get('pressure', {}).get('enabled', False): + if self.device_configs.get('pressure', {}).get('enable', False): future = self.executor.submit(self._init_pressure) futures.append(('pressure', future)) # 遥控器 - if self.device_configs.get('remote', {}).get('enabled', False): + if self.device_configs.get('remote', {}).get('enable', False): future = self.executor.submit(self._init_remote) futures.append(('remote', future)) @@ -244,8 +244,8 @@ class DeviceCoordinator: return parser.getboolean(sec, key) except Exception: return fallback - enabled = get_bool(section, 'enabled', True) - if not enabled: + enable = get_bool(section, 'enable', True) + if not enable: self.logger.info(f"{device_name} 未启用,跳过初始化") return False # 填充覆盖项 @@ -682,8 +682,8 @@ class DeviceCoordinator: return parser.getboolean(sec, key) except Exception: return fallback - enabled = get_bool(section, 'enabled', True) - if not enabled: + enable = get_bool(section, 'enable', True) + if not enable: raise Exception(f"{device_name} 未启用") idx2 = get_int(section, 'device_index', None) if idx2 is not None: diff --git a/backend/devices/remote_control_manager.py b/backend/devices/remote_control_manager.py index f9c58dd2..68fb6538 100644 --- a/backend/devices/remote_control_manager.py +++ b/backend/devices/remote_control_manager.py @@ -39,7 +39,7 @@ class RemoteControlManager(BaseDevice): timeout = float(self.config_manager.get_config_value('REMOTE', 'timeout', fallback='0.1')) instance_config: Dict[str, Any] = { - 'enabled': True, + 'enable': True, 'port': port, 'baudrate': baudrate, 'timeout': timeout, diff --git a/backend/devices/screen_recorder.py b/backend/devices/screen_recorder.py index d5b63cfa..14b871eb 100644 --- a/backend/devices/screen_recorder.py +++ b/backend/devices/screen_recorder.py @@ -1280,7 +1280,7 @@ class RecordingManager: 'body_pose': None, 'body_image': None, 'foot_data': detection_data.get('foot_data'), - 'foot_data_image': None, + 'foot_data_image': detection_data.get('foot_data_image'), 'foot1_image': None, 'foot2_image': None, 'screen_image': None, @@ -1292,8 +1292,7 @@ class RecordingManager: image_fields = [ ('body_image', 'body'), ('foot1_image', 'foot1'), - ('foot2_image', 'foot2'), - ('foot_data_image', 'foot_data') + ('foot2_image', 'foot2') ] for field, prefix in image_fields: @@ -1322,11 +1321,15 @@ class RecordingManager: except Exception as e: self.logger.error(f'保存{field}失败: {e}') - # 屏幕截图 - screen_image = self._capture_screen_image(data_dir, data.get('screen_location'), timestamp=timestamp) + # 完整屏幕截图--根据screen_location 进行截图 + screen_image = self._capture_screen_image(data_dir, data.get('screen_location'),'screen', timestamp=timestamp) if screen_image: data['screen_image'] = str(os.path.join( patient_id, session_id, f"image_{timestamp}", screen_image)) - + # 足部压力屏幕截图——根据foot_data_image 进行截图 + foot_data_image = self._capture_screen_image(data_dir, data.get('foot_data_image'),'foot_data', timestamp=timestamp) + if foot_data_image: + data['foot_data_image'] = str(os.path.join( patient_id, session_id, f"image_{timestamp}", foot_data_image)) + self.logger.debug(f'数据保存完成: {session_id}, 时间戳: {timestamp}') except Exception as e: @@ -1336,7 +1339,7 @@ class RecordingManager: - def _capture_screen_image(self, data_dir, screen_location, timestamp) -> Optional[str]: + def _capture_screen_image(self, data_dir, screen_location,type, timestamp) -> Optional[str]: """ 采集屏幕截图,根据screen_region 进行截图 @@ -1358,7 +1361,7 @@ class RecordingManager: # 保存截图 from pathlib import Path - screen_filename = f'screen_{timestamp}.jpg' + screen_filename = f'{type}_{timestamp}.jpg' image_path = Path(data_dir) / screen_filename screenshot.save(str(image_path), quality=95, optimize=True) diff --git a/backend/devices/utils/config_manager.py b/backend/devices/utils/config_manager.py index d152e93a..3e3a94e5 100644 --- a/backend/devices/utils/config_manager.py +++ b/backend/devices/utils/config_manager.py @@ -143,7 +143,7 @@ class ConfigManager: 获取设备配置 Args: - device_name: 设备名称 (camera1, camera2, femtobolt, imu, pressure) + device_name: 设备名称 (camera1, camera2, femtobolt, imu, pressure, remote) Returns: Dict[str, Any]: 设备配置字典 @@ -180,7 +180,7 @@ class ConfigManager: Dict[str, Any]: 相机配置 """ return { - 'enabled': self.config.getboolean('CAMERA1', 'enabled', fallback=True), + 'enable': self.config.getboolean('CAMERA1', 'enable', fallback=False), 'device_index': self.config.getint('CAMERA1', 'device_index', fallback=0), 'width': self.config.getint('CAMERA1', 'width', fallback=1280), 'height': self.config.getint('CAMERA1', 'height', fallback=720), @@ -197,7 +197,7 @@ class ConfigManager: Dict[str, Any]: """ return { - 'enabled': self.config.getboolean('CAMERA2', 'enabled', fallback=True), + 'enable': self.config.getboolean('CAMERA2', 'enable', fallback=False), 'device_index': self.config.getint('CAMERA2', 'device_index', fallback=0), 'width': self.config.getint('CAMERA2', 'width', fallback=1280), 'height': self.config.getint('CAMERA2', 'height', fallback=720), @@ -214,7 +214,7 @@ class ConfigManager: Dict[str, Any]: FemtoBolt配置 """ return { - 'enabled': self.config.getboolean('FEMTOBOLT', 'enabled', fallback=True), + 'enable': self.config.getboolean('FEMTOBOLT', 'enable', fallback=False), 'algorithm_type': self.config.get('FEMTOBOLT', 'algorithm_type', fallback='opencv'), 'color_resolution': self.config.get('FEMTOBOLT', 'color_resolution', fallback='1080P'), 'depth_mode': self.config.get('FEMTOBOLT', 'depth_mode', fallback='NFOV_UNBINNED'), @@ -232,7 +232,7 @@ class ConfigManager: Dict[str, Any]: IMU配置 """ return { - 'enabled': self.config.getboolean('DEVICES', 'imu_enabled', fallback=True), + 'enable': self.config.getboolean('DEVICES', 'imu_enable', fallback=False), 'device_type': self.config.get('DEVICES', 'imu_device_type', fallback='mock'), 'port': self.config.get('DEVICES', 'imu_port', fallback='COM7'), 'baudrate': self.config.getint('DEVICES', 'imu_baudrate', fallback=9600), @@ -249,7 +249,7 @@ class ConfigManager: Dict[str, Any]: 压力传感器配置 """ return { - 'enabled': self.config.getboolean('DEVICES', 'pressure_enabled', fallback=True), + 'enable': self.config.getboolean('DEVICES', 'pressure_enable', fallback=False), 'device_type': self.config.get('DEVICES', 'pressure_device_type', fallback='mock'), 'port': self.config.get('DEVICES', 'pressure_port', fallback='COM8'), 'baudrate': self.config.getint('DEVICES', 'pressure_baudrate', fallback=115200), @@ -265,7 +265,7 @@ class ConfigManager: Dict[str, Any]: 远程控制配置 """ return { - 'enabled': self.config.getboolean('REMOTE', 'enable', fallback=True), + 'enable': self.config.getboolean('REMOTE', 'enable', fallback=False), 'port': self.config.get('REMOTE', 'port', fallback='COM6'), 'baudrate': self.config.getint('REMOTE', 'baudrate', fallback=115200), 'timeout': self.config.getfloat('REMOTE', 'timeout', fallback=0.1), @@ -376,7 +376,7 @@ class ConfigManager: warnings = [] # 验证必需的配置段 - required_sections = ['DEVICES', 'CAMERA1', 'CAMERA2', 'FEMTOBOLT', 'SYSTEM'] + required_sections = ['DEVICES', 'CAMERA1', 'CAMERA2', 'FEMTOBOLT', 'REMOTE'] for section in required_sections: if not self.config.has_section(section): errors.append(f"缺少必需的配置段: {section}") @@ -395,228 +395,7 @@ class ConfigManager: 'valid': len(errors) == 0 } - # HTTP接口设备参数设置方法 - def set_imu_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]: - """ - 设置IMU设备配置 - - Args: - config_data: IMU配置数据 - { - 'device_type': 'real' | 'mock' | 'ble', - 'port': 'COM6', - 'baudrate': 9600, - 'mac_address': 'ef:3c:1a:0a:fe:02' - } - - Returns: - Dict[str, Any]: 设置结果 - """ - try: - # 验证必需参数 - if 'device_type' in config_data: - self.set_config_value('DEVICES', 'imu_device_type', config_data['device_type']) - if 'port' in config_data: - self.set_config_value('DEVICES', 'imu_port', config_data['port']) - if 'baudrate' in config_data: - self.set_config_value('DEVICES', 'imu_baudrate', str(config_data['baudrate'])) - if 'mac_address' in config_data: - self.set_config_value('DEVICES', 'imu_mac_address', config_data['mac_address']) - - # 保存配置 - self.save_config() - - self.logger.info(f"IMU配置已更新: {config_data}") - return { - 'success': True, - 'message': 'IMU配置更新成功', - 'config': self.get_device_config('imu') - } - except Exception as e: - self.logger.error(f"设置IMU配置失败: {e}") - return { - 'success': False, - 'message': f'设置IMU配置失败: {str(e)}' - } - - def set_pressure_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]: - """ - 设置压力板设备配置 - - Args: - config_data: 压力板配置数据 - { - 'device_type': 'real' | 'mock', - 'use_mock': False, - 'port': 'COM5', - 'baudrate': 115200 - } - - Returns: - Dict[str, Any]: 设置结果 - """ - try: - # 验证必需参数 - if 'device_type' in config_data: - self.set_config_value('DEVICES', 'pressure_device_type', config_data['device_type']) - if 'use_mock' in config_data: - self.set_config_value('DEVICES', 'pressure_use_mock', str(config_data['use_mock'])) - if 'port' in config_data: - self.set_config_value('DEVICES', 'pressure_port', config_data['port']) - if 'baudrate' in config_data: - self.set_config_value('DEVICES', 'pressure_baudrate', str(config_data['baudrate'])) - - # 保存配置 - self.save_config() - - self.logger.info(f"压力板配置已更新: {config_data}") - return { - 'success': True, - 'message': '压力板配置更新成功', - 'config': self.get_device_config('pressure') - } - except Exception as e: - self.logger.error(f"设置压力板配置失败: {e}") - return { - 'success': False, - 'message': f'设置压力板配置失败: {str(e)}' - } - - def set_camera1_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]: - """ - 设置相机设备配置 - - Args: - config_data: 相机配置数据 - { - 'device_index': 1, - 'width': 1280, - 'height': 720, - 'fps': 30 - } - - Returns: - Dict[str, Any]: 设置结果 - """ - try: - # 验证必需参数 - if 'device_index' in config_data: - self.set_config_value('CAMERA1', 'device_index', str(config_data['device_index'])) - if 'width' in config_data: - self.set_config_value('CAMERA1', 'width', str(config_data['width'])) - if 'height' in config_data: - self.set_config_value('CAMERA1', 'height', str(config_data['height'])) - if 'fps' in config_data: - self.set_config_value('CAMERA1', 'fps', str(config_data['fps'])) - if 'backend' in config_data: - self.set_config_value('CAMERA1', 'backend', str(config_data['backend'])) - - # 保存配置 - self.save_config() - - self.logger.info(f"相机配置已更新: {config_data}") - return { - 'success': True, - 'message': '相机配置更新成功', - 'config': self.get_device_config('camera1') - } - except Exception as e: - self.logger.error(f"设置相机配置失败: {e}") - return { - 'success': False, - 'message': f'设置相机配置失败: {str(e)}' - } - def set_camera2_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]: - """ - 设置相机设备配置 - - Args: - config_data: 相机配置数据 - { - 'device_index': 1, - 'width': 1280, - 'height': 720, - 'fps': 30 - } - - Returns: - Dict[str, Any]: 设置结果 - """ - try: - # 验证必需参数 - if 'device_index' in config_data: - self.set_config_value('CAMERA2', 'device_index', str(config_data['device_index'])) - if 'width' in config_data: - self.set_config_value('CAMERA2', 'width', str(config_data['width'])) - if 'height' in config_data: - self.set_config_value('CAMERA2', 'height', str(config_data['height'])) - if 'fps' in config_data: - self.set_config_value('CAMERA2', 'fps', str(config_data['fps'])) - if 'backend' in config_data: - self.set_config_value('CAMERA2', 'backend', str(config_data['backend'])) - - # 保存配置 - self.save_config() - - self.logger.info(f"相机配置已更新: {config_data}") - return { - 'success': True, - 'message': '相机配置更新成功', - 'config': self.get_device_config('camera2') - } - except Exception as e: - self.logger.error(f"设置相机配置失败: {e}") - return { - 'success': False, - 'message': f'设置相机配置失败: {str(e)}' - } - def set_femtobolt_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]: - """ - 设置FemtoBolt设备配置 - - Args: - config_data: FemtoBolt配置数据 - { - 'color_resolution': '1080P', - 'depth_mode': 'NFOV_UNBINNED', - 'fps': 30, - 'depth_range_min': 1200, - 'depth_range_max': 1500 - } - - Returns: - Dict[str, Any]: 设置结果 - """ - try: - # 验证必需参数 - if 'algorithm_type' in config_data: - self.set_config_value('FEMTOBOLT', 'algorithm_type', config_data['algorithm_type']) - if 'color_resolution' in config_data: - self.set_config_value('FEMTOBOLT', 'color_resolution', config_data['color_resolution']) - if 'depth_mode' in config_data: - self.set_config_value('FEMTOBOLT', 'depth_mode', config_data['depth_mode']) - if 'camera_fps' in config_data: - self.set_config_value('FEMTOBOLT', 'camera_fps', str(config_data['camera_fps'])) - if 'depth_range_min' in config_data: - self.set_config_value('FEMTOBOLT', 'depth_range_min', str(config_data['depth_range_min'])) - if 'depth_range_max' in config_data: - self.set_config_value('FEMTOBOLT', 'depth_range_max', str(config_data['depth_range_max'])) - - # 保存配置 - self.save_config() - - self.logger.info(f"FemtoBolt配置已更新: {config_data}") - return { - 'success': True, - 'message': 'FemtoBolt配置更新成功', - 'config': self.get_device_config('femtobolt') - } - except Exception as e: - self.logger.error(f"设置FemtoBolt配置失败: {e}") - return { - 'success': False, - 'message': f'设置FemtoBolt配置失败: {str(e)}' - } + def get_all_device_configs(self) -> Dict[str, Any]: """ @@ -652,6 +431,8 @@ class ConfigManager: if 'imu' in configs: try: config_data = configs['imu'] + if 'enable' in config_data: + self.set_config_value('DEVICES', 'imu_enable', str(config_data['enable'])) if 'device_type' in config_data: self.set_config_value('DEVICES', 'imu_device_type', config_data['device_type']) if 'use_mock' in config_data: @@ -677,6 +458,8 @@ class ConfigManager: if 'pressure' in configs: try: config_data = configs['pressure'] + if 'enable' in config_data: + self.set_config_value('DEVICES', 'pressure_enable', str(config_data['enable'])) if 'device_type' in config_data: self.set_config_value('DEVICES', 'pressure_device_type', config_data['device_type']) if 'use_mock' in config_data: @@ -702,6 +485,8 @@ class ConfigManager: if 'camera1' in configs: try: config_data = configs['camera1'] + if 'enable' in config_data: + self.set_config_value('CAMERA1', 'enable', str(config_data['enable'])) if 'device_index' in config_data: self.set_config_value('CAMERA1', 'device_index', str(config_data['device_index'])) if 'width' in config_data: @@ -734,6 +519,8 @@ class ConfigManager: if 'camera2' in configs: try: config_data = configs['camera2'] + if 'enable' in config_data: + self.set_config_value('CAMERA2', 'enable', str(config_data['enable'])) if 'device_index' in config_data: self.set_config_value('CAMERA2', 'device_index', str(config_data['device_index'])) if 'width' in config_data: @@ -767,6 +554,8 @@ class ConfigManager: if 'femtobolt' in configs: try: config_data = configs['femtobolt'] + if 'enable' in config_data: + self.set_config_value('FEMTOBOLT', 'enable', str(config_data['enable'])) if 'algorithm_type' in config_data: self.set_config_value('FEMTOBOLT', 'algorithm_type', config_data['algorithm_type']) if 'color_resolution' in config_data: @@ -802,8 +591,8 @@ class ConfigManager: if 'remote' in configs: try: config_data = configs['remote'] - if 'enabled' in config_data: - self.set_config_value('REMOTE', 'enable', str(config_data['enabled'])) + if 'enable' in config_data: + self.set_config_value('REMOTE', 'enable', str(config_data['enable'])) if 'port' in config_data: self.set_config_value('REMOTE', 'port', config_data['port']) if 'baudrate' in config_data: diff --git a/backend/main.py b/backend/main.py index 982e8550..a0aec180 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1211,7 +1211,7 @@ class AppServer: }), 400 # 验证数据格式 - supported_devices = ['camera1','camera2', 'femtobolt','imu','pressure'] + supported_devices = ['camera1','camera2', 'femtobolt','imu','pressure','remote'] for device_name in data.keys(): if device_name not in supported_devices: return jsonify({ @@ -1386,7 +1386,7 @@ class AppServer: diagnosis_info = data.get('diagnosis_info') treatment_info = data.get('treatment_info') suggestion_info = data.get('suggestion_info') - success = self.db_manager.update_session_endcheck( + success = self.db_manager.update_session_all_info( session_id, diagnosis_info=diagnosis_info, treatment_info=treatment_info, @@ -1534,13 +1534,6 @@ class AppServer: suggestion_info = data.get('suggestion_info') - # 验证至少提供一个要更新的字段 - if not any([diagnosis_info, treatment_info, suggestion_info]): - return jsonify({ - 'success': False, - 'error': '至少需要提供一个要更新的字段(diagnosis_info, treatment_info, suggestion_info)' - }), 400 - # 调用数据库管理器的批量更新方法 self.db_manager.update_session_all_info( session_id=session_id, @@ -1556,9 +1549,7 @@ class AppServer: if treatment_info is not None: updated_fields.append('处理信息') if suggestion_info is not None: - updated_fields.append('建议信息') - if status is not None: - updated_fields.append(f'状态({status})') + updated_fields.append('建议信息') self.logger.info(f'会话信息保存成功: {session_id}, 更新字段: {", ".join(updated_fields)}') diff --git a/document/串口遥控器遥控界面操作说明.md b/document/串口遥控器遥控界面操作说明.md index 4f721397..fcb8eab5 100644 --- a/document/串口遥控器遥控界面操作说明.md +++ b/document/串口遥控器遥控界面操作说明.md @@ -10,7 +10,7 @@ - [REMOTE] port,缺省 COM6 - [REMOTE] baudrate,缺省 115200 - [REMOTE] timeout,缺省 0.1 秒 - - [DEVICES] remote_enabled(是否启用),缺省 true + - [DEVICES] remote_enable(是否启用),缺省 true - 串口参数:115200 bps,8 数据位,1 停止位,无校验(8N1)。 ## 报文格式 diff --git a/frontend/src/renderer/src/views/Detection.vue b/frontend/src/renderer/src/views/Detection.vue index 5e0a697b..ade6bb60 100644 --- a/frontend/src/renderer/src/views/Detection.vue +++ b/frontend/src/renderer/src/views/Detection.vue @@ -17,15 +17,14 @@ 结束检测
-
- -
-
- +
+ +
+
@@ -712,8 +711,7 @@
本次检测未截图或录像操作,不予存档记录!
本次检测未截图操作,存档记录不可生成报告!
- 确定 - 确定 + 确定
@@ -746,7 +744,7 @@
- +
@@ -757,27 +755,27 @@
相机上
+ 0号 1号 2号 3号 - 4号 - 5号 + 4号
- +
相机下
+ 0号 1号 2号 3号 - 4号 - 5号 + 4号
- +
@@ -788,7 +786,7 @@ - +
@@ -1017,7 +1015,7 @@ const cameraForm = ref({ // 相机参数 }, remote:{ port: '', // IMU串口号 - enabled: false + enable: false } }) const calculatedAge = ref(null) @@ -1922,51 +1920,7 @@ function handlePressureData(data) { } -async function handleDiagnosticInfo(status) { - try { - // 检查是否有活跃的会话ID - if (!patientInfo.value.sessionId) { - throw new Error('缺少会话Id') - } - // 调用后端API采集检测数据 - const response = await fetch(`${BACKEND_URL}/api/detection/${patientInfo.value.sessionId}/save-info`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - diagnosis_info: diagnosticForm.diagnosis_info, - treatment_info: diagnosticForm.treatment_info, - suggestion_info: diagnosticForm.suggestion_info, - status: status, - session_id: patientInfo.value.sessionId, - }) - }) - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`) - } - const result = await response.json() - if (result.success) { - // 显示成功消息 - ElMessage.success({ - message: status + '诊断信息成功', - duration: 5000 - }) - - } else { - throw new Error(result.message || '诊断信息失败') - } - } catch (error) { - ElMessage.error({ - message: errorMessage, - duration: 5000 - }) - - } finally { - - } -} // 保存检测数据 async function saveDetectionData() { @@ -2216,10 +2170,6 @@ const loadPatientInfo = async () => { // 处理页面关闭或刷新事件 const handleBeforeUnload = (event) => { console.log('页面即将关闭,正在清理资源...') - - - // 停止检测 - stopDetection() // 断开WebSocket连接 disconnectWebSocket() @@ -2404,17 +2354,8 @@ onUnmounted(() => { clearInterval(timerId.value) timerId.value = null console.log('✅ 定时器已清理') - } - - // // 停止录制 - // if (isRecording.value === true) { - // stopRecord() - // console.log('✅ 录制已停止') - // } - - // // 停止检测 - // stopDetection() - + } + // 断开WebSocket连接 disconnectWebSocket() @@ -2576,6 +2517,8 @@ function refreshClick(type) { devicesSocket.emit('restart_device', { device_type: 'imu' }) }else if(type == 'pressure'){ devicesSocket.emit('restart_device', { device_type: 'pressure' }) + }else if(type == 'remote'){ + devicesSocket.emit('restart_device', { device_type: 'remote' }) } } else { console.warn('⚠️ Socket服务未连接,无法重启设备!') diff --git a/frontend/src/renderer/src/views/PatientProfile.vue b/frontend/src/renderer/src/views/PatientProfile.vue index 938d2c59..ad287a2f 100644 --- a/frontend/src/renderer/src/views/PatientProfile.vue +++ b/frontend/src/renderer/src/views/PatientProfile.vue @@ -103,7 +103,27 @@