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>✓—實際上傳函式。元件只管流程,網路層由外部注入
acceptstringimage/*檔案選擇框的 accept 屬性
thumbnailbooleanfalse是否作為縮圖上傳,作為第二參數傳給 uploadFn
multiplebooleanfalse是否允許多檔案
fileListImageUploadResult[]undefined已傳檔案受控列表(v-model:file-list)。傳入後成功結果自動追加,配合 #file 插槽渲染預覽 + 刪除;不傳保持「單次上傳薄殼」行為
maxCountnumberundefined檔案數量上限(含 fileList 現有計數)。選擇超限時整批拒絕並 emit exceed
beforeUpload(file: File, batch: File[]) => boolean | Promise<boolean>undefined逐檔案前置否決鉤子:返回 false 剔除該檔案(其餘照傳,全剔則本批終止)。體積 / 重名 / 自訂校驗與使用者提示都在鉤子裡做

Events

事件名載荷類型說明
successImageUploadResult單個檔案上傳成功後觸發
errorError上傳異常時觸發
update:fileListImageUploadResult[]受控列表變化(成功追加 / remove() 移除),攜帶新列表
remove(file: ImageUploadResult, index: number)#file 插槽的 remove() 被調用
exceedFile[]選擇檔案數超出 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 是外部注入的函式,通常封裝自 useUploader composable,與實際業務介面對接;Demo 中使用 mock 實作演示流程。
  • 上傳中(pending=true)元件靜默拒絕重複觸發,slot UI 必須用 pending 把觸發元素做 disabled 處理。
  • 影片分片上傳見 SwUploadVideo,一般檔案上傳見 SwUploadFile。