From 9a9352b3407ccd1879947ec078b43acf912f6224 Mon Sep 17 00:00:00 2001 From: wang <3202024218@qq.com> Date: Wed, 9 Jul 2025 16:28:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A9=B6=E6=9E=81=E6=97=A0=E6=95=8C=E7=A8=B3?= =?UTF-8?q?=E5=AE=9A=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- goldminer/backend/Dockerfile | 2 +- goldminer/backend/app.py | 123 +++++++++--------- goldminer/frontend/.gitignore | 19 +++ goldminer/frontend/nginx.conf | 11 +- .../node_modules/.cache/eslint/123ee647.json | 2 +- .../frontend/src/components/ChatRoom.vue | 10 +- 6 files changed, 94 insertions(+), 73 deletions(-) create mode 100644 goldminer/frontend/.gitignore diff --git a/goldminer/backend/Dockerfile b/goldminer/backend/Dockerfile index d87b44ee..c8458b0c 100644 --- a/goldminer/backend/Dockerfile +++ b/goldminer/backend/Dockerfile @@ -40,7 +40,7 @@ EXPOSE 5001/udp # 创建启动脚本 RUN echo '#!/bin/bash\n\ python voice_udp_server.py &\n\ -gunicorn --workers 2 --bind 0.0.0.0:5000 app:app\n\ +gunicorn --workers 1 --worker-class eventlet --bind 0.0.0.0:5000 app:app\n\ ' > /app/start.sh && chmod +x /app/start.sh # 使用启动脚本启动应用 diff --git a/goldminer/backend/app.py b/goldminer/backend/app.py index 1622ebc5..ae1b67e7 100644 --- a/goldminer/backend/app.py +++ b/goldminer/backend/app.py @@ -638,33 +638,36 @@ def handle_send_message(data): if not room_id or not message_text: return - # 获取用户和房间信息 - user = User.query.get(user_id) - room = ChatRoom.query.get(room_id) - - if not user or not room: - return - - # 保存消息到数据库 - message = ChatMessage( - room_id=room_id, - user_id=user_id, - message=message_text, - message_type='text' - ) - - db.session.add(message) - db.session.commit() - - # 广播消息给房间内的所有用户 - emit('new_message', { - 'id': message.id, - 'user_id': user_id, - 'username': user.username, - 'message': message_text, - 'message_type': 'text', - 'created_at': message.created_at.isoformat() - }, room=str(room_id)) + try: + with app.app_context(): + user = User.query.get(user_id) + room = ChatRoom.query.get(room_id) + + if not user or not room: + return + + message = ChatMessage( + room_id=room_id, + user_id=user_id, + message=message_text, + message_type='text' + ) + + db.session.add(message) + db.session.commit() + + emit('new_message', { + 'id': message.id, + 'user_id': user_id, + 'username': user.username, + 'message': message_text, + 'message_type': 'text', + 'created_at': message.created_at.isoformat() + }, room=str(room_id)) + + except Exception as e: + logger.error(f"处理文本消息时出错: {e}") + db.session.rollback() @socketio.on('send_audio_message') def handle_send_audio_message(data): @@ -704,40 +707,38 @@ def handle_send_audio_message(data): logger.info(f"处理语音消息: 用户ID={user_id}, 房间ID={room_id}, 音频时长={audio_duration}秒, MIME类型={audio_mime_type}, 数据长度={len(audio_data)}") try: - # 获取用户和房间信息 - user = User.query.get(user_id) - room = ChatRoom.query.get(room_id) - - if not user or not room: - logger.error(f"用户或房间不存在: user_id={user_id}, room_id={room_id}") - return - - # 保存消息到数据库 - message = ChatMessage( - room_id=room_id, - user_id=user_id, - message=audio_data, # 存储Base64编码的音频数据 - message_type='audio', - audio_duration=audio_duration - ) - - db.session.add(message) - db.session.commit() - logger.info(f"语音消息已保存到数据库: ID={message.id}") - - # 广播消息给房间内的所有用户 - emit('new_message', { - 'id': message.id, - 'user_id': user_id, - 'username': user.username, - 'message': audio_data, - 'message_type': 'audio', - 'audio_duration': audio_duration, - 'audio_mime_type': audio_mime_type, - 'created_at': message.created_at.isoformat() - }, room=str(room_id)) - logger.info(f"语音消息已广播到房间: {room_id}") - + with app.app_context(): + user = User.query.get(user_id) + room = ChatRoom.query.get(room_id) + + if not user or not room: + logger.error(f"用户或房间不存在: user_id={user_id}, room_id={room_id}") + return + + message = ChatMessage( + room_id=room_id, + user_id=user_id, + message=audio_data, + message_type='audio', + audio_duration=audio_duration + ) + + db.session.add(message) + db.session.commit() + logger.info(f"语音消息已保存到数据库: ID={message.id}") + + emit('new_message', { + 'id': message.id, + 'user_id': user_id, + 'username': user.username, + 'message': audio_data, + 'message_type': 'audio', + 'audio_duration': audio_duration, + 'audio_mime_type': audio_mime_type, + 'created_at': message.created_at.isoformat() + }, room=str(room_id)) + logger.info(f"语音消息已广播到房间: {room_id}") + except Exception as e: logger.error(f"处理语音消息时出错: {e}") db.session.rollback() diff --git a/goldminer/frontend/.gitignore b/goldminer/frontend/.gitignore new file mode 100644 index 00000000..71293a5c --- /dev/null +++ b/goldminer/frontend/.gitignore @@ -0,0 +1,19 @@ +# Dependencies +/node_modules + +# Build files +/dist + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# IDE and editor directories +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/goldminer/frontend/nginx.conf b/goldminer/frontend/nginx.conf index a9149040..39b26bb2 100644 --- a/goldminer/frontend/nginx.conf +++ b/goldminer/frontend/nginx.conf @@ -1,3 +1,8 @@ +upstream backend { + ip_hash; + server backend:5000; +} + server { listen 80 default_server; listen [::]:80 default_server; @@ -76,7 +81,7 @@ server { # API请求代理到后端服务 location /api/ { - proxy_pass http://backend:5000; + proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -88,7 +93,7 @@ server { # Socket.IO请求代理到后端服务 location /socket.io/ { - proxy_pass http://backend:5000; + proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; @@ -104,7 +109,7 @@ server { # 支持WebRTC信令转发 location /rtc/ { - proxy_pass http://backend:5000; + proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; diff --git a/goldminer/frontend/node_modules/.cache/eslint/123ee647.json b/goldminer/frontend/node_modules/.cache/eslint/123ee647.json index df3e8f6e..708f0997 100644 --- a/goldminer/frontend/node_modules/.cache/eslint/123ee647.json +++ b/goldminer/frontend/node_modules/.cache/eslint/123ee647.json @@ -1 +1 @@ -[{"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\main.js":"1","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\App.vue":"2","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\router.js":"3","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Home.vue":"4","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Register.vue":"5","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Game.vue":"6","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Login.vue":"7","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\UserProfile.vue":"8","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\ChatRoom.vue":"9","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Leaderboard.vue":"10","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Header.vue":"11","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Admin.vue":"12","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\AdminSetup.vue":"13"},{"size":2756,"mtime":1751556761222,"results":"14","hashOfConfig":"15"},{"size":1004,"mtime":1750128639386,"results":"16","hashOfConfig":"15"},{"size":2623,"mtime":1751556546605,"results":"17","hashOfConfig":"15"},{"size":5735,"mtime":1750209720346,"results":"18","hashOfConfig":"15"},{"size":4492,"mtime":1750147385471,"results":"19","hashOfConfig":"15"},{"size":53697,"mtime":1752025017871,"results":"20","hashOfConfig":"15"},{"size":7100,"mtime":1751556546604,"results":"21","hashOfConfig":"15"},{"size":11652,"mtime":1750381631833,"results":"22","hashOfConfig":"15"},{"size":60164,"mtime":1752033607652,"results":"23","hashOfConfig":"15"},{"size":13225,"mtime":1752025017873,"results":"24","hashOfConfig":"15"},{"size":4886,"mtime":1751556546600,"results":"25","hashOfConfig":"15"},{"size":18677,"mtime":1751677918715,"results":"26","hashOfConfig":"15"},{"size":4836,"mtime":1750303858491,"results":"27","hashOfConfig":"15"},{"filePath":"28","messages":"29","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},"i331ru",{"filePath":"31","messages":"32","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"34","messages":"35","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},{"filePath":"36","messages":"37","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"38","messages":"39","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"40","messages":"41","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"42","messages":"43","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"44","messages":"45","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"46","messages":"47","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"50","messages":"51","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"52","messages":"53","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"54","messages":"55","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\main.js",[],[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\App.vue",[],[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\router.js",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Home.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Register.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Game.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Login.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\UserProfile.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\ChatRoom.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Leaderboard.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Header.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Admin.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\AdminSetup.vue",[]] \ No newline at end of file +[{"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\main.js":"1","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\App.vue":"2","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\router.js":"3","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Home.vue":"4","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Register.vue":"5","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Game.vue":"6","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Login.vue":"7","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\UserProfile.vue":"8","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\ChatRoom.vue":"9","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Leaderboard.vue":"10","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Header.vue":"11","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Admin.vue":"12","D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\AdminSetup.vue":"13"},{"size":2756,"mtime":1751556761222,"results":"14","hashOfConfig":"15"},{"size":1004,"mtime":1750128639386,"results":"16","hashOfConfig":"15"},{"size":2623,"mtime":1751556546605,"results":"17","hashOfConfig":"15"},{"size":5735,"mtime":1750209720346,"results":"18","hashOfConfig":"15"},{"size":4492,"mtime":1750147385471,"results":"19","hashOfConfig":"15"},{"size":53697,"mtime":1752044908715,"results":"20","hashOfConfig":"15"},{"size":7100,"mtime":1751556546604,"results":"21","hashOfConfig":"15"},{"size":11652,"mtime":1750381631833,"results":"22","hashOfConfig":"15"},{"size":60164,"mtime":1752047473893,"results":"23","hashOfConfig":"15"},{"size":13225,"mtime":1752044908715,"results":"24","hashOfConfig":"15"},{"size":4886,"mtime":1751556546600,"results":"25","hashOfConfig":"15"},{"size":18677,"mtime":1751677918715,"results":"26","hashOfConfig":"15"},{"size":4836,"mtime":1750303858491,"results":"27","hashOfConfig":"15"},{"filePath":"28","messages":"29","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},"i331ru",{"filePath":"31","messages":"32","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"34","messages":"35","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},{"filePath":"36","messages":"37","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"38","messages":"39","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"40","messages":"41","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"44","messages":"45","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"46","messages":"47","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"50","messages":"51","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"52","messages":"53","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},{"filePath":"54","messages":"55","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"33"},"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\main.js",[],[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\App.vue",[],[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\router.js",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Home.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Register.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Game.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Login.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\UserProfile.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\ChatRoom.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Leaderboard.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Header.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\Admin.vue",[],"D:\\学习\\网络应用程序开发\\pdf\\goldminer\\frontend\\src\\components\\AdminSetup.vue",[]] \ No newline at end of file diff --git a/goldminer/frontend/src/components/ChatRoom.vue b/goldminer/frontend/src/components/ChatRoom.vue index a71dbfb5..aba7425e 100644 --- a/goldminer/frontend/src/components/ChatRoom.vue +++ b/goldminer/frontend/src/components/ChatRoom.vue @@ -310,14 +310,10 @@ export default { // 初始化Socket连接 const initSocketConnection = () => { - // 创建Socket连接 - const currentHost = window.location.hostname; - const url = `http://${currentHost}:5000`; - - // 使用轮询模式避免WebSocket连接问题 - socket = io(url, { + // 当不带URL调用时,它会默认连接到提供当前页面的服务器 + socket = io({ withCredentials: true, - transports: ['polling'], + // path选项对于Nginx反向代理很重要 path: '/socket.io' });