expo-popcore-app/.claude/skills/repo-sdk/references/workflows.md

25 KiB
Raw Blame History

接口组合使用场景

本文档详细描述 @repo/sdk 中各接口的组合使用场景,帮助理解业务流程中接口之间的依赖关系。

推荐:所有示例都使用 root.get(Controller) 方式调用,并复用 SDK 导出的类型。

目录

  1. 模板运行完整流程
  2. 模板社交互动流程
  3. 项目管理与标签流程
  4. 文件上传与处理流程
  5. 分类标签管理流程
  6. 消息通知处理流程
  7. 用户收藏夹管理流程
  8. AI 内容生成流程
  9. 权限角色管理流程

1. 模板运行完整流程

场景:用户选择模板,填写表单,生成内容,保存到项目

涉及控制器

  • TemplateController
  • AigcController
  • FileController
  • TemplateGenerationController
  • ProjectController

流程图

用户选择模板
    ↓
TemplateController.get(templateId)
    ↓
用户填写表单(根据 formSchema
    ↓
TemplateController.run({ templateId, formData, projectId? })
    ↓ 返回 generationId
轮询任务状态
    ↓
AigcController.getTaskStatus(taskId)
    ↓ status === 'COMPLETED'
获取生成结果
    ↓
FileController.convertToWebp({ videoUrl }) [可选:格式转换]
    ↓
ProjectController.update({ id, resultUrl }) [保存到项目]

代码示例

import { root } from '@repo/core'
import {
  TemplateController,
  AigcController,
  FileController,
  ProjectController
} from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  TemplateDetail,
  Project,
  GetTaskStatusResult,
  ConvertToWebpRequest
} from '@repo/sdk'

async function runTemplateWorkflow(templateId: string, formData: Record<string, any>) {
  // 使用 root.get 获取控制器(类型安全)
  const templateCtrl = root.get(TemplateController)
  const aigcCtrl = root.get(AigcController)
  const fileCtrl = root.get(FileController)
  const projectCtrl = root.get(ProjectController)

  // 1. 获取模板详情(了解表单结构)
  const template: TemplateDetail = await templateCtrl.get(templateId)
  console.log('模板表单结构:', template.formSchema)

  // 2. 创建项目(可选,用于保存结果)
  const project: Project = await projectCtrl.create({
    title: `基于 ${template.title} 的创作`,
    content: { templateId, formData },
    sourceTemplateId: templateId
  })

  // 3. 运行模板
  const { generationId } = await templateCtrl.run({
    templateId,
    formData,
    projectId: project.id
  })

  // 4. 轮询任务状态
  let taskStatus: GetTaskStatusResult = await aigcCtrl.getTaskStatus(generationId)
  while (taskStatus.status === 'PENDING' || taskStatus.status === 'PROCESSING') {
    await new Promise(resolve => setTimeout(resolve, 2000))
    taskStatus = await aigcCtrl.getTaskStatus(generationId)
    console.log(`进度: ${taskStatus.progress || 0}%`)
  }

  if (taskStatus.status === 'FAILED') {
    throw new Error(`生成失败: ${taskStatus.error_message}`)
  }

  // 5. 处理生成结果(转换为 WebP 格式)
  const webpResult = await fileCtrl.convertToWebp({
    videoUrl: taskStatus.result_url!,
    quality: 80,
    compressionLevel: 4,
    loop: true,
    resolution: '720p',
    fps: 15
  })

  // 6. 更新项目结果
  await projectCtrl.update({
    id: project.id,
    resultUrl: webpResult.data
  })

  return {
    project,
    generationId,
    resultUrl: webpResult.data
  }
}

重新运行场景

import { root } from '@repo/core'
import { TemplateController } from '@repo/sdk'

// 基于历史生成记录重新运行
async function rerunFromHistory(generationId: string) {
  const templateCtrl = root.get(TemplateController)

  // 直接使用历史记录的参数重新运行
  const { generationId: newId } = await templateCtrl.rerun({ generationId })

  // 继续轮询新任务...
  return newId
}

2. 模板社交互动流程

场景:用户浏览模板列表,点赞、收藏、评论

涉及控制器

  • TemplateController
  • TemplateSocialController

流程图

获取模板列表
    ↓
TemplateController.list({ page, limit })
    ↓
批量检查社交状态
    ↓
TemplateSocialController.checkLikedBatch({ templateIds })
TemplateSocialController.checkFavoritedBatch({ templateIds })
    ↓
用户交互
    ↓
点赞: TemplateSocialController.like({ templateId })
收藏: TemplateSocialController.favorite({ templateId })
评论: TemplateSocialController.createComment({ templateId, content })

代码示例

import { root } from '@repo/core'
import { TemplateController, TemplateSocialController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  TemplateDetail,
  ListTemplatesResult,
  CheckLikedBatchResponse,
  CheckFavoritedBatchResponse,
  TemplateComment,
  GetCommentsResponse
} from '@repo/sdk'

// 获取模板列表并附加社交状态
async function getTemplatesWithSocialStatus(page: number = 1) {
  const templateCtrl = root.get(TemplateController)
  const socialCtrl = root.get(TemplateSocialController)

  // 1. 获取模板列表
  const { templates, total }: ListTemplatesResult = await templateCtrl.list({
    page,
    limit: 20,
    sortBy: 'likeCount',
    sortOrder: 'desc'
  })

  const templateIds = templates.map(t => t.id)

  // 2. 批量检查点赞和收藏状态
  const [likedStatus, favoritedStatus]: [CheckLikedBatchResponse, CheckFavoritedBatchResponse] = await Promise.all([
    socialCtrl.checkLikedBatch({ templateIds }),
    socialCtrl.checkFavoritedBatch({ templateIds })
  ])

  // 3. 合并状态到模板数据
  const templatesWithStatus = templates.map(template => ({
    ...template,
    isLiked: likedStatus.results[template.id] || false,
    isFavorited: favoritedStatus.results[template.id] || false
  }))

  return { templates: templatesWithStatus, total }
}

// 点赞/取消点赞
async function toggleLike(templateId: string, isCurrentlyLiked: boolean): Promise<boolean> {
  const socialCtrl = root.get(TemplateSocialController)

  if (isCurrentlyLiked) {
    await socialCtrl.unlike({ templateId })
  } else {
    await socialCtrl.like({ templateId })
  }

  return !isCurrentlyLiked
}

// 获取评论列表(含回复)
async function getCommentsWithReplies(templateId: string): Promise<GetCommentsResponse> {
  const socialCtrl = root.get(TemplateSocialController)

  // 1. 获取顶级评论自动包含前3条回复
  const { comments, total } = await socialCtrl.getComments({
    templateId,
    page: 1,
    limit: 20
  })

  // 2. 对于回复数超过3的评论加载更多回复
  for (const comment of comments) {
    if (comment.replyCount && comment.replyCount > 3) {
      const { replies } = await socialCtrl.getCommentReplies({
        commentId: comment.id,
        page: 1,
        limit: 50
      })
      comment.replies = replies
    }
  }

  return { comments, total }
}

// 发表评论或回复
async function postComment(templateId: string, content: string, parentId?: string): Promise<TemplateComment> {
  const socialCtrl = root.get(TemplateSocialController)

  const comment = await socialCtrl.createComment({
    templateId,
    content,
    parentId  // 如果是回复传入父评论ID
  })

  return comment
}

3. 项目管理与标签流程

场景:用户创建项目,使用标签分类管理

涉及控制器

  • ProjectController
  • ProjectTagController

流程图

创建用户标签
    ↓
ProjectTagController.create({ name, color })
    ↓
创建项目
    ↓
ProjectController.create({ title, content })
    ↓
给项目添加标签
    ↓
ProjectTagController.addToProject({ projectId, tagId })
    ↓
按标签筛选项目
    ↓
ProjectController.list({ tagId })

代码示例

import { root } from '@repo/core'
import { ProjectController, ProjectTagController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  Project,
  CreateProjectInput,
  ListProjectsResult,
  UserTag,
  TransferProjectResult
} from '@repo/sdk'

// 初始化用户标签系统
async function initUserTags(): Promise<UserTag[]> {
  const tagCtrl = root.get(ProjectTagController)

  // 创建默认标签
  const defaultTags = [
    { name: '收藏夹', color: '#FF6B6B' },
    { name: '工作', color: '#4ECDC4' },
    { name: '个人', color: '#45B7D1' },
    { name: '灵感', color: '#96CEB4' }
  ]

  const tags = await Promise.all(
    defaultTags.map(tag => tagCtrl.create(tag))
  )

  return tags
}

// 创建项目并分类
async function createProjectWithTags(
  projectData: CreateProjectInput,
  tagIds: string[]
): Promise<Project> {
  const projectCtrl = root.get(ProjectController)
  const tagCtrl = root.get(ProjectTagController)

  // 1. 创建项目
  const project: Project = await projectCtrl.create(projectData)

  // 2. 批量设置标签
  await tagCtrl.setProjectTags({
    projectId: project.id,
    tagIds
  })

  return project
}

// 获取用户所有标签及项目数量
async function getTagsWithProjectCount(): Promise<Array<UserTag & { projectCount: number }>> {
  const tagCtrl = root.get(ProjectTagController)
  const projectCtrl = root.get(ProjectController)

  // 1. 获取所有标签
  const tags = await tagCtrl.list()

  // 2. 获取每个标签下的项目数量
  const tagsWithCount = await Promise.all(
    tags.map(async tag => {
      const { total } = await projectCtrl.list({ tagId: tag.id, limit: 1 })
      return { ...tag, projectCount: total }
    })
  )

  return tagsWithCount
}

// 项目转移(复制到其他用户)
async function copyProjectToUser(projectId: string, targetUserId: string): Promise<TransferProjectResult> {
  const projectCtrl = root.get(ProjectController)

  const result = await projectCtrl.transfer({
    projectId,
    targetUserId,
    mode: 'copy'  // 'transfer' 会移动所有权,'copy' 会复制
  })

  return result
}

4. 文件上传与处理流程

场景:用户上传文件,进行格式转换和处理

涉及控制器

  • FileController
  • FFmpegController(视频合成)

流程图

用户选择文件
    ↓
FileController.uploadS3(formData)
    ↓ 返回文件URL
选择处理方式
    ↓
├─ 压缩视频: FileController.compressVideo({ videoUrl, quality })
├─ 转WebP: FileController.convertToWebp({ videoUrl, ... })
├─ 转ANI: FileController.convertToAni({ videoUrl })
├─ 加水印: FileController.convertToWatermark({ videoUrl, watermarkUrl })
└─ 视频合成: FFmpegController.concat({ videoUrls })

代码示例

import { root } from '@repo/core'
import { FileController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  FileUploadResponse,
  VideoCompressRequest,
  ConvertToWebpRequest,
  ConvertToWatermarkRequest
} from '@repo/sdk'

// 上传文件
async function uploadFile(file: File): Promise<string> {
  const fileCtrl = root.get(FileController)

  const formData = new FormData()
  formData.append('file', file)

  const result: FileUploadResponse = await fileCtrl.uploadS3(formData)

  if (!result.status) {
    throw new Error(result.msg)
  }

  return result.data  // 文件URL
}

// 完整的视频处理流程
async function processVideo(file: File, options: {
  compress?: boolean;
  addWatermark?: boolean;
  watermarkUrl?: string;
  convertToWebp?: boolean;
}): Promise<string> {
  const fileCtrl = root.get(FileController)

  // 1. 上传原始文件
  let videoUrl = await uploadFile(file)

  // 2. 压缩视频(可选)
  if (options.compress) {
    const compressed = await fileCtrl.compressVideo({
      videoUrl,
      quality: 'medium'
    })
    videoUrl = compressed.data
  }

  // 3. 添加水印(可选)
  if (options.addWatermark && options.watermarkUrl) {
    const watermarked = await fileCtrl.convertToWatermark({
      videoUrl,
      watermarkUrl: options.watermarkUrl,
      position: 'bottomRight'
    })
    videoUrl = watermarked.data
  }

  // 4. 转换为 WebP可选
  if (options.convertToWebp) {
    const webp = await fileCtrl.convertToWebp({
      videoUrl,
      quality: 80,
      compressionLevel: 4,
      loop: true,
      resolution: '720p',
      fps: 15
    })
    videoUrl = webp.data
  }

  return videoUrl
}

// 一键上传并转换为 ANI 格式
async function uploadAndConvertToAni(file: File): Promise<string> {
  const fileCtrl = root.get(FileController)

  const formData = new FormData()
  formData.append('file', file)

  // 使用组合接口,一步完成上传和转换
  const result = await fileCtrl.uploadAndConvertToAni(formData)

  return result.data
}

5. 分类标签管理流程

场景:管理员管理模板分类和标签体系

涉及控制器

  • CategoryController
  • TagController

流程图

创建分类
    ↓
CategoryController.create({ name, nameEn })
    ↓
创建标签
    ↓
TagController.create({ name, nameEn })
    ↓
关联标签到分类
    ↓
TagController.updateCategoryTag({ tagId, categoryId, sortOrder })
    ↓
调整排序
    ↓
CategoryController.batchUpdateSortOrder({ items })
CategoryController.batchUpdateTagSortOrder({ categoryId, items })

代码示例

import { root } from '@repo/core'
import { CategoryController, TagController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  Category,
  Tag,
  ListCategoriesWithTagsResult
} from '@repo/sdk'

// 创建完整的分类标签体系
async function setupCategorySystem(): Promise<{ categories: Category[]; tags: Tag[] }> {
  const categoryCtrl = root.get(CategoryController)
  const tagCtrl = root.get(TagController)

  // 1. 创建分类
  const categories: Category[] = await Promise.all([
    categoryCtrl.create({ name: '热门推荐', nameEn: 'Hot', sortOrder: 1 }),
    categoryCtrl.create({ name: '视频生成', nameEn: 'Video', sortOrder: 2 }),
    categoryCtrl.create({ name: '图片生成', nameEn: 'Image', sortOrder: 3 })
  ])

  // 2. 创建标签
  const tags: Tag[] = await Promise.all([
    tagCtrl.create({ name: '人物', nameEn: 'Portrait' }),
    tagCtrl.create({ name: '风景', nameEn: 'Landscape' }),
    tagCtrl.create({ name: '动漫', nameEn: 'Anime' }),
    tagCtrl.create({ name: '写实', nameEn: 'Realistic' })
  ])

  // 3. 关联标签到分类
  const videoCategory = categories[1]
  for (let i = 0; i < tags.length; i++) {
    await tagCtrl.updateCategoryTag({
      tagId: tags[i].id,
      categoryId: videoCategory.id,
      sortOrder: i + 1
    })
  }

  return { categories, tags }
}

// 获取分类及其标签(用于前端导航)
async function getCategoryNavigation(): Promise<Category[]> {
  const categoryCtrl = root.get(CategoryController)

  const { categories }: ListCategoriesWithTagsResult = await categoryCtrl.listWithTags({
    page: 1,
    limit: 100
  })

  return categories
}

// 获取分类下的模板(带分页)
async function getCategoryTemplates(categoryId: string, page: number = 1) {
  const categoryCtrl = root.get(CategoryController)

  const category: Category = await categoryCtrl.getById(
    categoryId,
    page,
    20,
    'sortOrder',
    'asc'
  )

  return {
    category,
    templates: category.templates || []
  }
}

// 批量调整分类排序
async function reorderCategories(items: Array<{ id: string; sortOrder: number }>): Promise<void> {
  const categoryCtrl = root.get(CategoryController)

  await categoryCtrl.batchUpdateSortOrder({ items })
}

6. 消息通知处理流程

场景:用户查看和管理消息通知

涉及控制器

  • MessageController
  • AnnouncementController

流程图

获取未读数量
    ↓
MessageController.getUnreadCount()
AnnouncementController.getUnreadCount()
    ↓
获取消息列表
    ↓
MessageController.list({ type, isRead })
    ↓
标记已读
    ↓
MessageController.markRead({ id })
MessageController.batchMarkRead({ ids })

代码示例

import { root } from '@repo/core'
import { MessageController, AnnouncementController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  Message,
  UnreadCountResult,
  ListMessagesResult
} from '@repo/sdk'

// 获取所有未读通知数量
async function getAllUnreadCounts() {
  const messageCtrl = root.get(MessageController)
  const announcementCtrl = root.get(AnnouncementController)

  const [messageUnread, announcementUnread]: [UnreadCountResult, number] = await Promise.all([
    messageCtrl.getUnreadCount(),
    announcementCtrl.getUnreadCount()
  ])

  return {
    messages: messageUnread,
    announcements: announcementUnread,
    total: messageUnread.total + announcementUnread
  }
}

// 获取分类消息
async function getMessagesByType(type: 'SYSTEM' | 'ACTIVITY' | 'BILLING' | 'MARKETING'): Promise<ListMessagesResult> {
  const messageCtrl = root.get(MessageController)

  const { messages, total } = await messageCtrl.list({
    type,
    page: 1,
    limit: 50
  })

  return { messages, total }
}

// 一键已读所有消息
async function markAllAsRead(): Promise<void> {
  const messageCtrl = root.get(MessageController)

  // 获取所有未读消息
  const { messages } = await messageCtrl.list({
    isRead: false,
    limit: 1000
  })

  if (messages.length === 0) return

  // 批量标记已读
  await messageCtrl.batchMarkRead({
    ids: messages.map(m => m.id)
  })
}

// 消息中心完整数据
async function getMessageCenter() {
  const messageCtrl = root.get(MessageController)
  const announcementCtrl = root.get(AnnouncementController)

  const [
    unreadCount,
    systemMessages,
    activityMessages,
    billingMessages,
    announcements
  ] = await Promise.all([
    messageCtrl.getUnreadCount(),
    messageCtrl.list({ type: 'SYSTEM', limit: 10 }),
    messageCtrl.list({ type: 'ACTIVITY', limit: 10 }),
    messageCtrl.list({ type: 'BILLING', limit: 10 }),
    announcementCtrl.list({ page: 1, limit: 5 })
  ])

  return {
    unreadCount,
    systemMessages: systemMessages.messages,
    activityMessages: activityMessages.messages,
    billingMessages: billingMessages.messages,
    announcements: announcements.announcements
  }
}

7. 用户收藏夹管理流程

场景:用户管理收藏的模板和喜欢的内容

涉及控制器

  • TemplateSocialController
  • TemplateController

代码示例

import { root } from '@repo/core'
import { TemplateSocialController, TemplateController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  TemplateDetail,
  GetUserFavoritesResponse,
  GetUserLikesResponse
} from '@repo/sdk'

// 获取用户收藏列表(带模板详情)
async function getUserFavorites(page: number = 1): Promise<{ templates: TemplateDetail[]; total: number }> {
  const socialCtrl = root.get(TemplateSocialController)
  const templateCtrl = root.get(TemplateController)

  // 1. 获取收藏列表
  const { favorites, total }: GetUserFavoritesResponse = await socialCtrl.getUserFavorites({
    page,
    limit: 20
  })

  // 2. 获取模板详情
  const templates: TemplateDetail[] = await Promise.all(
    favorites.map(fav => templateCtrl.get(fav.templateId))
  )

  return { templates, total }
}

// 获取用户喜欢列表
async function getUserLikes(page: number = 1): Promise<GetUserLikesResponse> {
  const socialCtrl = root.get(TemplateSocialController)

  const { likes, total } = await socialCtrl.getUserLikes({
    page,
    limit: 20
  })

  return { likes, total }
}

// 收藏/取消收藏
async function toggleFavorite(templateId: string, isCurrentlyFavorited: boolean): Promise<boolean> {
  const socialCtrl = root.get(TemplateSocialController)

  if (isCurrentlyFavorited) {
    await socialCtrl.unfavorite({ templateId })
  } else {
    await socialCtrl.favorite({ templateId })
  }

  return !isCurrentlyFavorited
}

8. AI 内容生成流程

场景:直接使用 AI 模型生成图片或视频

涉及控制器

  • AigcController
  • ChatController

代码示例

import { root } from '@repo/core'
import { AigcController, ChatController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  AigcModel,
  GetModelsResult,
  SubmitTaskBody,
  GetTaskStatusResult,
  ChatRequest,
  ChatResponse
} from '@repo/sdk'

// 获取可用模型列表
async function getAvailableModels(category?: 'image' | 'video'): Promise<Record<string, AigcModel[]>> {
  const aigcCtrl = root.get(AigcController)

  const { models }: GetModelsResult = await aigcCtrl.getModels(category)

  // 按提供商分组
  const groupedModels = models.reduce((acc, model) => {
    const provider = model.provider
    if (!acc[provider]) acc[provider] = []
    acc[provider].push(model)
    return acc
  }, {} as Record<string, AigcModel[]>)

  return groupedModels
}

// 生成图片
async function generateImage(prompt: string, modelName: string, options?: {
  aspectRatio?: string;
  watermark?: boolean;
}): Promise<string | undefined> {
  const aigcCtrl = root.get(AigcController)

  // 1. 提交任务
  const { task_id } = await aigcCtrl.submitTask({
    mode: 'image',
    model_name: modelName,
    prompt,
    aspect_ratio: options?.aspectRatio || '1:1',
    watermark: options?.watermark ?? false
  })

  // 2. 轮询状态
  let status: GetTaskStatusResult = await aigcCtrl.getTaskStatus(task_id)
  while (status.status === 'PENDING' || status.status === 'PROCESSING') {
    await new Promise(resolve => setTimeout(resolve, 2000))
    status = await aigcCtrl.getTaskStatus(task_id)
  }

  if (status.status === 'FAILED') {
    throw new Error(status.error_message)
  }

  return status.result_url
}

// AI 对话(支持图片输入)
async function chat(prompt: string, options?: {
  modelName?: string;
  images?: string[];
  stream?: boolean;
}): Promise<string> {
  const chatCtrl = root.get(ChatController)

  const response: ChatResponse = await chatCtrl.chat({
    prompt,
    model_name: options?.modelName || 'gpt-4o',
    img_list: options?.images,
    stream: options?.stream ?? false
  })

  return response.data
}

// 图生图
async function imageToImage(imageUrl: string, prompt: string, modelName: string): Promise<string | undefined> {
  const aigcCtrl = root.get(AigcController)

  const { task_id } = await aigcCtrl.submitTask({
    mode: 'image',
    model_name: modelName,
    prompt,
    img_url: imageUrl
  })

  // 轮询状态
  let status: GetTaskStatusResult = await aigcCtrl.getTaskStatus(task_id)
  while (status.status === 'PENDING' || status.status === 'PROCESSING') {
    await new Promise(resolve => setTimeout(resolve, 2000))
    status = await aigcCtrl.getTaskStatus(task_id)
  }

  return status.result_url
}

9. 权限角色管理流程

场景:管理员配置系统权限和角色

涉及控制器

  • PermissionController
  • RoleController

代码示例

import { root } from '@repo/core'
import { PermissionController, RoleController } from '@repo/sdk'
// 复用 SDK 导出的类型
import type {
  Permission,
  RoleWithPermissions
} from '@repo/sdk'

// 初始化权限系统
async function initPermissionSystem(): Promise<{ permissions: Permission[]; roles: RoleWithPermissions[] }> {
  const permCtrl = root.get(PermissionController)
  const roleCtrl = root.get(RoleController)

  // 1. 创建基础权限
  const permissions: Permission[] = await Promise.all([
    permCtrl.create({ resource: 'project', action: 'create' }),
    permCtrl.create({ resource: 'project', action: 'read' }),
    permCtrl.create({ resource: 'project', action: 'update' }),
    permCtrl.create({ resource: 'project', action: 'delete' }),
    permCtrl.create({ resource: 'template', action: 'run' }),
    permCtrl.create({ resource: 'category', action: 'create' }),
    permCtrl.create({ resource: 'category', action: 'update' })
  ])

  // 2. 创建角色
  const userRole = await roleCtrl.create({
    name: 'user',
    displayName: '普通用户',
    description: '基础用户权限'
  })

  const adminRole = await roleCtrl.create({
    name: 'admin',
    displayName: '管理员',
    description: '管理员权限'
  })

  // 3. 分配权限给角色
  await roleCtrl.updatePermissions({
    roleId: userRole.id,
    permissionIds: permissions
      .filter(p => p.resource === 'project' || p.action === 'run')
      .map(p => p.id)
  })

  await roleCtrl.updatePermissions({
    roleId: adminRole.id,
    permissionIds: permissions.map(p => p.id)
  })

  return { permissions, roles: [userRole, adminRole] }
}

// 获取角色及其权限
async function getRolesWithPermissions(): Promise<RoleWithPermissions[]> {
  const roleCtrl = root.get(RoleController)

  const { roles } = await roleCtrl.list()

  return roles
}

接口依赖关系总结

主流程 依赖接口 说明
模板运行 Template → AIGC → File → Project 完整的内容生成流程
社交互动 Template → TemplateSocial 点赞、收藏、评论
项目管理 Project ↔ ProjectTag 双向关联
文件处理 File多个方法链式调用 上传→压缩→转换→水印
分类标签 Category ↔ Tag 多对多关联
消息通知 Message + Announcement 并行获取
AI 生成 AIGC + Chat 独立或组合使用
权限管理 Permission → Role 权限分配给角色