You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

7.4 KiB

RFC 132: 剧本资源数据结构重构

状态: 已实施
创建时间: 2026-01-26
实施时间: 2026-01-26


背景

原有的 resources.ts Mock 数据混淆了两个不同的概念:

  1. 剧本元素档案:从剧本中提取的角色、场景、道具的基础信息(纯文字描述)
  2. 项目素材:实际的图片/视频文件,用于视觉呈现

这导致数据结构混乱,不符合后端架构设计。

问题分析

原有设计的问题

// ❌ 错误:resources.ts 混合了两种数据
export const mockResources: Resource[] = [
  {
    id: '001',
    name: '孙悟空形象1',
    type: 'character',
    fileUrl: 'https://...',  // 图片 URL
    elementTagId: 'tag_char_002',  // 关联到标签
    // ... 这是项目素材,不是剧本元素档案
  }
];

正确的数据架构

根据后端文档分析,应该有三层数据结构:

1. screenplay_characters/scenes/props (剧本元素档案)
   ↓ 从剧本中提取的基础信息,不包含具体形象
   
2. screenplay_element_tags (元素标签)
   ↓ 元素的不同状态/变体(如年龄段、时代)
   
3. project_resources (项目素材 - 图片/视频)
   ↓ 关联到标签的具体视觉素材

解决方案

1. 文件拆分

重命名resources.tsscreenplay-resources.ts

  • 存储:剧本元素档案(角色、场景、道具的文字信息)
  • 不包含:图片、视频等视觉素材

新建project-resources.ts

  • 存储:实际的图片/视频素材
  • 关联:通过 elementTagId 关联到标签

2. 数据结构对比

screenplay-resources.ts(剧本元素档案)

export const mockScreenplayCharacters = [
  {
    character_id: '018e1234-5678-7abc-8def-300000000001',
    screenplay_id: '018e1234-5678-7abc-8def-100000000001',
    name: '孙悟空',
    description: '主角,齐天大圣,从被压五行山到护送唐僧西天取经的成长故事',
    role_type: 'main',
    line_count: 150,
    appearance_count: 45,
    has_tags: true, // 标识该角色有多个标签
    default_tag_id: 'tag_char_002', // 默认显示"青年"标签
    metadata: {
      gender: 'male',
      species: '石猴',
      personality: '桀骜不驯、勇敢正义',
      abilities: ['七十二变', '筋斗云', '火眼金睛']
    },
    // ❌ 没有 fileUrl, thumbnailUrl 等字段
  }
];

project-resources.ts(项目素材)

export const mockProjectResources: Resource[] = [
  {
    id: '018e1234-5678-7abc-8def-200000000001',
    projectId: '018e1234-5678-7abc-8def-100000000001',
    name: '孙悟空-青年形象1',
    type: 'character',
    fileUrl: 'https://images.unsplash.com/...',
    thumbnailUrl: 'https://images.unsplash.com/...',
    fileSize: 1024000,
    mimeType: 'image/png',
    width: 400,
    height: 533,
    elementTagId: 'tag_char_002', // 关联到"孙悟空-青年"标签
    isDefault: true, // 该标签的默认素材
    // ...
  }
];

3. 数据关联关系

剧本元素档案 (screenplay-resources.ts)
  └─ 孙悟空 (character_id: char_001)
      ├─ has_tags: true
      └─ default_tag_id: tag_char_002

剧本元素标签 (screenplay-tags.ts)
  ├─ 孙悟空-少年 (tag_id: tag_char_001)
  └─ 孙悟空-青年 (tag_id: tag_char_002) ← 默认标签

项目素材 (project-resources.ts)
  ├─ 孙悟空-少年形象1 (elementTagId: tag_char_001, isDefault: true)
  ├─ 孙悟空-少年形象2 (elementTagId: tag_char_001, isDefault: false)
  ├─ 孙悟空-青年形象1 (elementTagId: tag_char_002, isDefault: true)
  └─ 孙悟空-青年形象2 (elementTagId: tag_char_002, isDefault: false)

实施步骤

1. 创建新文件

  • client/src/mocks/screenplay-resources.ts
  • client/src/mocks/project-resources.ts

2. 更新导出

  • client/src/mocks/index.ts

3. 更新引用

  • client/src/services/mockApi.ts
  • client/src/services/mock/resourceApi.ts

4. 删除旧文件

  • client/src/mocks/resources.ts

数据示例

剧本元素档案(screenplay-resources.ts)

// 角色档案
{
  character_id: '018e1234-5678-7abc-8def-300000000001',
  screenplay_id: '018e1234-5678-7abc-8def-100000000001',
  name: '孙悟空',
  description: '主角,齐天大圣',
  role_type: 'main',
  has_tags: true,
  default_tag_id: 'tag_char_002',
  metadata: { gender: 'male', species: '石猴' }
}

// 场景档案
{
  scene_id: '018e1234-5678-7abc-8def-400000000001',
  screenplay_id: '018e1234-5678-7abc-8def-100000000001',
  scene_number: 1,
  title: '花果山水帘洞',
  location: '花果山',
  time_of_day: 'morning',
  description: '孙悟空的老家,瀑布后的洞府',
  has_tags: true,
  default_tag_id: 'tag_scene_001'
}

// 道具档案
{
  prop_id: '018e1234-5678-7abc-8def-500000000001',
  screenplay_id: '018e1234-5678-7abc-8def-100000000001',
  name: '金箍棒',
  description: '孙悟空的武器,可大可小',
  category: '武器',
  importance: 'key',
  has_tags: true,
  default_tag_id: 'tag_prop_001'
}

项目素材(project-resources.ts)

// 角色素材(关联到标签)
{
  id: '018e1234-5678-7abc-8def-200000000001',
  projectId: '018e1234-5678-7abc-8def-100000000001',
  name: '孙悟空-青年形象1',
  type: 'character',
  fileUrl: 'https://...',
  thumbnailUrl: 'https://...',
  elementTagId: 'tag_char_002', // 关联到"孙悟空-青年"标签
  isDefault: true // 该标签的默认素材
}

// 场景素材(关联到标签)
{
  id: '018e1234-5678-7abc-8def-200000000006',
  projectId: '018e1234-5678-7abc-8def-100000000001',
  name: '花果山水帘洞-白天1',
  type: 'scene',
  fileUrl: 'https://...',
  elementTagId: 'tag_scene_001', // 关联到"花果山-白天"标签
  isDefault: true
}

// 通用素材(不关联标签)
{
  id: '018e1234-5678-7abc-8def-200000000004',
  projectId: '018e1234-5678-7abc-8def-100000000001',
  name: '唐僧形象1',
  type: 'character',
  fileUrl: 'https://...',
  elementTagId: undefined, // 未关联标签
  isDefault: false
}

优势

1. 符合后端架构

  • 与后端数据库设计一致
  • 清晰的数据层级关系
  • 便于后续 API 集成

2. 职责分离

  • 剧本元素档案:纯文字信息,从剧本提取
  • 项目素材:视觉资源,用户上传或 AI 生成
  • 标签系统:连接档案和素材

3. 易于维护

  • 数据结构清晰,不混淆
  • 便于扩展新功能
  • 便于理解和调试

后续工作

短期(本周)

  • 更新所有引用 mockResources 的组件
  • 更新 TypeScript 类型定义(如需要)
  • 测试数据关联是否正确

中期(下周)

  • 实现剧本元素档案的 CRUD API
  • 实现项目素材的上传和管理 API
  • 集成标签系统

长期(未来)

  • AI 自动提取剧本元素档案
  • AI 生成项目素材
  • 素材库功能

参考文档

变更记录

2026-01-26

  • 创建 RFC
  • 实施文件拆分和重构
  • 更新所有引用

RFC 编号: 132
状态: 已实施
创建时间: 2026-01-26