From dd695cfccaf39030b4bbac27ab5048f52cbf3f8b Mon Sep 17 00:00:00 2001
From: zhaozilong12 <405241463@qq.com>
Date: Tue, 29 Jul 2025 16:44:17 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/app.py | 66 ++++++++++++++++---
backend/config.ini | 4 ++
frontend/src/renderer/src/views/Dashboard.vue | 2 +-
frontend/src/renderer/src/views/Detection.vue | 59 ++++++++++++-----
4 files changed, 107 insertions(+), 24 deletions(-)
diff --git a/backend/app.py b/backend/app.py
index 3dc87b24..6c5780e1 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -16,6 +16,10 @@ from flask_cors import CORS
import sqlite3
import logging
from pathlib import Path
+from flask_socketio import SocketIO, emit
+import cv2
+import base64
+import configparser
# 添加当前目录到Python路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
@@ -40,10 +44,16 @@ logger = logging.getLogger(__name__)
# 创建Flask应用
app = Flask(__name__)
app.config['SECRET_KEY'] = 'body-balance-detection-system-2024'
+socketio = SocketIO(app, cors_allowed_origins='*', async_mode='threading')
# 启用CORS支持
CORS(app, origins=['http://localhost:3000', 'http://localhost:3001', 'file://*'])
+# 读取RTSP配置
+config = configparser.ConfigParser()
+config.read(os.path.join(os.path.dirname(__file__), 'config.ini'), encoding='utf-8')
+rtsp_url = config.get('CAMERA', 'rtsp_url', fallback=None)
+
# 全局变量
db_manager = None
device_manager = None
@@ -51,6 +61,8 @@ detection_engine = None
data_processor = None
current_detection = None
detection_thread = None
+rtsp_thread = None
+rtsp_running = False
def init_app():
"""初始化应用"""
@@ -612,19 +624,57 @@ if __name__ == '__main__':
# 初始化应用
init_app()
- # 启动Flask服务
+ # 启动Flask+SocketIO服务
logger.info('启动后端服务...')
- app.run(
- host='127.0.0.1',
- port=5000,
- debug=False,
- threaded=True
+ socketio.run(app,
+ host=config.get('SERVER', 'host', fallback='127.0.0.1'),
+ port=config.getint('SERVER', 'port', fallback=5000),
+ debug=config.getboolean('APP', 'debug', fallback=False),
+ allow_unsafe_werkzeug=True
)
-
except KeyboardInterrupt:
logger.info('服务被用户中断')
except Exception as e:
logger.error(f'服务启动失败: {e}')
sys.exit(1)
finally:
- logger.info('后端服务已停止')
\ No newline at end of file
+ logger.info('后端服务已停止')
+
+# ==================== WebSocket 实时推送RTSP帧 ====================
+
+def generate_rtsp_frames():
+ global rtsp_running
+ cap = cv2.VideoCapture(rtsp_url)
+ if not cap.isOpened():
+ logger.error(f'无法打开RTSP流: {rtsp_url}')
+ return
+ rtsp_running = True
+ while rtsp_running:
+ ret, frame = cap.read()
+ if not ret:
+ logger.warning('RTSP读取帧失败,尝试重连...')
+ cap.release()
+ time.sleep(1)
+ cap = cv2.VideoCapture(rtsp_url)
+ continue
+ _, buffer = cv2.imencode('.jpg', frame)
+ jpg_as_text = base64.b64encode(buffer).decode('utf-8')
+ socketio.emit('rtsp_frame', {'image': jpg_as_text})
+ time.sleep(1/15) # 推送帧率可调
+ cap.release()
+
+@socketio.on('start_rtsp')
+def handle_start_rtsp():
+ global rtsp_thread, rtsp_running
+ if rtsp_thread and rtsp_thread.is_alive():
+ emit('rtsp_status', {'status': 'already_running'})
+ return
+ rtsp_thread = threading.Thread(target=generate_rtsp_frames)
+ rtsp_thread.start()
+ emit('rtsp_status', {'status': 'started'})
+
+@socketio.on('stop_rtsp')
+def handle_stop_rtsp():
+ global rtsp_running
+ rtsp_running = False
+ emit('rtsp_status', {'status': 'stopped'})
\ No newline at end of file
diff --git a/backend/config.ini b/backend/config.ini
index cb814776..3a3cfa8b 100644
--- a/backend/config.ini
+++ b/backend/config.ini
@@ -39,3 +39,7 @@ secret_key = 026efbf83a2fe101f168780740da86bf1c9260625458e6782738aa9cf18f8e37
session_timeout = 3600
max_login_attempts = 5
+
+[CAMERA]
+rtsp_url = rtsp://admin:password@192.168.1.100:554/Streaming/Channels/101
+
diff --git a/frontend/src/renderer/src/views/Dashboard.vue b/frontend/src/renderer/src/views/Dashboard.vue
index 3fa0f899..197d4735 100644
--- a/frontend/src/renderer/src/views/Dashboard.vue
+++ b/frontend/src/renderer/src/views/Dashboard.vue
@@ -265,7 +265,7 @@ const formatDate = (date) => {
const loadPatients = async () => {
try {
- const response = await patientAPI.getList()
+ const response = await patientAPI.getPatients()
if (response.success) {
patients.value = response.data
}
diff --git a/frontend/src/renderer/src/views/Detection.vue b/frontend/src/renderer/src/views/Detection.vue
index 885703d6..a99db0d8 100644
--- a/frontend/src/renderer/src/views/Detection.vue
+++ b/frontend/src/renderer/src/views/Detection.vue
@@ -142,13 +142,13 @@
-
-
-
+
+
+
-
-
-
+
+
+
@@ -289,7 +289,7 @@
视频
-
+
@@ -298,15 +298,9 @@