|
|
@@ -13,6 +13,7 @@
|
|
|
:on-exceed="handleExceed"
|
|
|
:on-success="showSuccessNotification ? uploadSuccess : undefined"
|
|
|
:on-error="uploadError"
|
|
|
+ :on-change="handleFileListChange"
|
|
|
:drag="drag"
|
|
|
:accept="fileType.join(',')"
|
|
|
>
|
|
|
@@ -55,7 +56,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="UploadImgs">
|
|
|
-import { ref, computed, inject, watch } from "vue";
|
|
|
+import { ref, computed, inject, watch, nextTick } from "vue";
|
|
|
import { Plus, Picture } from "@element-plus/icons-vue";
|
|
|
import { uploadImg } from "@/api/modules/upload";
|
|
|
import type { UploadProps, UploadFile, UploadUserFile, UploadRequestOptions } from "element-plus";
|
|
|
@@ -106,14 +107,38 @@ const self_disabled = computed(() => {
|
|
|
|
|
|
const _fileList = ref<UploadUserFile[]>(props.fileList);
|
|
|
|
|
|
+// 标记是否正在从 props 同步,避免循环更新
|
|
|
+let isSyncingFromProps = false;
|
|
|
+
|
|
|
// 监听 props.fileList 列表默认值改变
|
|
|
watch(
|
|
|
() => props.fileList,
|
|
|
(n: UploadUserFile[]) => {
|
|
|
+ isSyncingFromProps = true;
|
|
|
_fileList.value = n;
|
|
|
+ nextTick(() => {
|
|
|
+ isSyncingFromProps = false;
|
|
|
+ });
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+// 监听 _fileList 的变化,自动同步到父组件(排除从 props 同步的情况)
|
|
|
+// 注意:on-change 事件已经处理了大部分情况,这个 watch 作为备用
|
|
|
+watch(
|
|
|
+ () => _fileList.value,
|
|
|
+ (newList, oldList) => {
|
|
|
+ if (!isSyncingFromProps && newList !== oldList) {
|
|
|
+ // 延迟执行,避免与 on-change 重复
|
|
|
+ nextTick(() => {
|
|
|
+ if (!isSyncingFromProps) {
|
|
|
+ emit("update:fileList", [...newList]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true, immediate: false }
|
|
|
+);
|
|
|
+
|
|
|
// 记录正在上传的文件数量(使用 Set 跟踪文件 UID,更可靠)
|
|
|
const uploadingFiles = new Set<string | number>();
|
|
|
// 标记是否已经显示过成功提示,防止重复提示
|
|
|
@@ -170,11 +195,24 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
|
|
|
try {
|
|
|
const api = props.api ?? uploadImg;
|
|
|
const { data } = await api(formData);
|
|
|
- // 调用成功回调(如果提供了的话)
|
|
|
+ // 先调用 el-upload 的成功回调,确保文件列表更新
|
|
|
+ options.onSuccess(data);
|
|
|
+ // 然后调用自定义成功回调(如果提供了的话),即使回调失败也不影响文件列表
|
|
|
if (props.onSuccess) {
|
|
|
- props.onSuccess(data.fileUrl ? data.fileUrl : data[0]);
|
|
|
+ try {
|
|
|
+ const result = props.onSuccess(data.fileUrl ? data.fileUrl : data[0]);
|
|
|
+ // 如果回调返回 Promise,等待它完成(但不影响上传成功状态)
|
|
|
+ if (result && typeof result.then === "function") {
|
|
|
+ result.catch((callbackError: any) => {
|
|
|
+ // 回调失败不影响上传成功状态,只记录错误
|
|
|
+ console.error("onSuccess callback error:", callbackError);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (callbackError) {
|
|
|
+ // 回调失败不影响上传成功状态,只记录错误
|
|
|
+ console.error("onSuccess callback error:", callbackError);
|
|
|
+ }
|
|
|
}
|
|
|
- options.onSuccess(data);
|
|
|
} catch (error) {
|
|
|
// 上传失败,移除文件 UID
|
|
|
uploadingFiles.delete(fileUid);
|
|
|
@@ -224,6 +262,18 @@ const uploadSuccess = (response: { fileUrl: string } | string | string[] | undef
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
+ * @description 文件列表变化处理
|
|
|
+ * @param uploadFile 变化的文件
|
|
|
+ * @param uploadFiles 当前文件列表
|
|
|
+ */
|
|
|
+const handleFileListChange: UploadProps["onChange"] = (uploadFile, uploadFiles) => {
|
|
|
+ // 当文件列表变化时,同步到父组件
|
|
|
+ if (!isSyncingFromProps) {
|
|
|
+ emit("update:fileList", uploadFiles as UploadUserFile[]);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
* @description 删除图片
|
|
|
* @param file 删除的文件
|
|
|
* */
|