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

Changelog: 智能分镜工作台对接剧本上传和解析 API

日期: 2026-02-06
类型: Feature
影响范围: 前端 - 智能分镜工作台

概述

为智能分镜工作台(ParseFlowDialog)对接后端剧本上传和解析 API,支持多种文件格式的上传和智能解析,提升用户体验。

变更内容

1. 新增 API 服务层

文件: client/src/services/api/screenplay.ts

实现了完整的剧本 API 服务:

  • uploadAndParse() - 上传并解析剧本文件

    • 支持 FormData 上传
    • 支持上传进度回调
    • 智能路由:TXT/Markdown 同步解析,DOCX/PDF/RTF 异步解析
  • getParseStatus() - 查询解析状态

    • 用于轮询异步解析进度
    • 返回解析进度、内容和错误信息
  • getById() - 获取剧本详情

  • getAll() - 获取剧本列表

  • create() - 创建文本剧本

  • update() - 更新剧本

  • parseFile() - 手动触发文件解析

2. 新增 React Query Hooks

文件: client/src/hooks/api/useScreenplays.ts

实现了剧本相关的 React Query hooks:

  • useUploadScreenplay() - 上传剧本 mutation

    • 支持上传进度回调
    • 自动更新缓存
  • useParseStatus() - 解析状态查询

    • 支持自动轮询(默认 2 秒间隔)
    • 解析完成或失败时自动停止轮询
    • 自动更新剧本详情缓存
  • useScreenplays() - 剧本列表查询

  • useScreenplay() - 剧本详情查询

  • useCreateScreenplay() - 创建剧本 mutation

  • useUpdateScreenplay() - 更新剧本 mutation

  • useParseScreenplayFile() - 手动触发解析 mutation

3. 完善类型定义

文件: client/src/types/screenplay.ts

新增/补充了完整的剧本类型定义:

// 基础类型
export type ScreenplayType = 'text' | 'file';
export type ScreenplayStatus = 'draft' | 'in_review' | 'approved' | 'archived';
export type ParsingStatus = 'idle' | 'pending' | 'parsing' | 'completed' | 'failed';

// 核心接口
export interface Screenplay { ... }
export interface UploadScreenplayDto { ... }
export interface UploadScreenplayResponse { ... }
export interface ParseStatusResponse { ... }

4. 集成到 ParseFlowDialog

文件: client/src/components/features/storyboard/ParseFlowDialog.tsx

主要改动:

  1. 引入 hooks:

    import { useUploadScreenplay, useParseStatus } from '@/hooks/api/useScreenplays';
    
  2. 上传逻辑改造:

    • 优先使用后端 API 上传
    • 支持上传进度显示
    • 失败时降级到本地文件读取
    • 异步解析时启动轮询
  3. 解析状态监听:

    const { data: parseStatusData } = useParseStatus(uploadingScreenplayId, {
      enabled: !!uploadingScreenplayId,
      refetchInterval: 2000,
    });
    
  4. 状态同步:

    • 实时更新剧本列表中的解析状态
    • 解析完成/失败时显示 Toast 提示
    • 自动停止轮询

5. 更新 ParseFlowFile 类型

文件: client/src/components/features/storyboard/ParseFlowUploadPanel.tsx

export interface ParseFlowFile {
  id: string;
  title: string;
  content: string;
  uploadTime: number;
  parsingStatus?: 'idle' | 'pending' | 'parsing' | 'completed' | 'failed';
  taskId?: string;
}

6. 更新 API 导出

文件: client/src/services/api/index.ts

export { screenplayApi } from './screenplay';

技术亮点

1. 智能降级策略

try {
  // 优先使用后端 API
  const result = await uploadScreenplayMutation.mutateAsync({ ... });
} catch (error) {
  // 降级到本地文件读取
  const content = await readDocx(file);
  // ...
}

2. 自动轮询机制

refetchInterval: (query) => {
  const data = query.state.data;
  // 解析完成或失败时停止轮询
  if (data?.parsingStatus === 'completed' || data?.parsingStatus === 'failed') {
    return false;
  }
  return 2000; // 否则每 2 秒轮询
}

3. 上传进度反馈

onUploadProgress: (progressEvent) => {
  if (onProgress && progressEvent.total) {
    const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    onProgress(progress);
  }
}

4. 缓存自动更新

onSuccess: (result) => {
  // 使列表缓存失效
  queryClient.invalidateQueries({ queryKey: screenplayKeys.lists() });
  
  // 同步解析完成时直接设置详情缓存
  if (result.parsingStatus === 'completed' && result.content) {
    queryClient.setQueryData(screenplayKeys.detail(result.screenplayId), { ... });
  }
}

用户体验提升

  1. 实时进度反馈: 上传进度条 + 解析状态提示
  2. 智能路由: 小文件同步解析(秒级响应),大文件异步解析(后台处理)
  3. 容错机制: API 失败时自动降级到本地解析
  4. 状态同步: 解析状态实时更新,无需手动刷新

后端接口依赖

1. 上传并解析剧本

POST /api/v1/screenplays/upload-and-parse
Content-Type: multipart/form-data

Body:
- project_id: string
- name: string
- file: File

Response:
{
  "screenplay_id": "uuid",
  "name": "string",
  "type": "file",
  "file_url": "string",
  "parsing_status": "parsing" | "completed",
  "content": "string?",
  "task_id": "string?"
}

2. 查询解析状态

GET /api/v1/screenplays/{screenplay_id}/parse-status

Response:
{
  "screenplay_id": "uuid",
  "parsing_status": "idle" | "pending" | "parsing" | "completed" | "failed",
  "progress": 0-100,
  "content": "string?",
  "word_count": number?,
  "parsing_error": "string?",
  "message": "string"
}

测试建议

1. 功能测试

  • 上传 TXT 文件(同步解析)
  • 上传 DOCX 文件(异步解析)
  • 上传 PDF 文件(异步解析)
  • 上传进度显示正常
  • 解析状态轮询正常
  • 解析完成后内容显示正常
  • 解析失败时错误提示正常

2. 边界测试

  • 网络断开时的降级处理
  • 超大文件上传(>100MB)
  • 解析超时处理
  • 并发上传多个文件
  • 重复上传同一文件

3. 性能测试

  • 轮询不会造成性能问题
  • 缓存更新策略正确
  • 内存泄漏检查

后续优化

  1. 批量上传: 支持一次上传多个文件
  2. 断点续传: 大文件上传失败后可续传
  3. 解析预览: 解析过程中显示部分内容
  4. 智能重试: 解析失败时自动重试
  5. 进度详情: 显示更详细的解析进度(如:正在提取文本、正在分析结构等)

相关文档

  • 后端接口文档: server/app/api/v1/screenplays.py
  • 后端 Schema: server/app/schemas/screenplay.py
  • 前端类型定义: client/src/types/screenplay.ts
  • API 服务层: client/src/services/api/screenplay.ts
  • React Query Hooks: client/src/hooks/api/useScreenplays.ts

影响评估

  • 破坏性变更: 无
  • 向后兼容: 是(保留本地文件读取作为降级方案)
  • 依赖变更: 无新增依赖
  • 数据库变更: 无

作者

  • 开发者: AI Assistant
  • 审核者: 待定
  • 日期: 2026-02-06