|
|
@@ -23,8 +23,9 @@ High - 新功能实现,增强用户体验
|
|
|
6. 无障碍功能支持 - 键盘导航、屏幕阅读器兼容、色彩对比度符合WCAG 2.1 AA
|
|
|
7. 测试覆盖和性能验证 - 组件测试覆盖率>80%,响应延迟<2秒,动画流畅60fps
|
|
|
8. 实现Agora Token动态获取后端路由 - 提供安全的Token生成API,支持RTC和RTM两种类型
|
|
|
-9. 前端集成Token动态获取 - 组件自动从后端获取Token,避免硬编码敏感信息
|
|
|
-10. 安全认证集成 - Token路由集成现有JWT认证系统,确保只有授权用户可访问
|
|
|
+9. 前端集成Token和配置统一获取 - 组件自动从后端获取Token和配置常量,避免硬编码敏感信息
|
|
|
+10. 测试用例验证配置常量 - 所有测试用例验证API响应包含正确的配置常量字段
|
|
|
+11. 安全认证集成 - Token路由集成现有JWT认证系统,确保只有授权用户可访问
|
|
|
|
|
|
## Tasks / Subtasks
|
|
|
- [x] 创建Agora STT React组件 (AC: #1)
|
|
|
@@ -60,15 +61,22 @@ High - 新功能实现,增强用户体验
|
|
|
- [ ] 创建Agora Token生成服务模块
|
|
|
- [ ] 实现RTC Token生成路由(用于STT功能)
|
|
|
- [ ] 实现RTM Token生成路由(用于实时消息)
|
|
|
+ - [ ] 扩展Token API响应包含配置常量(appId、sttJoinUrl、sttWsUrl、defaultChannel)
|
|
|
- [ ] 集成现有JWT认证中间件
|
|
|
- [ ] 实现参数验证和错误处理
|
|
|
- [ ] 编写路由单元测试和集成测试
|
|
|
-- [ ] 前端集成Token动态获取 (AC: #9)
|
|
|
- - [ ] 修改前端组件使用动态Token获取
|
|
|
+- [ ] 前端集成Token和配置统一获取 (AC: #9)
|
|
|
+ - [ ] 修改前端组件移除getGlobalConfig依赖
|
|
|
+ - [ ] 实现统一获取Token和配置的函数
|
|
|
+ - [ ] 更新组件初始化流程使用API返回的配置常量
|
|
|
- [ ] 实现Token过期自动刷新机制
|
|
|
- - [ ] 更新前端配置管理
|
|
|
- - [ ] 测试Token获取和刷新流程
|
|
|
-- [ ] 安全认证集成 (AC: #10)
|
|
|
+ - [ ] 测试Token和配置获取流程
|
|
|
+- [ ] 更新测试用例验证配置常量 (AC: #10)
|
|
|
+ - [ ] 更新集成测试验证API响应包含配置常量字段
|
|
|
+ - [ ] 更新真实API测试验证配置常量值与环境变量一致
|
|
|
+ - [ ] 更新前端组件测试验证配置常量使用正确
|
|
|
+ - [ ] 更新E2E测试验证完整配置获取流程
|
|
|
+- [ ] 安全认证集成 (AC: #11)
|
|
|
- [ ] 验证Token路由的认证保护
|
|
|
- [ ] 测试权限控制机制
|
|
|
- [ ] 确保敏感配置安全存储
|
|
|
@@ -95,23 +103,19 @@ High - 新功能实现,增强用户体验
|
|
|
|
|
|
### Agora配置参数 [Source: docs/agora实时语音转录翻译参考文档.md]
|
|
|
```typescript
|
|
|
-// 前端配置 - 使用全局配置安全访问(通过服务器端注入)
|
|
|
-import { getGlobalConfig } from '@/client/utils/utils';
|
|
|
-
|
|
|
-const AGORA_CONFIG = {
|
|
|
- appId: getGlobalConfig('AGORA_APP_ID'),
|
|
|
- channel: getGlobalConfig('AGORA_CHANNEL') || '123',
|
|
|
- sttJoinUrl: getGlobalConfig('AGORA_STT_JOIN_URL') || 'https://api.agora.io/v7/rtm/stt/join',
|
|
|
- sttWsUrl: getGlobalConfig('AGORA_STT_WS_URL') || 'wss://api.agora.io/v7/rtm/stt/connect',
|
|
|
- tokenEndpoint: '/api/v1/agora/token' // 动态Token获取端点
|
|
|
-};
|
|
|
+// 前端配置 - 统一通过Token API返回,不再使用getGlobalConfig
|
|
|
+// Token API现在同时返回Token和配置常量
|
|
|
+const AGORA_TOKEN_ENDPOINT = '/api/v1/agora/token';
|
|
|
|
|
|
// 后端配置 - 使用环境变量安全存储
|
|
|
const AGORA_SERVER_CONFIG = {
|
|
|
appId: process.env.AGORA_APP_ID || '',
|
|
|
appSecret: process.env.AGORA_APP_SECRET || '',
|
|
|
tokenExpiry: parseInt(process.env.AGORA_TOKEN_EXPIRY || '3600'),
|
|
|
- primaryCert: process.env.AGORA_PRIMARY_CERT || ''
|
|
|
+ primaryCert: process.env.AGORA_PRIMARY_CERT || '',
|
|
|
+ sttJoinUrl: process.env.AGORA_STT_JOIN_URL || 'https://api.agora.io/v7/rtm/stt/join',
|
|
|
+ sttWsUrl: process.env.AGORA_STT_WS_URL || 'wss://api.agora.io/v7/rtm/stt/connect',
|
|
|
+ defaultChannel: process.env.AGORA_DEFAULT_CHANNEL || '123'
|
|
|
};
|
|
|
```
|
|
|
|
|
|
@@ -168,15 +172,15 @@ const AGORA_SERVER_CONFIG = {
|
|
|
- **动画规范**: 状态切换300ms ease-out,音频波形实时更新
|
|
|
|
|
|
### 前端组件Token集成详细说明 [Source: docs/agora实时语音转录翻译参考文档.md]
|
|
|
-前端组件需要修改以支持动态Token获取,主要变更包括:
|
|
|
+前端组件需要修改以支持统一通过Token API获取配置常量,主要变更包括:
|
|
|
|
|
|
-1. **移除硬编码Token配置**
|
|
|
- - 删除AGORA_CONFIG中的硬编码token字段
|
|
|
- - 添加tokenEndpoint配置指向后端API
|
|
|
+1. **移除getGlobalConfig依赖**
|
|
|
+ - 删除AGORA_CONFIG中的getGlobalConfig调用
|
|
|
+ - 配置常量统一通过Token API返回
|
|
|
|
|
|
-2. **实现Token获取函数**
|
|
|
+2. **实现配置和Token统一获取函数**
|
|
|
```typescript
|
|
|
-// 使用项目现有的API客户端配置获取Token
|
|
|
+// 使用项目现有的API客户端配置获取Token和配置
|
|
|
import { hc } from 'hono/client';
|
|
|
import type { AgoraRoutes } from '@/server/api'; // 需要创建AgoraRoutes类型
|
|
|
|
|
|
@@ -185,29 +189,40 @@ const agoraClient = hc<AgoraRoutes>('/', {
|
|
|
fetch: axiosFetch, // 使用项目现有的axiosFetch适配器
|
|
|
}).api.v1.agora;
|
|
|
|
|
|
-const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: string) => {
|
|
|
+const fetchAgoraConfigAndToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: string) => {
|
|
|
// 使用项目标准的API客户端调用方式
|
|
|
const response = await agoraClient.token.$get({
|
|
|
query: { type, channel, userId }
|
|
|
});
|
|
|
|
|
|
if (!response.ok) {
|
|
|
- throw new Error('Token获取失败');
|
|
|
+ throw new Error('Token和配置获取失败');
|
|
|
}
|
|
|
|
|
|
const data = await response.json();
|
|
|
- return data.data.token;
|
|
|
+
|
|
|
+ // 现在API返回包含Token和配置常量的完整响应
|
|
|
+ return {
|
|
|
+ token: data.data.token,
|
|
|
+ config: {
|
|
|
+ appId: data.data.appId,
|
|
|
+ sttJoinUrl: data.data.sttJoinUrl,
|
|
|
+ sttWsUrl: data.data.sttWsUrl,
|
|
|
+ defaultChannel: data.data.defaultChannel
|
|
|
+ }
|
|
|
+ };
|
|
|
};
|
|
|
```
|
|
|
|
|
|
3. **修改组件初始化流程**
|
|
|
- - 在加入频道前先获取Token
|
|
|
+ - 在加入频道前先获取Token和配置
|
|
|
+ - 使用API返回的配置常量替代getGlobalConfig
|
|
|
- 处理Token过期自动刷新
|
|
|
- 更新错误处理机制
|
|
|
|
|
|
-4. **Token刷新机制**
|
|
|
+4. **Token和配置刷新机制**
|
|
|
- 监听Token过期时间
|
|
|
- - 在过期前自动刷新Token
|
|
|
+ - 在过期前自动刷新Token和配置
|
|
|
- 处理刷新过程中的连接状态
|
|
|
|
|
|
### 安全考虑
|
|
|
@@ -234,17 +249,20 @@ const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: s
|
|
|
### 测试策略 [Source: docs/architecture/testing-strategy.md]
|
|
|
- **单元测试**: 组件逻辑和工具函数测试
|
|
|
- **集成测试**: WebSocket连接和音频流处理测试
|
|
|
+- **API集成测试**: Token API响应格式验证,包含配置常量
|
|
|
- **E2E测试**: 完整语音转文字流程测试
|
|
|
|
|
|
### 测试覆盖目标
|
|
|
- **组件功能**: 100%覆盖核心功能
|
|
|
- **错误处理**: 所有错误场景测试
|
|
|
+- **API响应格式**: 验证Token API返回的配置常量字段
|
|
|
- **性能基准**: 转录延迟和准确率验证
|
|
|
- **浏览器兼容性**: 主流浏览器测试
|
|
|
|
|
|
### 测试数据
|
|
|
- **模拟音频流**: 使用测试音频文件
|
|
|
- **模拟转录结果**: 预定义的转录文本
|
|
|
+- **API响应数据**: 包含Token和配置常量的完整响应
|
|
|
- **错误场景**: 网络异常、权限拒绝等
|
|
|
|
|
|
### 测试工具
|
|
|
@@ -260,27 +278,65 @@ const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: s
|
|
|
- **前端测试步骤**:
|
|
|
1. 导航到Agora STT功能页面
|
|
|
2. 验证组件初始状态(未连接、未录制)
|
|
|
- 3. 测试Token动态获取流程
|
|
|
- 4. 测试加入频道功能
|
|
|
- 5. 验证连接状态更新
|
|
|
- 6. 测试麦克风权限申请
|
|
|
- 7. 测试开始/停止录音功能
|
|
|
- 8. 验证转录结果显示
|
|
|
- 9. 测试离开频道功能
|
|
|
+ 3. 测试Token和配置统一获取流程
|
|
|
+ 4. 验证API返回的配置常量正确性
|
|
|
+ 5. 测试加入频道功能
|
|
|
+ 6. 验证连接状态更新
|
|
|
+ 7. 测试麦克风权限申请
|
|
|
+ 8. 测试开始/停止录音功能
|
|
|
+ 9. 验证转录结果显示
|
|
|
+ 10. 测试离开频道功能
|
|
|
- **后端测试步骤**:
|
|
|
1. 测试未认证用户访问Token API
|
|
|
2. 测试认证用户生成RTC Token
|
|
|
3. 测试认证用户生成RTM Token
|
|
|
4. 测试参数验证错误处理
|
|
|
5. 验证Token有效期和格式
|
|
|
+ 6. 验证API响应包含配置常量字段(appId、sttJoinUrl、sttWsUrl、defaultChannel)
|
|
|
+ 7. 验证配置常量值与后端环境变量一致
|
|
|
- **断言验证**:
|
|
|
- 组件各状态正确显示
|
|
|
- - Token获取和刷新流程正常
|
|
|
+ - Token和配置获取流程正常
|
|
|
+ - API响应包含完整的配置常量字段
|
|
|
+ - 配置常量值与后端环境变量匹配
|
|
|
- 按钮交互功能正常
|
|
|
- 转录结果正确展示
|
|
|
- 错误处理机制有效
|
|
|
- API认证保护正常工作
|
|
|
|
|
|
+### 测试用例示例:配置常量验证
|
|
|
+```typescript
|
|
|
+// 集成测试示例:验证Token API返回配置常量
|
|
|
+test('Token API返回配置常量', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtc', channel: 'test-channel' }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(200);
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ // 验证Token信息
|
|
|
+ expect(data).toHaveProperty('token');
|
|
|
+ expect(data).toHaveProperty('type');
|
|
|
+ expect(data).toHaveProperty('expiresAt');
|
|
|
+ expect(data).toHaveProperty('expiresIn');
|
|
|
+ expect(data).toHaveProperty('generatedAt');
|
|
|
+
|
|
|
+ // 验证配置常量字段
|
|
|
+ expect(data).toHaveProperty('appId');
|
|
|
+ expect(data).toHaveProperty('sttJoinUrl');
|
|
|
+ expect(data).toHaveProperty('sttWsUrl');
|
|
|
+ expect(data).toHaveProperty('defaultChannel');
|
|
|
+
|
|
|
+ // 验证配置常量值与后端环境变量一致
|
|
|
+ expect(data.appId).toBe(process.env.AGORA_APP_ID || '');
|
|
|
+ expect(data.sttJoinUrl).toBe(process.env.AGORA_STT_JOIN_URL || 'https://api.agora.io/v7/rtm/stt/join');
|
|
|
+ expect(data.sttWsUrl).toBe(process.env.AGORA_STT_WS_URL || 'wss://api.agora.io/v7/rtm/stt/connect');
|
|
|
+ expect(data.defaultChannel).toBe(process.env.AGORA_DEFAULT_CHANNEL || '123');
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
## Change Log
|
|
|
| Date | Version | Description | Author |
|
|
|
|------|---------|-------------|--------|
|
|
|
@@ -292,6 +348,7 @@ const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: s
|
|
|
| 2025-09-23 | 1.3 | 组件实现验证和代码修复,状态更新为Ready for Review | James (Dev) |
|
|
|
| 2025-09-23 | 1.4 | 发现缺少E2E测试文件,状态回退为In Development | Bob (SM) |
|
|
|
| 2025-09-23 | 1.5 | 补充Token动态获取后端路由和前端集成需求 | Bob (SM) |
|
|
|
+| 2025-09-23 | 1.6 | 优化:Agora前端常量统一通过Token API返回,便于调试和统一管理 | Bob (SM) |
|
|
|
|
|
|
## Dev Agent Record
|
|
|
|
|
|
@@ -302,7 +359,8 @@ const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: s
|
|
|
- 组件已存在并完整实现,无需重新开发
|
|
|
- 已验证功能完整性、无障碍功能和响应式设计
|
|
|
- 已修复代码检查问题(console语句和未使用变量)
|
|
|
-- 需要修改前端组件以支持动态Token获取
|
|
|
+- 需要修改前端组件以支持统一通过Token API获取配置常量
|
|
|
+- Token API需要扩展以返回配置常量(appId、sttJoinUrl、sttWsUrl、defaultChannel)
|
|
|
|
|
|
### Completion Notes List
|
|
|
- ✅ Agora STT组件已完整实现并符合所有验收标准
|
|
|
@@ -314,8 +372,8 @@ const fetchAgoraToken = async (type: 'rtc' | 'rtm', channel?: string, userId?: s
|
|
|
- ✅ 组件测试已通过(8个测试用例全部通过)
|
|
|
- ✅ 代码检查已通过(修复了console语句和未使用变量)
|
|
|
- ⚠️ E2E测试文件待创建 - 需要创建完整的端到端测试
|
|
|
-- ⚠️ 前端组件需要修改以支持动态Token获取
|
|
|
-- ⚠️ 需要实现后端Token生成路由
|
|
|
+- ⚠️ 前端组件需要修改以支持统一通过Token API获取配置常量
|
|
|
+- ⚠️ 需要实现后端Token生成路由,并扩展响应包含配置常量
|
|
|
|
|
|
### File List
|
|
|
- `src/client/admin/components/agora-stt/AgoraSTTComponent.tsx` - 主组件文件(已存在,需要修改)
|