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)
| 名稱 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
uploadFn | Function | ✓ | — | 分片上傳函式,簽名見下方 VideoUploadOptions |
queryFn | Function | ✓ | — | 轉碼查詢函式,回傳 Promise<VideoQueryResult> |
accept | string | 'video/*' | 允許的檔案類型 | |
chunkSize | number | 2097152 | 分片大小(位元組),預設 2MB | |
retries | number | 3 | 分片上傳失敗時的重試次數 | |
multiple | boolean | false | 是否允許多選 | |
pollVideo | boolean | true | 上傳完成後是否輪詢轉碼結果 | |
fileList | ChunkSuccess | VideoQueryResult[] | undefined | 已傳檔案受控列表(v-model:file-list)。傳入後成功結果自動追加,配合 #file 插槽渲染預覽 + 刪除;不傳保持「單次上傳薄殼」行為 | |
maxCount | number | undefined | 檔案數量上限(含 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:fileList | ChunkSuccess | VideoQueryResult[] | 受控列表變化(成功追加 / remove() 移除),攜帶新列表 |
remove | (file: ChunkSuccess | VideoQueryResult, index: number) | #file 插槽的 remove() 被調用 |
exceed | File[] | 選擇檔案數超出 maxCount,攜帶本次選擇的檔案(本批已被整體拒絕) |
插槽(Slots)
default(作用域插槽)
| 作用域變數 | 類型 | 說明 |
|---|---|---|
isOver | boolean | 檔案正在拖曳懸停區域上方 |
pending | boolean | 上傳或輪詢進行中 |
progress | number | 當前上傳進度(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 }。