151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Vue
		
	
	
| <template>
 | ||
|   <el-upload
 | ||
|     ref="uploadRef"
 | ||
|     style="width: 100%"
 | ||
|     :file-list="modelValue"
 | ||
|     :action="action"
 | ||
|     multiple
 | ||
|     :limit="limit"
 | ||
|     :list-type="listType"
 | ||
|     :auto-upload="autoUpload"
 | ||
|     :disabled="disabled"
 | ||
|     :accept="accept"
 | ||
|     :on-remove="onRemove"
 | ||
|     :before-remove="beforeRemove"
 | ||
|     :on-change="onChange"
 | ||
|     :on-exceed="onExceed"
 | ||
|     :on-preview="onPreview"
 | ||
|     :http-request="httpRequest"
 | ||
|     :show-file-list="showFileList"
 | ||
|     :class="{ hide: modelValue.length === limit }"
 | ||
|   >
 | ||
|     <el-icon v-if="listType === 'picture-card'" size="32"><plus /></el-icon>
 | ||
|     <el-button v-else type="primary">点击选择文件上传</el-button>
 | ||
|     <template #tip>
 | ||
|       <div class="mt-10 text-red">
 | ||
|         <slot name="tip">
 | ||
|           <div>{{ tip.join(",") }}。</div>
 | ||
|         </slot>
 | ||
|       </div>
 | ||
|     </template>
 | ||
|   </el-upload>
 | ||
|   <el-dialog v-model="visible" title="查看图片">
 | ||
|     <img :src="imageUrl" alt="Preview Image" style="width: 100%; object-fit: scale-down" />
 | ||
|   </el-dialog>
 | ||
| </template>
 | ||
| 
 | ||
| <script setup>
 | ||
| import { computed, ref, useTemplateRef } from "vue";
 | ||
| import { ElMessage, ElMessageBox, ElUpload, ElIcon, ElButton, ElDialog } from "element-plus";
 | ||
| import { Plus } from "@element-plus/icons-vue";
 | ||
| import "element-plus/es/components/upload/style/css";
 | ||
| import "element-plus/es/components/icon/style/css";
 | ||
| import "element-plus/es/components/button/style/css";
 | ||
| import "element-plus/es/components/dialog/style/css";
 | ||
| 
 | ||
| defineOptions({
 | ||
|   name: "AppUpload",
 | ||
| });
 | ||
| const props = defineProps({
 | ||
|   autoUpload: { type: Boolean, default: false },
 | ||
|   action: { type: String, default: "" },
 | ||
|   limit: { type: Number, default: 1 },
 | ||
|   listType: { type: String, default: "text" },
 | ||
|   accept: { type: String, default: "" },
 | ||
|   ratio: { type: String, default: "" },
 | ||
|   disabled: { type: Boolean, default: false },
 | ||
|   deleteToServer: { type: Boolean, default: false },
 | ||
|   showFileList: { type: Boolean, default: true },
 | ||
|   httpRequest: { type: Function },
 | ||
|   size: { type: Number, default: 0 },
 | ||
|   beforeRemove: { type: Function, default: () => {} },
 | ||
| });
 | ||
| const visible = ref(false);
 | ||
| const imageUrl = ref("");
 | ||
| const modelValue = defineModel({ type: Array, required: true });
 | ||
| const deleteFiles = defineModel("deleteFiles", {
 | ||
|   type: Array,
 | ||
|   default: () => [],
 | ||
| });
 | ||
| const emits = defineEmits(["preview", "delete"]);
 | ||
| const uploadRef = useTemplateRef("uploadRef");
 | ||
| const tip = computed(() =>
 | ||
|   [
 | ||
|     `最多上传${props.limit}个文件`,
 | ||
|     props.accept
 | ||
|       ? `并且只能上传${props.accept
 | ||
|           .replaceAll(".", "")
 | ||
|           .split(",")
 | ||
|           .join("、")}格式的文件`
 | ||
|       : "可以上传任意格式的文件",
 | ||
|     props.size ? `文件大小不能超过${props.size}M` : "",
 | ||
|     props.ratio ? `只能上传${props.ratio}分辨率的图片` : "",
 | ||
|   ].filter(Boolean)
 | ||
| );
 | ||
| const onExceed = () => {
 | ||
|   ElMessage.warning(`最多上传${props.limit}个文件`);
 | ||
| };
 | ||
| const beforeRemove = async (uploadFile) => {
 | ||
|   if (props.deleteToServer && uploadFile.imgFilesId) {
 | ||
|     await ElMessageBox.confirm("确定要删除吗?", {
 | ||
|       type: "warning",
 | ||
|     });
 | ||
|     await props.beforeRemove(uploadFile);
 | ||
|   }
 | ||
| };
 | ||
| const onRemove = (uploadFile, uploadFiles) => {
 | ||
|   modelValue.value = uploadFiles;
 | ||
|   deleteFiles.value.push(uploadFile);
 | ||
|   emits("delete", uploadFile);
 | ||
| };
 | ||
| const onChange = (uploadFile, uploadFiles) => {
 | ||
|   const accept = props.accept && props.accept.split(",");
 | ||
|   const ratio = props.ratio && props.ratio.split("*");
 | ||
|   const suffix = uploadFile.raw.name.substring(
 | ||
|     uploadFile.raw.name.lastIndexOf("."),
 | ||
|     uploadFile.raw.name.length
 | ||
|   );
 | ||
|   const size = props.size * 1024 * 1024;
 | ||
|   if (ratio) {
 | ||
|     const img = new Image();
 | ||
|     img.src = uploadFile.url;
 | ||
|     img.onload = () => {
 | ||
|       if (img.width !== +ratio[0] && img.height !== +ratio[1]) {
 | ||
|         ElMessage.warning(`只能上传${props.ratio}分辨率的图片`);
 | ||
|         uploadRef.value.handleRemove(uploadFile.raw);
 | ||
|       }
 | ||
|     };
 | ||
|   }
 | ||
|   if (size) {
 | ||
|     if (uploadFile.size > size) {
 | ||
|       ElMessage.warning(`文件大小不能超过${props.size}M`);
 | ||
|       uploadRef.value.handleRemove(uploadFile.raw);
 | ||
|     }
 | ||
|   }
 | ||
|   if (accept) {
 | ||
|     if (accept.includes(suffix)) {
 | ||
|       modelValue.value = uploadFiles;
 | ||
|     } else {
 | ||
|       ElMessage.warning(`只能上传${props.accept}格式的文件`);
 | ||
|       uploadRef.value.handleRemove(uploadFile.raw);
 | ||
|     }
 | ||
|   } else {
 | ||
|     modelValue.value = uploadFiles;
 | ||
|   }
 | ||
| };
 | ||
| const onPreview = (uploadFile) => {
 | ||
|   if (props.listType === "picture-card") {
 | ||
|     visible.value = true;
 | ||
|     imageUrl.value = uploadFile.url;
 | ||
|   } else {
 | ||
|     emits("preview", uploadFile);
 | ||
|   }
 | ||
| };
 | ||
| </script>
 | ||
| 
 | ||
| <style scoped lang="scss">
 | ||
| .hide :deep(.el-upload--picture-card) {
 | ||
|   display: none;
 | ||
| }
 | ||
| </style>
 |