feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View File

@@ -0,0 +1,296 @@
# 播课功能技术方案
## 一、需求背景
课程管理员需要为课程生成播课音频,学员可以在课程卡片上点击"播课"按钮收听课程内容,支持音频播放控制。
## 二、核心设计
### 2.1 触发方式
- **管理员手动触发**:在课程编辑页的"学习资料与知识点"选项卡,点击"生成播课"按钮
- **生成范围**:一个课程生成一个综合播课音频(多个资料合并生成)
- **存储方式**:只存储 mp3 URL不存储在本地服务器
### 2.2 技术选型
| 技术项 | 选型 | 说明 |
|--------|------|------|
| AI 工作流 | Coze 工作流 | workflow_id: 7561161554420482088 |
| SDK | cozepy 0.2.0 | 已安装,与陪练功能共用 |
| 认证方式 | Personal Access Token | 与陪练功能共用 token |
| 数据库字段 | `broadcast_audio_url` | 存储 mp3 URL |
| 前端播放器 | HTML5 audio | 原生支持,无需额外依赖 |
### 2.3 数据流程
```
管理员点击"生成播课"
→ 前端调用后端 API
→ 后端调用 Coze 工作流
→ Coze 生成 mp3 音频
→ 返回 mp3 URL
→ 后端保存到数据库
→ 前端显示成功提示
学员点击"播课"
→ 前端查询播课信息
→ 跳转到播放页面
→ 加载并播放音频
```
## 三、数据库设计
### 3.1 courses 表新增字段
```sql
ALTER TABLE courses
ADD COLUMN broadcast_audio_url VARCHAR(500) NULL COMMENT '播课音频URL',
ADD COLUMN broadcast_generated_at DATETIME NULL COMMENT '播课生成时间';
```
**字段说明**
- `broadcast_audio_url`: 存储 Coze 工作流返回的 mp3 文件 URL
- `broadcast_generated_at`: 记录生成时间,用于判断是否需要重新生成
**索引**: 无需额外索引(查询通过主键 course_id
## 四、后端架构
### 4.1 配置层
**文件**: `app/core/config.py`
```python
class Settings(BaseSettings):
# 播课工作流配置
COZE_BROADCAST_WORKFLOW_ID: str = Field(default="7561161554420482088")
COZE_BROADCAST_SPACE_ID: str = Field(default="7474971491470688296")
```
### 4.2 服务层
**文件**: `app/services/coze_broadcast_service.py`
**职责**
- 封装 Coze 工作流调用逻辑
- 解析返回的 mp3 URL
- 错误处理和日志记录
**关键方法**
```python
class CozeBroadcastService:
async def generate_broadcast(self, course_id: int) -> str:
"""
调用 Coze 工作流生成播课音频
Args:
course_id: 课程ID
Returns:
mp3 音频文件 URL
Raises:
CozeError: Coze API 调用失败
ValueError: 返回结果解析失败
"""
```
### 4.3 API 层
**文件**: `app/api/v1/broadcast.py`
**接口1**: 生成播课
- 路径: `POST /api/v1/courses/{course_id}/generate-broadcast`
- 权限: manager, admin
- 超时: 180秒
- 功能: 调用工作流生成音频,更新数据库
**接口2**: 获取播课信息
- 路径: `GET /api/v1/courses/{course_id}/broadcast`
- 权限: trainee, manager, admin
- 功能: 查询课程是否有播课以及播课 URL
### 4.4 Schema 定义
```python
class GenerateBroadcastResponse(BaseModel):
"""生成播课响应"""
mp3_url: str = Field(..., description="播课音频URL")
generated_at: datetime = Field(..., description="生成时间")
class BroadcastInfo(BaseModel):
"""播课信息"""
has_broadcast: bool = Field(..., description="是否有播课")
mp3_url: Optional[str] = Field(None, description="播课音频URL")
generated_at: Optional[datetime] = Field(None, description="生成时间")
```
## 五、前端架构
### 5.1 类型定义
**文件**: `src/types/broadcast.ts`
```typescript
export interface BroadcastInfo {
has_broadcast: boolean
mp3_url?: string
generated_at?: string
}
export interface GenerateBroadcastResponse {
mp3_url: string
generated_at: string
}
```
### 5.2 API 封装
**文件**: `src/api/broadcast.ts`
```typescript
export const broadcastApi = {
generate(courseId: number): Promise<ResponseData<GenerateBroadcastResponse>>
getInfo(courseId: number): Promise<ResponseData<BroadcastInfo>>
}
```
### 5.3 页面改造
**1. 课程编辑页** (`src/views/manager/edit-course.vue`)
新增功能:
- 在"学习资料与知识点"选项卡添加"生成播课"按钮
- 查询并显示播课信息(是否已生成、生成时间)
- 生成中显示 Loading 状态
- 生成成功后显示"重新生成"按钮
**2. 播放页面** (`src/views/trainee/broadcast-course.vue`)
播放器功能:
- 播放/暂停控制
- 进度条拖动
- 当前时间/总时长显示
- 播放速度调节1.0x, 1.25x, 1.5x, 2.0x
**3. 课程卡片** (`src/views/trainee/course-center.vue`)
修改播课按钮点击事件:
- 查询播课信息
- 如无播课,提示"该课程暂无播课内容"
- 如有播课,跳转到播放页面
## 六、交互流程
### 6.1 生成播课流程
```
1. 管理员进入课程编辑页
2. 切换到"学习资料与知识点"选项卡
3. 点击"生成播课"按钮
4. 前端调用 POST /api/v1/courses/{id}/generate-broadcast
5. 后端调用 Coze 工作流约10分钟
6. Coze 返回 mp3 URL
7. 后端更新数据库 broadcast_audio_url 和 broadcast_generated_at
8. 前端显示"生成成功"提示
9. 按钮文本变为"重新生成",显示生成时间
```
### 6.2 播放流程
```
1. 学员在课程中心查看课程卡片
2. 点击"播课"按钮
3. 前端调用 GET /api/v1/courses/{id}/broadcast
4. 如 has_broadcast=false显示"暂无播课内容"
5. 如 has_broadcast=true跳转到播放页面
6. 播放页面加载 mp3 音频
7. 学员使用播放器控制播放
```
## 七、性能与安全
### 7.1 性能优化
- **超时配置**: 前后端统一设置 180 秒超时
- **缓存策略**: 音频 URL 从数据库读取,无需额外缓存
- **CDN 加速**: mp3 文件由 Coze 托管,自带 CDN 加速
### 7.2 错误处理
| 场景 | 处理方式 |
|------|---------|
| 工作流调用超时 | 提示"生成超时,请稍后重试" |
| 工作流执行失败 | 记录 logid提示"生成失败,请联系管理员" |
| mp3 URL 解析失败 | 记录错误日志,提示"结果解析失败" |
| 播放加载失败 | 提示"音频加载失败,请检查网络" |
### 7.3 日志记录
```python
# 生成开始
logger.info(f"开始生成播课: course_id={course_id}, user_id={user_id}")
# 生成成功
logger.info(f"播课生成成功: course_id={course_id}, mp3_url={mp3_url}, duration={duration}")
# 生成失败
logger.error(
f"播课生成失败: course_id={course_id}",
extra={"logid": logid, "error": str(error)}
)
```
## 八、测试策略
### 8.1 单元测试
- CozeBroadcastService 工作流调用测试
- broadcast API 接口测试
- 前端 broadcastApi 封装测试
### 8.2 集成测试
- 管理员生成播课端到端测试
- 学员播放端到端测试
- 错误场景测试(无播课、生成失败、播放失败)
### 8.3 性能测试
- 工作流调用耗时(预期 10 分钟左右)
- 前端音频加载时间
- 并发生成请求测试
## 九、部署与监控
### 9.1 配置检查
部署前确认以下配置:
- ✅ COZE_API_TOKEN 正确配置
- ✅ COZE_BROADCAST_WORKFLOW_ID = 7561161554420482088
- ✅ COZE_BROADCAST_SPACE_ID = 7474971491470688296
- ✅ 工作流已在 Coze 平台发布
### 9.2 监控指标
- 生成成功率(目标 >95%
- 平均生成时长(预期 10 分钟)
- 播放失败率(目标 <5%
- Coze API 调用错误率
## 十、后续优化方向
1. **自动生成**:资料上传后自动触发生成(需评估资源消耗)
2. **进度提示**:显示生成进度(需 Coze 工作流支持进度回调)
3. **音频预览**:生成后在编辑页预览播放
4. **历史版本**:保存多个版本的播课音频
5. **字幕支持**:工作流返回字幕文件,前端同步显示
---
**文档版本**: v1.0
**创建日期**: 2025-10-14
**维护人**: 考培练系统开发团队