完成积分模块
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<template>
|
||||
<el-upload v-model:file-list="fileList" list-type="picture-card" :before-upload="handleBeforeUpload"
|
||||
:http-request="handleUpload" :on-success="handleSuccess" :on-progress="handleProgress" :on-error="handleError"
|
||||
:on-exceed="handleExceed" :accept="props.accept" :limit="props.limit" multiple>
|
||||
:on-exceed="handleExceed" :accept="props.accept" :limit="props.limit" multiple :auto-upload="true">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
@@ -12,7 +12,9 @@
|
||||
<span class="el-upload-list__item-actions">
|
||||
<!-- 预览 -->
|
||||
<span @click="handlePreviewImage(file.url!)">
|
||||
<el-icon><zoom-in /></el-icon>
|
||||
<el-icon>
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
</span>
|
||||
<!-- 删除 -->
|
||||
<span @click="handleRemove(file.url!)">
|
||||
@@ -28,104 +30,86 @@
|
||||
<el-image-viewer v-if="previewVisible" :zoom-rate="1.2" :initial-index="previewImageIndex" :url-list="modelValue"
|
||||
@close="handlePreviewClose" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, PropType, computed } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { UploadRawFile, UploadRequestOptions, UploadUserFile } from "element-plus";
|
||||
import FileAPI, { FileInfo } from "@/api/account/common";
|
||||
|
||||
// 定义Props
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 请求携带的额外参数
|
||||
*/
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
default: () => ({}),
|
||||
},
|
||||
/**
|
||||
* 上传文件的参数名
|
||||
*/
|
||||
name: {
|
||||
type: String,
|
||||
default: "file",
|
||||
},
|
||||
/**
|
||||
* 文件上传数量限制
|
||||
*/
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
},
|
||||
/**
|
||||
* 单个文件的最大允许大小
|
||||
*/
|
||||
maxFileSize: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
default: 10, // 单位:M
|
||||
},
|
||||
/**
|
||||
* 上传文件类型
|
||||
*/
|
||||
accept: {
|
||||
type: String,
|
||||
default: "image/*", // 默认支持所有图片格式 ,如果需要指定格式,格式如下:'.png,.jpg,.jpeg,.gif,.bmp'
|
||||
default: "image/*",
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['upDataEvent'])
|
||||
const previewVisible = ref(false); // 是否显示预览
|
||||
const previewImageIndex = ref(0); // 预览图片的索引
|
||||
|
||||
// 定义Emits
|
||||
const emit = defineEmits(['upDataEvent', 'uploadAllSuccess']); // 新增:所有图片上传完成事件
|
||||
|
||||
// 响应式数据
|
||||
const previewVisible = ref(false);
|
||||
const previewImageIndex = ref(0);
|
||||
const progress = ref(0);
|
||||
const modelValue = defineModel("modelValue", {
|
||||
type: [Array] as PropType<string[]>,
|
||||
// 修复:defineModel 类型定义
|
||||
const modelValue = defineModel<string[]>("modelValue", {
|
||||
type: Array as PropType<string[]>,
|
||||
required: true,
|
||||
default: () => [],
|
||||
});
|
||||
|
||||
const fileList = ref<UploadUserFile[]>([]);
|
||||
// 新增:批量上传计数
|
||||
const pendingUploadCount = ref(0); // 待上传文件数
|
||||
const completedUploadCount = ref(0); // 已完成上传数
|
||||
|
||||
/**
|
||||
* 删除图片
|
||||
*/
|
||||
function handleRemove(imageUrl: string) {
|
||||
// FileAPI.delete(imageUrl).then(() => {
|
||||
// const index = modelValue.value.indexOf(imageUrl);
|
||||
// if (index !== -1) {
|
||||
// // 直接修改数组避免触发整体更新
|
||||
// modelValue.value.splice(index, 1);
|
||||
// fileList.value.splice(index, 1); // 同步更新 fileList
|
||||
// }
|
||||
// });
|
||||
const index = modelValue.value.indexOf(imageUrl);
|
||||
if (index !== -1) {
|
||||
// 直接修改数组避免触发整体更新
|
||||
modelValue.value.splice(index, 1);
|
||||
fileList.value.splice(index, 1); // 同步更新 fileList
|
||||
fileList.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
function handleProgress(event: any, file: any, fileList: any) {
|
||||
// console.log("handleProgress", evt, file, fileList);
|
||||
// this.progress = Math.round(event.percent); // Element UI 已计算好百分比
|
||||
// console.log(`文件 ${file.name} 上传进度: ${this.progress}%`);
|
||||
// progress.value = Math.round(event.percent);
|
||||
|
||||
/**
|
||||
* 上传进度
|
||||
*/
|
||||
function handleProgress(event: any) {
|
||||
console.log("文件上传进度", Math.round(event.percent));
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传前校验
|
||||
* 上传前校验 & 初始化待上传文件
|
||||
*/
|
||||
function handleBeforeUpload(file: UploadRawFile) {
|
||||
|
||||
// 校验文件类型:虽然 accept 属性限制了用户在文件选择器中可选的文件类型,但仍需在上传时再次校验文件实际类型,确保符合 accept 的规则
|
||||
// 1. 文件类型校验
|
||||
const acceptTypes = props.accept.split(",").map((type) => type.trim());
|
||||
// 检查文件格式是否符合 accept
|
||||
const isValidType = acceptTypes.some((type) => {
|
||||
if (type === "image/*") {
|
||||
// 如果是 image/*,检查 MIME 类型是否以 "image/" 开头
|
||||
return file.type.startsWith("image/");
|
||||
} else if (type.startsWith(".")) {
|
||||
// 如果是扩展名 (.png, .jpg),检查文件名是否以指定扩展名结尾
|
||||
return file.name.toLowerCase().endsWith(type);
|
||||
} else {
|
||||
// 如果是具体的 MIME 类型 (image/png, image/jpeg),检查是否完全匹配
|
||||
return file.type === type;
|
||||
}
|
||||
});
|
||||
@@ -135,29 +119,42 @@ function handleBeforeUpload(file: UploadRawFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 限制文件大小
|
||||
// 2. 文件大小校验
|
||||
if (file.size > props.maxFileSize * 1024 * 1024) {
|
||||
ElMessage.warning("上传图片不能大于" + props.maxFileSize + "M");
|
||||
ElMessage.warning(`上传图片不能大于${props.maxFileSize}M`);
|
||||
return false;
|
||||
}
|
||||
emit('upDataEvent', true)
|
||||
|
||||
// 3. 新增:初始化待上传文件到fileList,确保uid匹配
|
||||
const uploadFile: UploadUserFile = {
|
||||
uid: file.uid, // 关键:复用文件原生uid
|
||||
name: file.name,
|
||||
status: "ready",
|
||||
raw: file,
|
||||
};
|
||||
fileList.value.push(uploadFile);
|
||||
|
||||
// 4. 新增:增加待上传计数
|
||||
pendingUploadCount.value++;
|
||||
emit('upDataEvent', true); // 开始上传,触发loading
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 上传文件
|
||||
/**
|
||||
* 自定义上传逻辑
|
||||
*/
|
||||
function handleUpload(options: UploadRequestOptions) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = options.file;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append(props.name, file);
|
||||
|
||||
// 处理附加参数
|
||||
// 附加参数
|
||||
Object.keys(props.data).forEach((key) => {
|
||||
formData.append(key, props.data[key]);
|
||||
});
|
||||
|
||||
FileAPI.upload(formData)
|
||||
.then((data) => {
|
||||
resolve(data);
|
||||
@@ -169,23 +166,38 @@ function handleUpload(options: UploadRequestOptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件超出限制
|
||||
* 超出数量限制
|
||||
*/
|
||||
function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
|
||||
ElMessage.warning("最多只能上传" + props.limit + "张图片");
|
||||
ElMessage.warning(`最多只能上传${props.limit}张图片`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传成功回调
|
||||
* 单文件上传成功回调
|
||||
*/
|
||||
const handleSuccess = (fileInfo: FileInfo, uploadFile: UploadUserFile) => {
|
||||
ElMessage.success("上传成功");
|
||||
emit('upDataEvent', false)
|
||||
// 1. 修复:通过uid精准匹配文件
|
||||
const index = fileList.value.findIndex((file) => file.uid === uploadFile.uid);
|
||||
if (index !== -1) {
|
||||
fileList.value[index].url = fileInfo;
|
||||
fileList.value[index].url = fileInfo as string; // 确保fileInfo是字符串类型
|
||||
fileList.value[index].status = "success";
|
||||
modelValue.value[index] = fileInfo;
|
||||
// 同步更新modelValue(若index超出当前长度,push;否则替换)
|
||||
if (index >= modelValue.value.length) {
|
||||
modelValue.value.push(fileInfo as string);
|
||||
} else {
|
||||
modelValue.value[index] = fileInfo as string;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 新增:完成计数+判断所有上传完成
|
||||
completedUploadCount.value++;
|
||||
if (completedUploadCount.value === pendingUploadCount.value) {
|
||||
ElMessage.success("所有图片上传成功!");
|
||||
emit('uploadAllSuccess', modelValue.value); // 所有图片上传完成,emit成功事件
|
||||
// 重置计数
|
||||
pendingUploadCount.value = 0;
|
||||
completedUploadCount.value = 0;
|
||||
emit('upDataEvent', false); // 结束loading
|
||||
}
|
||||
};
|
||||
|
||||
@@ -193,9 +205,12 @@ const handleSuccess = (fileInfo: FileInfo, uploadFile: UploadUserFile) => {
|
||||
* 上传失败回调
|
||||
*/
|
||||
const handleError = (error: any) => {
|
||||
console.log("handleError");
|
||||
emit('upDataEvent', false)
|
||||
ElMessage.error("上传失败: " + error.message);
|
||||
console.error("上传失败:", error);
|
||||
ElMessage.error("上传失败: " + (error.message || "未知错误"));
|
||||
// 重置计数+结束loading
|
||||
pendingUploadCount.value = 0;
|
||||
completedUploadCount.value = 0;
|
||||
emit('upDataEvent', false);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -212,12 +227,24 @@ const handlePreviewImage = (imageUrl: string) => {
|
||||
const handlePreviewClose = () => {
|
||||
previewVisible.value = false;
|
||||
};
|
||||
|
||||
// 监听modelValue同步fileList
|
||||
watch(modelValue, (newValue) => {
|
||||
fileList.value = newValue.map((url) => ({ url }) as UploadUserFile);
|
||||
});
|
||||
fileList.value = newValue.map((url) => ({
|
||||
url,
|
||||
uid: Date.now() + Math.random(), // 为已有图片生成唯一uid
|
||||
status: "success"
|
||||
}) as UploadUserFile);
|
||||
}, { immediate: true });
|
||||
|
||||
onMounted(() => {
|
||||
fileList.value = modelValue.value.map((url) => ({ url }) as UploadUserFile);
|
||||
// 初始化fileList
|
||||
fileList.value = modelValue.value.map((url) => ({
|
||||
url,
|
||||
uid: Date.now() + Math.random(),
|
||||
status: "success"
|
||||
}) as UploadUserFile);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog title="选择优惠劵" top="5vh" :visible.sync="dialogVisible">
|
||||
<el-dialog title="选择优惠券" top="5vh" :visible.sync="dialogVisible">
|
||||
<div class="head-container">
|
||||
<el-table ref="table" :data="tableData.list" height="500" v-loading="tableData.loading">
|
||||
<!-- <el-table-column type="selection" width="55" align="center" v-if="!radio"></el-table-column> -->
|
||||
|
||||
Reference in New Issue
Block a user