Appearance
BizUploadImage 图片上传
图片墙形态的图片上传:数量 / 大小前置校验、上传中占位、失败可删重传、点击全屏预览。上传实现由业务侧以 request 注入,组件零接口;v-model 同步图片地址数组,可直接进表单提交。
基础用法
上传
最多 9 张,单张不超过 5MB,支持点击放大预览
v-model(0 张):(空)
request 返回图片地址即入墙;v-model 同步地址数组。
<script setup lang="ts">
/** 基础用法:request 注入上传实现(组件零接口),v-model 同步图片地址数组 */
import { ref } from 'vue'
import { BizUploadImage } from 'vue3-ep-biz-lib'
const urls = ref<string[]>([])
/** 在线图池(模拟上传服务返回的地址) */
const POOL = [
'photo-1506744038136-46273834b3fb',
'photo-1470071459604-3b5ec3a7fe05',
'photo-1501785888041-af3ef285b470',
]
let cursor = 0
/** 模拟上传接口:800ms 后返回图片地址 */
const upload = async (_file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 800))
const id = POOL[cursor % POOL.length]
cursor += 1
return `https://images.unsplash.com/${id}?w=400&h=400&fit=crop&q=60`
}
</script>
<template>
<div>
<BizUploadImage v-model="urls" :request="upload" tip="最多 9 张,单张不超过 5MB,支持点击放大预览" />
<div class="tip">v-model({{ urls.length }} 张):{{ urls.length > 0 ? urls.join('、') : '(空)' }}</div>
</div>
</template>
<style scoped>
.tip {
margin-top: 8px;
font-size: 13px;
color: var(--el-text-color-secondary);
word-break: break-all;
}
</style>
显示代码
其他用法
上传
最多 3 张;尺寸覆盖为 72px(css 变量 --biz-upload-image-size)
limit 数量上限、css 变量覆盖缩略尺寸、编辑回显(:model 初始值)、clear() 清空。
<script setup lang="ts">
/** 其他用法:limit 限制 + 尺寸 css 变量覆盖 + 编辑回显(:model 初始值)+ clear() */
import { ref } from 'vue'
import { BizButton, BizUploadImage } from 'vue3-ep-biz-lib'
import type { BizUploadImageInstance } from 'vue3-ep-biz-lib'
/** 编辑场景:已有图片回显 */
const urls = ref<string[]>(['https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&h=400&fit=crop&q=60'])
const upload = async (_file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 600))
return 'https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=400&h=400&fit=crop&q=60'
}
const viewerRef = ref<BizUploadImageInstance | null>(null)
</script>
<template>
<div>
<BizUploadImage
ref="viewerRef"
v-model="urls"
:request="upload"
:limit="3"
tip="最多 3 张;尺寸覆盖为 72px(css 变量 --biz-upload-image-size)"
style="--biz-upload-image-size: 72px"
/>
<div class="row">
<BizButton size="small" @click="urls = ['https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&h=400&fit=crop&q=60']">重置为回显数据</BizButton>
<BizButton size="small" @click="viewerRef?.clear()">清空</BizButton>
</div>
</div>
</template>
<style scoped>
.row {
display: flex;
gap: 8px;
margin-top: 12px;
}
</style>
显示代码
证照上传
上传证照
营业执照清晰原件照片(jpg / png),单张不超过 2MB,正本 + 副本各一张
已上传 1 / 2 张;点击缩略图可全屏预览
实名场景:
accept 限定 jpg / png、limit=2(正本 + 副本)、max-size=2,trigger-text 定制触发文案,tip 说明拍摄要求;上传后点击缩略图全屏预览。<script setup lang="ts">
/** 场景:证照上传——严格限制数量 / 大小,trigger 文案定制 */
import { ref } from 'vue'
import { BizUploadImage } from 'vue3-ep-biz-lib'
const images = ref<string[]>([
'https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=200&h=140&fit=crop',
])
const upload = async (file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 700))
return URL.createObjectURL(file)
}
</script>
<template>
<div style="max-width: 420px">
<BizUploadImage
v-model="images"
:request="upload"
accept="image/jpeg,image/png"
:limit="2"
:max-size="2"
trigger-text="上传证照"
tip="营业执照清晰原件照片(jpg / png),单张不超过 2MB,正本 + 副本各一张"
/>
<div style="margin-top: 8px; font-size: 13px; color: var(--el-text-color-secondary)">
已上传 {{ images.length }} / 2 张;点击缩略图可全屏预览
</div>
</div>
</template>
显示代码
个人头像
正方形照片效果最佳,上传后自动裁切为圆形展示
当前头像地址:https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop
头像场景:limit=1 单图、css 变量放大触发块,上传后圆形展示。
<script setup lang="ts">
/** 场景:个人头像——单图裁切位 + 圆形缩略预览 */
import { ref } from 'vue'
import { BizUploadImage } from 'vue3-ep-biz-lib'
const avatar = ref<string[]>(['https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop'])
const upload = async (file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 600))
return URL.createObjectURL(file)
}
</script>
<template>
<div style="max-width: 420px">
<BizUploadImage
v-model="avatar"
:request="upload"
:limit="1"
:max-size="5"
trigger-text="更换头像"
tip="正方形照片效果最佳,上传后自动裁切为圆形展示"
style="--biz-upload-image-size: 88px"
/>
<div style="margin-top: 8px; font-size: 13px; color: var(--el-text-color-secondary)">当前头像地址:{{ avatar[0] ?? '(未设置)' }}</div>
</div>
</template>
显示代码
商品图册
添加图片
首图为主图;jpg / png / webp,单张 ≤ 3MB
已传 2 / 9 张,还可传 7 张
电商场景:最多 9 张、实时额度提示(已传 / 还可传),首图即主图。
<script setup lang="ts">
/** 场景:商品图册——最多 9 张 + 剩余额度提示 */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizUploadImage } from 'vue3-ep-biz-lib'
const gallery = ref<string[]>([
'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=200&h=150&fit=crop',
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=200&h=150&fit=crop',
])
const upload = async (file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 700))
if (file.size > 0) return URL.createObjectURL(file)
return ''
}
const onChange = (): void => {
if (gallery.value.length >= 9) ElMessage.warning('图册已满 9 张,请先删除再上传')
}
</script>
<template>
<div style="max-width: 560px">
<BizUploadImage
v-model="gallery"
:request="upload"
:limit="9"
:max-size="3"
trigger-text="添加图片"
tip="首图为主图;jpg / png / webp,单张 ≤ 3MB"
@update:model-value="onChange"
/>
<div style="margin-top: 8px; font-size: 13px; color: var(--el-text-color-secondary)">已传 {{ gallery.length }} / 9 张,还可传 {{ 9 - gallery.length }} 张</div>
</div>
</template>
显示代码
多规格图分组
红 1 张 蓝 0 张 绿 0 张
上传红色规格图
每个规格最多 3 张,至少 1 张才可上架该规格
SKU 场景:红 / 蓝 / 绿三规格各自独立 v-model(:key 切换重建),规格徽标实时显示各自张数。
<script setup lang="ts">
/** 场景:多规格图——按规格分组各自上传(每个规格独立 v-model) */
import { ref } from 'vue'
import { ElRadioButton, ElRadioGroup, ElTag } from 'element-plus'
import { BizUploadImage } from 'vue3-ep-biz-lib'
const spec = ref('red')
const images = ref<Record<string, string[]>>({
red: ['https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=160&h=120&fit=crop'],
blue: [],
green: [],
})
const upload = async (file: File): Promise<string> => {
await new Promise((resolve) => setTimeout(resolve, 600))
return URL.createObjectURL(file)
}
</script>
<template>
<div style="max-width: 560px">
<div style="display: flex; gap: 10px; align-items: center; margin-bottom: 10px">
<ElRadioGroup v-model="spec" size="small">
<ElRadioButton value="red">红色</ElRadioButton>
<ElRadioButton value="blue">蓝色</ElRadioButton>
<ElRadioButton value="green">绿色</ElRadioButton>
</ElRadioGroup>
<ElTag v-for="(count, key) in images" :key="key" size="small" :type="count.length > 0 ? 'success' : 'info'">
{{ key === 'red' ? '红' : key === 'blue' ? '蓝' : '绿' }} {{ count.length }} 张
</ElTag>
</div>
<BizUploadImage
:key="spec"
v-model="images[spec]"
:request="upload"
:limit="3"
:max-size="2"
:trigger-text="`上传${spec === 'red' ? '红' : spec === 'blue' ? '蓝' : '绿'}色规格图`"
tip="每个规格最多 3 张,至少 1 张才可上架该规格"
/>
</div>
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| model-value / v-model | string[] | [] | 已上传图片地址 |
| request | (file: File) => Promise<string> | — | 必填。上传实现(业务接口在业务侧),resolve 图片地址 |
| accept | string | 'image/*' | 接受的文件类型 |
| limit | number | 9 | 数量上限(达上限隐藏加号) |
| max-size | number | 5 | 单张大小上限(MB) |
| tip | string | '' | 底部提示文案 |
| trigger-text | string | '上传' | 触发块文字说明;传空串仅显示图标 |
其余属性(
name/headers/multiple...)经v-bind="$attrs"全量透传 el-upload。
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| update:model-value | (urls: string[]) | 图片列表变化(仅成功项) |
| error | (message: string) | 前置校验不过 / 上传失败 |
Slots
| 插槽名 | 说明 |
|---|---|
| — | 无插槽 |
Expose
| 属性/方法 | 说明 |
|---|---|
| clear | () => void 清空全部图片 |
| records | 当前记录(含上传中 / 失败态) |