From c73d94b83b6fcf7818376b150a17948978e8cec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=87=E5=B3=B0?= Date: Mon, 13 Apr 2026 12:47:25 +0800 Subject: [PATCH] up --- .../ops_vue_js/src/components/useDropzone.vue | 461 +++++++++++++++--- 1 file changed, 394 insertions(+), 67 deletions(-) diff --git a/frontend/ops_vue_js/src/components/useDropzone.vue b/frontend/ops_vue_js/src/components/useDropzone.vue index 0ba35b8..010ff70 100644 --- a/frontend/ops_vue_js/src/components/useDropzone.vue +++ b/frontend/ops_vue_js/src/components/useDropzone.vue @@ -3,109 +3,436 @@ import { ref, onMounted, onUnmounted, defineProps, reactive } from "vue"; import { useI18n } from "vue-i18n"; const { t, locale } = useI18n(); import Dropzone from "dropzone"; -//import "dropzone/dist/dropzone.css"; +import "dropzone/dist/dropzone.css"; + import { useUserStore } from "@/stores/user"; + import "fslightbox"; + const userStore = useUserStore(); + const dropzoneElement = ref(null); var dropzoneInstance = null; + const files = reactive([]); + function get_file_from_uuid(uuid) { - if (files.length != 0) { for (var i = 0; i < files.length; i++) { if (files[i].uuid == uuid) { return i; } } return -1; } return -2; + if (files.length != 0) { + for (var i = 0; i < files.length; i++) { + if (files[i].uuid == uuid) { + return i; + } + } + return -1; + } + return -2; } -function remove_file_from_uuie(uuid) { var id = get_file_from_uuid(uuid); if (id >= 0) { files.splice(id, 1); } } + +function remove_file_from_uuie(uuid) { + //devare files[uuid] + var id = get_file_from_uuid(uuid); + if (id >= 0) { + files.splice(id, 1); + } +} + const prop = defineProps({ - maxFiles: { type: Number, default: 5 }, - acceptedFiles: { type: String, default: "image/*" }, - maxFilesize: { type: Number, default: 10 }, - uploadURL: { type: String, default: "/api/files/upload" }, + maxFiles: { + type: Number, + default: 5, + }, + acceptedFiles: { + type: String, + default: "image/*", + }, + maxFilesize: { + type: Number, + default: 10, + }, + uploadURL: { + type: String, + default: "/api/files/upload", + }, }); + +// 初始化 Dropzone const initDropzone = () => { if (!dropzoneElement.value) return; + + // 禁用自动发现 Dropzone.autoDiscover = false; - if (dropzoneInstance) { dropzoneInstance.destroy(); } + + // 移除任何现有的 Dropzone 实例 + if (dropzoneInstance) { + dropzoneInstance.destroy(); + } + + // 初始化新的实例 dropzoneInstance = new Dropzone(dropzoneElement.value, { - url: prop.uploadURL, + url: prop.uploadURL, // 上传地址 + // headers: { + // user_cookie: "cccc", + // }, method: "post", + + //uploadMultiple: true, + previewTemplate: document.getElementById("custom-template").innerHTML, - parallelUploads: 3, - maxFilesize: prop.maxFilesize, - maxFiles: prop.maxFiles, - acceptedFiles: prop.acceptedFiles, - dictDefaultMessage: "", + + parallelUploads: 3, // 同时上传的文件数 + maxFilesize: prop.maxFilesize, // MB + maxFiles: prop.maxFiles, // 最大文件数 + acceptedFiles: prop.acceptedFiles, // 接受的文件类型 + //addRemoveLinks: true, // 显示移除链接 + dictDefaultMessage: t("dropzone.upload_drop_or_click"), dictFallbackMessage: t("dropzone.upload_browser_not_supported"), - dictFileTooBig: t("dropzone.upload_file_too_big") + "({{filesize}}MB). " + t("dropzone.upload_max_file_size") + "{{maxFilesize}}MB.", - dictInvalidFileType: t("dropzone.upload_invalid_file_type"), + dictFivarooBig: + t("dropzone.upload_file_too_big") + + "({{filesize}}MB). " + + t("dropzone.upload_max_file_size") + + "{{maxFilesize}}MB.", + dictInvalidFivarype: t("dropzone.upload_invalid_file_type"), dictResponseError: t("dropzone.upload_server_error") + "{{statusCode}}", + //dictCancelUpload: t('dropzone.upload_cancel'), + //dictUploadCanceled: t('dropzone.upload_canceled'), + //dictCancelUploadConfirmation: t('dropzone.upload_cancel_confirmation'), dictRemoveFile: t("dropzone.upload_remove_file"), - dictMaxFilesExceeded: t("dropzone.upload_max_files") + " " + prop.maxFiles + t("dropzone.upload_max_files_unit"), - init: function() { - this.on("sending", function(file, xhr, formData) { - formData.append("cookie", userStore.cookieValue); - }); - this.on("success", function(file, serverResponse) { - const data = JSON.parse(serverResponse); - if (data.return && data.return.uuid) { - file.uuid = data.return.uuid; - files.push({ uuid: data.return.uuid, name: file.name, url: data.return.url || "" }); + dictMaxFilesExceeded: + t("dropzone.upload_max_files") + + "{{maxFiles}}" + + t("dropzone.upload_max_files_unit"), + + // 事件处理 + init: function () { + this.on("success", (file, response) => { + //console.log("上传成功:", file, response); + + // 移除旧的事件监听器,避免重复绑定 + const oldHandler = file.previewElement._lightboxClickHandler; + if (oldHandler) { + file.previewElement.removeEventListener("click", oldHandler); } + + // 创建新的点击处理器 + const clickHandler = function (e) { + e.preventDefault(); + e.stopPropagation(); + + // 每次点击创建新实例,sources 自动是空的 + const lightbox = new FsLightbox(); + + var dis_id = 0; + var dis_id_t = 0; + for (var i = 0; i < files.length; i++) { + if (files[i]["is_upload"] == true) { + lightbox.props.sources.push(files[i]["get_url"]); + if (files[i]["uuid"] == file.upload.uuid) { + dis_id = dis_id_t; + } + } + dis_id_t += 1; + } + + lightbox.open(dis_id); + }; + + // 保存处理器引用,以便后续移除 + file.previewElement._lightboxClickHandler = clickHandler; + file.previewElement.addEventListener("click", clickHandler); + + var file_id = get_file_from_uuid(file.upload.uuid); + if (file_id >= 0) { + files[file_id]["hash"] = response.return.hash; + files[file_id]["get_url"] = response.return.get; + files[file_id]["download_url"] = response.return.download; + files[file_id]["file_name"] = file.name; + files[file_id]["file_size"] = file.size; + + files[file_id]["is_upload"] = true; + + //console.log(files) + } + + //files.push(t) + // files[file.upload.uuid]=t + // console.log(files) + + // lightbox.props.sources.push(t.get_url) + // console.log(lightbox) }); - this.on("removedfile", function(file) { - if (file.uuid) { remove_file_from_uuie(file.uuid); } + this.on("error", (file, errorMessage) => { + console.error("上传失败:", file.name, errorMessage); + }); + this.on("removedfile", (file) => { + //console.log("remove:", file); + //files.value = files.value.filter(f => f.name !== file.name) + remove_file_from_uuie(file.upload.uuid); + //console.log(files) + }); + this.on("addedfile", (file) => { + //添加文件 + + //控制排序 需要从添加文件开始操作 + + //限制文件数量 + if (files.length < prop.maxFiles) { + var t = { + uuid: file.upload.uuid, + is_upload: false, + }; + files.push(t); + } else { + this.removeFile(file); + } + + //console.log(files); + }); + this.on("sending", function (file, xhr, formData) { + // 获取表单值并添加到 FormData + //console.log(userStore.userCookie.Value) + formData.append("cookie", userStore.userCookie.Value); }); }, }); }; -const emit = defineEmits(['files-updated', 'uuid-updated']) -onMounted(() => { initDropzone(); }); -onUnmounted(() => { if (dropzoneInstance) { dropzoneInstance.destroy(); } }); -defineExpose({ getFiles: () => files, getDropzone: () => dropzoneInstance }); + + +function return_files() { + return files; +} + +// 组件挂载时初始化 +onMounted(() => { + initDropzone(); + + //console.log(lightbox) +}); + +// 组件卸载时销毁 +onUnmounted(() => { + if (dropzoneInstance) { + dropzoneInstance.destroy(); + } +}); + +defineExpose({ + return_files, +}); +.dz_mark { + height: 60px; + width: 60px; +} -