🎨chore: 使用 oxlint, oxfmt&格式化代码

This commit is contained in:
2026-02-08 21:16:25 +08:00
parent 9d35c6a9d8
commit 3a801ba016
78 changed files with 3367 additions and 1468 deletions

View File

@@ -32,6 +32,7 @@ Pinia Stores持久化状态
```
**关键模式**
- **Pinia stores 必须是单一实例**,通过 `storeToRefs()` 获取响应式引用
- **API 请求必须通过 `useFetchWrapped`** 来自动处理认证头token/user_id
- **FFmpeg 采用单例模式**`useFFmpeg()` 返回全局加载的实例),避免重复初始化
@@ -53,6 +54,7 @@ useFetchWrapped<AuthedRequest, BaseResponse<resp.xxx>>(
```
**约定**
- **每个请求必须包含** `token``user_id`(来自 `useLoginState`
- **响应结构统一**: `BaseResponse<T>` 包含 `ret: number` 状态码和 `data: T` 数据
- **API_BASE 在 `nuxt.config.ts` 中定义**,所有请求都相对于此 URL
@@ -60,11 +62,13 @@ useFetchWrapped<AuthedRequest, BaseResponse<resp.xxx>>(
### 3. 媒体处理架构
#### FFmpeg 初始化流程
- **单例加载**: 首次调用 `useFFmpeg()` 时初始化,后续复用缓存的实例
- **WASM 资源加载**: 从 CDN`cdn.jsdelivr.net`)加载 FFmpeg core、wasm、worker
- **错误恢复**: 调用 `cleanupFFmpeg()` 清理资源并重置单例
#### 视频合成流程(核心用例)
```
输入: 透明通道视频 (WebM) + 背景图 (PNG/File)
@@ -82,7 +86,9 @@ useFetchWrapped<AuthedRequest, BaseResponse<resp.xxx>>(
### 4. UI 组件架构
#### 内置组件库(`components/uni/`
自定义包装组件,提供统一 API
- `UniButton`: 按钮 + loading 状态
- `UniInput`/`UniTextArea`: 表单输入
- `UniSelect`: 下拉选择
@@ -90,8 +96,9 @@ useFetchWrapped<AuthedRequest, BaseResponse<resp.xxx>>(
- `UniCopyable`: 可复制文本
**消息通知用法**
```typescript
const toast = useToast() // Radix Vue 的 Toast顶部通知
const toast = useToast() // Radix Vue 的 Toast顶部通知
// 或从 provide 注入
const messageApi = inject('uni-message')
messageApi.success('操作成功')
@@ -99,6 +106,7 @@ messageApi.error('操作失败', 5000)
```
#### Radix Vue + Nuxt UI 集成
- 使用 Radix Vue for 基础组件button, dialog, select
- Nuxt UI 用于高级组件 + 主题管理
- **颜色方案**: primary='indigo', gray='neutral',详见 `app.config.ts`
@@ -106,6 +114,7 @@ messageApi.error('操作失败', 5000)
### 5. 路由与页面结构
**目录映射**
```
pages/
├── generation.vue (导航枢纽)
@@ -122,6 +131,7 @@ pages/
```
**导航约定**
- `/generation` → 功能导航页面
- `/aigc/chat` → 聊天/文本生成
- `/generation/course` → 视频生成工作流
@@ -130,6 +140,7 @@ pages/
## 开发工作流
### 启动项目
```bash
ni # 安装依赖
nr dev # 启动 http://localhost:3000
@@ -139,11 +150,13 @@ nr generate # 生产构建 (生成静态文件)
### 常见任务
**添加新的 API 端点**
1. 定义 Request 和 Response 类型(参考 `typings/llm.ts`
2. 在 composable 中使用 `useFetchWrapped` 调用
3. 自动包含 token/user_id来自 `useLoginState`
**添加新的视频处理功能**
1. 使用 `useFFmpeg()` 获取实例(自动初始化)
2. 写入文件到 vFS: `ffmpeg.writeFile()`
3. 执行命令:`ffmpeg.exec([...filterArgs])`
@@ -151,6 +164,7 @@ nr generate # 生产构建 (生成静态文件)
5. 使用 progress callback 通报处理进度
**添加新的 UI 组件**
1. 创建在 `components/` 下(自动注册)
2. 优先使用 Radix Vue + Nuxt UI已集成
3. 使用 Tailwind CSS utility classes + `@apply` 指令
@@ -159,22 +173,26 @@ nr generate # 生产构建 (生成静态文件)
## 项目特定的约定
### 类型定义位置
- **LLM 相关**: `typings/llm.ts`ChatMessage, ChatSession, ModelTag, LLMModal
- **全局类型**: `typings/types.d.ts`BaseResponse, AuthedRequest, UserSchema
- **组件接口**: 组件目录下的 `index.d.ts`(例 `components/aigc/drawing/index.d.ts`
### 命名规范
- **Composables**: `use` 前缀(`useLoginState`, `useLLM`
- **Stores**: `use` + 功能名(`useHistory`, `useTourState`
- **组件**: PascalCase`ChatItem.vue`, `ModalAuthentication.vue`
- **工具函数**: camelCase放在 `composables/` 或各功能目录
### 响应式数据模式
- **Pinia store 返回值**: 必须通过 `storeToRefs()` 才能保持响应式
- **模板中的 ref**: 直接访问Vue 自动展开)
- **跨组件数据**: 优先使用 Pinia store带持久化
### 进度反馈与错误处理
- **长时间操作** (视频处理): 通过 callback 函数报告 progress0-100
- **错误处理**: 返回 Promise reject上层 catch 处理;可选通过 toast/message 提示
- **FFmpeg 错误**: 捕获 exitCode 非零,记录详细的 FFmpeg 输出
@@ -182,6 +200,7 @@ nr generate # 生产构建 (生成静态文件)
## 依赖与性能优化
### 关键依赖
- **@ffmpeg/ffmpeg@0.12.15**: WASM 视频处理(从 CDN 加载)
- **@webav/av-cliper**: 客户端视频剪辑库
- **markdown-it + highlight.js**: 内容渲染(支持代码高亮)
@@ -189,13 +208,16 @@ nr generate # 生产构建 (生成静态文件)
- **idb-keyval**: IndexedDB 简化操作(缓存大文件)
### Vite 优化设置
```typescript
// nuxt.config.ts 中排除以下包进行优化,避免 bundling WASM
optimizeDeps.exclude: ['@ffmpeg/ffmpeg', 'idb-keyval', '@webav/av-cliper', 'gsap', 'markdown-it']
```
### 构建排除项
Worker 格式设置为 ES Module避免 Vite 默认处理:
```typescript
vite.worker.format = 'es'
```
@@ -209,13 +231,13 @@ vite.worker.format = 'es'
## 常见陷阱与解决方案
| 问题 | 原因 | 解决方案 |
|------|------|--------|
| API 请求 401 | 缺少 token 或已过期 | 检查 `useLoginState().token`,通过 ModalAuthentication 重新登录 |
| FFmpeg 加载超时 | CDN 资源加载慢 | 检查网络,可切换到本地 `/public/assets/ffmpeg` |
| 视频输出无声音 | 滤镜链未映射音频 | 确保 FFmpeg 命令包含 `-map '1:a?'` 映射音频轨道 |
| 组件未注册 | 文件位置错误 | 确保在 `components/` 目录下,子目录自动扁平化注册 |
| Pinia 状态未持久化 | 未配置 persist 选项 | 在 store 返回语句后添加 persist 配置(参考 `useLoginState` |
| 问题 | 原因 | 解决方案 |
| ------------------ | ------------------- | --------------------------------------------------------------- |
| API 请求 401 | 缺少 token 或已过期 | 检查 `useLoginState().token`,通过 ModalAuthentication 重新登录 |
| FFmpeg 加载超时 | CDN 资源加载慢 | 检查网络,可切换到本地 `/public/assets/ffmpeg` |
| 视频输出无声音 | 滤镜链未映射音频 | 确保 FFmpeg 命令包含 `-map '1:a?'` 映射音频轨道 |
| 组件未注册 | 文件位置错误 | 确保在 `components/` 目录下,子目录自动扁平化注册 |
| Pinia 状态未持久化 | 未配置 persist 选项 | 在 store 返回语句后添加 persist 配置(参考 `useLoginState` |
## 资源链接