225 lines
21 KiB
Plaintext
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(),
|