|
@@ -0,0 +1,125 @@
|
|
|
+<script lang="ts">
|
|
|
+import { imageUploadProps, imageUploadEmits } from './props'
|
|
|
+import type { UploadItem } from './types'
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ props: imageUploadProps,
|
|
|
+ emits: imageUploadEmits,
|
|
|
+ setup(props, { emit }) {
|
|
|
+ // 是否可上传
|
|
|
+ const isUpload = computed<boolean>(() => {
|
|
|
+ return (
|
|
|
+ !props.readonly &&
|
|
|
+ !(
|
|
|
+ typeof props.limit === 'number' &&
|
|
|
+ props.limit > 0 &&
|
|
|
+ props.modelValue != null &&
|
|
|
+ props.modelValue.length >= props.limit
|
|
|
+ )
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ // 预览图片列表
|
|
|
+ const previewList = computed(() => {
|
|
|
+ if (!props.preview) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ return props.modelValue?.map(x => x.url) || []
|
|
|
+ })
|
|
|
+
|
|
|
+ /* 选择文件 */
|
|
|
+ const onUpload = (file: File) => {
|
|
|
+ if (!isUpload.value || props.disabled) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ const item: UploadItem = {
|
|
|
+ key: Date.now(),
|
|
|
+ name: file.name,
|
|
|
+ status: void 0,
|
|
|
+ progress: 0,
|
|
|
+ file
|
|
|
+ }
|
|
|
+ if (file.type.startsWith('image')) {
|
|
|
+ item.url = window.URL.createObjectURL(file)
|
|
|
+ }
|
|
|
+ // 是否自动上传
|
|
|
+ if (props.autoUpload) {
|
|
|
+ uploadItem(item)
|
|
|
+ }
|
|
|
+ updateModelValue(props.modelValue ? props.modelValue.concat([item]) : [item])
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 上传文件 */
|
|
|
+ const uploadItem = (item: UploadItem) => {
|
|
|
+ emit('upload', item)
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 修改modelValue */
|
|
|
+ const updateModelValue = (items: UploadItem[]) => {
|
|
|
+ emit('update:modelValue', items)
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ isUpload,
|
|
|
+ previewList,
|
|
|
+ onUpload
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="upload-container">
|
|
|
+ <div class="upload-image" v-for="(item, index) in modelValue" :key="item.key">
|
|
|
+ <el-image :src="item.url" :preview-src-list="previewList" :initial-index="index" fit="cover"></el-image>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ action=""
|
|
|
+ :accept="accept"
|
|
|
+ :multiple="multiple"
|
|
|
+ :disabled="disabled"
|
|
|
+ :show-file-list="false"
|
|
|
+ :beforeUpload="onUpload"
|
|
|
+ v-if="isUpload"
|
|
|
+ >
|
|
|
+ <div class="upload-plus" :style="buttonStyle">
|
|
|
+ <el-icon size="30">
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.upload-container {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ .upload-image {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ border: 1px dashed #dcdfe6;
|
|
|
+ border-radius: var(--el-border-radius-base);
|
|
|
+ overflow: hidden;
|
|
|
+ margin: 0px 8px 8px 0;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .upload-plus {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: var(--el-color-info);
|
|
|
+ border: 1px dashed #dcdfe6;
|
|
|
+ border-radius: var(--el-border-radius-base);
|
|
|
+ background-color: #fff;
|
|
|
+ &:hover {
|
|
|
+ border-color: var(--el-color-primary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|