feat: 调整UI/RTC逻辑

This commit is contained in:
MatrixSeven
2025-08-04 21:35:50 +08:00
parent 324408f6b2
commit ef02e88ee9
22 changed files with 1042 additions and 285 deletions

View File

@@ -279,3 +279,52 @@ func (h *Handler) RoomInfoHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(response)
}
// WebRTCRoomStatusHandler 获取WebRTC房间状态API
func (h *Handler) WebRTCRoomStatusHandler(w http.ResponseWriter, r *http.Request) {
// 设置响应为JSON格式
w.Header().Set("Content-Type", "application/json")
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "方法不允许",
})
return
}
code := r.URL.Query().Get("code")
if code == "" || len(code) != 6 {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "请提供正确的6位房间码",
})
return
}
// 获取WebRTC房间状态
status := h.webrtcService.GetRoomStatus(code)
if !status["exists"].(bool) {
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]interface{}{
"success": false,
"message": "房间不存在",
})
return
}
// 构建响应
response := map[string]interface{}{
"success": true,
"message": "房间状态获取成功",
"exists": status["exists"],
"sender_online": status["sender_online"],
"receiver_online": status["receiver_online"],
"created_at": status["created_at"],
}
json.NewEncoder(w).Encode(response)
}

View File

@@ -53,6 +53,8 @@ type WebRTCMessage struct {
// HandleWebSocket 处理WebRTC信令WebSocket连接
func (ws *WebRTCService) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
log.Printf("收到WebRTC WebSocket连接请求: %s", r.URL.String())
conn, err := ws.upgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("WebRTC WebSocket升级失败: %v", err)
@@ -64,6 +66,8 @@ func (ws *WebRTCService) HandleWebSocket(w http.ResponseWriter, r *http.Request)
code := r.URL.Query().Get("code")
role := r.URL.Query().Get("role")
log.Printf("WebRTC连接参数: code=%s, role=%s", code, role)
if code == "" || (role != "sender" && role != "receiver") {
log.Printf("WebRTC连接参数无效: code=%s, role=%s", code, role)
return
@@ -78,6 +82,8 @@ func (ws *WebRTCService) HandleWebSocket(w http.ResponseWriter, r *http.Request)
Room: code,
}
log.Printf("WebRTC客户端已创建: ID=%s, Role=%s, Room=%s", clientID, role, code)
// 添加客户端到房间
ws.addClientToRoom(code, client)
log.Printf("WebRTC %s连接到房间: %s (客户端ID: %s)", role, code, clientID)
@@ -86,6 +92,9 @@ func (ws *WebRTCService) HandleWebSocket(w http.ResponseWriter, r *http.Request)
defer func() {
ws.removeClientFromRoom(code, clientID)
log.Printf("WebRTC客户端断开连接: %s (房间: %s)", clientID, code)
// 通知房间内其他客户端对方已断开连接
ws.notifyRoomDisconnection(code, clientID, client.Role)
}()
// 处理消息
@@ -201,7 +210,45 @@ func (ws *WebRTCService) generateClientID() string {
return fmt.Sprintf("webrtc_client_%d", rand.Int63())
}
// 获取房间状态
// 通知房间内客户端有人断开连接
func (ws *WebRTCService) notifyRoomDisconnection(roomCode string, disconnectedClientID string, disconnectedRole string) {
ws.roomsMux.Lock()
defer ws.roomsMux.Unlock()
room := ws.rooms[roomCode]
if room == nil {
return
}
// 构建断开连接通知消息
disconnectionMsg := &WebRTCMessage{
Type: "disconnection",
From: disconnectedClientID,
Payload: map[string]interface{}{
"role": disconnectedRole,
"message": "对方已停止传输",
},
}
// 通知房间内其他客户端
if room.Sender != nil && room.Sender.ID != disconnectedClientID {
err := room.Sender.Connection.WriteJSON(disconnectionMsg)
if err != nil {
log.Printf("通知发送方断开连接失败: %v", err)
} else {
log.Printf("已通知发送方: 对方已断开连接")
}
}
if room.Receiver != nil && room.Receiver.ID != disconnectedClientID {
err := room.Receiver.Connection.WriteJSON(disconnectionMsg)
if err != nil {
log.Printf("通知接收方断开连接失败: %v", err)
} else {
log.Printf("已通知接收方: 对方已断开连接")
}
}
}
func (ws *WebRTCService) GetRoomStatus(code string) map[string]interface{} {
ws.roomsMux.RLock()
defer ws.roomsMux.RUnlock()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
2:I[6801,["177","static/chunks/app/layout-d0f2a5cbcfca20f5.js"],"ToastProvider"]
3:I[7555,[],""]
4:I[1295,[],""]
5:I[1287,["423","static/chunks/423-3db9dd818e8fd852.js","974","static/chunks/app/page-6f704b6eb3095813.js"],"default"]
5:I[7443,["423","static/chunks/423-3db9dd818e8fd852.js","974","static/chunks/app/page-c710cf440dafbd05.js"],"default"]
6:I[9665,[],"OutletBoundary"]
8:I[4911,[],"AsyncMetadataOutlet"]
a:I[9665,[],"ViewportBoundary"]
@@ -12,7 +12,7 @@ f:I[8393,[],""]
:HL["/_next/static/media/569ce4b8f30dc480-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
:HL["/_next/static/media/93f479601ee12b01-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
:HL["/_next/static/css/f6f47fde0030ec04.css","style"]
0:{"P":null,"b":"8bbWAyBmnmNj0Jk5ryXl4","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f6f47fde0030ec04.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"zh-CN","children":["$","body",null,{"className":"__variable_5cfdac __variable_9a8899 antialiased","children":["$","$L2",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$L5",null,{}],null,["$","$L6",null,{"children":["$L7",["$","$L8",null,{"promise":"$@9"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$La",null,{"children":"$Lb"}],["$","meta",null,{"name":"next-size-adjust","content":""}]],["$","$Lc",null,{"children":["$","div",null,{"hidden":true,"children":["$","$d",null,{"fallback":null,"children":"$Le"}]}]}]]}],false]],"m":"$undefined","G":["$f",[]],"s":false,"S":true}
0:{"P":null,"b":"8y8TXPJV_4IIplGqW3zUm","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f6f47fde0030ec04.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"zh-CN","children":["$","body",null,{"className":"__variable_5cfdac __variable_9a8899 antialiased","children":["$","$L2",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$L5",null,{}],null,["$","$L6",null,{"children":["$L7",["$","$L8",null,{"promise":"$@9"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$La",null,{"children":"$Lb"}],["$","meta",null,{"name":"next-size-adjust","content":""}]],["$","$Lc",null,{"children":["$","div",null,{"hidden":true,"children":["$","$d",null,{"fallback":null,"children":"$Le"}]}]}]]}],false]],"m":"$undefined","G":["$f",[]],"s":false,"S":true}
b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
7:null
10:I[8175,[],"IconMark"]