优化目录结构
This commit is contained in:
458
client/public/docs/code-structure.md
Normal file
458
client/public/docs/code-structure.md
Normal file
@@ -0,0 +1,458 @@
|
||||
# onebyone 模块代码调用结构图
|
||||
|
||||
> 本文档基于优化后的代码自动生成,反映当前实际架构。
|
||||
|
||||
---
|
||||
|
||||
## 3.1 文件依赖关系图
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
main[main.js] --> store[store.js]
|
||||
main --> renderer[renderer.js]
|
||||
main --> utils[utils.js]
|
||||
main --> chatmsg[chatmessage.js]
|
||||
|
||||
store --> models[models.js]
|
||||
store --> utils
|
||||
store --> chatmsg
|
||||
store --> signaling[../../module/signaling.js]
|
||||
store --> rs[../../module/renderstreaming.js]
|
||||
store --> config[../js/config.js]
|
||||
|
||||
renderer --> utils
|
||||
renderer --> models
|
||||
renderer --> chatmsg
|
||||
renderer -.-> store
|
||||
|
||||
chatmsg --> utils
|
||||
chatmsg --> store
|
||||
chatmsg --> models
|
||||
|
||||
connect[connect/connect.js] --> store
|
||||
connect --> utils
|
||||
|
||||
endcall[endcall/endcall.js] --> utils
|
||||
|
||||
index[index.html] --> main
|
||||
connectHtml[connect/connect.html] --> connect
|
||||
endcallHtml[endcall/endcall.html] --> endcall
|
||||
|
||||
style utils fill:#e1f5fe
|
||||
style models fill:#e1f5fe
|
||||
style signaling fill:#fff3e0
|
||||
style rs fill:#fff3e0
|
||||
style config fill:#fff3e0
|
||||
```
|
||||
|
||||
**图例说明**
|
||||
- 蓝色:内部工具/数据模块
|
||||
- 橙色:外部依赖模块(signaling.js、renderstreaming.js、config.js)
|
||||
|
||||
---
|
||||
|
||||
## 3.2 核心调用链
|
||||
|
||||
### 通话初始化流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Browser
|
||||
participant main as main.js
|
||||
participant store as store.js
|
||||
participant render as renderer.js
|
||||
participant RS as RenderStreaming
|
||||
participant Sig as Signaling
|
||||
|
||||
Browser->>main: DOMContentLoaded
|
||||
main->>main: 检查 localStorage.connectionId
|
||||
alt 无连接ID
|
||||
main->>Browser: 跳转 connect/connect.html
|
||||
else 有连接ID
|
||||
main->>render: new UIRenderer(store)
|
||||
render->>store: subscribe(render)
|
||||
main->>store: joinCall(connectionId)
|
||||
store->>store: init()
|
||||
store->>store: setupConfig() / getServerConfig()
|
||||
store->>store: loadUserSettings()
|
||||
store->>store: getLocalStream()
|
||||
store->>Browser: getUserMedia(MEDIA_CONSTRAINTS)
|
||||
Browser-->>store: MediaStream
|
||||
store->>store: notify(LOCAL_STREAM_OBTAINED)
|
||||
store->>store: notify(LOCAL_MEDIA_CHANGE x2)
|
||||
store->>store: emitMediaStateChange()
|
||||
main->>store: setUp(connectionId)
|
||||
store->>store: _createSignalingAndRTC()
|
||||
store->>Sig: new WebSocketSignaling() / new Signaling()
|
||||
store->>RS: new RenderStreaming(signaling, config)
|
||||
store->>store: _registerCallbacks()
|
||||
store->>store: _startConnection()
|
||||
store->>RS: start()
|
||||
store->>RS: createConnection(connectionId)
|
||||
RS-->>store: onConnect(role, participantId)
|
||||
store->>store: notify(CALL_STATUS_CHANGE, ongoing)
|
||||
store->>store: sendMessage(user-info)
|
||||
store->>store: emitMediaStateChange()
|
||||
main->>main: bindDomEvents()
|
||||
end
|
||||
```
|
||||
|
||||
### 媒体控制流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User
|
||||
participant main as main.js
|
||||
participant store as store.js
|
||||
participant render as renderer.js
|
||||
participant RS as RenderStreaming
|
||||
participant Remote as 远端
|
||||
|
||||
User->>main: 点击 toggleMute / toggleVideo
|
||||
main->>store: updateLocalMedia(type, value)
|
||||
|
||||
alt 开启视频
|
||||
store->>Browser: getUserMedia(VIDEO_ONLY_CONSTRAINT)
|
||||
Browser-->>store: newVideoTrack
|
||||
store->>RS: replaceTrack / addTransceiver
|
||||
store->>store: notify(LOCAL_STREAM_OBTAINED)
|
||||
store->>store: notify(LOCAL_MEDIA_CHANGE, video=true)
|
||||
store->>store: emitMediaStateChange()
|
||||
else 关闭视频
|
||||
store->>store: track.stop()
|
||||
store->>store: notify(LOCAL_MEDIA_CHANGE, video=false)
|
||||
store->>store: emitMediaStateChange()
|
||||
else 切换音频
|
||||
store->>store: track.enabled = value
|
||||
store->>store: notify(LOCAL_MEDIA_CHANGE, audio=value)
|
||||
store->>store: emitMediaStateChange()
|
||||
end
|
||||
|
||||
store->>render: notify(USER_LIST_UPDATE)
|
||||
render->>render: renderUserList()
|
||||
render->>render: renderControlButtons()
|
||||
render->>render: renderLocalVideo()
|
||||
|
||||
store->>RS: sendMessage(media-state-changed)
|
||||
RS->>Remote: WebSocket 信令
|
||||
Remote-->>store: onMessage(media-state-changed)
|
||||
store->>store: updateRemoteMedia()
|
||||
store->>render: notify(REMOTE_MEDIA_CHANGE)
|
||||
render->>render: renderRemoteVideo()
|
||||
render->>render: renderUserList()
|
||||
render->>render: renderParticipantVideoPlaceholder()
|
||||
```
|
||||
|
||||
### 消息发送流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User
|
||||
participant chat as chatmessage.js
|
||||
participant store as store.js
|
||||
participant render as renderer.js
|
||||
participant RS as RenderStreaming
|
||||
participant Remote as 远端
|
||||
|
||||
User->>chat: 输入消息 / 回车
|
||||
chat->>chat: sendMessage()
|
||||
chat->>chat: addMessage() 本地
|
||||
chat->>chat: notify(NEW_MESSAGE)
|
||||
render->>render: renderMessageState(NEW_MESSAGE)
|
||||
render->>render: renderChatMessages()
|
||||
render->>render: renderUnreadCount()
|
||||
|
||||
chat->>store: getRenderStreaming()
|
||||
chat->>RS: sendMessage(chat-message)
|
||||
RS->>Remote: WebSocket 信令
|
||||
|
||||
Remote-->>chat: handleChatMessage(data)
|
||||
chat->>chat: addMessage() 远端
|
||||
chat->>chat: notify(NEW_MESSAGE)
|
||||
render->>render: renderMessageState(NEW_MESSAGE)
|
||||
render->>render: renderChatMessages()
|
||||
render->>render: renderUnreadCount()
|
||||
|
||||
User->>chat: 点击 toggleSidebar()
|
||||
chat->>chat: notify(SIDEBAR_TOGGLE)
|
||||
render->>render: renderMessageState(SIDEBAR_TOGGLE)
|
||||
render->>render: renderSidebar()
|
||||
```
|
||||
|
||||
### Participant 管理流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant store as store.js
|
||||
participant render as renderer.js
|
||||
participant RS as RenderStreaming
|
||||
participant Remote as 远端Participant
|
||||
|
||||
Note over RS,Remote: 新 Participant 加入
|
||||
RS-->>store: onParticipantJoined(participantId)
|
||||
store->>store: 初始化 participant 默认信息
|
||||
store->>store: notify(PARTICIPANTS_UPDATE)
|
||||
store->>RS: broadcastParticipantsList()
|
||||
render->>render: renderUserList()
|
||||
render->>render: syncParticipantTileNames()
|
||||
|
||||
Note over RS,Remote: Participant 离开
|
||||
RS-->>store: onParticipantLeft(participantId)
|
||||
store->>store: 清理 remoteStreams / participants
|
||||
store->>store: notify(PARTICIPANT_LEFT)
|
||||
store->>store: notify(PARTICIPANTS_UPDATE)
|
||||
store->>RS: broadcastParticipantsList()
|
||||
render->>render: renderParticipantLeft()
|
||||
render->>render: renderUserList()
|
||||
|
||||
Note over RS,Remote: 成员列表同步
|
||||
RS-->>store: onMessage(participants-sync)
|
||||
store->>store: 过滤自身条目 -> state.participants
|
||||
store->>store: notify(PARTICIPANTS_UPDATE)
|
||||
render->>render: renderUserList()
|
||||
render->>render: syncParticipantTileNames()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.3 状态变化流转图
|
||||
|
||||
### Store -> Renderer 状态流转
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph StoreNotify[store.js notify 类型]
|
||||
A[INIT]
|
||||
B[LOCAL_STREAM_OBTAINED]
|
||||
C[LOCAL_MEDIA_CHANGE]
|
||||
D[REMOTE_STREAM_OBTAINED]
|
||||
E[REMOTE_MEDIA_CHANGE]
|
||||
F[USER_LIST_UPDATE]
|
||||
G[PARTICIPANTS_UPDATE]
|
||||
H[NETWORK_CHANGE]
|
||||
I[CALL_STATUS_CHANGE]
|
||||
J[CALL_ENDED]
|
||||
K[PARTICIPANT_LEFT]
|
||||
L[DURATION_UPDATE]
|
||||
end
|
||||
|
||||
subgraph RenderMethod[renderer.js 渲染方法]
|
||||
RM1[renderRemoteVideo]
|
||||
RM2[renderLocalVideo]
|
||||
RM3[renderLocalStream]
|
||||
RM4[renderRemoteStream]
|
||||
RM5[renderControlButtons]
|
||||
RM6[renderUserList]
|
||||
RM7[renderNetworkStatus]
|
||||
RM8[renderCallStatus]
|
||||
RM9[renderCallEnded]
|
||||
RM10[renderParticipantLeft]
|
||||
RM11[renderCallDuration]
|
||||
RM12[renderHeader]
|
||||
RM13[renderParticipantVideoPlaceholder]
|
||||
RM14[syncParticipantTileNames]
|
||||
end
|
||||
|
||||
A --> RM1 & RM2 & RM5 & RM6 & RM12
|
||||
B --> RM3 & RM2
|
||||
C --> RM5 & RM2 & RM6
|
||||
D --> RM4
|
||||
E --> RM1 & RM6 & RM13
|
||||
F --> RM6
|
||||
G --> RM6 & RM14
|
||||
H --> RM7
|
||||
I --> RM8
|
||||
J --> RM9
|
||||
K --> RM10
|
||||
L --> RM11
|
||||
```
|
||||
|
||||
### chatMessage -> Renderer 状态流转
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph ChatNotify[chatmessage.js notify 类型]
|
||||
N[NEW_MESSAGE]
|
||||
S[SIDEBAR_TOGGLE]
|
||||
end
|
||||
|
||||
subgraph MsgRender[renderer.js 消息渲染]
|
||||
MR1[renderChatMessages]
|
||||
MR2[renderUnreadCount]
|
||||
MR3[renderSidebar]
|
||||
end
|
||||
|
||||
N --> MR1 & MR2
|
||||
S --> MR3 & MR2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3.4 各模块导出函数清单
|
||||
|
||||
### main.js
|
||||
|
||||
| 导出 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| store | 变量 | 重新导出 store 单例,供外部调试使用 |
|
||||
|
||||
**内部全局函数(绑定到 window):**
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| toggleSidebar | 切换侧边栏显示 |
|
||||
| toggleMute | 切换麦克风状态 |
|
||||
| toggleVideo | 切换摄像头状态 |
|
||||
| toggleLocalVideo | 本地视频悬停控制 |
|
||||
| toggleRecording | 切换录屏状态 |
|
||||
| endCall | 显示结束通话确认对话框 |
|
||||
| cancelEndCall | 取消结束通话 |
|
||||
| confirmEndCall | 确认结束通话,调用 store.endCall() |
|
||||
| showCallRequest | 显示通话请求弹窗 |
|
||||
| rejectCall | 拒绝通话请求 |
|
||||
| acceptCall | 接受通话请求,初始化通话 |
|
||||
|
||||
### store.js (CallStateManager 类 / store 单例)
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| subscribe(callback) | 订阅状态变化 |
|
||||
| notify(changes) | 通知所有监听器 |
|
||||
| init() | 初始化配置、用户设置、本地流 |
|
||||
| loadUserSettings() | 从 localStorage 加载用户设置 |
|
||||
| setupConfig() | 获取服务器配置(WebSocket 模式) |
|
||||
| getLocalStream() | 获取本地摄像头媒体流 |
|
||||
| updateLocalMedia(mediaType, value) | 更新本地媒体状态(音频/视频/录屏) |
|
||||
| _createSignalingAndRTC(connectionId) | 创建信令和 RTC 实例 |
|
||||
| setUp(connectionId) | 设置 WebRTC 连接入口 |
|
||||
| _registerCallbacks() | 注册所有 WebRTC 回调 |
|
||||
| _startConnection(connectionId) | 启动连接和检测 |
|
||||
| hangUp() | 挂断连接,清理资源 |
|
||||
| sendMessage(type, data) | 通过 RenderStreaming 发送消息 |
|
||||
| broadcastParticipantsList() | Host 端广播成员列表 |
|
||||
| setCodecPreferences(participantId) | 设置 H264 编解码器偏好 |
|
||||
| updateRemoteMedia(mediaState, participantId) | 更新远端媒体状态 |
|
||||
| updateRemoteUserStatus(status) | 更新远端用户在线状态 |
|
||||
| updateRemoteUserNetworkQuality(q) | 更新远端网络质量 |
|
||||
| endCall() | 用户主动结束通话入口 |
|
||||
| joinCall(connectionId) | 加入通话 |
|
||||
| createCall() | 创建通话 |
|
||||
| detectNetworkQuality() | 基于 WebRTC stats 检测网络质量 |
|
||||
| startActivityDetection(stream, opts) | 启动音频活动检测(VAD) |
|
||||
| startNetworkQualityDetection() | 启动定时网络质量检测 |
|
||||
| stopNetworkQualityDetection() | 停止网络质量检测 |
|
||||
| emitMediaStateChange() | 发送媒体状态变化信令 |
|
||||
| showStatsMessage() | 显示并定时输出 WebRTC 统计信息 |
|
||||
| clearStatsMessage() | 清除统计定时器 |
|
||||
| getState / getLocalUser / getRemoteUser / getConnectionId / getRenderStreaming | Getter 方法 |
|
||||
|
||||
### renderer.js (UIRenderer 类)
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| constructor(stateManager) | 构造函数,订阅 store 和 chatMessage |
|
||||
| render(state, changes) | 核心渲染分发器,根据 changes.type 路由 |
|
||||
| renderMessageState(msgState, changes) | 消息状态渲染分发器 |
|
||||
| renderCallStatus(status) | 渲染通话状态(连接中覆盖层) |
|
||||
| renderHeader(session) | 渲染头部信息 |
|
||||
| renderHeaderTitle() | 渲染标题(含 connectionId) |
|
||||
| renderCallDuration(duration) | 渲染通话时长 |
|
||||
| renderRemoteVideo(remoteUser) | 渲染远端视频和占位符 |
|
||||
| renderHeaderNetworkStatus(q) | 渲染头部网络质量文本 |
|
||||
| renderLocalVideo(localUser, stream) | 渲染本地视频和占位符 |
|
||||
| renderLocalStream(stream) | 将本地流绑定到 video 元素 |
|
||||
| renderRemoteStream(stream, id, isHost) | 远端流渲染分发 |
|
||||
| renderParticipantStream(stream, id) | Host 端多 participant 视频网格渲染 |
|
||||
| renderParticipantVideoPlaceholder(id, show) | 精准更新 participant tile 占位背景 |
|
||||
| syncParticipantTileNames(participants) | 同步所有 tile 名称标签 |
|
||||
| updateParticipantTileName(id, name) | 更新指定 tile 名称 |
|
||||
| renderSingleRemoteStream(stream) | Participant 端单路远端视频渲染 |
|
||||
| renderLocalUserStatus(localUser) | 渲染本地用户媒体状态文本 |
|
||||
| renderUserList(local, remote, participants) | 渲染侧边栏用户列表(支持多 participant) |
|
||||
| createUserEntry(options) | 创建通用用户条目 DOM |
|
||||
| getVideoResolution(track) | 获取视频轨道分辨率 |
|
||||
| adjustVideoSize(video, resolution) | 调整视频元素尺寸 |
|
||||
| renderControlButtons(mediaState) | 渲染底部控制按钮状态 |
|
||||
| renderChatMessages(messages) | 渲染聊天消息列表 |
|
||||
| createMessageElement(message) | 创建单条消息 DOM |
|
||||
| renderUnreadCount(count) | 渲染未读消息角标 |
|
||||
| renderSidebar(isOpen) | 渲染侧边栏显隐 |
|
||||
| renderNetworkStatus(quality) | 渲染网络状态提示 |
|
||||
| updateHeaderNetworkIndicator(q) | 更新头部网络指示器颜色 |
|
||||
| renderCallEnded() | 渲染通话结束,跳转 endcall 页面 |
|
||||
| renderParticipantLeft(id) | 清理 participant tile |
|
||||
| getStatusText / getNetworkQualityText | 状态/质量文本映射 |
|
||||
| destroy() | 销毁,取消订阅 |
|
||||
|
||||
### chatmessage.js
|
||||
|
||||
| 导出函数 | 说明 |
|
||||
|----------|------|
|
||||
| subscribe(callback) | 订阅消息状态变化 |
|
||||
| addMessage(message) | 添加消息到列表 |
|
||||
| sendChatMessage(message) | 通过 RenderStreaming 发送聊天消息 |
|
||||
| handleChatMessage(data) | 处理接收到的聊天消息 |
|
||||
| toggleSidebar() | 切换侧边栏,重置未读数 |
|
||||
| getMessageState() | 获取当前消息状态 |
|
||||
| sendMessage() | 用户发送消息入口(文本) |
|
||||
| handleChatSubmit(event) | 回车发送处理 |
|
||||
| openImagePicker() | 打开图片选择器 |
|
||||
| handleImageUpload(event) | 处理图片上传(限制 5MB) |
|
||||
| sendImageMessage(url, fileName) | 发送图片消息 |
|
||||
| bindMessageEvents() | 绑定消息相关 DOM 事件到 window |
|
||||
|
||||
### utils.js
|
||||
|
||||
| 导出函数 | 说明 |
|
||||
|----------|------|
|
||||
| formatTime(seconds) | 格式化为 MM:SS |
|
||||
| formatTimestamp(timestamp) | 格式化为 HH:MM |
|
||||
| generateId() | 生成随机唯一 ID |
|
||||
| showNotification(message, duration) | 显示顶部通知 |
|
||||
| toggleElement(element, show) | 切换元素显隐(hidden 类) |
|
||||
| toggleButtonState(button, active) | 切换按钮图标状态 |
|
||||
|
||||
### models.js
|
||||
|
||||
| 导出 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| mockCallSession | 常量对象 | 默认通话会话数据结构(含 localUser / remoteUser) |
|
||||
| mockMessages | 常量数组 | 默认聊天消息数组(含系统消息) |
|
||||
|
||||
### connect/connect.js
|
||||
|
||||
| 全局函数 | 说明 |
|
||||
|----------|------|
|
||||
| joinCall() | 读取输入框 connectionId,保存并跳转 |
|
||||
| createCall() | 生成随机 connectionId,保存并跳转 |
|
||||
| getAllConnectionIds() | 从服务器获取所有连接 ID 列表 |
|
||||
| displayConnectionIds(ids) | 渲染连接 ID 列表到 DOM |
|
||||
| selectConnectionId(id) | 选择指定 ID 填充输入框 |
|
||||
| saveSettings() | 保存用户设置到 localStorage |
|
||||
| handleAvatarUpload(event) | 上传头像(限制 2MB) |
|
||||
| copyUserId() | 复制用户 ID 到剪贴板 |
|
||||
| toggleSettingsMenu() | 切换设置菜单显隐 |
|
||||
|
||||
### endcall/endcall.js
|
||||
|
||||
| 全局函数 | 说明 |
|
||||
|----------|------|
|
||||
| reconnectCall() | 重新连接,跳转 index.html |
|
||||
| leaveCall() | 清除 connectionId,跳转 connect.html |
|
||||
|
||||
---
|
||||
|
||||
## 附录:页面跳转关系
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
connect[connect/connect.html] -->|joinCall / createCall| index[index.html]
|
||||
index -->|endCall| endcall[endcall/endcall.html]
|
||||
endcall -->|reconnectCall| index
|
||||
endcall -->|leaveCall| connect
|
||||
index -->|无 connectionId| connect
|
||||
```
|
||||
Reference in New Issue
Block a user