SwUploadVideo 是视频文件的分片上传组件。它将上传逻辑完全交由调用方通过 uploadFn 和 queryFn 两个 Props 注入,自身不预设任何接口地址,适配任意后端协议。

上传完成后可选择是否通过 queryFn 轮询转码结果(pollVideo 控制)。组件通过默认 slot 暴露当前状态,支持完全自定义触发区域 UI,包括拖拽上传。

基础用法(按钮式)

最简用法:按钮触发选视频 → 分片进度 → 转码轮询 → 完成后给出可播放预览。

基础用法(按钮 + 进度 + 可播放预览)

加载中...
<!-- accept 限定格式(默认 'video/*');multiple 允许多选——
     每个文件独立走「上传 + 转码轮询」,逐个 emit @success -->
<SwUploadVideo
  v-slot="{ open, pending }"
  :upload-fn="chunkUpload"
  :query-fn="queryVideo"
  accept="video/mp4"
  multiple
  @success="(r) => list.push(r)"
>
  <SwButton :disabled="pending" @click="() => open()">批量上传视频</SwButton>
</SwUploadVideo>

自定义触发区(#default slot)

「+ 号上传卡」:默认 slot 完全接管触发区 UI,上传 / 转码进度直接画在卡内。

+ 号上传卡(slot 自定义)

加载中...

拖拽上传

slot 的 isOver 状态可以高亮拖拽区域;进度条 + 转码等待提示也由 slot 自绘。

拖拽 + 进度 + 转码轮询

加载中...

不轮询转码(pollVideo=false)

仅需获取分片上传成功的原始结果(ChunkSuccess),不等待转码完成时使用。

不等转码(ChunkSuccess 即返回)

加载中...

错误处理

分片失败(重试耗尽)时触发 error 事件。

分片失败反馈(@error)

加载中...

受控列表(fileList + #file + maxCount + beforeUpload)

传 v-model:file-list 后组件接管已传列表:成功结果自动追加、#file 插槽逐条渲染预览与删除;maxCount 控制数量上限(超限整批拒绝并 emit exceed)、beforeUpload 做逐文件前置校验(体积 / 重名 / 类型,返回 false 剔除)。这是迁移老项目多文件上传(预览 + 删除 + limit + 校验)的完整形态。

<template>
  <SwUploadVideo
    v-model:file-list="videos"
    :upload-fn="chunkUpload"
    :query-fn="queryVideo"
    :max-count="3"
    :before-upload="(f) => f.size <= maxSize || (useToast().warning('视频过大'), false)"
    multiple
    @exceed="useToast().warning('最多上传 3 个视频')"
  >
    <template #default="{ open, pending, progress }">
      <SwButton :loading="pending" @click="open">
        {{ pending ? `上传中 ${progress}%` : '选择视频' }}
      </SwButton>
    </template>
    <template #file="{ file, remove }">
      <span>{{ file.id }} <SwButton aria-label="删除" @click="remove">✕</SwButton></span>
    </template>
  </SwUploadVideo>
</template>

Props

名称类型必填默认值说明
uploadFn(_files: File[], _options: VideoUploadOptions) => void✓—分片上传函数
queryFn(_id: string, _retries?: number) => Promise<VideoQueryResult>✓—转码结果查询函数
acceptstring'video/*'文件选择 accept
chunkSizenumber2097152(2 MB)分片大小(字节)
retriesnumber3单片重试次数
multiplebooleanfalse是否允许多文件
pollVideobooleantrue上传完成后是否轮询转码结果
fileListChunkSuccess | VideoQueryResult[]undefined已传文件受控列表(v-model:file-list)。传入后成功结果自动追加,配合 #file 插槽渲染预览 + 删除;不传保持"单次上传薄壳"行为
maxCountnumberundefined文件数量上限(含 fileList 现有计数)。选择超限时整批拒绝并 emit exceed
beforeUpload(file: File, batch: File[]) => boolean | Promise<boolean>undefined逐文件前置否决钩子:返回 false 剔除该文件(其余照传,全剔则本批终止)。体积 / 重名 / 自定义校验与用户提示都在钩子里做

类型定义

VideoUploadOptions

interface VideoUploadOptions {
  chunkSize?: number
  retries?: number
  onProcess?: (result: ChunkProgress) => void
  onSuccess?: (result: { id: string; file_md5: string; file: File }) => void
  onError?: (result: { file: File; error: unknown }) => void
  onBefore?: (file: File) => void
}

interface ChunkProgress {
  file: File
  processed_num: number
  chunk_total: number
  chunk_index: number
  file_md5: string
}

VideoQueryResult

interface VideoQueryResult {
  id: string
  file_m3u8: string
  file_duration: string
  file_preview_m3u8: string
  file_status: string
  width: number
  height: number
}

Events

事件名载荷类型说明
progresspct: number上传进度百分比(0-100)
successresult: ChunkSuccess | VideoQueryResultpollVideo=true 时 VideoQueryResult(转码完);pollVideo=false 时 ChunkSuccess(仅分片上传完)
errorerr: Error上传或转码错误
update:fileListChunkSuccess | VideoQueryResult[]受控列表变化(成功追加 / remove() 移除),携带新列表
remove(file: ChunkSuccess | VideoQueryResult, index: number)#file 插槽的 remove() 被调用
exceedFile[]选择文件数超出 maxCount,携带本次选择的文件(本批已被整体拒绝)

Slots

default(作用域 slot)

作用域变量类型说明
isOverboolean文件正在拖拽悬停区域上方
pendingboolean上传或轮询进行中
progressnumber当前上传进度(0–100)
open() => void手动触发文件选择对话框
file{ file, index, remove }传了 fileList 时对列表逐条渲染(预览 / 删除按钮由消费方自绘);remove() 从列表移除该条并 emit remove

注意事项

  • uploadFn 和 queryFn 均为必填,需由业务层自行实现并传入。
  • chunkSize 默认 2MB(2097152 字节),需与后端约定保持一致。
  • pollVideo=true 时,success 事件将在转码完成后才触发,结果类型为 VideoQueryResult。
  • pollVideo=false 时,success 在分片上传完成后立即触发,结果为 { id, file_md5, file }。