writeOff/patch2.txt
haomingming 52fd2e7560 优化
2026-06-04 10:42:23 +08:00

225 lines
21 KiB
Plaintext

diff --git a/frontend/src/views/modules/MeetingPage.vue b/frontend/src/views/modules/MeetingPage.vue
index 4f45db0..9338aff 100644
--- a/frontend/src/views/modules/MeetingPage.vue
+++ b/frontend/src/views/modules/MeetingPage.vue
@@ -1,4 +1,4 @@
-锘?template>
+<template>
<PageContainer title="浼氳绠$悊">
<MeetingQueryToolbar v-model:query-form="queryForm" @load="handleMeetingQueryLoad" @reset-query="resetQuery" />
<MeetingListTable
@@ -111,6 +111,13 @@
:handle-theme-photo-picture-change="handleThemePhotoPictureChange"
:handle-theme-photo-picture-preview="handleThemePhotoPicturePreview"
:handle-theme-photo-picture-remove="handleThemePhotoPictureRemove"
+ v-model:meeting-video-type="docForm.videoType"
+ v-model:meeting-video-link="docForm.videoLink"
+ :meeting-video-upload-file-list="meetingVideoUploadFileList"
+ :before-meeting-video-upload="beforeMeetingVideoUpload"
+ :handle-meeting-video-picture-change="handleMeetingVideoChange"
+ :handle-meeting-video-picture-remove="handleMeetingVideoRemove"
+ :meeting-form="resolveSelectedMeetingForm()"
:invitation-upload-file-list="invitationUploadFileList"
:before-invitation-upload="beforeInvitationUpload"
:handle-invitation-picture-change="handleInvitationPictureChange"
@@ -944,6 +951,10 @@ const docForm = ref({
themePhotoName: "",
themePhotoOssKey: "",
invitationLines: "",
+ videoType: "file" as "file" | "link",
+ videoName: "",
+ videoOssKey: "",
+ videoLink: "",
});
const expertProfileForm = ref({
fileName: "",
@@ -968,6 +979,7 @@ const agendaFile = ref<File | null>(null);
const signInFile = ref<File | null>(null);
const themePhotoFile = ref<File | null>(null);
const invitationFile = ref<File | null>(null);
+const meetingVideoFile = ref<File | null>(null);
const photoAutoUploading = ref(false);
const laborProtocolAutoUploading = ref(false);
const laborInvoiceAutoUploading = ref(false);
@@ -1438,6 +1450,19 @@ const agendaUploadFileList = computed<UploadUserFile[]>(() =>
} as UploadUserFile & { ossKey: string };
}),
);
+const meetingVideoUploadFileList = computed<UploadUserFile[]>(() => {
+ if (!docForm.value.videoOssKey) {
+ return [];
+ }
+ const name = displayDocName(docForm.value.videoName, docForm.value.videoOssKey, "浼氳瑙嗛");
+ return [{
+ name,
+ url: "",
+ status: "success",
+ uid: 2,
+ ossKey: docForm.value.videoOssKey,
+ } as UploadUserFile & { ossKey: string }];
+});
const signInUploadFileList = computed<UploadUserFile[]>(() => {
if (!docForm.value.signInOssKey) {
return [];
@@ -4275,9 +4300,7 @@ const showPendingIssueSubmitBlockDialog = async (meetingId: number, pendingIssue
}, "褰撳墠浼氳浠嶆湁椹冲洖椤规湭澶勭悊瀹屾垚锛屾殏涓嶈兘鎻愪氦瀹℃牳銆?),
h("div", {
style: "margin-top:8px;font-size:13px;line-height:1.7;color:#606266;",
- }, firstOpenIssue
- ? "璇峰厛鎸夐┏鍥炲師鍥犲畬鎴愪慨鏀癸紱鐘舵€佷负鈥滃凡淇敼锛屽緟瀹℃牳纭鈥濈殑闂锛岄渶瑕佺瓑寰呭鏍镐汉鍛樼‘璁ゅ悗鎵嶈兘鍐嶆鎻愪氦銆?
- : "浠ヤ笅椹冲洖椤瑰凡淇敼浣嗕粛寰呭鏍镐汉鍛樼‘璁わ紝纭瀹屾垚鍓嶆殏涓嶈兘鍐嶆鎻愪氦銆?),
+ }, "璇峰厛鎸夐┏鍥炲師鍥犲畬鎴愪笅鏂瑰垪鍑虹殑闂淇敼鍚庯紝鍐嶅皾璇曟彁浜ゅ鏍搞€?),
h("div", {
style: "margin-top:16px;max-height:360px;overflow:auto;padding-right:6px;",
}, groups.map((group) => h("div", {
@@ -4468,7 +4491,7 @@ const openDocPicturePreview = async (ossKey: string, fileNameHint = "") => {
};
const handleDocPicturePreview = async (
uploadFile: Parameters<NonNullable<UploadProps["onPreview"]>>[0],
- target: "agenda" | "signIn" | "themePhoto" | "invitation",
+ target: "agenda" | "signIn" | "themePhoto" | "invitation" | "meetingVideo",
) => {
const row = uploadFile as UploadUserFile & { ossKey?: string };
const fallbackOssKey = target === "agenda"
@@ -4666,6 +4689,50 @@ const validateExpertProfileFile = (file: File | null, maxSizeMb = MATERIAL_MAX_F
}
return true;
};
+
+const validateVideoFile = (file: File | null, label: string, maxSizeMb = 500) => {
+ if (!file) {
+ return false;
+ }
+ const ext = extractExt(file.name || "");
+ const mime = String(file.type || "").toLowerCase();
+ const allowedExts = new Set([".mp4", ".mov", ".avi", ".mkv"]);
+ if (!allowedExts.has(ext) && !mime.startsWith("video/")) {
+ ElMessage.warning(`${label}浠呮敮鎸佽棰戞枃浠?mp4/mov/avi/mkv)`);
+ return false;
+ }
+ if (Number(file.size || 0) > maxSizeMb * 1024 * 1024) {
+ ElMessage.warning(`${label}澶у皬涓嶈兘瓒呰繃${maxSizeMb}MB`);
+ return false;
+ }
+ return true;
+};
+
+const beforeMeetingVideoUpload = (rawFile: any, maxSizeMb = 500) =>
+ validateVideoFile((rawFile as File) || null, "浼氳瑙嗛", maxSizeMb);
+
+const handleMeetingVideoChange = async (uploadFile: any, uploadFiles: any, maxSizeMb = 500) => {
+ if (isReviewApproved("meetingVideo")) {
+ warnReviewedMaterialLocked();
+ return;
+ }
+ const file = (uploadFile?.raw as File) || null;
+ meetingVideoFile.value = validateVideoFile(file, "浼氳瑙嗛", maxSizeMb) ? file : null;
+ if (!meetingVideoFile.value) {
+ return;
+ }
+ await uploadDocFile("meetingVideo");
+};
+
+const handleMeetingVideoRemove = () => {
+ if (isReviewApproved("meetingVideo")) {
+ warnReviewedMaterialLocked();
+ return false;
+ }
+ docForm.value.videoName = "";
+ docForm.value.videoOssKey = "";
+};
+
const beforeAgendaUpload = (rawFile: any, maxSizeMb?: number) => {
if (!validateMaterialFile((rawFile as File) || null, "浼氳鏃ョ▼", maxSizeMb)) {
return false;
@@ -4891,7 +4958,7 @@ const handleLaborInvoiceFileRemove: UploadProps["onRemove"] = async (uploadFile)
laborInvoiceUploadFiles.value = [];
};
-const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invitation") => {
+const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invitation" | "meetingVideo") => {
if (!selectedMeetingId.value) {
return;
}
@@ -4901,7 +4968,9 @@ const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invit
? signInFile.value
: target === "themePhoto"
? themePhotoFile.value
- : invitationFile.value;
+ : target === "meetingVideo"
+ ? meetingVideoFile.value
+ : invitationFile.value;
if (!file) {
ElMessage.warning("璇峰厛閫夋嫨鏂囦欢");
return;
@@ -4930,6 +4999,10 @@ const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invit
docForm.value.themePhotoName = file.name;
docForm.value.themePhotoOssKey = objectKey;
themePhotoFile.value = null;
+ } else if (target === "meetingVideo") {
+ docForm.value.videoName = file.name;
+ docForm.value.videoOssKey = objectKey;
+ meetingVideoFile.value = null;
} else {
const line = `${file.name}|${objectKey}`;
docForm.value.invitationLines = docForm.value.invitationLines ? `${docForm.value.invitationLines}\n${line}` : line;
@@ -5463,7 +5536,7 @@ const resetMaterialForms = () => {
improvementSuggestion: "",
meetingEffect: "",
};
- docForm.value = { agendaLines: "", signInName: "", signInOssKey: "", themePhotoName: "", themePhotoOssKey: "", invitationLines: "" };
+ docForm.value = { agendaLines: "", signInName: "", signInOssKey: "", themePhotoName: "", themePhotoOssKey: "", invitationLines: "", videoType: "file", videoName: "", videoOssKey: "", videoLink: "" };
expertProfileForm.value = { fileName: "", ossKey: "" };
photoForm.value = { photoLines: "", summary: "" };
photoSummaryByExpert.value = {};
@@ -5900,6 +5973,10 @@ const loadMaterialModule = async (
docForm.value.signInOssKey = parsed.signInSheet?.ossKey || "";
docForm.value.themePhotoName = resolveStoredDocFileName(parsed.themePhoto);
docForm.value.themePhotoOssKey = parsed.themePhoto?.ossKey || "";
+ docForm.value.videoType = parsed.meetingVideo?.type || "file";
+ docForm.value.videoName = resolveStoredDocFileName(parsed.meetingVideo) || String(parsed.meetingVideo?.name || "");
+ docForm.value.videoOssKey = parsed.meetingVideo?.ossKey || "";
+ docForm.value.videoLink = parsed.meetingVideo?.link || "";
expertProfileForm.value.fileName = resolveStoredDocFileName(parsed?.profileFile) || String(parsed?.fileName || "").trim();
expertProfileForm.value.ossKey = String(parsed?.profileFile?.ossKey || parsed?.ossKey || "").trim();
const invitationList = Array.isArray(parsed.invitation) ? parsed.invitation : [];
@@ -5913,6 +5990,10 @@ const loadMaterialModule = async (
docForm.value.signInOssKey = parsed.signInSheet?.ossKey || "";
docForm.value.themePhotoName = resolveStoredDocFileName(parsed.themePhoto);
docForm.value.themePhotoOssKey = parsed.themePhoto?.ossKey || "";
+ docForm.value.videoType = parsed.meetingVideo?.type || "file";
+ docForm.value.videoName = resolveStoredDocFileName(parsed.meetingVideo) || String(parsed.meetingVideo?.name || "");
+ docForm.value.videoOssKey = parsed.meetingVideo?.ossKey || "";
+ docForm.value.videoLink = parsed.meetingVideo?.link || "";
const invitationList = Array.isArray(parsed.invitation) ? parsed.invitation : [];
docForm.value.invitationLines = invitationList
.map((x: any) => `${resolveStoredDocFileName(x)}|${x?.ossKey || ""}`.trim())
@@ -6801,6 +6882,13 @@ const buildContentJson = () => {
fileName: String(docForm.value.themePhotoName || "").trim(),
ossKey: String(docForm.value.themePhotoOssKey || "").trim(),
},
+ meetingVideo: {
+ type: docForm.value.videoType,
+ name: String(docForm.value.videoName || "").trim(),
+ fileName: String(docForm.value.videoName || "").trim(),
+ ossKey: String(docForm.value.videoOssKey || "").trim(),
+ link: String(docForm.value.videoLink || "").trim(),
+ },
invitation: (docForm.value.invitationLines || "")
.split("\n")
.map((line) => line.trim())
@@ -6848,6 +6936,13 @@ const buildContentJson = () => {
fileName: String(docForm.value.themePhotoName || "").trim(),
ossKey: String(docForm.value.themePhotoOssKey || "").trim(),
},
+ meetingVideo: {
+ type: docForm.value.videoType,
+ name: String(docForm.value.videoName || "").trim(),
+ fileName: String(docForm.value.videoName || "").trim(),
+ ossKey: String(docForm.value.videoOssKey || "").trim(),
+ link: String(docForm.value.videoLink || "").trim(),
+ },
invitation: invitations,
profileFile: {
name: String(expertProfileForm.value.fileName || "").trim(),