115 lines
4.7 KiB
Markdown
115 lines
4.7 KiB
Markdown
# QAFrame
|
||
|
||
QAFrame 是一个用于实现问答交互流程的容器控件,通常用于在线教育、测试或互动课程场景。它通过 WebSocket 与后端通信,接收题目、课件内容、答题结果等数据,并动态渲染对应的界面。该控件继承自 `bricks.VBox`,属于**容器控件**。
|
||
|
||
---
|
||
|
||
## 主要方法
|
||
|
||
| 方法名 | 描述 |
|
||
|-------|------|
|
||
| `start_question_answer()` | 向服务器发送 `'qa_start'` 消息,启动问答流程。绑定在开始按钮点击事件上。 |
|
||
| `show_question(d)` | 接收题目数据并显示,更新当前题号和总题数,将题目描述(HTML/文本)渲染到主区域。 |
|
||
| `show_courseware(d)` | 根据传入的数据类型(video/audio/image/markdown),创建对应媒体控件并展示在主区域。 |
|
||
| `show_conform(d)` | 显示确认开始的提示按钮,供用户点击确认后进入下一阶段。 |
|
||
| `conform_start()` | 发送 `'conform_start'` 消息至 WebSocket,表示用户已确认准备就绪。 |
|
||
| `send_text_answer(e)` | 处理文本答案提交,从事件中提取文本内容并通过 WebSocket 发送给服务端。 |
|
||
| `send_audio_answer(e)` | 将录音 Blob 转为 Base64 编码,并以 `'audio_answer'` 类型发送给服务端。 |
|
||
| `build_input_widgets()` | 构建输入控件:文本输入框和语音录制按钮,添加到底部工具栏。 |
|
||
| `play_course()` | 根据配置的 courseware 类型播放课件内容(视频、音频、图片或 Markdown)。 |
|
||
|
||
---
|
||
|
||
## 主要事件
|
||
|
||
| 事件名 | 触发时机 | 数据格式示例 |
|
||
|--------|---------|-------------|
|
||
| `onopen` (WebSocket) | WebSocket 连接建立时 | 自动触发 `start_question_answer()` |
|
||
| `onquestion` | 收到新题目消息时 | `{ type: "question", data: { q_desc: "...", total_q: 5, cur_q: 1 } }` |
|
||
| `oncourseware` | 收到课件推送时 | `{ type: "video", url: "/video/1.mp4" }` |
|
||
| `onaskstart` | 服务端要求用户确认是否准备好时 | 显示“Start?”按钮等待点击 |
|
||
| `record_ended` (AudioRecorder) | 用户完成录音时 | 触发 `send_audio_answer()` 发送音频数据 |
|
||
| `blur` (文本输入框) | 文本输入失去焦点时 | 触发 `send_text_answer()` 发送答案 |
|
||
|
||
---
|
||
|
||
## 源码例子
|
||
|
||
```json
|
||
{
|
||
"id": "qa_frame_main",
|
||
"widgettype": "QAFrame",
|
||
"options": {
|
||
// WebSocket 地址,用于实时通信
|
||
"ws_url": "wss://example.com/ws/qa-session",
|
||
|
||
// 可选参数,附加到 ws_url 后作为查询字符串
|
||
"ws_params": {
|
||
"session_id": "12345",
|
||
"user_id": "U001"
|
||
},
|
||
|
||
// 页面标题(可选)
|
||
"title": "智能问答练习",
|
||
|
||
// 描述信息(可选)
|
||
"description": "请认真作答每一道问题。",
|
||
|
||
// 初始课件配置(可选),支持多种类型
|
||
"courseware": {
|
||
"type": "markdown", // 支持 "audio", "video", "image", "markdown"
|
||
"url": "/static/intro.md", // 内容资源地址
|
||
"timeout": 10 // 展示超时时间(秒),0 表示无超时
|
||
},
|
||
|
||
// 其他 UI 配置项(如有)
|
||
"cheight": 6 // 占据高度(基于网格布局)
|
||
},
|
||
|
||
// 子控件(此控件自身是容器,但一般不手动添加 subwidgets)
|
||
// 实际子组件由内部逻辑动态生成(如 main_w、top_w 等)
|
||
"subwidgets": [],
|
||
|
||
// 绑定事件:例如外部触发重新开始
|
||
"binds": [
|
||
{
|
||
"actiontype": "method",
|
||
"wid": "btn_restart",
|
||
"event": "click",
|
||
"target": "qa_frame_main",
|
||
"method": "start_question_answer",
|
||
"conform": {
|
||
"title": "确认重启?",
|
||
"message": "你确定要重新开始本次问答吗?",
|
||
"confirm_label": "确定",
|
||
"cancel_label": "取消"
|
||
}
|
||
},
|
||
{
|
||
"actiontype": "script",
|
||
"wid": "qa_frame_main",
|
||
"event": "onquestion",
|
||
"target": "console_logger",
|
||
"script": "console.log('New question received:', params.q_desc);",
|
||
"params": {
|
||
"q_desc": "{data.q_desc}"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> ✅ **注释说明:**
|
||
> - `ws_url` 必须为有效的 WebSocket 地址(`ws://` 或 `wss://`)。
|
||
> - `ws_params` 中的参数会自动拼接到连接 URL 上,便于身份验证或会话追踪。
|
||
> - `courseware` 字段定义初始加载的内容,可在连接后由服务端消息覆盖。
|
||
> - 所有 UI 更新均由 WebSocket 推送驱动,无需手动操作 DOM。
|
||
> - 使用 `binds` 可扩展与其他控件的交互行为,如日志记录、弹窗提醒等。
|
||
|
||
---
|
||
|
||
💡 **使用建议:**
|
||
|
||
- 配合后台使用 Node.js / Python WebSocket 服务实现题库推送与评分逻辑。
|
||
- 在移动端注意音频录制权限处理。
|
||
- 可结合 `Popup` 控件实现更复杂的交互确认流程。 |