SwUploadVideo 是視訊檔案的分片上傳元件。上傳邏輯完全由呼叫方透過 uploadFn 和 queryFn 兩個屬性注入,元件本身不預設任何介面位址,可適配任意後端協定。

上傳完成後可選擇是否透過 queryFn 輪詢轉碼結果(由 pollVideo 控制)。元件透過預設插槽 暴露當前狀態,支援完全自訂觸發區域 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 剔除)。

<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)

名稱類型必填預設值說明
uploadFnFunction✓—分片上傳函式,簽名見下方 VideoUploadOptions
queryFnFunction✓—轉碼查詢函式,回傳 Promise<VideoQueryResult>
acceptstring'video/*'允許的檔案類型
chunkSizenumber2097152分片大小(位元組),預設 2MB
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)

名稱參數說明
progress[pct: number]分片上傳進度,0–100
success[result: ChunkSuccess | VideoQueryResult]pollVideo=false 時為 ChunkSuccess,true 時為 VideoQueryResult
error[err: Error]上傳或輪詢失敗時觸發
update:fileListChunkSuccess | VideoQueryResult[]受控列表變化(成功追加 / remove() 移除),攜帶新列表
remove(file: ChunkSuccess | VideoQueryResult, index: number)#file 插槽的 remove() 被調用
exceedFile[]選擇檔案數超出 maxCount,攜帶本次選擇的檔案(本批已被整體拒絕)

插槽(Slots)

default(作用域插槽)

作用域變數類型說明
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 }。