页面
- pages/meeting/create.vue:创建表单,标题(默认"{昵称}的会议"/40 字限制) + 密码(4-16 位)
+ 入会静音开关 + 允许聊天开关。提交时表单暂存到 store.draftCreatePayload,跳 preview 页
- pages/meeting/join.vue:会议号输入(9 位纯数字/带连字符均可,自动格式化 XXX-XXX-XXX)
+ 可选密码。支持 URL query code/password 回填(邀请链接一键入会入口)
- pages/meeting/preview.vue:设备预览页
- navigator.mediaDevices.enumerateDevices() 列出摄像头/麦克风/扬声器
- getUserMedia({video,audio}) 本地画面预览(用原生 <video> 避开 uni-input 对 srcObject 的限制)
- AudioContext.AnalyserNode 以 rAF 采样 RMS,渲染渐变音量条
- 显示名输入 + 入会默认开麦/开摄像头开关
- 权限被拒/浏览器不支持 WebRTC 时给清晰错误提示
- 离开页时释放 preview stream 与 AudioContext,避免占用摄像头
Store 扩展(meeting.js)
- 新增 state:draftCreatePayload(create→preview 暂存) + devicePreview(设备选择结果)
- createAndEnter(payload, mediaPrefs?) / joinAndEnter(code, password, mediaPrefs?) 新增
可选 mediaPrefs 参数:{ startAudio, startVideo, audioDeviceId, videoDeviceId }
- _afterJoined 内按 mediaPrefs 入会后自动 startLocalAudio/Video(失败仅告警不阻断)
- startLocalAudio/Video 支持可选 deviceId,映射到 getUserMedia 的 deviceId.exact 约束
路由
- pages.json 注册 create/join/preview 3 条路由(均非 TabBar 页,从 URL 或后续入口跳入)
临时占位
- preview 页加入成功后暂时 redirectTo 到 debug.vue(Task 11 room 页待落地时改为 /pages/meeting/room)
Playwright 验证(真实 macOS 设备)
- create → preview:表单 "新昵称的会议" 正确携带到 preview 页
- preview 页:FaceTime 摄像头 + MacBook Pro 麦克风枚举成功,video readyState=4,音量条工作正常
- 点"加入会议":createAndEnter 成功,debug 页显示 localState=connected,主持人=是
mediaPrefs 生效——麦克风/摄像头按钮显示"关闭麦克风/关闭摄像头"说明自动推流成功
- join 页:URL ?code=123-456-789&password=secret 正确预填,"下一步" 按钮启用
Made-with: Cursor
203 lines
3.9 KiB
JSON
203 lines
3.9 KiB
JSON
{
|
||
"easycom": {
|
||
"autoscan": true,
|
||
"custom": {
|
||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||
}
|
||
},
|
||
"pages": [
|
||
{
|
||
"path": "pages/index/index",
|
||
"style": {
|
||
"navigationBarTitleText": "EchoChat",
|
||
"navigationStyle": "custom"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/auth/login",
|
||
"style": {
|
||
"navigationBarTitleText": "登录"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/auth/register",
|
||
"style": {
|
||
"navigationBarTitleText": "注册"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/chat/index",
|
||
"style": {
|
||
"navigationBarTitleText": "消息"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/index",
|
||
"style": {
|
||
"navigationBarTitleText": "联系人",
|
||
"navigationStyle": "custom"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/request",
|
||
"style": {
|
||
"navigationBarTitleText": "好友申请"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/detail",
|
||
"style": {
|
||
"navigationBarTitleText": "好友详情"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/search",
|
||
"style": {
|
||
"navigationBarTitleText": "搜索好友"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/groups",
|
||
"style": {
|
||
"navigationBarTitleText": "好友分组"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/contact/blacklist",
|
||
"style": {
|
||
"navigationBarTitleText": "黑名单"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/chat/conversation",
|
||
"style": {
|
||
"navigationBarTitleText": "聊天",
|
||
"navigationStyle": "custom"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/chat/settings",
|
||
"style": {
|
||
"navigationBarTitleText": "聊天设置"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/chat/search",
|
||
"style": {
|
||
"navigationBarTitleText": "搜索消息"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/chat/read-detail",
|
||
"style": {
|
||
"navigationBarTitleText": "已读详情"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/conversation",
|
||
"style": {
|
||
"navigationBarTitleText": "群聊",
|
||
"navigationStyle": "custom"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/create",
|
||
"style": {
|
||
"navigationBarTitleText": "创建群聊"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/settings",
|
||
"style": {
|
||
"navigationBarTitleText": "群设置"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/members",
|
||
"style": {
|
||
"navigationBarTitleText": "群成员"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/invite",
|
||
"style": {
|
||
"navigationBarTitleText": "邀请入群"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/join-requests",
|
||
"style": {
|
||
"navigationBarTitleText": "入群申请"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/group/search",
|
||
"style": {
|
||
"navigationBarTitleText": "搜索群聊"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/meeting/index",
|
||
"style": {
|
||
"navigationBarTitleText": "会议"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/meeting/debug",
|
||
"style": {
|
||
"navigationBarTitleText": "会议调试(Task 9)"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/meeting/create",
|
||
"style": {
|
||
"navigationBarTitleText": "创建会议"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/meeting/join",
|
||
"style": {
|
||
"navigationBarTitleText": "加入会议"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/meeting/preview",
|
||
"style": {
|
||
"navigationBarTitleText": "设备预览"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/notify/index",
|
||
"style": {
|
||
"navigationBarTitleText": "通知中心",
|
||
"navigationStyle": "custom"
|
||
}
|
||
},
|
||
{
|
||
"path": "pages/profile/index",
|
||
"style": {
|
||
"navigationBarTitleText": "我的"
|
||
}
|
||
}
|
||
],
|
||
"tabBar": {
|
||
"custom": true,
|
||
"color": "#94A3B8",
|
||
"selectedColor": "#2563EB",
|
||
"backgroundColor": "#FFFFFF",
|
||
"borderStyle": "white",
|
||
"list": [
|
||
{ "pagePath": "pages/chat/index", "text": "消息" },
|
||
{ "pagePath": "pages/contact/index", "text": "联系人" },
|
||
{ "pagePath": "pages/meeting/index", "text": "会议" },
|
||
{ "pagePath": "pages/profile/index", "text": "我的" }
|
||
]
|
||
},
|
||
"globalStyle": {
|
||
"navigationBarTextStyle": "black",
|
||
"navigationBarTitleText": "EchoChat",
|
||
"navigationBarBackgroundColor": "#FFFFFF",
|
||
"backgroundColor": "#F8FAFC"
|
||
}
|
||
}
|