You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.4 KiB
213 lines
6.4 KiB
<template>
|
|
<component :is="render" />
|
|
</template>
|
|
<script setup lang="jsx">
|
|
import config from '@/configs';
|
|
import { ElMessage } from '@/plugins/element-plus';
|
|
import { ElUpload } from 'element-plus/es/components/upload/index';
|
|
import 'element-plus/es/components/upload/style/css';
|
|
import { ElImage } from 'element-plus/es/components/image/index';
|
|
import 'element-plus/es/components/image/style/css';
|
|
const store = useStore();
|
|
const props = defineProps({
|
|
action: {
|
|
type: String,
|
|
default: config.baseURL + '/edu-oss/oss/fileUpload',
|
|
},
|
|
data: {
|
|
type: Object,
|
|
default() {
|
|
return { service: 'msb-edu-course' };
|
|
},
|
|
},
|
|
headers: {
|
|
type: Object,
|
|
default() {
|
|
return {};
|
|
},
|
|
},
|
|
drag: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
multiple: {
|
|
type: Boolean,
|
|
defualt: false,
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
defualt: false,
|
|
},
|
|
limit: {
|
|
type: Number,
|
|
default: 1,
|
|
},
|
|
size: {
|
|
type: Number,
|
|
default: 1024 * 1024 * 20,
|
|
},
|
|
accept: {
|
|
type: String,
|
|
default: '*.*',
|
|
},
|
|
});
|
|
const attrs = useAttrs();
|
|
const emits = defineEmits(['update:modelValue']);
|
|
let headers = { ...props.headers };
|
|
headers['Authorization'] = 'Bearer ' + store.state.local.token;
|
|
let imgList = ref([]);
|
|
const refsUpload = ref(null);
|
|
watch(
|
|
() => imgList,
|
|
() => {
|
|
if (props.limit === 1) {
|
|
emits('update:modelValue', unref(imgList)[0]?.response.data);
|
|
} else {
|
|
emits('update:modelValue', unref(imgList));
|
|
}
|
|
},
|
|
{ deep: true }
|
|
);
|
|
const handleSuccess = (res, file, list) => {
|
|
console.info('[upload] success', list);
|
|
imgList.value = list;
|
|
};
|
|
const handleRemove = (file, list) => {
|
|
console.info('[upload] remove', list);
|
|
imgList.value = list;
|
|
};
|
|
const handleExceed = (list) => {
|
|
console.info('[upload] exceed', list);
|
|
ElMessage.error('超出最大上传数量');
|
|
};
|
|
const handleBeforeUpload = (file) => {
|
|
console.info('[upload] upload', file);
|
|
if (file.size >= props.size) {
|
|
ElMessage.error('超出文件大小限制');
|
|
return false;
|
|
}
|
|
};
|
|
const fmtSize = computed(() => {
|
|
const units = ['byte', 'KB', 'MB', 'GB', 'TB'];
|
|
let res = props.size,
|
|
unit = 0;
|
|
while (res >= 800) {
|
|
res /= 1024;
|
|
unit++;
|
|
}
|
|
return res + units[unit];
|
|
});
|
|
watch(
|
|
() => attrs.modelValue,
|
|
(value) => {
|
|
if (props.limit === 1 && value) {
|
|
imgList.value = [
|
|
{
|
|
name: value,
|
|
response: {
|
|
data: value,
|
|
},
|
|
},
|
|
];
|
|
} else {
|
|
imgList.value = value || [];
|
|
}
|
|
},
|
|
{ immediate: true, deep: true }
|
|
);
|
|
const handleDeleteImage = (index) => {
|
|
if (unref(refsUpload)) {
|
|
unref(refsUpload).handleRemove(imgList[index]);
|
|
} else {
|
|
unref(imgList).splice(index, 1);
|
|
}
|
|
};
|
|
const render = () => (
|
|
<div class="upload-box">
|
|
<div class="upload-image">
|
|
{unref(imgList).map((item, index) => (
|
|
<div class="img-li">
|
|
<ElImage src={item?.response?.data} alt={item.name} />
|
|
{!props.disabled ? (
|
|
<div class="img-li-cover" onClick={() => handleDeleteImage(index)}>
|
|
<ElIcon class="upload-del-icon" name="delete-bin-fill" size="20" />
|
|
</div>
|
|
) : (
|
|
''
|
|
)}
|
|
</div>
|
|
))}
|
|
{props.limit !== unref(imgList).length ? (
|
|
<ElUpload
|
|
ref={refsUpload}
|
|
{...{ ...props, headers }}
|
|
{...attrs}
|
|
before-upload={handleBeforeUpload}
|
|
on-exceed={handleExceed}
|
|
on-remove={handleRemove}
|
|
on-success={handleSuccess}
|
|
show-file-list={false}
|
|
>
|
|
<ElIcon class="el-icon--upload" name="add-fill" size="20" />
|
|
</ElUpload>
|
|
) : (
|
|
''
|
|
)}
|
|
</div>
|
|
<div class="el-upload__tip">支持小于 {unref(fmtSize)} 的 文件</div>
|
|
</div>
|
|
);
|
|
</script>
|
|
<style lang="less" scoped>
|
|
.upload-box {
|
|
:deep(.upload-image) {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
.img-li {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
width: 150px;
|
|
height: 150px;
|
|
margin-right: 20px;
|
|
overflow: hidden;
|
|
.img-li-cover {
|
|
display: none;
|
|
}
|
|
&:hover {
|
|
.img-li-cover {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
cursor: pointer;
|
|
.upload-del-icon {
|
|
color: #fff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
:deep(.el-upload) {
|
|
width: 150px;
|
|
height: 150px;
|
|
.el-upload-dragger {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
.el-icon--upload {
|
|
margin: 0;
|
|
}
|
|
}
|
|
}
|
|
</style>
|