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 剔除)。这是迁移老项目多文件上传(预览 + 删除 + limit + 校验)的完整形态。

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