"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");
|
const _easycom_uni_file_picker2 = common_vendor.resolveComponent("uni-file-picker");
|
(_easycom_uni_icons2 + _easycom_uni_popup2 + _easycom_uni_file_picker2)();
|
}
|
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";
|
const _easycom_uni_file_picker = () => "../../node-modules/@dcloudio/uni-ui/lib/uni-file-picker/uni-file-picker.js";
|
if (!Math) {
|
(_easycom_uni_icons + _easycom_uni_popup + _easycom_uni_file_picker)();
|
}
|
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 filePicker = 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 currentFileList = common_vendor.computed(() => {
|
if (!props.showGradeSlip) {
|
return baseFiles.value;
|
}
|
return currentTab.value === "base" ? baseFiles.value : gradeFiles.value;
|
});
|
const totalFileCount = common_vendor.computed(() => {
|
return 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://")) {
|
return path;
|
}
|
return `${baseUrlHt}${path.startsWith("/") ? "" : "/"}${path}`;
|
};
|
const imageStyles = {
|
width: 120,
|
height: 120,
|
border: false
|
};
|
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 = () => {
|
if (popup.value) {
|
popup.value.open();
|
}
|
};
|
const closePopup = () => {
|
if (popup.value) {
|
popup.value.close();
|
}
|
};
|
const chooseFile = () => {
|
var _a;
|
(_a = filePicker.value) == null ? void 0 : _a.choose();
|
};
|
const getFileTypeFromName = (filename) => {
|
if (!filename)
|
return "application/octet-stream";
|
const ext = filename.split(".").pop().toLowerCase();
|
const typeMap = {
|
jpg: "image/jpeg",
|
jpeg: "image/jpeg",
|
png: "image/png",
|
gif: "image/gif",
|
webp: "image/webp",
|
bmp: "image/bmp",
|
SVG: "image/svg+xml",
|
pdf: "application/pdf"
|
};
|
return typeMap[ext] || "application/octet-stream";
|
};
|
const onFileSelect = (e) => {
|
const isGradeTab = props.showGradeSlip && currentTab.value === "grade";
|
const targetFiles = isGradeTab ? gradeFiles.value : baseFiles.value;
|
const newFiles = e.tempFiles.filter((file) => {
|
const fileExt = file.name ? file.name.split(".").pop().toLowerCase() : "";
|
const isImage = supportedImageTypes.includes(file.type) || ["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"].includes(fileExt);
|
const isPDF = file.type && file.type.includes("pdf") || fileExt === "pdf";
|
return isImage || isPDF;
|
}).map((file) => ({
|
name: file.name,
|
url: file.path || file.url,
|
type: file.type || getFileTypeFromName(file.name),
|
size: file.size,
|
file,
|
status: "pending",
|
// 明确标记附件类型
|
attachmentType: isGradeTab ? "grade" : "base"
|
}));
|
if (targetFiles.length + newFiles.length > props.maxCount) {
|
common_vendor.index.showToast({
|
title: `最多只能上传${props.maxCount}个文件`,
|
icon: "none"
|
});
|
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 getAllFiles = () => {
|
return [...baseFiles.value, ...gradeFiles.value];
|
};
|
const removeFile = (type, index, event) => {
|
if (event) {
|
event.stopPropagation();
|
}
|
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) => {
|
const fullUrl = getFullUrl(file.url);
|
if (file.type && supportedImageTypes.includes(file.type)) {
|
const allFiles = getAllFiles();
|
common_vendor.index.previewImage({
|
urls: allFiles.filter((f) => f.type && supportedImageTypes.includes(f.type)).map((f) => getFullUrl(f.url)),
|
current: fullUrl
|
});
|
} else if (file.type && file.type.includes("pdf")) {
|
common_vendor.index.downloadFile({
|
url: fullUrl,
|
success: (res) => {
|
const filePath = res.tempFilePath;
|
common_vendor.index.openDocument({
|
filePath,
|
fileType: "pdf",
|
success: () => common_vendor.index.__f__("log", "at components/attachment/index.vue:358", "打开PDF成功"),
|
fail: (err) => {
|
common_vendor.index.__f__("error", "at components/attachment/index.vue:360", "打开PDF失败", err);
|
common_vendor.index.showToast({
|
title: "打开PDF失败",
|
icon: "none"
|
});
|
}
|
});
|
},
|
fail: (err) => {
|
common_vendor.index.__f__("error", "at components/attachment/index.vue:369", "下载PDF失败", err);
|
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");
|
common_vendor.index.uploadFile({
|
url: "/api/common/upload",
|
filePath: file.path || file.url,
|
name: "file",
|
header: {
|
"Authorization": `Bearer ${token}`
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
const data = JSON.parse(res.data);
|
common_vendor.index.__f__("log", "at components/attachment/index.vue:397", data, "文件");
|
if (data.code === 200) {
|
resolve({
|
...data,
|
fileName: data.fileName
|
});
|
} else {
|
reject(new Error(data.msg || "上传失败"));
|
}
|
} else {
|
reject(new Error(`上传失败,状态码: ${res.statusCode}`));
|
}
|
},
|
fail: (err) => {
|
reject(err);
|
}
|
});
|
});
|
};
|
const confirmUpload = async () => {
|
if (props.showGradeSlip && props.isGradeRequired && gradeFiles.value.length === 0) {
|
common_vendor.index.showToast({
|
title: "请上传成绩单附件",
|
icon: "none"
|
});
|
currentTab.value = "grade";
|
return;
|
}
|
const allFiles = getAllFiles();
|
if (allFiles.length === 0) {
|
common_vendor.index.showToast({
|
title: "请先添加附件",
|
icon: "none"
|
});
|
return;
|
}
|
common_vendor.index.showLoading({
|
title: "上传中",
|
mask: true
|
});
|
try {
|
const pendingBaseFiles = baseFiles.value.filter((file) => !file.url || file.status === "pending");
|
const pendingGradeFiles = gradeFiles.value.filter((file) => !file.url || file.status === "pending");
|
for (const file of pendingBaseFiles) {
|
try {
|
file.status = "uploading";
|
const res = await uploadFile(file.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 (error) {
|
common_vendor.index.__f__("error", "at components/attachment/index.vue:466", "上传失败:", error);
|
file.status = "error";
|
common_vendor.index.showToast({
|
title: `文件 ${file.name} 上传失败`,
|
icon: "none"
|
});
|
}
|
}
|
for (const file of pendingGradeFiles) {
|
try {
|
file.status = "uploading";
|
const res = await uploadFile(file.file, "grade");
|
Object.assign(file, {
|
url: res.fileName,
|
fileName: res.fileName,
|
newFileName: res.newFileName,
|
originalFilename: res.originalFilename,
|
status: "success"
|
});
|
emit("upload-grade", file);
|
} catch (error) {
|
common_vendor.index.__f__("error", "at components/attachment/index.vue:489", "成绩单附件上传失败:", error);
|
file.status = "error";
|
common_vendor.index.showToast({
|
title: `文件 ${file.name} 上传失败`,
|
icon: "none"
|
});
|
}
|
}
|
common_vendor.index.__f__("log", "at components/attachment/index.vue:497", baseFiles.value, "1");
|
common_vendor.index.__f__("log", "at components/attachment/index.vue:498", gradeFiles.value, "2");
|
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:511", "上传出错:", error);
|
common_vendor.index.showToast({
|
title: "上传出错",
|
icon: "none"
|
});
|
} finally {
|
common_vendor.index.hideLoading();
|
}
|
};
|
const getFilesByType = (type) => {
|
return type === "grade" ? gradeFiles.value : baseFiles.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: !__props.readonly
|
}, !__props.readonly ? {
|
K: common_vendor.sr(filePicker, "2d320176-8", {
|
"k": "filePicker"
|
}),
|
L: common_vendor.o(onFileSelect),
|
M: common_vendor.o(_ctx.onFileDelete),
|
N: common_vendor.p({
|
["auto-upload"]: false,
|
["file-mediatype"]: "all",
|
limit: __props.maxCount - currentFileList.value.length,
|
["image-styles"]: imageStyles
|
})
|
} : {}, {
|
O: common_vendor.gei(_ctx, "")
|
});
|
};
|
}
|
};
|
wx.createComponent(_sfc_main);
|
//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/attachment/index.js.map
|