import { ElUpload, ElIcon, ElProgress } from 'element-plus'
import { SuccessFilled, CircleCloseFilled, Paperclip } from '@element-plus/icons-vue'
import './index.less'
import { toRefs, defineComponent, computed } from 'vue'
import CipButton from '@cip/components/cip-button'
export default defineComponent({
name: 'CipUpload',
props: {
uploadFile: { // 文件上传
type: Function,
default: (info) => {}
},
accept: { // 可选择文件类型控制
type: String,
default: '' // 所有
},
beforeRemove: Function, // 删除文件之前的钩子
onRemove: Function, // 文件列表移除文件时的钩子
beforeUpload: Function, // 上传文件之前的钩子
onError: Function, // 文件上传失败时的钩子
onSuccess: Function, // 文件上传成功时的钩子
onPreview: Function, // 点击文件列表中已上传的文件时的钩子
fileList: { type: Array, default: () => [] }, // 默认上传文件
multiple: Boolean, // 是否允许多个
disabled: Boolean, // 禁用状态
drag: Boolean, // 是否拖拽上传
action: String, // 上传地址
limit: Number, // 上传数量限制
showFileList: { // 是否展示默认,后期考虑不用默认的
type: Boolean,
default: true
},
itemStyle: { // 文件列表的行内样式
type: Object,
default: () => ({})
},
listType: { // 展示形式
type: String,
default: 'text'
}
},
emits: ['update:fileList'],
inheritAttrs: false,
setup (props, { slots, emit, attrs }) {
const { fileList } = toRefs(props)
const uploadDisabled = computed(() => props.disabled || props.limit <= fileList.value.length)
function genDefault () {
if (props.drag) { // 拖拽
return
点击或将文件拖拽到这里上传
{slots.tip?.()}
} else if (props.listType === 'picture-card') { // 缩略图
return uploadDisabled.value ||
} else { // 默认
return
}
}
async function deleteItem (index) {
const uploadFiles = fileList.value.concat()
const file = uploadFiles.splice(index, 1)[0]
let flag
try {
flag = await props.beforeRemove?.(file, uploadFiles)
} catch (err) {
flag = props.beforeRemove?.(file, uploadFiles)
}
// 如果beforeRemove函数不存在 或者 返回值为true
if (flag || !props.beforeRemove) {
emit('update:fileList', uploadFiles)
props.onRemove?.(file, uploadFiles)
}
}
function genUpload (slots) {
return emit('update:fileList', list)}
class={'cip-upload-content'}
action={props.action}
httpRequest={httpRequest}
beforeUpload={props.beforeUpload}
multiple={props.multiple}
disabled={props.disabled}
accept={props.accept}
drag={props.drag}
show-file-list={false}
>
{{
// 1. default或者trigger存在,不渲染默认;渲染对应的default或者trigger;trigger在下面一行渲染
default: () => slots.default?.() || (slots.trigger ? undefined : genDefault()),
// 这个trigger要这么写,如果给它赋值函数,会出bug
trigger: slots.trigger ? () => slots.trigger() : undefined,
tip: () => props.drag || {slots.tip?.()}
}}
}
function httpRequest (opts) {
function setStatus (status, uploadFile) {
const uid = opts.file.uid
const index = fileList.value.findIndex(file => file.uid === uid)
if (status === 'error') {
Object.assign(fileList.value[index], { status, opts })
} else if (status === 'success') {
Object.assign(fileList.value[index], { status, ...uploadFile, opts: undefined })
}
emit('update:fileList', fileList.value.concat())
}
props.uploadFile(opts)?.then(file => {
setStatus('success', file)
props.onSuccess?.(file, opts.file, fileList.value.concat())
}).catch((err) => {
setStatus('error')
props.onError?.(err, opts.file, fileList.value.concat())
})
}
function reUpload (item) {
item.status = 'ready'
httpRequest(item.opts)
}
function genItems () {
return <>
{genUpload(slots)}
{ fileList.value?.length === 0
? undefined
:
{
fileList.value.map((item, index) => - props.onPreview?.(item)}>
{item.status === 'error' && reUpload(item)}>}
deleteItem(index)}>
{item.status === 'ready' && }
)
}
}
>
}
function genPictureCard () {
return <>
{
fileList.value.map((item, index) => - props.onPreview?.(item)}>
{item.status === 'success' && }
deleteItem(index)}>
{item.status === 'ready' && }
)
}
{uploadDisabled.value || - {genUpload({ trigger: slots.trigger, default: slots.default })}
}
{slots.tip?.()}
>
}
function genPicture () {
return <>
{genUpload(slots)}
{ fileList.value?.length === 0
? undefined
:
{
fileList.value.map((item, index) => - props.onPreview?.(item)}>
{['jpeg', 'jpg', 'png', 'gif', 'svg'].includes(item.name?.split('.').pop())
?
: }
deleteItem(index)}>
)
}
}
>
}
const renderTypeMap = {
text: genItems,
'picture-card': genPictureCard,
picture: genPicture
}
return () =>
{ props.showFileList ? (renderTypeMap[props.listType]?.()) : genUpload(slots) }
}
})