forked from 77media/video-flow
129 lines
5.2 KiB
Markdown
129 lines
5.2 KiB
Markdown
## Video-Flow API 使用指南(方案一:保持现状,统一规范与示例)
|
||
|
||
> 目标:在不改动现有代码结构与签名的前提下,提供清晰的一致性用法、错误处理约定与多场景接入示例。
|
||
|
||
### 目录结构与职责
|
||
|
||
- 基础配置从 `@/lib/env` 导入 `baseUrl`
|
||
- `request.ts`:Axios 实例与拦截器、通用 `get/post/put/del`、`stream`(SSE风格下载进度)、`downloadStream`、`streamJsonPost`
|
||
- `errorHandle.ts`:错误码映射与统一提示、特殊码处理(如 401 跳转登录、402 不弹提示)
|
||
- `common.ts`:通用类型与与上传相关的工具(获取七牛 Token、上传)
|
||
- `resources.ts`:示例资源接口封装(基于 `post`)
|
||
- 其他业务模块(如 `video_flow.ts`、`export-adapter.ts` 等)各自封装具体接口/逻辑
|
||
|
||
### 统一调用规范
|
||
|
||
1. 使用 `request.ts` 提供的 `get/post/put/del` 包装函数发起请求,返回后端响应体(已通过响应拦截器做业务码检查)。
|
||
2. 业务成功码:`code === 0` 或 `code === 202`(长任务/排队等需要前端自行处理状态)。若非成功码,拦截器会调用 `errorHandle` 并 `Promise.reject`。
|
||
3. 认证:前端从 `localStorage.token` 注入 `Authorization: Bearer <token>`,请确保登录流程写入 `token`。
|
||
4. 基础地址:从 `@/lib/env` 的 `baseUrl` 获取,统一管理环境变量。
|
||
|
||
### 错误处理约定
|
||
|
||
- `errorHandle(code, message?)`:统一弹出错误(402 除外),并处理特殊码:
|
||
- `401`:清除 `localStorage.token` 并跳转 `/login`
|
||
- `402`:由 `request.ts` 响应拦截器在收到后端 `402` 且带 `detail` 时触发通知(积分不足),并拒绝请求
|
||
- 网络/解析类错误:`handleRequestError` 会降级为通用错误提示并抛出异常
|
||
|
||
### 常用请求示例
|
||
|
||
```ts
|
||
import { get, post, put, del } from '@/api/request';
|
||
|
||
type User = { id: number; name: string };
|
||
type ApiResponse<T> = { code: number; successful: boolean; message: string; data: T };
|
||
|
||
// GET
|
||
const user = await get<ApiResponse<User>>('/user/detail?id=1');
|
||
|
||
// POST
|
||
const created = await post<ApiResponse<User>>('/user/create', { name: 'Evan' });
|
||
|
||
// PUT
|
||
await put<ApiResponse<null>>('/user/update', { id: 1, name: 'Kent' });
|
||
|
||
// DELETE
|
||
await del<ApiResponse<null>>('/user/remove?id=1');
|
||
```
|
||
|
||
### 流式与下载(SSE/文件)
|
||
|
||
1) SSE/渐进消息(基于 Axios 下载进度事件解析 `data: {}` 行)
|
||
|
||
```ts
|
||
import { stream } from '@/api/request';
|
||
|
||
await stream<{ type: string; message?: string; progress?: number }>({
|
||
url: '/api/video-flow/export/ai-clips',
|
||
method: 'POST',
|
||
data: { /* your body */ },
|
||
onMessage: (evt) => {
|
||
if (evt.type === 'progress') {
|
||
// 更新进度条
|
||
}
|
||
},
|
||
onError: (err) => { /* 兜底错误处理 */ },
|
||
onComplete: () => { /* 完成回调 */ }
|
||
});
|
||
```
|
||
|
||
2) 文本行分隔的 JSON 流(`fetch` + `ReadableStream`,每行一个 JSON)
|
||
|
||
```ts
|
||
import { streamJsonPost } from '@/api/request';
|
||
|
||
await streamJsonPost('/sse/json', { /* body */ }, (json) => {
|
||
// 每次解析到一行 JSON
|
||
});
|
||
```
|
||
|
||
3) 文件下载(Blob)
|
||
|
||
```ts
|
||
import { downloadStream } from '@/api/request';
|
||
|
||
await downloadStream('/download/file', 'result.mp4');
|
||
```
|
||
|
||
### 多场景接入指南
|
||
|
||
#### 浏览器前端(React/Next.js CSR)
|
||
|
||
- 直接使用 `get/post/put/del`;确保登录后将 `token` 写入 `localStorage`
|
||
- 环境变量:在 `.env.local` 配置 `NEXT_PUBLIC_BASE_URL`,通过 `@/lib/env` 统一管理
|
||
- 错误提示:由 `errorHandle` 统一处理;402 会展示积分不足通知
|
||
|
||
#### Next.js Route Handler(服务端 API)
|
||
|
||
- 如需在 Route Handler 内调用后端接口:建议使用服务端 `fetch` 并自行附加服务端凭证;避免直接依赖 `localStorage`
|
||
- 若需要转发到现有后端并复用通知/事件流格式,可参考 `api/export-adapter.ts` 的 SSE 写法
|
||
|
||
#### Next.js Server Components/SSR
|
||
|
||
- 服务端不具备 `localStorage`,如需鉴权请改为从 Cookie/Headers 传递 token,并在转发时设置 `Authorization`
|
||
- 服务器端可直接使用 `fetch(baseUrl + path, { headers })`
|
||
|
||
#### Node/Serverless(Vercel/Cloudflare)
|
||
|
||
- 同 SSR 原则:不使用 `localStorage`;从密钥存储中读取后以请求头传递
|
||
- SSE 转发时,按 `text/event-stream` 写入 `ReadableStream` 并传递 `data: <json>\n\n`
|
||
|
||
### 最佳实践
|
||
|
||
- 统一通过 `request.ts` 发起请求,不绕过拦截器;对长任务/排队返回 `202` 时在页面层处理轮询或 SSE
|
||
- 上传流程:使用 `common.ts/getUploadToken` 获取 token 与 domain,再使用 `uploadToQiniu` 上传,监听进度
|
||
- 将后端的业务错误码保持为服务端规范,在前端只做展示与关键码分支(401/402)
|
||
|
||
### 常见问题(FAQ)
|
||
|
||
- Q: 为什么拿不到 `localStorage` 中的 token?
|
||
- A: 服务端渲染或 Route Handler 中无 `localStorage`,需通过 Cookie/Headers 传递。
|
||
- Q: 返回 `code !== 0/202` 时如何自定义处理?
|
||
- A: 可在业务层 `try/catch` 捕获 `post/get` 的拒绝 Promise,并根据 `error.message` 或后端 `data.message` 做分支。
|
||
- Q: SSE 收不到事件?
|
||
- A: 确认后端使用 `text/event-stream`,每条消息以 `data: <json>\n\n` 输出;前端在 `onDownloadProgress` 中按行解析。
|
||
|
||
---
|
||
|
||
|