清理了屏幕录制,截图相关方法。调整了系统启动逻辑。
This commit is contained in:
parent
9f2ecf02c4
commit
685765e2b2
@ -29,8 +29,8 @@ fourcc = MJPG
|
|||||||
backend = directshow
|
backend = directshow
|
||||||
|
|
||||||
[CAMERA2]
|
[CAMERA2]
|
||||||
enable = True
|
enable = False
|
||||||
device_index = 1
|
device_index = 2
|
||||||
width = 1280
|
width = 1280
|
||||||
height = 720
|
height = 720
|
||||||
fps = 30
|
fps = 30
|
||||||
|
|||||||
@ -1096,22 +1096,18 @@ class DatabaseManager:
|
|||||||
"""保存检测视频记录(与 detection_video 表结构保持一致)"""
|
"""保存检测视频记录(与 detection_video 表结构保持一致)"""
|
||||||
conn = self.get_connection()
|
conn = self.get_connection()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
video_id = self.generate_detection_video_id()
|
video_id = self.generate_detection_video_id()
|
||||||
china_time = self.get_china_time()
|
china_time = self.get_china_time()
|
||||||
|
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
INSERT INTO detection_video (
|
INSERT INTO detection_video (
|
||||||
id, session_id, screen_video, body_video, foot_video1, foot_video2, timestamp
|
id, session_id, screen_video, timestamp
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
) VALUES (?, ?, ?, ?)
|
||||||
''', (
|
''', (
|
||||||
video_id,
|
video_id,
|
||||||
session_id,
|
session_id,
|
||||||
video.get('screen_video_path'),
|
video.get('screen_video_path'),
|
||||||
video.get('femtobolt_video_path'),
|
|
||||||
video.get('camera1_video_path'),
|
|
||||||
video.get('camera2_video_path'),
|
|
||||||
china_time
|
china_time
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -228,34 +228,13 @@ class AppServer:
|
|||||||
self.device_coordinator = DeviceCoordinator(self.socketio)
|
self.device_coordinator = DeviceCoordinator(self.socketio)
|
||||||
# 设置状态变化回调
|
# 设置状态变化回调
|
||||||
self.device_coordinator.set_status_change_callback(self._on_device_status_change)
|
self.device_coordinator.set_status_change_callback(self._on_device_status_change)
|
||||||
# 调用初始化方法来初始化设备
|
# 设备初始化现在延迟到用户登录成功后进行,加快启动速度
|
||||||
if self.device_coordinator.initialize():
|
|
||||||
self.logger.info('设备协调器初始化完成')
|
|
||||||
# 获取设备管理器实例
|
|
||||||
self.device_managers = self.device_coordinator.get_device_managers()
|
|
||||||
|
|
||||||
# 为每个设备添加状态变化回调(双重保险)
|
|
||||||
for device_name, manager in self.device_managers.items():
|
|
||||||
if manager and hasattr(manager, 'add_status_change_callback'):
|
|
||||||
manager.add_status_change_callback(self._on_device_status_change)
|
|
||||||
|
|
||||||
self.logger.info(f'已获取设备管理器: {list(self.device_managers.keys())}')
|
|
||||||
else:
|
|
||||||
self.logger.warning('设备协调器初始化失败,但系统将继续运行')
|
|
||||||
self.device_managers = {} # 初始化为空字典以避免后续错误
|
|
||||||
|
|
||||||
# 初始化录制管理器
|
# 初始化录制管理器
|
||||||
self.logger.info('正在初始化录制管理器...')
|
self.logger.info('正在初始化录制管理器...')
|
||||||
femtobolt_manager = self.device_managers.get('femtobolt')
|
|
||||||
pressure_manager = self.device_managers.get('pressure')
|
|
||||||
|
|
||||||
# 录制管理器当前采用屏幕区域截取方式进行相机录制,不依赖 CameraManager
|
# 录制管理器
|
||||||
# 但保留其他设备管理器以便后续扩展(如FemtoBolt、压力传感器)
|
|
||||||
self.recording_manager = RecordingManager(
|
self.recording_manager = RecordingManager(
|
||||||
camera_manager=None,
|
|
||||||
db_manager=self.db_manager,
|
|
||||||
femtobolt_manager=femtobolt_manager,
|
|
||||||
pressure_manager=pressure_manager,
|
|
||||||
config_manager=self.config_manager
|
config_manager=self.config_manager
|
||||||
)
|
)
|
||||||
self.logger.info('录制管理器初始化完成')
|
self.logger.info('录制管理器初始化完成')
|
||||||
@ -276,6 +255,29 @@ class AppServer:
|
|||||||
self.logger.error(f'应用初始化失败: {e}')
|
self.logger.error(f'应用初始化失败: {e}')
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def _initialize_devices(self):
|
||||||
|
"""
|
||||||
|
初始化设备(在用户登录成功后调用)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.logger.info('开始初始化设备...')
|
||||||
|
if self.device_coordinator.initialize():
|
||||||
|
self.logger.info('设备协调器初始化完成')
|
||||||
|
# 获取设备管理器实例
|
||||||
|
self.device_managers = self.device_coordinator.get_device_managers()
|
||||||
|
|
||||||
|
# 为每个设备添加状态变化回调(双重保险)
|
||||||
|
for device_name, manager in self.device_managers.items():
|
||||||
|
if manager and hasattr(manager, 'add_status_change_callback'):
|
||||||
|
manager.add_status_change_callback(self._on_device_status_change)
|
||||||
|
|
||||||
|
self.logger.info(f'已获取设备管理器: {list(self.device_managers.keys())}')
|
||||||
|
else:
|
||||||
|
self.logger.warning('设备协调器初始化失败,但系统将继续运行')
|
||||||
|
self.device_managers = {} # 初始化为空字典以避免后续错误
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f'设备初始化异常: {e}')
|
||||||
|
|
||||||
def require_license(self, feature=None):
|
def require_license(self, feature=None):
|
||||||
"""
|
"""
|
||||||
授权检查装饰器
|
授权检查装饰器
|
||||||
@ -755,6 +757,10 @@ class AppServer:
|
|||||||
|
|
||||||
self.logger.info(f'用户 {username} 登录成功')
|
self.logger.info(f'用户 {username} 登录成功')
|
||||||
|
|
||||||
|
# 登录成功后,异步初始化设备(如果尚未初始化)
|
||||||
|
if self.device_coordinator and not self.device_coordinator.is_initialized:
|
||||||
|
threading.Thread(target=self._initialize_devices, daemon=True).start()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
'data': {
|
'data': {
|
||||||
@ -1219,9 +1225,7 @@ class AppServer:
|
|||||||
'message': f'不支持的设备类型: {device_name},支持的设备类型: {", ".join(supported_devices)}'
|
'message': f'不支持的设备类型: {device_name},支持的设备类型: {", ".join(supported_devices)}'
|
||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
result = self.config_manager.set_all_device_configs(data)
|
result = self.config_manager.set_all_device_configs(data)
|
||||||
|
|
||||||
|
|
||||||
status_code = 200 if result['success'] else 400
|
status_code = 200 if result['success'] else 400
|
||||||
return jsonify(result), status_code
|
return jsonify(result), status_code
|
||||||
|
|
||||||
@ -1282,6 +1286,17 @@ class AppServer:
|
|||||||
if not self.db_manager or not self.device_coordinator:
|
if not self.db_manager or not self.device_coordinator:
|
||||||
return jsonify({'success': False, 'error': '数据库管理器或设备管理器未初始化'}), 500
|
return jsonify({'success': False, 'error': '数据库管理器或设备管理器未初始化'}), 500
|
||||||
|
|
||||||
|
# 检查设备是否已初始化
|
||||||
|
if self.device_coordinator and not self.device_coordinator.is_initialized:
|
||||||
|
self.logger.info('设备尚未初始化,等待初始化完成...')
|
||||||
|
# 最多等待10秒
|
||||||
|
start_wait = time.time()
|
||||||
|
while not self.device_coordinator.is_initialized:
|
||||||
|
if time.time() - start_wait > 10:
|
||||||
|
return jsonify({'success': False, 'error': '设备初始化超时,请稍后重试'}), 503
|
||||||
|
time.sleep(0.5)
|
||||||
|
self.logger.info('设备初始化完成,继续开始检测')
|
||||||
|
|
||||||
data = flask_request.get_json()
|
data = flask_request.get_json()
|
||||||
patient_id = data.get('patient_id')
|
patient_id = data.get('patient_id')
|
||||||
creator_id = data.get('creator_id')
|
creator_id = data.get('creator_id')
|
||||||
@ -1324,7 +1339,6 @@ class AppServer:
|
|||||||
try:
|
try:
|
||||||
if not self.db_manager:
|
if not self.db_manager:
|
||||||
return jsonify({'success': False, 'error': '数据库管理器未初始化'}), 500
|
return jsonify({'success': False, 'error': '数据库管理器未初始化'}), 500
|
||||||
|
|
||||||
# 获取检测数据和视频数据
|
# 获取检测数据和视频数据
|
||||||
session_data = self.db_manager.get_session_data(session_id)
|
session_data = self.db_manager.get_session_data(session_id)
|
||||||
if not session_data:
|
if not session_data:
|
||||||
@ -1417,17 +1431,15 @@ class AppServer:
|
|||||||
|
|
||||||
data = flask_request.get_json()
|
data = flask_request.get_json()
|
||||||
patient_id = data.get('patient_id')
|
patient_id = data.get('patient_id')
|
||||||
screen_location = data.get('screen_location') # [0,0,1920,1080]
|
screen_location = data.get('screen_location') # [0,0,1920,1080]
|
||||||
femtobolt_location = data.get('femtobolt_location') # [0,0,640,480]
|
|
||||||
camera1_location = data.get('camera1_location') # [0,0,640,480]
|
|
||||||
camera2_location = data.get('camera2_location') # [0,0,640,480]
|
|
||||||
if not patient_id:
|
if not patient_id:
|
||||||
return jsonify({'success': False, 'error': '缺少患者ID'}), 400
|
return jsonify({'success': False, 'error': '缺少患者ID'}), 400
|
||||||
|
|
||||||
# 开始视频录制
|
# 开始视频录制
|
||||||
recording_response = None
|
recording_response = None
|
||||||
try:
|
try:
|
||||||
recording_response = self.recording_manager.start_recording(session_id, patient_id,screen_location,camera1_location,camera2_location,femtobolt_location)
|
# 使用新的ffmpeg录制方法
|
||||||
|
recording_response = self.recording_manager.start_recording_ffmpeg(session_id, patient_id, screen_location)
|
||||||
|
|
||||||
# 处理录制管理器返回的数据库更新信息
|
# 处理录制管理器返回的数据库更新信息
|
||||||
if recording_response and recording_response.get('success') and 'database_updates' in recording_response:
|
if recording_response and recording_response.get('success') and 'database_updates' in recording_response:
|
||||||
@ -1436,10 +1448,7 @@ class AppServer:
|
|||||||
# 保存检测视频记录(映射到 detection_video 表字段)
|
# 保存检测视频记录(映射到 detection_video 表字段)
|
||||||
video_paths = db_updates.get('video_paths', {})
|
video_paths = db_updates.get('video_paths', {})
|
||||||
video_record = {
|
video_record = {
|
||||||
'screen_video_path': video_paths.get('screen_video_path'),
|
'screen_video_path': video_paths.get('screen_video_path')
|
||||||
'femtobolt_video_path': video_paths.get('femtobolt_video_path'),
|
|
||||||
'camera1_video_path': video_paths.get('camera1_video_path'),
|
|
||||||
'camera2_video_path': video_paths.get('camera2_video_path'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1473,7 +1482,7 @@ class AppServer:
|
|||||||
}), 400
|
}), 400
|
||||||
# 停止同步录制,传递视频数据
|
# 停止同步录制,传递视频数据
|
||||||
try:
|
try:
|
||||||
restrt = self.recording_manager.stop_recording(session_id)
|
restrt = self.recording_manager.stop_recording_ffmpeg(session_id)
|
||||||
self.logger.info(f'停止录制结果: {restrt}')
|
self.logger.info(f'停止录制结果: {restrt}')
|
||||||
except Exception as rec_e:
|
except Exception as rec_e:
|
||||||
self.logger.error(f'停止同步录制失败: {rec_e}', exc_info=True)
|
self.logger.error(f'停止同步录制失败: {rec_e}', exc_info=True)
|
||||||
|
|||||||
@ -91,10 +91,10 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果已登录用户访问登录页,重定向到仪表板
|
// 如果已登录用户访问登录页,重定向到仪表板
|
||||||
if (to.name === 'Login' && authStore.isAuthenticated) {
|
// if (to.name === 'Login' && authStore.isAuthenticated) {
|
||||||
next({ name: 'Dashboard' })
|
// next({ name: 'Dashboard' })
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import { authAPI } from '../services/api'
|
|||||||
// 认证状态管理
|
// 认证状态管理
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
// 状态
|
// 状态
|
||||||
const authToken = ref(localStorage.getItem('authToken') || null)
|
const authToken = ref(sessionStorage.getItem('authToken') || null)
|
||||||
const currentUser = ref(JSON.parse(localStorage.getItem('currentUser') || 'null'))
|
const currentUser = ref(JSON.parse(sessionStorage.getItem('currentUser') || 'null'))
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const error = ref(null)
|
const error = ref(null)
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
authToken.value = token
|
authToken.value = token
|
||||||
currentUser.value = user
|
currentUser.value = user
|
||||||
|
|
||||||
// 保存到本地存储
|
// 保存到会话存储(关闭浏览器/应用后失效)
|
||||||
localStorage.setItem('authToken', token)
|
sessionStorage.setItem('authToken', token)
|
||||||
localStorage.setItem('currentUser', JSON.stringify(user))
|
sessionStorage.setItem('currentUser', JSON.stringify(user))
|
||||||
|
|
||||||
return { success: true, data: response.data }
|
return { success: true, data: response.data }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -79,8 +79,8 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
// 清除本地状态
|
// 清除本地状态
|
||||||
authToken.value = null
|
authToken.value = null
|
||||||
currentUser.value = null
|
currentUser.value = null
|
||||||
localStorage.removeItem('authToken')
|
sessionStorage.removeItem('authToken')
|
||||||
localStorage.removeItem('currentUser')
|
sessionStorage.removeItem('currentUser')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,10 @@
|
|||||||
<div v-for="(item, index) in useImgList" :key="index"
|
<div v-for="(item, index) in useImgList" :key="index"
|
||||||
class="PhotoAlbum-imgbox">
|
class="PhotoAlbum-imgbox">
|
||||||
<div class="PhotoAlbum-imgactive" @click="clickImg(item,index)">
|
<div class="PhotoAlbum-imgactive" @click="clickImg(item,index)">
|
||||||
<img :src="BACKEND_URL+'/' + item.screen_image" alt="" style="width: 100%;height: 100%;">
|
<img v-if="item.type == 'data'" :src="BACKEND_URL+'/' + item.screen_image" alt="" style="width: 100%;height: 100%;">
|
||||||
|
<video v-else-if="item.type == 'video'" :src="item.screen_video ? BACKEND_URL+'/' + item.screen_video.replace(/\\/g, '/') : ''" controls width="100%" height="100%">
|
||||||
|
您的浏览器不支持视频播放
|
||||||
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div class="PhotoAlbum-imgtextbox">
|
<div class="PhotoAlbum-imgtextbox">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@ -111,7 +114,7 @@ async function tipConfirm(){
|
|||||||
if(elements.type == 'data'){
|
if(elements.type == 'data'){
|
||||||
imgIds.push(elements.id)
|
imgIds.push(elements.id)
|
||||||
}
|
}
|
||||||
if(elements.type == 'videos'){
|
if(elements.type == 'video'){
|
||||||
videoIds.push(elements.id)
|
videoIds.push(elements.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user