fix: 添加skills
This commit is contained in:
619
.claude/skills/repo-sdk/references/client-usage.md
Normal file
619
.claude/skills/repo-sdk/references/client-usage.md
Normal file
@@ -0,0 +1,619 @@
|
||||
# 客户端使用指南
|
||||
|
||||
本文档详细介绍 @repo/sdk 的客户端调用方式及其配置方法。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [推荐方式:root.get (DI 风格)](#1-推荐方式rootget-di-风格)
|
||||
2. [复用 Schema 和类型](#2-复用-schema-和类型)
|
||||
3. [Better Auth 插件风格](#3-better-auth-插件风格)
|
||||
4. [API 函数风格](#4-api-函数风格)
|
||||
5. [服务端实现](#5-服务端实现)
|
||||
6. [错误处理](#6-错误处理)
|
||||
|
||||
---
|
||||
|
||||
## 1. 推荐方式:root.get (DI 风格)
|
||||
|
||||
**强烈推荐使用此方式**,保证完整的类型安全和最佳开发体验。
|
||||
|
||||
### 基本用法
|
||||
|
||||
```typescript
|
||||
import { root } from '@repo/core'
|
||||
import {
|
||||
ProjectController,
|
||||
TemplateController,
|
||||
TemplateSocialController,
|
||||
AigcController,
|
||||
FileController
|
||||
} from '@repo/sdk'
|
||||
import type { CreateProjectInput, Project, ListProjectsResult } from '@repo/sdk'
|
||||
|
||||
// 获取控制器实例(完整类型推导)
|
||||
const projectCtrl = root.get(ProjectController)
|
||||
const templateCtrl = root.get(TemplateController)
|
||||
const socialCtrl = root.get(TemplateSocialController)
|
||||
const aigcCtrl = root.get(AigcController)
|
||||
const fileCtrl = root.get(FileController)
|
||||
|
||||
// 调用方法(参数和返回值都有完整类型提示)
|
||||
const projects: ListProjectsResult = await projectCtrl.list({ page: 1, limit: 10 })
|
||||
const project: Project = await projectCtrl.create({ title: '新项目', content: {} })
|
||||
const template = await templateCtrl.get('template-id')
|
||||
await socialCtrl.like({ templateId: 'xxx' })
|
||||
```
|
||||
|
||||
### 优势
|
||||
|
||||
1. **完整类型安全**:参数和返回值都有精确的类型推导
|
||||
2. **IDE 支持**:自动补全、跳转定义、重构支持
|
||||
3. **可测试性**:可以轻松 mock Controller 进行单元测试
|
||||
4. **前后端一致**:服务端和客户端使用相同的接口定义
|
||||
5. **灵活性**:可以自定义代理实现(如添加缓存、日志等)
|
||||
|
||||
### 前置条件
|
||||
|
||||
需要先初始化客户端插件(注册 HTTP 代理):
|
||||
|
||||
```typescript
|
||||
import { createAuthClient } from 'better-auth/client'
|
||||
import { createSkerClientPlugin } from '@repo/sdk'
|
||||
|
||||
// 初始化(会自动将 Controller 替换为 HTTP 代理)
|
||||
const auth = createAuthClient({
|
||||
baseURL: 'http://localhost:3000',
|
||||
plugins: [createSkerClientPlugin()]
|
||||
})
|
||||
```
|
||||
|
||||
### 自定义代理(高级)
|
||||
|
||||
```typescript
|
||||
import { root } from '@repo/core'
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
import type { ListProjectsInput, ListProjectsResult } from '@repo/sdk'
|
||||
|
||||
// 注册带缓存的自定义实现
|
||||
root.set([{
|
||||
provide: ProjectController,
|
||||
useFactory: () => ({
|
||||
list: async (input: ListProjectsInput): Promise<ListProjectsResult> => {
|
||||
const cacheKey = `projects-${JSON.stringify(input)}`
|
||||
const cached = cache.get(cacheKey)
|
||||
if (cached) return cached
|
||||
|
||||
const result = await originalProxy.list(input)
|
||||
cache.set(cacheKey, result)
|
||||
return result
|
||||
},
|
||||
// ... 其他方法
|
||||
})
|
||||
}])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 复用 Schema 和类型
|
||||
|
||||
**强烈推荐复用 SDK 导出的 Zod Schema 和 TypeScript 类型**,确保前后端数据一致性。
|
||||
|
||||
### 导入类型(推荐)
|
||||
|
||||
```typescript
|
||||
// 始终从 @repo/sdk 导入类型,不要自己定义
|
||||
import type {
|
||||
// 项目相关
|
||||
Project,
|
||||
CreateProjectInput,
|
||||
ListProjectsInput,
|
||||
ListProjectsResult,
|
||||
UpdateProjectInput,
|
||||
TransferProjectInput,
|
||||
|
||||
// 模板相关
|
||||
TemplateDetail,
|
||||
CreateTemplateInput,
|
||||
RunTemplateInput,
|
||||
ListTemplatesInput,
|
||||
ListTemplatesResult,
|
||||
|
||||
// AI 生成
|
||||
AigcModel,
|
||||
SubmitTaskBody,
|
||||
SubmitTaskResult,
|
||||
GetTaskStatusResult,
|
||||
|
||||
// 社交
|
||||
LikeTemplateInput,
|
||||
CreateCommentInput,
|
||||
TemplateComment,
|
||||
GetCommentsResponse,
|
||||
|
||||
// 消息
|
||||
Message,
|
||||
ListMessagesInput,
|
||||
UnreadCountResult,
|
||||
|
||||
// 文件
|
||||
FileUploadResponse,
|
||||
VideoCompressRequest,
|
||||
ConvertToWebpRequest
|
||||
} from '@repo/sdk'
|
||||
```
|
||||
|
||||
### 复用 Zod Schema 验证
|
||||
|
||||
```typescript
|
||||
import {
|
||||
CreateProjectSchema,
|
||||
ListProjectsSchema,
|
||||
RunTemplateSchema,
|
||||
SubmitTaskBodySchema,
|
||||
CreateCommentSchema
|
||||
} from '@repo/sdk'
|
||||
|
||||
// 验证用户输入(抛出错误)
|
||||
function validateInput(data: unknown) {
|
||||
return CreateProjectSchema.parse(data)
|
||||
}
|
||||
|
||||
// 安全验证(不抛错,返回结果对象)
|
||||
function safeValidate(data: unknown) {
|
||||
const result = CreateProjectSchema.safeParse(data)
|
||||
if (!result.success) {
|
||||
console.error('验证失败:', result.error.flatten())
|
||||
return null
|
||||
}
|
||||
return result.data // 类型安全的数据
|
||||
}
|
||||
|
||||
// 部分验证(用于更新操作)
|
||||
const PartialProjectSchema = CreateProjectSchema.partial()
|
||||
function validatePartialUpdate(data: unknown) {
|
||||
return PartialProjectSchema.parse(data)
|
||||
}
|
||||
```
|
||||
|
||||
### 前端表单集成
|
||||
|
||||
```typescript
|
||||
import { CreateProjectSchema } from '@repo/sdk'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { z } from 'zod'
|
||||
import { root } from '@repo/core'
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
|
||||
// 从 Schema 推导表单类型
|
||||
type FormData = z.infer<typeof CreateProjectSchema>
|
||||
|
||||
function CreateProjectForm() {
|
||||
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
|
||||
resolver: zodResolver(CreateProjectSchema) // 复用 SDK Schema
|
||||
})
|
||||
|
||||
const onSubmit = async (data: FormData) => {
|
||||
const projectCtrl = root.get(ProjectController)
|
||||
const project = await projectCtrl.create(data) // 类型完全匹配
|
||||
console.log('创建成功:', project.id)
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<input {...register('title')} />
|
||||
{errors.title && <span>{errors.title.message}</span>}
|
||||
{/* ... */}
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 服务端实现复用类型
|
||||
|
||||
```typescript
|
||||
import { Injectable } from '@repo/core'
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
// 直接复用 SDK 导出的类型
|
||||
import type {
|
||||
Project,
|
||||
CreateProjectInput,
|
||||
ListProjectsInput,
|
||||
ListProjectsResult,
|
||||
UpdateProjectInput
|
||||
} from '@repo/sdk'
|
||||
|
||||
@Injectable()
|
||||
export class ProjectControllerImpl implements ProjectController {
|
||||
constructor(
|
||||
private readonly db: DatabaseService,
|
||||
private readonly auth: AuthService
|
||||
) {}
|
||||
|
||||
// 参数和返回值类型直接复用 SDK 类型
|
||||
async create(data: CreateProjectInput): Promise<Project> {
|
||||
const userId = this.auth.getCurrentUserId()
|
||||
return this.db.project.create({
|
||||
data: { ...data, userId }
|
||||
})
|
||||
}
|
||||
|
||||
async list(body: ListProjectsInput): Promise<ListProjectsResult> {
|
||||
// 实现...
|
||||
}
|
||||
|
||||
async update(body: UpdateProjectInput): Promise<Project> {
|
||||
// 实现...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Better Auth 插件风格
|
||||
|
||||
**适用场景**:已使用 Better Auth 进行身份认证的项目
|
||||
|
||||
### 安装和配置
|
||||
|
||||
```typescript
|
||||
import { createAuthClient } from 'better-auth/client'
|
||||
import { createSkerClientPlugin } from '@repo/sdk'
|
||||
|
||||
// 创建带 Sker 插件的 Auth 客户端
|
||||
const auth = createAuthClient({
|
||||
baseURL: 'http://localhost:3000',
|
||||
plugins: [createSkerClientPlugin()]
|
||||
})
|
||||
|
||||
export { auth }
|
||||
```
|
||||
|
||||
### 调用方式
|
||||
|
||||
```typescript
|
||||
// 项目管理
|
||||
const projects = await auth.sker.project.list({ page: 1, limit: 10 })
|
||||
const project = await auth.sker.project.create({ title: '新项目', content: {} })
|
||||
const detail = await auth.sker.project.get('project-id')
|
||||
|
||||
// 模板管理
|
||||
const templates = await auth.sker.template.list({ page: 1 })
|
||||
const { generationId } = await auth.sker.template.run({ templateId: 'xxx', formData: {} })
|
||||
|
||||
// 社交功能
|
||||
await auth.sker.templateSocial.like({ templateId: 'xxx' })
|
||||
const comments = await auth.sker.templateSocial.getComments({ templateId: 'xxx' })
|
||||
|
||||
// AI 生成
|
||||
const models = await auth.sker.aigc.getModels('image')
|
||||
const { task_id } = await auth.sker.aigc.submitTask({ model_name: 'xxx', prompt: 'xxx' })
|
||||
|
||||
// 文件上传
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
const { data: fileUrl } = await auth.sker.file.uploadS3(formData)
|
||||
```
|
||||
|
||||
### 插件工作原理
|
||||
|
||||
`createSkerClientPlugin()` 做了以下事情:
|
||||
|
||||
1. **注册 HTTP 代理**:将所有 Controller 替换为 HTTP 调用代理
|
||||
2. **提供 Better Auth 风格 API**:通过 `auth.sker.xxx` 访问
|
||||
3. **自动处理认证**:使用 Better Auth 的 session 进行认证
|
||||
4. **生成路径映射**:自动从 Controller 元数据生成路由
|
||||
|
||||
```typescript
|
||||
// 插件内部实现简化版
|
||||
export function createSkerClientPlugin(): BetterAuthClientPlugin {
|
||||
return {
|
||||
id: 'sker',
|
||||
getActions: ($fetch) => {
|
||||
// 注册代理到 DI 容器
|
||||
registerControllerProxies($fetch)
|
||||
// 返回 Better Auth 风格的 actions
|
||||
return buildBetterAuthActions(controllers, $fetch)
|
||||
},
|
||||
pathMethods: generatePathMethods(controllers)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API 函数风格
|
||||
|
||||
**推荐场景**:不使用 Better Auth、需要独立的 API 客户端
|
||||
|
||||
### 配置客户端
|
||||
|
||||
```typescript
|
||||
import { client, generateApiFunctions } from '@repo/sdk'
|
||||
|
||||
// 配置基础 URL 和认证
|
||||
client.setConfig({
|
||||
baseUrl: 'http://localhost:3000',
|
||||
auth: async () => {
|
||||
// 返回认证 token
|
||||
return localStorage.getItem('token') || ''
|
||||
}
|
||||
})
|
||||
|
||||
// 生成所有 API 函数
|
||||
const apis = generateApiFunctions()
|
||||
```
|
||||
|
||||
### 调用方式
|
||||
|
||||
函数名格式:`{httpMethod}{Path}`(驼峰命名)
|
||||
|
||||
```typescript
|
||||
// POST /loomart/project/list -> postLoomartProjectList
|
||||
const projects = await apis.postLoomartProjectList({ page: 1, limit: 10 })
|
||||
|
||||
// GET /loomart/template/get -> getLoomartTemplateGet
|
||||
const template = await apis.getLoomartTemplateGet({ id: 'template-id' })
|
||||
|
||||
// POST /loomart/template/run -> postLoomartTemplateRun
|
||||
const { generationId } = await apis.postLoomartTemplateRun({
|
||||
templateId: 'xxx',
|
||||
formData: {}
|
||||
})
|
||||
|
||||
// GET /loomart/aigc/models -> getLoomartAigcModels
|
||||
const models = await apis.getLoomartAigcModels({ category: 'image' })
|
||||
|
||||
// POST /loomart/file/upload-s3 -> postLoomartFileUploadS3
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
const result = await apis.postLoomartFileUploadS3(formData)
|
||||
```
|
||||
|
||||
### 函数名映射规则
|
||||
|
||||
| 路由 | HTTP 方法 | 函数名 |
|
||||
|------|-----------|--------|
|
||||
| /loomart/project/create | POST | postLoomartProjectCreate |
|
||||
| /loomart/project/list | POST | postLoomartProjectList |
|
||||
| /loomart/project/get | GET | getLoomartProjectGet |
|
||||
| /loomart/template/run | POST | postLoomartTemplateRun |
|
||||
| /loomart/aigc/task/submit | POST | postLoomartAigcTaskSubmit |
|
||||
| /loomart/aigc/task/status | GET | getLoomartAigcTaskStatus |
|
||||
| /loomart/file/upload-s3 | POST | postLoomartFileUploadS3 |
|
||||
|
||||
### 动态认证
|
||||
|
||||
```typescript
|
||||
client.setConfig({
|
||||
baseUrl: 'http://localhost:3000',
|
||||
auth: async (authContext) => {
|
||||
// 可以根据上下文动态获取 token
|
||||
if (authContext?.refreshToken) {
|
||||
// 刷新 token
|
||||
const newToken = await refreshAccessToken(authContext.refreshToken)
|
||||
return newToken
|
||||
}
|
||||
return localStorage.getItem('token') || ''
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 服务端实现
|
||||
|
||||
**场景**:在 Hono/Express 等后端框架中实现 Controller
|
||||
|
||||
### 注册控制器实现
|
||||
|
||||
```typescript
|
||||
import { root } from '@repo/core'
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
import { ProjectControllerImpl } from './impl/project.controller.impl'
|
||||
|
||||
// 注册实现类
|
||||
root.set([
|
||||
{
|
||||
provide: ProjectController,
|
||||
useClass: ProjectControllerImpl
|
||||
}
|
||||
])
|
||||
```
|
||||
|
||||
### 实现类示例
|
||||
|
||||
```typescript
|
||||
import { Injectable } from '@repo/core'
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
import type {
|
||||
Project,
|
||||
CreateProjectInput,
|
||||
ListProjectsInput,
|
||||
ListProjectsResult
|
||||
} from '@repo/sdk'
|
||||
|
||||
@Injectable()
|
||||
export class ProjectControllerImpl implements ProjectController {
|
||||
constructor(
|
||||
private readonly db: DatabaseService,
|
||||
private readonly auth: AuthService
|
||||
) {}
|
||||
|
||||
async create(data: CreateProjectInput): Promise<Project> {
|
||||
const userId = this.auth.getCurrentUserId()
|
||||
|
||||
const project = await this.db.project.create({
|
||||
data: {
|
||||
...data,
|
||||
userId
|
||||
}
|
||||
})
|
||||
|
||||
return project
|
||||
}
|
||||
|
||||
async list(body: ListProjectsInput): Promise<ListProjectsResult> {
|
||||
const userId = this.auth.getCurrentUserId()
|
||||
|
||||
const [projects, total] = await Promise.all([
|
||||
this.db.project.findMany({
|
||||
where: { userId, isDeleted: false },
|
||||
skip: ((body.page || 1) - 1) * (body.limit || 20),
|
||||
take: body.limit || 20,
|
||||
orderBy: { [body.sortBy || 'createdAt']: body.sortOrder || 'desc' }
|
||||
}),
|
||||
this.db.project.count({ where: { userId, isDeleted: false } })
|
||||
])
|
||||
|
||||
return {
|
||||
projects,
|
||||
total,
|
||||
page: body.page || 1,
|
||||
limit: body.limit || 20
|
||||
}
|
||||
}
|
||||
|
||||
async get(id: string): Promise<Project> {
|
||||
const project = await this.db.project.findUnique({ where: { id } })
|
||||
if (!project) throw new Error('Project not found')
|
||||
return project
|
||||
}
|
||||
|
||||
async update(body: UpdateProjectInput): Promise<Project> {
|
||||
return this.db.project.update({
|
||||
where: { id: body.id },
|
||||
data: body
|
||||
})
|
||||
}
|
||||
|
||||
async delete(body: { id: string }): Promise<{ message: string }> {
|
||||
await this.db.project.update({
|
||||
where: { id: body.id },
|
||||
data: { isDeleted: true }
|
||||
})
|
||||
return { message: 'Project deleted' }
|
||||
}
|
||||
|
||||
async transfer(body: TransferProjectInput): Promise<TransferProjectResult> {
|
||||
// 实现转移逻辑...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 与 Hono 集成
|
||||
|
||||
```typescript
|
||||
import { Hono } from 'hono'
|
||||
import { root, CONTROLLES } from '@repo/core'
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
// 自动注册所有控制器路由
|
||||
const controllers = root.get(CONTROLLES, [])
|
||||
for (const controller of controllers) {
|
||||
// 使用 @repo/core 的路由注册逻辑
|
||||
registerControllerRoutes(app, controller)
|
||||
}
|
||||
|
||||
export default app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 错误处理
|
||||
|
||||
### 客户端错误处理
|
||||
|
||||
```typescript
|
||||
import { ProjectController } from '@repo/sdk'
|
||||
import { root } from '@repo/core'
|
||||
|
||||
const projectCtrl = root.get(ProjectController)
|
||||
|
||||
try {
|
||||
const project = await projectCtrl.get('non-existent-id')
|
||||
} catch (error) {
|
||||
if (error.message.includes('API error')) {
|
||||
// API 返回的错误
|
||||
console.error('API 错误:', error.message)
|
||||
} else {
|
||||
// 网络或其他错误
|
||||
console.error('请求失败:', error)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 统一错误处理
|
||||
|
||||
```typescript
|
||||
// 创建带错误处理的包装器
|
||||
function withErrorHandling<T extends (...args: any[]) => Promise<any>>(fn: T): T {
|
||||
return (async (...args: Parameters<T>) => {
|
||||
try {
|
||||
return await fn(...args)
|
||||
} catch (error: any) {
|
||||
// 统一错误处理
|
||||
if (error.message.includes('401')) {
|
||||
// 未认证,跳转登录
|
||||
window.location.href = '/login'
|
||||
return
|
||||
}
|
||||
if (error.message.includes('403')) {
|
||||
// 无权限
|
||||
throw new Error('您没有权限执行此操作')
|
||||
}
|
||||
if (error.message.includes('404')) {
|
||||
throw new Error('资源不存在')
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}) as T
|
||||
}
|
||||
|
||||
// 使用
|
||||
const safeList = withErrorHandling(projectCtrl.list.bind(projectCtrl))
|
||||
const projects = await safeList({ page: 1 })
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践总结
|
||||
|
||||
### 推荐做法
|
||||
|
||||
| 场景 | 推荐方式 |
|
||||
|------|----------|
|
||||
| 调用 API | `root.get(Controller)` - 完整类型安全 |
|
||||
| 定义类型 | 从 `@repo/sdk` 导入,不要自己定义 |
|
||||
| 验证数据 | 复用 SDK 导出的 Zod Schema |
|
||||
| 表单验证 | 使用 `zodResolver(Schema)` |
|
||||
| 服务端实现 | `implements Controller` + 复用类型 |
|
||||
|
||||
### 避免做法
|
||||
|
||||
```typescript
|
||||
// ❌ 不要自己定义类型
|
||||
interface MyProject {
|
||||
id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
// ✅ 从 SDK 导入类型
|
||||
import type { Project } from '@repo/sdk'
|
||||
|
||||
// ❌ 不要自己写验证逻辑
|
||||
if (!data.title || data.title.length < 1) {
|
||||
throw new Error('标题不能为空')
|
||||
}
|
||||
|
||||
// ✅ 复用 SDK Schema
|
||||
import { CreateProjectSchema } from '@repo/sdk'
|
||||
CreateProjectSchema.parse(data)
|
||||
|
||||
// ❌ 不要使用 any 类型
|
||||
const projectCtrl: any = root.get(ProjectController)
|
||||
|
||||
// ✅ 让 TypeScript 自动推导
|
||||
const projectCtrl = root.get(ProjectController) // 类型自动推导
|
||||
```
|
||||
691
.claude/skills/repo-sdk/references/controllers.md
Normal file
691
.claude/skills/repo-sdk/references/controllers.md
Normal file
@@ -0,0 +1,691 @@
|
||||
# 控制器 API 参考
|
||||
|
||||
## 目录
|
||||
|
||||
1. [项目管理](#项目管理)
|
||||
2. [模板管理](#模板管理)
|
||||
3. [模板生成记录](#模板生成记录)
|
||||
4. [社交互动](#社交互动)
|
||||
5. [AI 生成](#ai-生成)
|
||||
6. [聊天](#聊天)
|
||||
7. [文件处理](#文件处理)
|
||||
8. [分类管理](#分类管理)
|
||||
9. [标签管理](#标签管理)
|
||||
10. [项目标签](#项目标签)
|
||||
11. [消息系统](#消息系统)
|
||||
12. [公告系统](#公告系统)
|
||||
13. [权限管理](#权限管理)
|
||||
14. [角色管理](#角色管理)
|
||||
15. [支付相关](#支付相关)
|
||||
|
||||
---
|
||||
|
||||
## 项目管理
|
||||
|
||||
**控制器**: `ProjectController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /project/create | 创建新项目 | project:create |
|
||||
| POST | /project/list | 获取用户项目列表 | project:list |
|
||||
| GET | /project/get | 获取单个项目 | project:read |
|
||||
| POST | /project/update | 更新项目信息 | project:update |
|
||||
| POST | /project/delete | 删除项目 | project:delete |
|
||||
| POST | /project/transfer | 转移/复制项目所有权 | project:update OR project:create |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
// 创建项目
|
||||
interface CreateProjectInput {
|
||||
title: string;
|
||||
titleEn?: string;
|
||||
description?: string;
|
||||
descriptionEn?: string;
|
||||
content: any;
|
||||
sourceTemplateId?: string;
|
||||
}
|
||||
|
||||
// 列表查询
|
||||
interface ListProjectsInput {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
tagId?: string;
|
||||
search?: string;
|
||||
sortBy?: 'createdAt' | 'updatedAt' | 'title';
|
||||
sortOrder?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
// 项目响应
|
||||
interface Project {
|
||||
id: string;
|
||||
userId: string;
|
||||
title: string;
|
||||
titleEn: string;
|
||||
description?: string;
|
||||
descriptionEn?: string;
|
||||
resultUrl?: string;
|
||||
content: any;
|
||||
sourceTemplateId?: string;
|
||||
isDeleted: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
tags?: UserTagBasic[];
|
||||
}
|
||||
|
||||
// 转移项目
|
||||
interface TransferProjectInput {
|
||||
projectId: string;
|
||||
targetUserId: string;
|
||||
mode: 'transfer' | 'copy';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 模板管理
|
||||
|
||||
**控制器**: `TemplateController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /template/create | 创建新模板 | - |
|
||||
| POST | /template/list | 获取模板列表 | - |
|
||||
| GET | /template/get | 获取单个模板 | - |
|
||||
| POST | /template/update | 更新模板 | - |
|
||||
| POST | /template/delete | 删除模板 | - |
|
||||
| POST | /template/run | 运行模板工作流 | - |
|
||||
| POST | /template/rerun | 根据生成记录重新运行 | - |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
// 模板详情
|
||||
interface TemplateDetail {
|
||||
id: string;
|
||||
userId: string;
|
||||
title: string;
|
||||
titleEn: string;
|
||||
description: string;
|
||||
descriptionEn: string;
|
||||
coverImageUrl: string;
|
||||
previewUrl: string;
|
||||
watermarkedPreviewUrl?: string;
|
||||
webpPreviewUrl?: string;
|
||||
webpHighPreviewUrl?: string;
|
||||
content: any;
|
||||
formSchema?: any;
|
||||
sortOrder: number;
|
||||
viewCount: number;
|
||||
useCount: number;
|
||||
likeCount: number;
|
||||
favoriteCount: number;
|
||||
shareCount: number;
|
||||
commentCount: number;
|
||||
costPrice?: number;
|
||||
price?: number;
|
||||
aspectRatio: string;
|
||||
status: string;
|
||||
isDeleted: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
isLiked?: boolean;
|
||||
isFavorited?: boolean;
|
||||
}
|
||||
|
||||
// 运行模板
|
||||
interface RunTemplateInput {
|
||||
templateId: string;
|
||||
formData?: Record<string, any>;
|
||||
projectId?: string;
|
||||
}
|
||||
|
||||
// 列表查询
|
||||
interface ListTemplatesInput {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
categoryId?: string;
|
||||
tagId?: string;
|
||||
status?: string;
|
||||
search?: string;
|
||||
sortBy?: 'sortOrder' | 'likeCount' | 'useCount' | 'viewCount' | 'createdAt';
|
||||
sortOrder?: 'asc' | 'desc';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 模板生成记录
|
||||
|
||||
**控制器**: `TemplateGenerationController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /template-generation/list | 获取生成记录列表 | template:run |
|
||||
| GET | /template-generation/get | 获取单个记录 | template:run |
|
||||
| POST | /template-generation/update | 更新记录 | template:run |
|
||||
| POST | /template-generation/delete | 删除记录 | template:run |
|
||||
| POST | /template-generation/batch-delete | 批量删除 | template:run |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface TemplateGeneration {
|
||||
id: string;
|
||||
userId: string;
|
||||
templateId: string;
|
||||
projectId?: string;
|
||||
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
|
||||
formData?: any;
|
||||
resultUrl?: string;
|
||||
errorMessage?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
interface ListTemplateGenerationsInput {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
templateId?: string;
|
||||
projectId?: string;
|
||||
status?: string;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 社交互动
|
||||
|
||||
**控制器**: `TemplateSocialController`
|
||||
**路由前缀**: `/loomart/template`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /like | 点赞模板 | template:run |
|
||||
| POST | /unlike | 取消点赞 | template:run |
|
||||
| GET | /check-liked | 检查是否已点赞 | template:run |
|
||||
| POST | /check-liked-batch | 批量检查点赞状态 | template:run |
|
||||
| POST | /favorite | 收藏模板 | template:run |
|
||||
| POST | /unfavorite | 取消收藏 | template:run |
|
||||
| GET | /check-favorited | 检查是否已收藏 | template:run |
|
||||
| POST | /check-favorited-batch | 批量检查收藏状态 | template:run |
|
||||
| POST | /favorites | 获取用户收藏列表 | template:run |
|
||||
| POST | /likes | 获取用户喜欢列表 | template:run |
|
||||
| POST | /share | 转发模板 | template:run |
|
||||
| POST | /comment/create | 创建评论 | template:run |
|
||||
| POST | /comment/delete | 删除评论 | template:run |
|
||||
| GET | /comments | 获取评论列表 | template:run |
|
||||
| GET | /comment/replies | 获取评论回复 | template:run |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
// 点赞/收藏
|
||||
interface LikeTemplateInput { templateId: string; }
|
||||
interface FavoriteTemplateInput { templateId: string; }
|
||||
|
||||
// 批量检查
|
||||
interface CheckLikedBatchInput { templateIds: string[]; }
|
||||
interface CheckLikedBatchResponse {
|
||||
results: Record<string, boolean>;
|
||||
}
|
||||
|
||||
// 评论
|
||||
interface CreateCommentInput {
|
||||
templateId: string;
|
||||
content: string;
|
||||
parentId?: string; // 回复评论时使用
|
||||
}
|
||||
|
||||
interface TemplateComment {
|
||||
id: string;
|
||||
userId: string;
|
||||
templateId: string;
|
||||
content: string;
|
||||
parentId?: string;
|
||||
isDeleted: boolean;
|
||||
createdAt: Date;
|
||||
user?: { id: string; name: string; image?: string; };
|
||||
replies?: TemplateComment[];
|
||||
replyCount?: number;
|
||||
}
|
||||
|
||||
// 获取评论
|
||||
interface GetCommentsInput {
|
||||
templateId: string;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AI 生成
|
||||
|
||||
**控制器**: `AigcController`
|
||||
**路由前缀**: `/loomart/aigc`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | /models | 获取支持的模型列表 | project:run OR template:run |
|
||||
| POST | /task/submit | 提交图像/视频生成任务 | project:run OR template:run |
|
||||
| GET | /task/status | 获取任务状态 | project:run OR template:run |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
// 模型信息
|
||||
interface AigcModel {
|
||||
model_name: string;
|
||||
description: string;
|
||||
description_en: string;
|
||||
supported_ar: string[]; // 支持的宽高比
|
||||
supported_count: string[]; // 支持的生成数量
|
||||
supported_duration: string[]; // 支持的时长(视频)
|
||||
supported_resolution: string[];
|
||||
mode: string; // 'image' | 'video'
|
||||
model_provider: string;
|
||||
tags: string[];
|
||||
tags_en: string[];
|
||||
provider: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
// 提交任务
|
||||
interface SubmitTaskBody {
|
||||
mode?: string;
|
||||
model_name: string;
|
||||
prompt: string;
|
||||
aspect_ratio?: string;
|
||||
webhook_flag?: boolean;
|
||||
watermark?: boolean;
|
||||
extra?: string;
|
||||
img_url?: string;
|
||||
img_list?: any[];
|
||||
duration?: string;
|
||||
resolution?: string;
|
||||
}
|
||||
|
||||
// 任务状态
|
||||
interface GetTaskStatusResult {
|
||||
task_id: string;
|
||||
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
|
||||
progress?: number;
|
||||
result_url?: string;
|
||||
error_message?: string;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 聊天
|
||||
|
||||
**控制器**: `ChatController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /chat | 发送聊天消息 | project:run OR template:run |
|
||||
| GET | /chat/models | 获取模型列表 | project:run OR template:run |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface ChatRequest {
|
||||
prompt: string;
|
||||
model_name: string;
|
||||
img_list?: string[];
|
||||
video_url?: string[];
|
||||
stream?: boolean;
|
||||
tools?: string;
|
||||
tool_choice?: string;
|
||||
}
|
||||
|
||||
interface ChatResponse {
|
||||
data: string;
|
||||
status: boolean;
|
||||
msg: string;
|
||||
usage?: any;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 文件处理
|
||||
|
||||
**控制器**: `FileController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 | 内容类型 |
|
||||
|------|------|------|------|---------|
|
||||
| POST | /file/upload-s3 | 上传文件到S3 | RequireSession | multipart/form-data |
|
||||
| POST | /file/compress-video | 压缩视频 | project:run OR template:run | - |
|
||||
| POST | /file/convert-to-ani | 转换为ANI格式 | project:run OR template:run | - |
|
||||
| POST | /file/convert-to-webp | 转换为WebP格式 | project:run OR template:run | - |
|
||||
| POST | /file/convert-to-watermark | 添加水印 | project:run OR template:run | - |
|
||||
| POST | /file/upload-and-convert-ani | 上传并转换ANI | project:run OR template:run | multipart/form-data |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
// 文件上传响应
|
||||
interface FileUploadResponse {
|
||||
status: boolean;
|
||||
msg: string;
|
||||
data: string; // 文件URL
|
||||
}
|
||||
|
||||
// 视频压缩
|
||||
interface VideoCompressRequest {
|
||||
videoUrl: string;
|
||||
quality: 'low' | 'medium' | 'high';
|
||||
}
|
||||
|
||||
// 转换为 WebP
|
||||
interface ConvertToWebpRequest {
|
||||
videoUrl: string;
|
||||
compressionLevel: number; // 0-6
|
||||
quality: number; // 0-100
|
||||
loop: boolean;
|
||||
resolution: string;
|
||||
fps: number;
|
||||
mode?: string;
|
||||
}
|
||||
|
||||
// 添加水印
|
||||
interface ConvertToWatermarkRequest {
|
||||
videoUrl: string;
|
||||
watermarkUrl: string;
|
||||
position?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'center';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 分类管理
|
||||
|
||||
**控制器**: `CategoryController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /category/create | 创建分类 | category:create |
|
||||
| POST | /category/list | 获取分类列表 | - |
|
||||
| GET | /category/get | 获取单个分类 | - |
|
||||
| GET | /category/get-by-name | 按名称获取分类 | - |
|
||||
| GET | /category/get-by-id | 按ID获取分类及模板 | - |
|
||||
| POST | /category/list-with-tags | 获取分类及标签列表 | - |
|
||||
| POST | /category/update | 更新分类 | category:update |
|
||||
| POST | /category/delete | 删除分类 | category:delete |
|
||||
| POST | /category/batch-update-sort-order | 批量更新排序 | category:update |
|
||||
| POST | /category/batch-update-tag-sort-order | 批量更新标签排序 | category:update |
|
||||
| GET | /category/stats | 获取分类统计 | category:read |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
description?: string;
|
||||
descriptionEn?: string;
|
||||
coverImageUrl?: string;
|
||||
sortOrder: number;
|
||||
isDeleted: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
tags?: Tag[];
|
||||
templates?: TemplateDetail[];
|
||||
}
|
||||
|
||||
interface CreateCategoryInput {
|
||||
name: string;
|
||||
nameEn?: string;
|
||||
description?: string;
|
||||
descriptionEn?: string;
|
||||
coverImageUrl?: string;
|
||||
sortOrder?: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 标签管理
|
||||
|
||||
**控制器**: `TagController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /tags/create | 创建标签 | tag:create |
|
||||
| POST | /tags/list | 获取标签列表 | tag:list |
|
||||
| GET | /tags/get | 获取单个标签 | tag:read |
|
||||
| GET | /tags/get-by-name | 按名称获取标签 | tag:read |
|
||||
| GET | /tags/get-by-category-tag-id | 按CategoryTag ID获取 | - |
|
||||
| POST | /tags/update | 更新标签 | tag:update |
|
||||
| POST | /tags/delete | 删除标签 | tag:delete |
|
||||
| POST | /tags/update-category-tag | 更新分类标签关联 | tag:update |
|
||||
| POST | /tags/batch-update-sort-order | 批量更新排序 | tag:update |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface Tag {
|
||||
id: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
description?: string;
|
||||
sortOrder: number;
|
||||
isDeleted: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
interface CreateTagInput {
|
||||
name: string;
|
||||
nameEn?: string;
|
||||
description?: string;
|
||||
sortOrder?: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 项目标签
|
||||
|
||||
**控制器**: `ProjectTagController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /project-tags/create | 创建用户标签 | - |
|
||||
| GET | /project-tags/list | 获取标签列表 | - |
|
||||
| POST | /project-tags/update | 更新标签 | - |
|
||||
| POST | /project-tags/delete | 删除标签 | - |
|
||||
| POST | /project-tags/add-to-project | 添加标签到项目 | - |
|
||||
| POST | /project-tags/remove-from-project | 从项目移除标签 | - |
|
||||
| POST | /project-tags/set-project-tags | 设置项目标签 | - |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface UserTag {
|
||||
id: string;
|
||||
userId: string;
|
||||
name: string;
|
||||
color?: string;
|
||||
sortOrder: number;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
interface CreateUserTagInput {
|
||||
name: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
interface SetProjectTagsInput {
|
||||
projectId: string;
|
||||
tagIds: string[];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 消息系统
|
||||
|
||||
**控制器**: `MessageController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /messages/list | 获取消息列表 | RequireSession |
|
||||
| GET | /messages/get | 获取单条消息 | RequireSession |
|
||||
| POST | /messages/mark-read | 标记消息已读 | RequireSession |
|
||||
| POST | /messages/batch-mark-read | 批量标记已读 | RequireSession |
|
||||
| POST | /messages/delete | 删除消息 | RequireSession |
|
||||
| GET | /messages/unread-count | 获取未读数量 | RequireSession |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface Message {
|
||||
id: string;
|
||||
userId: string;
|
||||
type: 'SYSTEM' | 'ACTIVITY' | 'BILLING' | 'MARKETING';
|
||||
title: string;
|
||||
content: string;
|
||||
data?: any;
|
||||
link?: string;
|
||||
priority: 'URGENT' | 'HIGH' | 'NORMAL' | 'LOW';
|
||||
expiresAt?: Date;
|
||||
isRead: boolean;
|
||||
readAt?: Date;
|
||||
isDeleted: boolean;
|
||||
deletedAt?: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
interface ListMessagesInput {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
type?: 'SYSTEM' | 'ACTIVITY' | 'BILLING' | 'MARKETING';
|
||||
isRead?: boolean;
|
||||
}
|
||||
|
||||
interface UnreadCountResult {
|
||||
total: number;
|
||||
byType: {
|
||||
SYSTEM: number;
|
||||
ACTIVITY: number;
|
||||
BILLING: number;
|
||||
MARKETING: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 公告系统
|
||||
|
||||
**控制器**: `AnnouncementController`
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| POST | /announcements/create | 创建公告 | announcement:create |
|
||||
| POST | /announcements/list | 获取公告列表 | - |
|
||||
| GET | /announcements/get | 获取单条公告 | - |
|
||||
| POST | /announcements/update | 更新公告 | announcement:update |
|
||||
| POST | /announcements/delete | 删除公告 | announcement:delete |
|
||||
| POST | /announcements/mark-read | 标记已读 | RequireSession |
|
||||
| GET | /announcements/unread-count | 获取未读数量 | RequireSession |
|
||||
|
||||
---
|
||||
|
||||
## 权限管理
|
||||
|
||||
**控制器**: `PermissionController`
|
||||
**路由前缀**: `/loomart/admin/permissions`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | /permissions/list | 获取权限列表 | user:permissions |
|
||||
| POST | /permissions/create | 创建权限 | user:permissions |
|
||||
| PATCH | /permissions/get | 更新权限 | user:permissions |
|
||||
| DELETE | /permissions/delete | 删除权限 | user:permissions |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface Permission {
|
||||
id: string;
|
||||
resource: string;
|
||||
action: string;
|
||||
description?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 角色管理
|
||||
|
||||
**控制器**: `RoleController`
|
||||
**路由前缀**: `/loomart/admin`
|
||||
|
||||
| 方法 | 路由 | 功能 | 权限 |
|
||||
|------|------|------|------|
|
||||
| GET | /roles/list | 获取角色列表 | role:list |
|
||||
| POST | /roles/create | 创建角色 | role:create |
|
||||
| PATCH | /roles/update | 更新角色基本信息 | role:update |
|
||||
| PUT | /roles/update/permissions | 更新角色权限 | role:update |
|
||||
| DELETE | /roles/delete | 删除角色 | role:delete |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```typescript
|
||||
interface RoleWithPermissions {
|
||||
id: string;
|
||||
name: string;
|
||||
displayName: string;
|
||||
description?: string;
|
||||
isSystem: boolean;
|
||||
scope: string;
|
||||
organizationId?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
permissions: Permission[];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 支付相关
|
||||
|
||||
### AlipayController
|
||||
|
||||
**路由前缀**: `/loomart`
|
||||
|
||||
| 方法 | 路由 | 功能 |
|
||||
|------|------|------|
|
||||
| POST | /alipay/app-pay | 支付宝APP支付下单 |
|
||||
| POST | /alipay/auth-info | 获取支付宝授权字符串 |
|
||||
| POST | /alipay/webhook | 支付宝异步通知回调 |
|
||||
| POST | /credits/pre-recharge | 积分预充值 |
|
||||
|
||||
### AdminBalanceController
|
||||
|
||||
**路由前缀**: `/loomart/admin-balance`
|
||||
|
||||
| 方法 | 路由 | 功能 |
|
||||
|------|------|------|
|
||||
| POST | /add-user-balance | 管理员给用户充值 |
|
||||
| POST | /deduct-user-balance | 管理员扣除用户余额 |
|
||||
| POST | /get-user-balance | 查询用户当前余额 |
|
||||
1010
.claude/skills/repo-sdk/references/workflows.md
Normal file
1010
.claude/skills/repo-sdk/references/workflows.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user