AI_Painting_V2.0/CLAUDE.md
WangLeo 239b32fb95 重构 Painting 模型参数架构:每模型独立配置、动态参数表单、移除 workflow 适配
- 新增 src/config/models/ 每模型独立参数 schema(8 个模型)
- 新增 src/components/dialogBox/params/ 动态参数控件
- 模型选择器改为从 API 获取并按 tag 分组
- dialogBox 参数区改为根据模型 config 动态渲染控件
- createTask.js Painting 直接返回扁平 modelParams,Video 保留旧 workflow
- 删除旧的 proportion/painting.vue 和 quantity 组件
- 更新 CLAUDE.md 架构文档
2026-06-03 19:00:49 +08:00

159 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 常用命令
```bash
pnpm dev # 启动 Vite 开发服务器
pnpm build # 生产构建
pnpm preview # 预览生产构建
```
## 技术栈
Vue 3 (Composition API) + Vite 7 + Pinia + Vue Router + Element Plus + Less + pnpm
## 架构概览
AI 绘画/视频生成前端操作平台,通过 HTTP 接口对接算力调度后端suanli和第三方 AI 平台RunningHub提交生成任务并轮询结果。
**Painting 和 Video 走两套不同的任务构造路径:**
- **Painting新架构**:本地模型参数 schema → 动态表单 → 扁平 API body 提交
- **Video旧架构**:远程 workflow JSON → RunningHub Playload 适配器 → `{ workflowId, nodeInfoList }` body 提交
### 关键目录
```
src/
├── main.js # 入口:创建 Vue 应用,安装 Pinia/Router/VueVirtualScroller
├── router/index.js # 路由定义 + token 验证守卫
├── stores/ # Pinia 状态管理
│ ├── user.js # 用户认证、信息
│ └── display.js # 生成历史列表、UI 状态(滚动、画布等)
├── apis/ # HTTP API 层:纯请求封装,不含业务逻辑
│ ├── auth/ # 认证相关登录、token 校验、用户信息)
│ └── display/ # 任务创建/轮询/历史、平台模型、收藏/删除
├── components/
│ ├── dialogBox/ # 生成参数输入面板(核心交互入口)
│ │ ├── model/ # 模型选择器painting 按 tag 分组video 按 pattern 分组)
│ │ ├── params/ # 动态参数控件Painting 新架构ProportionSelect、ResolutionSelect、SelectInput 等
│ │ ├── proportion/ # 比例选择器(仅 video.vueVideo 旧架构)
│ │ ├── imageUploader/ # 图片上传Painting
│ │ └── videoImageUploader/ # 视频图片上传Video
│ ├── virtual-scroller/# 虚拟滚动列表组件自定义实现reverse 模式)
│ └── canvas/ # 图片画布编辑(圆/矩形选区,局部重绘)
├── views/ # 页面home、login
├── utils/
│ ├── request.js # Axios 实例 + 拦截器:统一 Auth不带 Bearer+ 按前缀路由 baseURL
│ ├── websocket.js # 任务生成入口:组装参数 → 调用 API → 20s 轮询直至完成/失败
│ ├── modelApi.js # 模型业务层localStorage 每日缓存 + 模型名称→UUID 查找 + 平台编码映射
│ ├── createTask.js # 任务 body 构造Painting 返回 modelParamsVideo 走 Playload 适配器
│ ├── modelConfig.js # Video 旧架构:从远程 JSON 加载 workflow 配置Video 专用)
│ └── auth.ts # token 存取工具localStorage
├── config/
│ ├── index.js # 平台配置入口(目前仅导出 runninghub 供 Video 使用)
│ ├── runninghub/ # RunningHub 平台适配器Playload() 构造和 result() 解析Video 专用)
│ └── models/ # Painting 模型参数配置:每模型一个 JS 文件,定义 params schema
```
### 模型参数配置Painting 新架构)
`src/config/models/` 下每个模型一个 JS 文件,定义该模型的 API 参数 schema
```js
export default {
name: 'Flux 2',
tag: '文生图', // 与 API 返回的 tag 对应,用于模型选择器分组
inputType: 'text', // 'text' | 'image' | 'both' — 控制是否显示图片上传
maxImages: 4, // 最大上传图片数inputType 为 image/both 时有效)
params: [
{
name: 'prompt', // API 字段名
label: '提示词',
type: 'string', // 'string' | 'number' | 'boolean' | 'select' | 'image'
required: true,
ui: 'textarea', // 渲染控件:'textarea' | 'proportion' | 'resolution' | 'select' | 'number' | 'switch' | 'imageUpload'
default: '',
options: [...], // select 类型的枚举值
showWhen: { aspectRatio: 'custom' }, // 条件显示(可选)
},
],
}
```
- `src/config/models/index.js` 提供 `getModelConfig(modelName)` 查找函数
- `ui: 'textarea'` 的参数由 Sender 组件承载prompt`ui: 'imageUpload'` 由独立上传组件处理,其余渲染为 params/ 下的动态控件
- 模型选择器从 API`fetchPlatformModels`)获取模型列表,按 `tag` 字段分组
### API 层设计原则
- `src/apis/` 中的函数只做**纯 HTTP 调用**`service.get/post/delete` 等不包含缓存、localStorage、业务判断等逻辑
- 缓存、数据转换等业务逻辑放在 `src/utils/` 中,调用 apis 层的原始函数
示例:`utils/modelApi.js` 导入 `apis/display` 的原始 `fetchPlatformModels`,在其上叠加 localStorage 每日缓存和 `getModelId` 查找逻辑。
### 核心数据流
**Painting新架构**
1. 用户在 `dialogBox` 中设置参数——模型选择器从 API 获取模型列表按 tag 分组,参数控件根据模型 config 动态渲染
2. 点击生成 → `dialogBox:handleStart()` 收集 `paramValues`(含 prompt→ 组装 data`modelParams` 扁平对象)
3. 调用 `websocket.js:generate(data, generateData)`
4. `generate()` 内部通过 `createTask(data)` → 因 `type === 'Painting'` 直接返回 `data.modelParams` 作为 body
5. 调用 `modelApi.getModelId(type, modelName)` 查找模型 UUID
6. 调用 `requestCreateTask(body, sessionId)` → POST `/suanli/v1/tasks``{ model_id, body: modelParams, request }`
7. 返回 task_id → 轮询直至完成
**Video旧架构保留**
1. 用户在 `dialogBox` 中设置参数Pattern、videoModel、比例、时长
2. 点击生成 → `dialogBox:handleStart()` 组装 data含旧 params 数组)
3. `createTask(data)``runninghub.Playload(data)``fetchModelConfig()` 获取 workflow JSON → 返回 `{ workflowId, nodeInfoList }`
4. 后续同 Painting 的步骤 5-7
### 接口速查
| 函数 | 端点 | 用途 |
|------|------|------|
| `requestCreateTask` | POST `/suanli/v1/tasks` | 创建生成任务 |
| `requestTaskStatus` | GET `/suanli/v1/tasks/:id` | 查询单个任务状态 |
| `requestTaskHistory` | GET `/suanli/v1/tasks/history` | 历史任务列表(支持 `user_id`/`platform_code`/`page`/`pageSize` |
| `fetchPlatformModels` | GET `/suanli/v1/platforms/:code/models` | 获取平台模型列表(返回 `{id, name, tag, disabled?}` |
| `cancelOrCollect` | POST `/collect/toggle` | 收藏/取消收藏 |
| `deleteGenerateHistory` | DELETE `/taskRecordHistory/delete` | 删除历史记录 |
### 请求拦截器路由
拦截器统一设置 `Authorization: <token>`(不带 Bearer 前缀),根据 URL 前缀切换后端:
| URL 前缀 | 环境变量 | 示例 target |
|----------|----------|-------------|
| `/suanli` | `VITE_API_TASK_TARGET` | `http://test.xueai.art` |
| `/pay` | `VITE_API_PAY_TARGET` | `http://test.xueai.art` |
| 其他 | `VITE_API_BASE_URL`(默认) | `http://test.xueai.art/newapi/api` |
### 响应格式兼容
响应拦截器同时识别 `code === 0``status === 0` 两种成功状态。用户信息接口兼容新旧两种格式:`data.userInfo` 嵌套(新)和 `data` 扁平(旧),在 store 的 `getInfo()` 中做了 `const u = res.data.userInfo || res.data` 的兼容处理。
### 平台编码映射
| 类型 | 平台编码 |
|------|----------|
| Painting | `ai_painting_talk` |
| Video | `ai_video_talk` |
映射函数 `getPlatformCode()` 位于 `utils/modelApi.js`
### 自动导入
- `unplugin-auto-import`:自动导入 Vue/Router/Pinia API`.vue` 中无需手动 import
- `unplugin-vue-components`:自动注册 `src/components/` 下的组件和 Element Plus 组件
- Element Plus 图标通过 `unplugin-icons` 按需加载
### 路由守卫
`src/router/index.js``beforeEach` 守卫检查 token 存在性和有效性(调用 `POST /login/validateToken`),无效则跳转 `/login`。支持通过 URL query `?token=xxx` 传入 token。