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.6 KiB

RFC 137: 角色-对白关联表单交互设计

状态:Draft
创建日期:2026-01-30
参考:ui-ux-pro-max UX 准则、现有 StoryboardDialogue 数据模型


1. 背景与目标

1.1 当前问题

  • 分镜表单的「角色」栏仅为 Badge 列表 + ResourcePicker,与对白无关联
  • 对白目前存在「拍摄描述」字段(原 dialogue),与角色无一一对应
  • 后端 StoryboardDialogue 已支持 characterName,一个分镜可有多个角色各自的对白

1.2 设计目标

  1. 关联展示:选择角色后自动展示该角色在此分镜下的对白
  2. 可编辑:对白以输入框形式,支持手动编辑
  3. 初始化:AI 解析剧本时自动提取对白并关联角色
  4. 数据一致:与 StoryboardDialogue 模型对齐(characterName + text)

2. 数据结构扩展

2.1 DraftShot 扩展

// client/src/types/storyboard.ts

export interface DraftShot {
  // ... 现有字段
  characters: string[];
  /** 角色-对白映射。key=角色名, value=该角色在此分镜的对白文本 */
  characterDialogues: Record<string, string>;
}
  • 保留 characters:角色列表(用于 ResourcePicker、智能提取)
  • 新增 characterDialogues:按角色存储对白
  • dialogue 已改为拍摄描述,不再用于对白

2.2 AI 解析输出

剧本 AI 解析时需输出分镜维度的角色对白,例如:

{
  "storyboards": [
    {
      "characters": ["唐僧", "孙悟空"],
      "characterDialogues": {
        "唐僧": "如何才能救你?",
        "孙悟空": "山顶有张符咒,撕下来就行!"
      }
    }
  ]
}

3. 交互设计(基于 ui-ux-pro-max)

3.1 推荐方案:角色-对白行式布局

布局:左侧角色名,右侧对白输入框,一行一个角色。类似两列表格,结构清晰、一目了然。

┌────────────┬──────────────────────────────────────┐
│ 角色       │ 对白                                 │
├────────────┼──────────────────────────────────────┤
│ 孙悟空     │ [师父!救救我!______________]       │
│ 唐僧       │ [如何才能救你?______________]       │
│ 土地公公   │ [(无对白)________________]         │  ← 此分镜该角色无对白
└────────────┴──────────────────────────────────────┘

无对白角色:该角色在此分镜无台词时,输入框为空,placeholder 显示「(此分镜无对白)」;用户仍可手动输入,以补充漏提取的对白。

UX 准则 应用
Form Labels 表头「角色」「对白」;每行角色名作为该行输入框的语义标签
Input Affordance 输入框有 border/background,明显可编辑
Empty States 无对白时 placeholder:「(此分镜无对白)」;无角色时显示「添加角色后可编辑对白」
Input Affordance 输入框保持可编辑,便于用户补充

优点

  • 结构简单,无展开/收起,学习成本低
  • 所有角色及对白同屏可见,便于对照修改
  • 天然支持「有/无对白」:无对白即为空输入框

4. 视觉与交互规格

4.1 角色-对白行式结构

┌─────────────────────────────────────────────────────────────┐
│ [User图标] 角色                      [+ 添加角色]            │
├──────────────────┬──────────────────────────────────────────┤
│ 孙悟空       [×] │ ┌────────────────────────────────────┐   │
│                  │ │ 师父!救救我!                      │   │
│                  │ └────────────────────────────────────┘   │
├──────────────────┼──────────────────────────────────────────┤
│ 唐僧         [×] │ ┌────────────────────────────────────┐   │
│                  │ │ 如何才能救你?                      │   │
│                  │ └────────────────────────────────────┘   │
├──────────────────┼──────────────────────────────────────────┤
│ 土地公公     [×] │ ┌────────────────────────────────────┐   │
│                  │ │ (此分镜无对白)                    │   │  ← placeholder
│                  │ └────────────────────────────────────┘   │
└──────────────────┴──────────────────────────────────────────┘
  • 左列:角色名 + 删除按钮 [×],固定宽度(如 100–120px)
  • 右列:单行 Input 或可折叠的 Textarea(短对白用 Input,长对白可展开)
  • 添加角色:顶部 ResourcePicker,与现有一致

4.2 状态与反馈

状态 表现
有对白 输入框显示对白内容
无对白 输入框为空,placeholder:「(此分镜无对白)」
无角色 空状态:「添加角色后可编辑对白」
焦点 输入框 focus:ring-2 focus:ring-brand

4.3 输入框类型建议

  • 默认:单行 Inputtype="text"),适合大多对白
  • 可选:对白较长时使用 Textarea,或支持点击展开为多行

4.4 无障碍

  • 每行用 role="row"aria-labelledby 关联角色名与输入框
  • 输入框有 aria-label 或通过 <label> 关联角色名

5. 数据流与回调

5.1 新增 Props

// ScreenplayStoryboardForm

onCharacterDialogueChange: (characterName: string, text: string) => void;

5.2 父组件职责

  • 维护 characterDialogues
  • 智能提取时写入 AI 返回的角色对白
  • 同步到 content markdown(若需持久化到现有格式)

6. 实现步骤建议

  1. 扩展 DraftShot 类型,增加 characterDialogues
  2. 实现 CharacterDialogueRow 组件(角色名 + 对白 Input,一行一个)
  3. 在表单中替换原 ResourceSelector(仅角色部分)为角色列表 + 行式对白区
  4. 连接 onCharacterDialogueChange 与父组件 state
  5. 更新 ScreenplayParseDialog 的解析与初始化逻辑,写入 characterDialogues
  6. 添加空状态、加载态(若 AI 提取异步)的 UI

7. 参考资料

  • client/src/mocks/storyboard-dialogues.ts:StoryboardDialogue 结构
  • client/src/mocks/storyboards.ts:分镜 dialogues 示例(多角色对白)
  • ui-ux-pro-max:Forms、Feedback、Animation、Accessibility 相关准则