"use strict"; const common_vendor = require("../../common/vendor.js"); const stores_user = require("../../stores/user.js"); if (!Array) { const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons"); const _easycom_uni_popup2 = common_vendor.resolveComponent("uni-popup"); (_easycom_uni_icons2 + _easycom_uni_popup2)(); } const _easycom_uni_icons = () => "../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.js"; const _easycom_uni_popup = () => "../../node-modules/@dcloudio/uni-ui/lib/uni-popup/uni-popup.js"; if (!Math) { (_easycom_uni_icons + _easycom_uni_popup)(); } const _sfc_main = { __name: "index", props: { files: { type: Array, default: () => [] }, gradesFiles: { type: Array, default: () => [] }, readonly: { type: Boolean, default: false }, position: { type: Object, default: () => ({ right: "30rpx", bottom: "200rpx" }) }, bgColor: { type: String, default: "#67AFAB" }, maxCount: { type: Number, default: 9 }, showGradeSlip: { type: Boolean, default: false }, isGradeRequired: { type: Boolean, default: false } }, emits: ["update:files", "update:gradesFiles", "upload", "preview", "upload-grade", "upload-base"], setup(__props, { expose: __expose, emit: __emit }) { const userStore = stores_user.useUserStore(); const props = __props; const emit = __emit; const popup = common_vendor.ref(null); const baseFiles = common_vendor.ref([]); const gradeFiles = common_vendor.ref([]); const showButton = common_vendor.ref(true); const mainColor = common_vendor.ref("#67AFAB"); const baseUrlHt = userStore.baseUrlHt; const currentTab = common_vendor.ref("base"); const blobUrls = common_vendor.ref([]); const currentFileList = common_vendor.computed(() => { if (!props.showGradeSlip) return baseFiles.value; return currentTab.value === "base" ? baseFiles.value : gradeFiles.value; }); const totalFileCount = common_vendor.computed(() => baseFiles.value.length + gradeFiles.value.length); common_vendor.watch(() => props.files, (newFiles) => { baseFiles.value = [...newFiles]; }, { immediate: true }); common_vendor.watch(() => props.gradesFiles, (newFiles) => { gradeFiles.value = [...newFiles]; }, { immediate: true }); const getFullUrl = (path) => { if (!path) return ""; if (path.startsWith("http://") || path.startsWith("https://")) { try { const url = new URL(path); return `${baseUrlHt}${url.pathname}${url.search}${url.hash}`; } catch { return path; } } return `${baseUrlHt}${path.startsWith("/") ? "" : "/"}${path}`; }; const supportedImageTypes = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/bmp", "image/svg+xml"]; const onPopupChange = (e) => { showButton.value = !e.show; }; const getFileIcon = (type) => { if (type && supportedImageTypes.includes(type)) return "image"; if (type && type.includes("pdf")) return "paperclip"; if (type && type.includes("word")) return "file-word"; if (type && type.includes("excel")) return "file-excel"; if (type && type.includes("powerpoint")) return "file-ppt"; return "file"; }; const getFileColor = (type) => { if (type && supportedImageTypes.includes(type)) return mainColor.value; if (type && type.includes("pdf")) return "#ff4d4f"; if (type && type.includes("word")) return "#2b579a"; if (type && type.includes("excel")) return "#217346"; if (type && type.includes("powerpoint")) return "#b7472a"; return "#666"; }; const formatFileSize = (size) => { if (!size) return ""; if (size < 1024) return `${size}B`; if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}KB`; return `${(size / (1024 * 1024)).toFixed(1)}MB`; }; const togglePopup = () => { var _a; (_a = popup.value) == null ? void 0 : _a.open(); }; const closePopup = () => { var _a; (_a = popup.value) == null ? void 0 : _a.close(); }; const addFilesToCurrentTab = (newFiles) => { const isGradeTab = props.showGradeSlip && currentTab.value === "grade"; const targetFiles = isGradeTab ? gradeFiles.value : baseFiles.value; if (targetFiles.length + newFiles.length > props.maxCount) { common_vendor.index.showToast({ title: `最多只能上传${props.maxCount}个文件`, icon: "none" }); newFiles.forEach((f) => { if (f.url && f.url.startsWith("blob:")) URL.revokeObjectURL(f.url); }); return; } if (isGradeTab) { gradeFiles.value = [...gradeFiles.value, ...newFiles]; emit("update:gradesFiles", gradeFiles.value); } else { baseFiles.value = [...baseFiles.value, ...newFiles]; emit("update:files", baseFiles.value); } }; const chooseFile = () => { common_vendor.index.showActionSheet({ itemList: ["拍照/相册", "从聊天记录选择文件"], success: (res) => { const remain = props.maxCount - currentFileList.value.length; if (remain <= 0) { common_vendor.index.showToast({ title: `最多上传${props.maxCount}个文件`, icon: "none" }); return; } if (res.tapIndex === 0) { common_vendor.index.chooseImage({ count: remain, sizeType: ["original", "compressed"], sourceType: ["album", "camera"], success: (chooseRes) => { const files = chooseRes.tempFiles.map((file) => ({ name: file.name || "image.jpg", path: file.path, url: file.path, uploadPath: file.path, // 小程序临时文件路径 type: file.type || "image/jpeg", size: file.size, raw: file, status: "pending" })); addFilesToCurrentTab(files); } }); } else if (res.tapIndex === 1) { common_vendor.index.chooseMessageFile({ count: remain, type: "all", success: (chooseRes) => { const files = chooseRes.tempFiles.map((file) => ({ name: file.name, path: file.path, url: file.path, uploadPath: file.path, type: file.type, size: file.size, raw: file, status: "pending" })); addFilesToCurrentTab(files); } }); } } }); }; const removeFile = (type, index, event) => { if (event) event.stopPropagation(); const file = type === "grade" ? gradeFiles.value[index] : baseFiles.value[index]; if (file.url && file.url.startsWith("blob:")) { URL.revokeObjectURL(file.url); const idx = blobUrls.value.indexOf(file.url); if (idx !== -1) blobUrls.value.splice(idx, 1); } if (type === "grade") { gradeFiles.value.splice(index, 1); emit("update:gradesFiles", gradeFiles.value); } else { baseFiles.value.splice(index, 1); emit("update:files", baseFiles.value); } }; const previewFile = (file) => { let previewUrl = file.url; if (previewUrl && !previewUrl.startsWith("blob:") && !previewUrl.startsWith("file://") && !previewUrl.startsWith("/")) { previewUrl = getFullUrl(previewUrl); } if (file.type && supportedImageTypes.includes(file.type)) { const allFiles = [...baseFiles.value, ...gradeFiles.value]; const imageUrls = allFiles.filter((f) => f.type && supportedImageTypes.includes(f.type)).map((f) => f.url.startsWith("blob:") || f.url.startsWith("file://") || f.url.startsWith("/") ? f.url : getFullUrl(f.url)); common_vendor.index.previewImage({ urls: imageUrls, current: previewUrl }); } else if (file.type && file.type.includes("pdf")) { common_vendor.index.downloadFile({ url: previewUrl, success: (res) => { common_vendor.index.openDocument({ filePath: res.tempFilePath, fileType: "pdf" }); }, fail: () => common_vendor.index.showToast({ title: "打开PDF失败", icon: "none" }) }); } else { emit("preview", file); } }; const uploadFile = (file, type) => { return new Promise((resolve, reject) => { const token = common_vendor.index.getStorageSync("token"); let filePath = file.uploadPath || file.url || file.path; if (!filePath || typeof filePath !== "string") { reject(new Error("无效的文件路径")); return; } let uploadUrl = "/api/common/upload"; uploadUrl = "https://opo.qduh.cn/common/upload"; common_vendor.index.uploadFile({ url: uploadUrl, filePath, name: "file", header: { "Authorization": `Bearer ${token}` }, success: (res) => { if (res.statusCode === 200) { try { const data = JSON.parse(res.data); if (data.code === 200) resolve({ ...data, fileName: data.fileName }); else reject(new Error(data.msg || "上传失败")); } catch { reject(new Error("解析响应失败")); } } else reject(new Error(`上传失败,状态码: ${res.statusCode}`)); }, fail: reject }); }); }; const confirmUpload = async () => { if (props.showGradeSlip && props.isGradeRequired && gradeFiles.value.length === 0) { common_vendor.index.showToast({ title: "请上传成绩单附件", icon: "none" }); currentTab.value = "grade"; return; } const totalPending = [...baseFiles.value, ...gradeFiles.value].filter((f) => !f.url || f.status === "pending").length; if (totalPending === 0) { common_vendor.index.showToast({ title: "没有待上传的文件", icon: "none" }); return; } common_vendor.index.showLoading({ title: "上传中", mask: true }); try { const pendingBase = baseFiles.value.filter((f) => !f.url || f.status === "pending"); const pendingGrade = gradeFiles.value.filter((f) => !f.url || f.status === "pending"); for (const file of pendingBase) { try { file.status = "uploading"; const res = await uploadFile(file, "base"); Object.assign(file, { url: res.url, fileName: res.name, newFileName: res.newFileName, originalFilename: res.originalFilename, status: "success", size: res.size }); emit("upload-base", file); } catch (err) { file.status = "error"; common_vendor.index.showToast({ title: `文件 ${file.name} 上传失败`, icon: "none" }); } } for (const file of pendingGrade) { try { file.status = "uploading"; const res = await uploadFile(file, "grade"); Object.assign(file, { url: res.fileName, fileName: res.fileName, newFileName: res.newFileName, originalFilename: res.originalFilename, status: "success" }); emit("upload-grade", file); } catch (err) { file.status = "error"; common_vendor.index.showToast({ title: `文件 ${file.name} 上传失败`, icon: "none" }); } } emit("update:files", baseFiles.value); emit("update:gradesFiles", gradeFiles.value); common_vendor.index.showToast({ title: "上传完成", icon: "success" }); closePopup(); } catch (error) { common_vendor.index.__f__("error", "at components/attachment/index.vue:398", "上传出错:", error); common_vendor.index.showToast({ title: "上传出错", icon: "none" }); } finally { common_vendor.index.hideLoading(); } }; const getFilesByType = (type) => type === "grade" ? gradeFiles.value : baseFiles.value; const getAllFiles = () => [...baseFiles.value, ...gradeFiles.value]; common_vendor.onBeforeUnmount(() => { blobUrls.value.forEach((url) => URL.revokeObjectURL(url)); blobUrls.value = []; }); __expose({ getFilesByType, getAllFiles }); return (_ctx, _cache) => { return common_vendor.e({ a: totalFileCount.value > 0 }, totalFileCount.value > 0 ? { b: common_vendor.t(totalFileCount.value) } : {}, { c: __props.position.right, d: __props.position.bottom, e: __props.bgColor, f: showButton.value ? "flex" : "none", g: common_vendor.o(togglePopup), h: !__props.readonly }, !__props.readonly ? { i: common_vendor.o(chooseFile), j: common_vendor.p({ type: "plus", size: "24", color: mainColor.value }) } : {}, { k: common_vendor.o(closePopup), l: common_vendor.p({ type: "close", size: "24", color: "#999" }), m: __props.showGradeSlip }, __props.showGradeSlip ? common_vendor.e({ n: currentTab.value === "base" ? 1 : "", o: common_vendor.o(($event) => currentTab.value = "base"), p: __props.isGradeRequired }, __props.isGradeRequired ? {} : {}, { q: currentTab.value === "grade" ? 1 : "", r: common_vendor.o(($event) => currentTab.value = "grade") }) : {}, { s: currentTab.value === "base" || !__props.showGradeSlip }, currentTab.value === "base" || !__props.showGradeSlip ? { t: common_vendor.f(baseFiles.value, (file, index, i0) => { return common_vendor.e({ a: "2d320176-3-" + i0 + ",2d320176-0", b: common_vendor.p({ type: getFileIcon(file.type), size: "24", color: getFileColor(file.type) }), c: common_vendor.o(($event) => previewFile(file), "base-" + index), d: common_vendor.t(file.originalFilename || file.name), e: common_vendor.t(formatFileSize(file.size)), f: file.status === "uploading" }, file.status === "uploading" ? {} : file.status === "error" ? {} : {}, { g: file.status === "error", h: common_vendor.o(($event) => previewFile(file), "base-" + index) }, !__props.readonly ? { i: common_vendor.o((e) => removeFile("base", index, e), "base-" + index), j: "2d320176-4-" + i0 + ",2d320176-0", k: common_vendor.p({ type: "trash", size: "20", color: "#ff4d4f" }) } : {}, { l: "base-" + index }); }), v: !__props.readonly } : {}, { w: currentTab.value === "grade" && __props.showGradeSlip }, currentTab.value === "grade" && __props.showGradeSlip ? { x: common_vendor.f(gradeFiles.value, (file, index, i0) => { return common_vendor.e({ a: "2d320176-5-" + i0 + ",2d320176-0", b: common_vendor.p({ type: getFileIcon(file.type), size: "24", color: getFileColor(file.type) }), c: common_vendor.o(($event) => previewFile(file), "grade-" + index), d: common_vendor.t(file.originalFilename || file.name), e: common_vendor.t(formatFileSize(file.size)), f: file.status === "uploading" }, file.status === "uploading" ? {} : file.status === "error" ? {} : {}, { g: file.status === "error", h: common_vendor.o(($event) => previewFile(file), "grade-" + index) }, !__props.readonly ? { i: common_vendor.o((e) => removeFile("grade", index, e), "grade-" + index), j: "2d320176-6-" + i0 + ",2d320176-0", k: common_vendor.p({ type: "trash", size: "20", color: "#ff4d4f" }) } : {}, { l: "grade-" + index }); }), y: !__props.readonly } : {}, { z: currentFileList.value.length === 0 }, currentFileList.value.length === 0 ? common_vendor.e({ A: common_vendor.p({ type: "info", size: "24", color: "#999" }), B: currentTab.value === "base" || !__props.showGradeSlip }, currentTab.value === "base" || !__props.showGradeSlip ? {} : currentTab.value === "grade" ? {} : {}, { C: currentTab.value === "grade" }) : {}, { D: !__props.readonly }, !__props.readonly ? { E: common_vendor.o(chooseFile), F: common_vendor.o(confirmUpload) } : {}, { G: common_vendor.sr(popup, "2d320176-0", { "k": "popup" }), H: common_vendor.o(onPopupChange), I: common_vendor.p({ type: "bottom", ["safe-area"]: false }), J: common_vendor.gei(_ctx, "") }); }; } }; wx.createComponent(_sfc_main); //# sourceMappingURL=../../../.sourcemap/mp-weixin/components/attachment/index.js.map