"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
|