SwUploadImage
圖片上傳元件,無樣式:自身不渲染任何 UI,透過 uploadFn prop 注入實際上傳邏輯,透過預設 slot 暴露狀態(isOver / pending / open),由消費方完全掌控視覺呈現。支援點擊選擇和拖拽兩種方式,多檔案並行上傳,成功 / 失敗按條 emit。
基本用法(按鈕式)
最簡用法:按鈕觸發選擇圖片,上傳完成後展示預覽。
基本用法(按鈕 + 結果預覽)
加载中...
自訂觸發區(#default slot)
經典「+ 號上傳卡」:預設 slot 完全接管觸發區 UI,上傳完成後 + 號變成預覽圖。
+ 號上傳卡(slot 自訂)
加载中...
拖拽上傳
slot 的 isOver 標記拖拽懸停態,可用來高亮放置區。
拖拽 + 點擊雙通道
加载中...
多圖上傳
開啟 multiple 後可同時選擇或拖入多張圖片,內部並行上傳並逐條 emit success。
多圖上傳
加载中...
錯誤處理
uploadFn reject 時觸發 error 事件,按條回饋。
上傳失敗回饋(@error)
加载中...
受控列表(fileList + #file + maxCount + beforeUpload)
傳 v-model:file-list 後元件接管已傳列表:成功結果自動追加、#file 插槽逐條渲染預覽與刪除;maxCount 控制數量上限(超限整批拒絕並 emit exceed)、beforeUpload 做逐檔案前置校驗(體積 / 重名 / 類型,返回 false 剔除)。
<template>
<SwUploadImage
v-model:file-list="images"
:upload-fn="uploadImage"
:max-count="9"
:before-upload="checkSize"
multiple
@exceed="useToast().warning('最多只能选择 9 张图片')"
>
<template #default="{ open, pending }">
<SwButton :loading="pending" @click="open">选择图片</SwButton>
</template>
<template #file="{ file, remove }">
<span class="thumb">
<SwImage :src="file.value" alt="已传图片" ratio="1/1" />
<SwButton aria-label="删除" @click="remove">✕</SwButton>
</span>
</template>
</SwUploadImage>
</template>
<script setup lang="ts">
const images = ref<ImageUploadResult[]>([])
const checkSize = (file: File) =>
file.size <= 10 * 1024 * 1024 || (useToast().warning('图片不能超过 10MB'), false)
</script>
Props
| 名稱 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
uploadFn | (file: File, thumbnail: boolean) => Promise<ImageUploadResult> | ✓ | — | 實際上傳函式。元件只管流程,網路層由外部注入 |
accept | string | image/* | 檔案選擇框的 accept 屬性 | |
thumbnail | boolean | false | 是否作為縮圖上傳,作為第二參數傳給 uploadFn | |
multiple | boolean | false | 是否允許多檔案 | |
fileList | ImageUploadResult[] | undefined | 已傳檔案受控列表(v-model:file-list)。傳入後成功結果自動追加,配合 #file 插槽渲染預覽 + 刪除;不傳保持「單次上傳薄殼」行為 | |
maxCount | number | undefined | 檔案數量上限(含 fileList 現有計數)。選擇超限時整批拒絕並 emit exceed | |
beforeUpload | (file: File, batch: File[]) => boolean | Promise<boolean> | undefined | 逐檔案前置否決鉤子:返回 false 剔除該檔案(其餘照傳,全剔則本批終止)。體積 / 重名 / 自訂校驗與使用者提示都在鉤子裡做 |
Events
| 事件名 | 載荷類型 | 說明 |
|---|---|---|
success | ImageUploadResult | 單個檔案上傳成功後觸發 |
error | Error | 上傳異常時觸發 |
update:fileList | ImageUploadResult[] | 受控列表變化(成功追加 / remove() 移除),攜帶新列表 |
remove | (file: ImageUploadResult, index: number) | #file 插槽的 remove() 被調用 |
exceed | File[] | 選擇檔案數超出 maxCount,攜帶本次選擇的檔案(本批已被整體拒絕) |
ImageUploadResult 結構:
type ImageUploadResult = { id: string; value: string; width: number; height: number }
Slots
| 插槽名 | 作用域參數 | 說明 |
|---|---|---|
default | { isOver, pending, open } | 拖拽懸停態、上傳中狀態、打開檔案選擇框 |
file | { file, index, remove } | 傳了 fileList 時對列表逐條渲染(預覽 / 刪除按鈕由消費方自繪);remove() 從列表移除該條並 emit remove |
注意事項
- 元件無樣式:不內建任何 CSS,UI 完全交給 slot 的消費方實作。
uploadFn是外部注入的函式,通常封裝自useUploadercomposable,與實際業務介面對接;Demo 中使用 mock 實作演示流程。- 上傳中(
pending=true)元件靜默拒絕重複觸發,slot UI 必須用pending把觸發元素做 disabled 處理。 - 影片分片上傳見 SwUploadVideo,一般檔案上傳見 SwUploadFile。