update MeetingPage
This commit is contained in:
parent
815aa04fe8
commit
edffa25ccd
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<PageContainer title="浼氳绠$悊">
|
||||
<PageContainer title="会议管理">
|
||||
<MeetingQueryToolbar v-model:query-form="queryForm" @load="load" @reset-query="resetQuery" />
|
||||
<MeetingListTable
|
||||
:rows="rows"
|
||||
@ -392,9 +392,9 @@ const defaultMeetingForm = () => ({
|
||||
projectName: "",
|
||||
projectStartDate: "",
|
||||
projectEndDate: "",
|
||||
topic: "MVP浼氳",
|
||||
topic: "MVP会议",
|
||||
meetingCategory: "学术会",
|
||||
meetingForm: "绾夸笅",
|
||||
meetingForm: "线下",
|
||||
location: "",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
@ -421,7 +421,7 @@ const meetingFormTimeRange = computed<string[]>({
|
||||
},
|
||||
});
|
||||
const materialDialogVisible = ref(false);
|
||||
const materialDialogTitle = ref("浼氳璧勬枡");
|
||||
const materialDialogTitle = ref("会议资料");
|
||||
const selectedMeetingId = ref<number | null>(null);
|
||||
const selectedMeetingAuditStatus = computed(() => {
|
||||
const meetingId = Number(selectedMeetingId.value || 0);
|
||||
@ -524,11 +524,11 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
{
|
||||
code: "VENUE_CONFIRMATION",
|
||||
order: 2,
|
||||
title: "浼氬満纭鍑?浼氬満鍗忚",
|
||||
title: "会场确认函/会场协议",
|
||||
needAmount: true,
|
||||
maxUploadCount: 5,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
],
|
||||
sampleImage: [VenueSampleImage, VenueAgreementSampleImage],
|
||||
@ -536,36 +536,36 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
{
|
||||
code: "CONSTRUCTION_DETAIL",
|
||||
order: 3,
|
||||
title: "浼氳鎼缓鏄庣粏",
|
||||
title: "会议搭建明细",
|
||||
needAmount: true,
|
||||
maxUploadCount: 15,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
{ key: "equipmentFile", label: "璁惧鐓х墖" },
|
||||
{ key: "equipmentFile", label: "设备照片" },
|
||||
],
|
||||
sampleImage: [ConstructionSampleImage, EquipmentSampleImage2]
|
||||
},
|
||||
{
|
||||
code: "ACCOMMODATION_DETAIL",
|
||||
order: 4,
|
||||
title: "浣忓鏄庣粏",
|
||||
title: "住宿明细",
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "CATERING_DETAIL",
|
||||
order: 5,
|
||||
title: "椁愰ギ鏄庣粏",
|
||||
title: "餐饮明细",
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "detailFile", label: "鏄庣粏鍗?姘村崟" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单/水单" },
|
||||
],
|
||||
sampleImage: CateringSampleImage,
|
||||
},
|
||||
@ -576,7 +576,7 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
],
|
||||
sampleImage: [LocalTransportSampleImage, LocalTransportSampleImage2, LocalTransportSampleImage3],
|
||||
@ -588,7 +588,7 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
],
|
||||
sampleImage: [IntercityTransportSampleImage, IntercityTransportSampleImage2, IntercityTransportSampleImage3, IntercityTransportSampleImage4],
|
||||
@ -596,13 +596,13 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
{
|
||||
code: "MATERIAL_DETAIL",
|
||||
order: 8,
|
||||
title: "鐗╂枡鏄庣粏",
|
||||
title: "物料明细",
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
{ key: "materialFile", label: "鐗╂枡鐓х墖" },
|
||||
{ key: "materialFile", label: "物料照片" },
|
||||
],
|
||||
sampleImage: [MaterialSampleImage, MaterialSampleImage2, MaterialSampleImage3, MaterialSampleImage4, MaterialSampleImage5, MaterialSampleImage6],
|
||||
},
|
||||
@ -613,7 +613,7 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
needAmount: true,
|
||||
maxUploadCount: 50,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍙戠エ" },
|
||||
{ key: "invoiceFile", label: "发票" },
|
||||
{ key: "detailFile", label: "明细单" },
|
||||
{ key: "designDraftFile", label: "设计稿" },
|
||||
],
|
||||
@ -622,15 +622,15 @@ const meetingInvoiceSectionDefs: MeetingInvoiceSectionDef[] = [
|
||||
{
|
||||
code: "OTHER",
|
||||
order: 10,
|
||||
title: "鍏朵粬",
|
||||
title: "其他",
|
||||
needAmount: true,
|
||||
maxUploadCount: 5,
|
||||
uploadFields: [
|
||||
{ key: "invoiceFile", label: "鍏朵粬闄勪欢1" },
|
||||
{ key: "detailFile", label: "鍏朵粬闄勪欢2" },
|
||||
{ key: "equipmentFile", label: "鍏朵粬闄勪欢3" },
|
||||
{ key: "materialFile", label: "鍏朵粬闄勪欢4" },
|
||||
{ key: "designDraftFile", label: "鍏朵粬闄勪欢5" },
|
||||
{ key: "invoiceFile", label: "其他附件1" },
|
||||
{ key: "detailFile", label: "其他附件2" },
|
||||
{ key: "equipmentFile", label: "其他附件3" },
|
||||
{ key: "materialFile", label: "其他附件4" },
|
||||
{ key: "designDraftFile", label: "其他附件5" },
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -765,7 +765,7 @@ const filterMeetingInvoiceSectionDefsByMeetingForm = (
|
||||
sectionDefs: MeetingInvoiceSectionDef[] = meetingInvoiceSectionDefs,
|
||||
) => {
|
||||
const meetingForm = String(meetingFormRaw || "").trim();
|
||||
if (meetingForm !== "绾夸笂") {
|
||||
if (meetingForm !== "线上") {
|
||||
return sectionDefs;
|
||||
}
|
||||
const otherSection = sectionDefs.find((def) => def.code === "OTHER");
|
||||
@ -785,7 +785,7 @@ const resolveSelectedMeetingForm = () => {
|
||||
};
|
||||
const filteredMeetingInvoiceSectionDefs = computed(() => {
|
||||
const meetingForm = resolveSelectedMeetingForm();
|
||||
if (meetingForm === "绾夸笂") {
|
||||
if (meetingForm === "线上") {
|
||||
return filterMeetingInvoiceSectionDefsByMeetingForm(meetingForm);
|
||||
}
|
||||
const meetingId = Number(selectedMeetingId.value || 0);
|
||||
@ -1142,10 +1142,10 @@ const resolveReviewResult = (itemKey: string | string[]) => resolveReviewField(i
|
||||
const toReviewResultText = (itemKey: string | string[]) => {
|
||||
const result = resolveReviewResult(itemKey);
|
||||
if (result === "APPROVED") {
|
||||
return "宸查€氳繃";
|
||||
return "已通过";
|
||||
}
|
||||
if (result === "REJECTED") {
|
||||
return "涓嶉€氳繃";
|
||||
return "已拒绝";
|
||||
}
|
||||
return "";
|
||||
};
|
||||
@ -1168,7 +1168,7 @@ const buildMeetingInvoiceFieldItemKey = (sectionCode: MeetingInvoiceSectionCode,
|
||||
`meeting_invoice:${sectionCode}:${fieldKey}`;
|
||||
const buildMeetingInvoiceAmountItemKey = (sectionCode: MeetingInvoiceSectionCode) => `meeting_invoice:${sectionCode}:amount`;
|
||||
const warnReviewedMaterialLocked = () => {
|
||||
ElMessage.warning("璇ヤ細璁祫鏂欎腑鐨勫凡瀹℃牳閫氳繃椤逛笉鍏佽淇敼");
|
||||
ElMessage.warning("该会议资料中的已审核通过项不允许修改");
|
||||
};
|
||||
const warnMeetingMaterialReadonly = () => {
|
||||
ElMessage.warning("该会议资料审核中或已审核通过,不允许再修改");
|
||||
@ -1244,7 +1244,7 @@ const isImageDocFile = (name: string, ossKey: string) => isImageFile(name || "")
|
||||
const isPdfDocFile = (name: string, ossKey: string) => extractExt(name || "") === ".pdf" || extractExt(ossKey || "") === ".pdf";
|
||||
const agendaUploadFileList = computed<UploadUserFile[]>(() =>
|
||||
agendaDocRows.value.map((item, index) => {
|
||||
const name = item.name || `浼氳鏃ョ▼${index + 1}`;
|
||||
const name = item.name || `会议日程${index + 1}`;
|
||||
const isImage = isImageDocFile(name, item.ossKey);
|
||||
return {
|
||||
name,
|
||||
@ -1273,7 +1273,7 @@ const themePhotoUploadFileList = computed<UploadUserFile[]>(() => {
|
||||
if (!docForm.value.themePhotoOssKey) {
|
||||
return [];
|
||||
}
|
||||
const name = displayDocName(docForm.value.themePhotoName, docForm.value.themePhotoOssKey, "涓婚鐓х墖");
|
||||
const name = displayDocName(docForm.value.themePhotoName, docForm.value.themePhotoOssKey, "主题照片");
|
||||
const isImage = isImageDocFile(name, docForm.value.themePhotoOssKey);
|
||||
return [{
|
||||
name,
|
||||
@ -1287,7 +1287,7 @@ const invitationUploadFileList = computed<UploadUserFile[]>(() =>
|
||||
invitationDocRows.value.map((item, index) => {
|
||||
const isImage = isImageDocFile(item.name, item.ossKey);
|
||||
return {
|
||||
name: item.name || `閭€璇峰嚱${index + 1}`,
|
||||
name: item.name || `邀请函${index + 1}`,
|
||||
url: isImage ? (docPreviewUrlMap.value[item.ossKey] || "") : "",
|
||||
status: "success",
|
||||
uid: index + 1,
|
||||
@ -1300,7 +1300,7 @@ const expertProfileUploadFileList = computed<UploadUserFile[]>(() => {
|
||||
if (!ossKey) {
|
||||
return [];
|
||||
}
|
||||
const fileName = String(expertProfileForm.value.fileName || "").trim() || "涓撳绠€浠?涓插満";
|
||||
const fileName = String(expertProfileForm.value.fileName || "").trim() || "专家简介/串场";
|
||||
return [{
|
||||
name: fileName,
|
||||
status: "success",
|
||||
@ -1318,7 +1318,7 @@ const laborProtocolUploadFileList = computed<UploadUserFile[]>(() => {
|
||||
if (!row || !ossKey) {
|
||||
return [];
|
||||
}
|
||||
const fileName = String(row.protocolFileName || "").trim() || String(row.protocolName || "").trim() || "鍗忚鏂囦欢";
|
||||
const fileName = String(row.protocolFileName || "").trim() || String(row.protocolName || "").trim() || "协议文件";
|
||||
const preview = String(row.protocolPreviewUrl || "").trim();
|
||||
const isImage = isImageDocFile(fileName, ossKey);
|
||||
return [{
|
||||
@ -1341,7 +1341,7 @@ const laborInvoiceUploadFileList = computed<UploadUserFile[]>(() => {
|
||||
}
|
||||
return files.map((file, index) => {
|
||||
const ossKey = String(file?.ossKey || "").trim();
|
||||
const fileName = String(file?.fileName || "").trim() || `鍔冲姟鍙戠エ${index + 1}`;
|
||||
const fileName = String(file?.fileName || "").trim() || `劳务发票${index + 1}`;
|
||||
const preview = String(file?.previewUrl || "").trim();
|
||||
const isImage = isImageDocFile(fileName, ossKey);
|
||||
return {
|
||||
@ -1398,7 +1398,7 @@ const getMeetingInvoiceFileRow = (
|
||||
};
|
||||
|
||||
const ocrRawDialogVisible = ref(false);
|
||||
const ocrRawDialogTitle = ref("OCR鍘熷缁撴灉");
|
||||
const ocrRawDialogTitle = ref("OCR原始结果");
|
||||
const ocrRawDialogText = ref("");
|
||||
const laborInvoiceOcrConfirmVisible = ref(false);
|
||||
const laborAgreementExtractConfirmVisible = ref(false);
|
||||
@ -1500,7 +1500,7 @@ const mergeLaborRow = (current: LaborRow | null | undefined, incoming: LaborRow)
|
||||
const openOcrRawDialog = (sectionCode: MeetingInvoiceSectionCode, fieldKey: MeetingInvoiceUploadFieldKey) => {
|
||||
const row = getMeetingInvoiceFileRow(sectionCode, fieldKey);
|
||||
const raw = row?.ocr?.raw;
|
||||
ocrRawDialogTitle.value = `OCR鍘熷缁撴灉 - ${sectionCode}/${fieldKey}`;
|
||||
ocrRawDialogTitle.value = `OCR原始结果 - ${sectionCode}/${fieldKey}`;
|
||||
try {
|
||||
ocrRawDialogText.value = raw ? JSON.stringify(raw, null, 2) : "";
|
||||
} catch (_e) {
|
||||
@ -1580,7 +1580,7 @@ const resolveCurrentExpertName = (expertId: number) => {
|
||||
const runLaborInvoiceOcr = async (targetOssKey?: string) => {
|
||||
const expertId = Number(selectedExpertMaterialId.value || 0);
|
||||
if (!expertId) {
|
||||
ElMessage.warning("鏈€夋嫨涓撳");
|
||||
ElMessage.warning("未选择专家");
|
||||
return;
|
||||
}
|
||||
const row = getCurrentLaborRow(expertId);
|
||||
@ -1607,7 +1607,7 @@ const runLaborInvoiceOcr = async (targetOssKey?: string) => {
|
||||
const totalAmountCent = Number(normalized?.totalAmountCent || 0);
|
||||
const taxCent = Number(normalized?.taxCent || 0);
|
||||
|
||||
console.groupCollapsed("[LaborInvoiceOCR] 濮撳悕姣斿璋冭瘯");
|
||||
console.groupCollapsed("[LaborInvoiceOCR] 姓名比对调试");
|
||||
console.info("expertId =", expertId);
|
||||
console.info("expertName =", expertName);
|
||||
console.info("normalized.name =", normalizedName);
|
||||
@ -1649,10 +1649,10 @@ const runLaborInvoiceOcr = async (targetOssKey?: string) => {
|
||||
status: "failed",
|
||||
normalized: row.invoiceOcr?.normalized,
|
||||
raw: row.invoiceOcr?.raw,
|
||||
message: String(e?.message || "鍔冲姟鍙戠エOCR璇嗗埆澶辫触"),
|
||||
message: String(e?.message || "劳务发票OCR识别失败"),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
ElMessage.error(row.invoiceOcr.message || "鍔冲姟鍙戠エOCR璇嗗埆澶辫触");
|
||||
ElMessage.error(row.invoiceOcr.message || "劳务发票OCR识别失败");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1679,7 +1679,7 @@ const confirmLaborInvoiceOcrFill = () => {
|
||||
if (!laborInvoiceOcrConfirmData.value.nameMatched) {
|
||||
ElMessage.warning(`劳务发票姓名识别为“${laborInvoiceOcrConfirmData.value.ocrName || "-"}”,与当前专家“${laborInvoiceOcrConfirmData.value.expertName || "-"}”不一致,请核对。`);
|
||||
} else {
|
||||
ElMessage.success("宸茬‘璁ゅ苟鍥炲~鍔冲姟鍙戠エOCR缁撴灉");
|
||||
ElMessage.success("已确认并回填劳务发票OCR结果");
|
||||
}
|
||||
laborInvoiceOcrConfirmVisible.value = false;
|
||||
};
|
||||
@ -1755,10 +1755,10 @@ const runMeetingInvoiceOcr = async (sectionCode: MeetingInvoiceSectionCode, fiel
|
||||
status: "failed",
|
||||
normalized: row.ocr?.normalized,
|
||||
raw: row.ocr?.raw,
|
||||
message: String(e?.message || "OCR璇嗗埆澶辫触"),
|
||||
message: String(e?.message || "OCR识别失败"),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
ElMessage.error(row.ocr.message || "OCR璇嗗埆澶辫触");
|
||||
ElMessage.error(row.ocr.message || "OCR识别失败");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1787,7 +1787,7 @@ const confirmMeetingInvoiceOcrFill = () => {
|
||||
const newAmountYuan = Number((Number(meetingInvoiceOcrConfirmData.value.totalAmountCent || 0) / 100).toFixed(2));
|
||||
section.totalAmountYuan = Number((currentAmountYuan + newAmountYuan).toFixed(2));
|
||||
}
|
||||
ElMessage.success("宸茬‘璁ゅ苟鍥炲~浼氳鍙戠エOCR缁撴灉");
|
||||
ElMessage.success("已确认并回填会议发票OCR结果");
|
||||
meetingInvoiceOcrConfirmVisible.value = false;
|
||||
};
|
||||
|
||||
@ -1815,7 +1815,7 @@ const meetingInvoiceOtherUploadFileList = computed<UploadUserFile[]>(() =>
|
||||
if (!ossKey) {
|
||||
return null;
|
||||
}
|
||||
const name = String(row?.fileName || "").trim() || `鍏朵粬闄勪欢${index + 1}-${rowIndex + 1}`;
|
||||
const name = String(row?.fileName || "").trim() || `其他附件${index + 1}-${rowIndex + 1}`;
|
||||
const isImage = isImageDocFile(name, ossKey);
|
||||
return {
|
||||
name,
|
||||
@ -1991,7 +1991,7 @@ const handleSelectExpertForMaterial = (row: any) => {
|
||||
const expertModuleDoneText = (expertId: number) => {
|
||||
const id = Number(expertId || 0);
|
||||
if (!id) {
|
||||
return "鏈~";
|
||||
return "未填";
|
||||
}
|
||||
if (selectedModuleCode.value === "EXPERT_LIST" && expertSubModule.value === "ONSITE_PHOTO") {
|
||||
return `${(photoByExpert.value[id] || []).length}张`;
|
||||
@ -1999,7 +1999,7 @@ const expertModuleDoneText = (expertId: number) => {
|
||||
if (selectedModuleCode.value === "EXPERT_LIST" && expertSubModule.value === "LABOR_PROTOCOL") {
|
||||
const row = laborByExpert.value[id];
|
||||
if (!row || isLaborRowEmpty(row)) {
|
||||
return "鏈~";
|
||||
return "未填";
|
||||
}
|
||||
return row.protocolOssKey ? "已上传协议" : "已填写";
|
||||
}
|
||||
@ -2015,7 +2015,7 @@ const putToSignedUrl = async (url: string, file: File, contentType?: string) =>
|
||||
body: file,
|
||||
});
|
||||
if (!result.ok) {
|
||||
throw new Error(`涓婁紶澶辫触: ${result.status}`);
|
||||
throw new Error(`上传失败: ${result.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2134,7 +2134,7 @@ const ensureSummaryTaskState = async (meetingId: number) => {
|
||||
|
||||
const showSummaryTaskStatusMessage = (state: SummaryTaskState | null | undefined) => {
|
||||
if (!state?.taskId) {
|
||||
ElMessage.warning("璇峰厛鐢熸垚浼氳鎬荤粨浠诲姟");
|
||||
ElMessage.warning("请先生成会议总结任务");
|
||||
return;
|
||||
}
|
||||
const status = String(state.status || "").toUpperCase();
|
||||
@ -2143,10 +2143,10 @@ const showSummaryTaskStatusMessage = (state: SummaryTaskState | null | undefined
|
||||
return;
|
||||
}
|
||||
if (status === "FAILED") {
|
||||
ElMessage.error(state.errorMessage ? `浼氳鎬荤粨浠诲姟澶辫触锛${state.errorMessage}` : "浼氳鎬荤粨浠诲姟澶辫触");
|
||||
ElMessage.error(state.errorMessage ? `会议总结任务失败:${state.errorMessage}` : "会议总结任务失败");
|
||||
return;
|
||||
}
|
||||
ElMessage.info(`浼氳鎬荤粨浠诲姟褰撳墠鐘舵€侊細${toZhStatus(status || "PENDING")}`);
|
||||
ElMessage.info(`会议总结任务当前状态:${toZhStatus(status || "PENDING")}`);
|
||||
};
|
||||
|
||||
const syncSearchRoute = async () => {
|
||||
@ -2252,7 +2252,7 @@ const handleUpdate = async () => {
|
||||
const nextBudgetCent = toCent(meetingForm.value.budgetYuan);
|
||||
const prevBudgetCent = Math.max(0, Number(currentEditOriginalBudgetCent.value || 0));
|
||||
if (!currentEditAllowMeetingOverBudget.value && nextBudgetCent > prevBudgetCent) {
|
||||
ElMessage.warning("褰撳墠椤圭洰涓嶅厑璁镐細璁绠楄皟楂橈紝浠呮敮鎸佷繚鎸佷笉鍙樻垨璋冧綆棰勭畻");
|
||||
ElMessage.warning("当前项目不允许会议预算调高,仅支持保持不变或调低预算");
|
||||
return;
|
||||
}
|
||||
await updateMeeting(currentEditMeetingId.value, {
|
||||
@ -2267,17 +2267,17 @@ const handleUpdate = async () => {
|
||||
laborRatio: meetingForm.value.laborRatio,
|
||||
cateringRatio: meetingForm.value.cateringRatio,
|
||||
});
|
||||
ElMessage.success("浼氳缂栬緫鎴愬姛");
|
||||
ElMessage.success("会议编辑成功");
|
||||
editDrawerVisible.value = false;
|
||||
await load();
|
||||
};
|
||||
|
||||
const REQUIRED_MODULES = [
|
||||
{ code: "BASIC_INFO", name: "浼氳鍩烘湰淇℃伅妯″潡" },
|
||||
{ code: "WRITE_OFF_DOCS", name: "鏍搁攢鏉愭枡妯″潡" },
|
||||
{ code: "EXPERT_PROFILE", name: "涓撳绠€浠?涓插満妯″潡" },
|
||||
{ code: "EXPERT_LIST", name: "涓撳鍒楄〃妯″潡" },
|
||||
{ code: "MEETING_INVOICE", name: "浼氳鍙戠エ妯″潡" },
|
||||
{ code: "BASIC_INFO", name: "会议基本信息模块" },
|
||||
{ code: "WRITE_OFF_DOCS", name: "核销材料模块" },
|
||||
{ code: "EXPERT_PROFILE", name: "专家简介/串场模块" },
|
||||
{ code: "EXPERT_LIST", name: "专家列表模块" },
|
||||
{ code: "MEETING_INVOICE", name: "会议发票模块" },
|
||||
];
|
||||
|
||||
const handleSubmit = async (meetingId: number) => {
|
||||
@ -2305,7 +2305,7 @@ const handleSubmit = async (meetingId: number) => {
|
||||
|
||||
if (missingModuleNames.length > 0) {
|
||||
ElMessageBox.alert(`请先完善以下模块后再提交审核:${missingModuleNames.join("、")}`, "提示", {
|
||||
confirmButtonText: "纭畾",
|
||||
confirmButtonText: "确定",
|
||||
type: "warning",
|
||||
});
|
||||
return;
|
||||
@ -2322,7 +2322,7 @@ const handleSubmit = async (meetingId: number) => {
|
||||
const handleWithdraw = async (meetingId: number) => {
|
||||
await withdrawMeeting(meetingId, {
|
||||
idempotencyKey: `withdraw-${Date.now()}-${meetingId}`,
|
||||
reason: "浼氳鎾ゅ洖鎻愪氦",
|
||||
reason: "会议撤回提交",
|
||||
});
|
||||
ElMessage.success("会议已撤回到待提交状态");
|
||||
await load();
|
||||
@ -2331,8 +2331,8 @@ const handleWithdraw = async (meetingId: number) => {
|
||||
const handleDeleteDraft = async (meetingId: number) => {
|
||||
await ElMessageBox.confirm("确认删除该草稿会议?删除后不可恢复。", "删除草稿", {
|
||||
type: "warning",
|
||||
confirmButtonText: "纭鍒犻櫎",
|
||||
cancelButtonText: "鍙栨秷",
|
||||
confirmButtonText: "确认删除",
|
||||
cancelButtonText: "取消",
|
||||
});
|
||||
await deleteMeeting(meetingId);
|
||||
ElMessage.success("草稿会议已删除");
|
||||
@ -2341,10 +2341,10 @@ const handleDeleteDraft = async (meetingId: number) => {
|
||||
|
||||
const handleCancelMeeting = async (meetingId: number) => {
|
||||
const result = await ElMessageBox.prompt("请输入取消原因", "取消会议", {
|
||||
confirmButtonText: "纭鍙栨秷",
|
||||
cancelButtonText: "杩斿洖",
|
||||
confirmButtonText: "确认取消",
|
||||
cancelButtonText: "返回",
|
||||
inputPlaceholder: "请输入取消原因",
|
||||
inputValidator: (val: string) => (val && val.trim() ? true : "鍙栨秷鍘熷洜涓嶈兘涓虹┖"),
|
||||
inputValidator: (val: string) => (val && val.trim() ? true : "取消原因不能为空"),
|
||||
}).catch(() => null);
|
||||
if (!result) return;
|
||||
await cancelMeeting(meetingId, { reason: result.value });
|
||||
@ -2358,13 +2358,13 @@ const handleExportMaterials = async (meetingId: number) => {
|
||||
fileName: buildMeetingExportFileName(meetingId, "会议资料包", ".zip"),
|
||||
});
|
||||
const taskId = Number(resp?.data?.taskId || 0);
|
||||
ElMessage.success(taskId > 0 ? `璧勬枡鍖呭鍑轰换鍔″凡鍒涘缓锛${taskId}锛岃鍓嶅線瀵煎嚭浠诲姟涓績涓嬭浇` : "璧勬枡鍖呭鍑轰换鍔″凡鍒涘缓锛岃鍓嶅線瀵煎嚭浠诲姟涓績涓嬭浇");
|
||||
ElMessage.success(taskId > 0 ? `资料包导出任务已创建:${taskId},请前往导出任务中心下载` : "资料包导出任务已创建,请前往导出任务中心下载");
|
||||
};
|
||||
|
||||
const handleGenerateSummary = async (meetingId: number) => {
|
||||
const resp = await generateMeetingSummaryTask(meetingId, {
|
||||
idempotencyKey: `summary-generate-${meetingId}-${Date.now()}`,
|
||||
fileName: buildMeetingExportFileName(meetingId, "浼氳鎬荤粨", ".docx"),
|
||||
fileName: buildMeetingExportFileName(meetingId, "会议总结", ".docx"),
|
||||
});
|
||||
const taskId = Number(resp?.data?.taskId || 0);
|
||||
if (taskId > 0) {
|
||||
@ -2390,7 +2390,7 @@ const handleRefreshSummaryToken = async (meetingId: number) => {
|
||||
const state = await ensureSummaryTaskState(meetingId);
|
||||
const taskId = Number(state?.taskId || 0);
|
||||
if (!taskId) {
|
||||
ElMessage.warning("璇峰厛鐢熸垚浼氳鎬荤粨浠诲姟");
|
||||
ElMessage.warning("请先生成会议总结任务");
|
||||
return;
|
||||
}
|
||||
const status = String(state?.status || "").toUpperCase();
|
||||
@ -2450,7 +2450,7 @@ const loadBoundExperts = async (meetingId: number, requestId?: number) => {
|
||||
const list = resp?.data || [];
|
||||
boundExpertRows.value = list.map((item: any) => ({
|
||||
expertId: item?.expertId,
|
||||
// 浼樺厛灞曠ず鍚庣杩斿洖鐨勮劚鏁忓瓧娈碉紝鏈彁渚涙椂鍏滃簳鍘熷瓧娈?
|
||||
// 优先展示后端返回的脱敏字段,未提供时兜底原字段
|
||||
expertName: item?.expertNameMasked || item?.maskedExpertName || item?.expertName || "",
|
||||
title: item?.title || "",
|
||||
organization: item?.organizationMasked || item?.maskedOrganization || item?.organization || "",
|
||||
@ -2488,14 +2488,14 @@ const loadPlatformExperts = async () => {
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
selectedPlatformExpertNameMap.value[id] = String(item?.expertName || "").trim() || `涓撳#${id}`;
|
||||
selectedPlatformExpertNameMap.value[id] = String(item?.expertName || "").trim() || `专家#${id}`;
|
||||
}
|
||||
const rowIdSet = new Set(platformExpertRows.value.map((item: any) => Number(item?.id || 0)).filter((id: number) => id > 0));
|
||||
currentSearchSelectedPlatformExpertIds.value = selectedPlatformExpertIds.value.filter((id) => rowIdSet.has(id));
|
||||
} catch (e: any) {
|
||||
platformExpertRows.value = [];
|
||||
currentSearchSelectedPlatformExpertIds.value = [];
|
||||
ElMessage.error(e?.response?.data?.message || "骞冲彴涓撳鍔犺浇澶辫触");
|
||||
ElMessage.error(e?.response?.data?.message || "平台专家加载失败");
|
||||
} finally {
|
||||
platformExpertSearched.value = true;
|
||||
}
|
||||
@ -2541,7 +2541,7 @@ const handleCurrentSearchExpertSelectChange = (checkedIds: Array<number | string
|
||||
if (removedBoundIds.length > 0) {
|
||||
removedBoundIds.forEach((id) => checkedIdSet.add(id));
|
||||
currentSearchSelectedPlatformExpertIds.value = Array.from(checkedIdSet);
|
||||
ElMessage.warning("宸茬粦瀹氫笓瀹惰鍏堣蛋瑙g粦娴佺▼锛屼笉鑳界洿鎺ュ湪妫€绱㈢粨鏋滀腑鍒犻櫎");
|
||||
ElMessage.warning("已绑定专家请先走解绑流程,不能直接在搜索结果中删除");
|
||||
}
|
||||
const nextSelected = selectedPlatformExpertIds.value
|
||||
.filter((id) => !rowIdSet.has(id));
|
||||
@ -2649,7 +2649,7 @@ const runCreateExpertIdOcr = async (side: "front" | "back", objectKey: string) =
|
||||
};
|
||||
createExpertIdOcrDialogVisible.value = true;
|
||||
} catch (e: any) {
|
||||
ElMessage.warning(e?.response?.data?.message || e?.message || "韬唤璇丱CR璇嗗埆澶辫触");
|
||||
ElMessage.warning(e?.response?.data?.message || e?.message || "身份证OCR识别失败");
|
||||
}
|
||||
};
|
||||
|
||||
@ -2663,7 +2663,7 @@ const confirmCreateExpertIdOcrFill = () => {
|
||||
}
|
||||
}
|
||||
createExpertIdOcrDialogVisible.value = false;
|
||||
ElMessage.success("宸茬‘璁ゅ苟鍥炲~韬唤璇丱CR缁撴灉");
|
||||
ElMessage.success("已确认并回填身份证OCR结果");
|
||||
};
|
||||
|
||||
const cancelCreateExpertIdOcrFill = () => {
|
||||
@ -2683,7 +2683,7 @@ const runCreateExpertBankCardOcr = async (objectKey: string) => {
|
||||
};
|
||||
createExpertBankCardOcrDialogVisible.value = true;
|
||||
} catch (e: any) {
|
||||
ElMessage.warning(e?.response?.data?.message || e?.message || "閾惰鍗CR璇嗗埆澶辫触");
|
||||
ElMessage.warning(e?.response?.data?.message || e?.message || "银行卡OCR识别失败");
|
||||
}
|
||||
};
|
||||
|
||||
@ -2698,7 +2698,7 @@ const confirmCreateExpertBankCardOcrFill = () => {
|
||||
createPlatformExpertForm.value.accountName = createExpertBankCardOcrData.value.accountName;
|
||||
}
|
||||
createExpertBankCardOcrDialogVisible.value = false;
|
||||
ElMessage.success("宸茬‘璁ゅ苟鍥炲~閾惰鍗CR缁撴灉");
|
||||
ElMessage.success("已确认并回填银行卡OCR结果");
|
||||
};
|
||||
|
||||
const cancelCreateExpertBankCardOcrFill = () => {
|
||||
@ -2707,7 +2707,7 @@ const cancelCreateExpertBankCardOcrFill = () => {
|
||||
|
||||
const uploadCreateExpertAsset = async (assetType: "ID_FRONT" | "ID_BACK" | "CARD") => {
|
||||
if (!selectedExpertManageMeetingId.value) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨浼氳鍚庡啀鏂板涓撳");
|
||||
ElMessage.warning("请先选择会议后再新增专家");
|
||||
return;
|
||||
}
|
||||
const file =
|
||||
@ -2717,7 +2717,7 @@ const uploadCreateExpertAsset = async (assetType: "ID_FRONT" | "ID_BACK" | "CARD
|
||||
? createExpertIdBackFile.value
|
||||
: createExpertCardFrontFile.value;
|
||||
if (!file) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鏂囦欢");
|
||||
ElMessage.warning("请先选择文件");
|
||||
return;
|
||||
}
|
||||
const signResp = await fetchMeetingMaterialUploadSign(selectedExpertManageMeetingId.value, "BASIC_INFO", {
|
||||
@ -2727,7 +2727,7 @@ const uploadCreateExpertAsset = async (assetType: "ID_FRONT" | "ID_BACK" | "CARD
|
||||
const uploadUrl = signResp?.data?.uploadUrl;
|
||||
const objectKey = signResp?.data?.objectKey;
|
||||
if (!uploadUrl || !objectKey) {
|
||||
ElMessage.error("鑾峰彇涓婁紶绛惧悕澶辫触");
|
||||
ElMessage.error("获取上传签名失败");
|
||||
return;
|
||||
}
|
||||
await putToSignedUrl(uploadUrl, file, signResp?.data?.contentType || file.type);
|
||||
@ -2747,7 +2747,7 @@ const uploadCreateExpertAsset = async (assetType: "ID_FRONT" | "ID_BACK" | "CARD
|
||||
createExpertCardFrontFile.value = null;
|
||||
await runCreateExpertBankCardOcr(objectKey);
|
||||
}
|
||||
ElMessage.success("涓婁紶鎴愬姛");
|
||||
ElMessage.success("上传成功");
|
||||
};
|
||||
|
||||
const loadExpertDictOptions = async () => {
|
||||
@ -2771,31 +2771,31 @@ const handleCreatePlatformExpert = async () => {
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.phone.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欐墜鏈哄彿");
|
||||
ElMessage.warning("请填写手机号");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.titleCode.trim()) {
|
||||
ElMessage.warning("璇烽€夋嫨鑱岀О");
|
||||
ElMessage.warning("请选择职称");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.hospitalCode.trim()) {
|
||||
ElMessage.warning("璇烽€夋嫨鍖婚櫌");
|
||||
ElMessage.warning("请选择医院");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.bankName.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欏紑鎴疯");
|
||||
ElMessage.warning("请填写开户行");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.bankProvince.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欏紑鎴疯鐪佷唤");
|
||||
ElMessage.warning("请填写开户行省份");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.bankCity.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欏紑鎴疯鍩庡競");
|
||||
ElMessage.warning("请填写开户行城市");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.bankBranchName.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欒缁嗗紑鎴疯");
|
||||
ElMessage.warning("请填写详细开户行");
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.bankCardNo.trim()) {
|
||||
@ -2803,7 +2803,7 @@ const handleCreatePlatformExpert = async () => {
|
||||
return;
|
||||
}
|
||||
if (!createPlatformExpertForm.value.accountName.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欏紑鎴峰悕");
|
||||
ElMessage.warning("请填写开户名");
|
||||
return;
|
||||
}
|
||||
const selectedTitle = expertTitleOptions.value.find((item) => item.dictCode === createPlatformExpertForm.value.titleCode);
|
||||
@ -2854,7 +2854,7 @@ const openBindExperts = async (row: any) => {
|
||||
if (!id) {
|
||||
continue;
|
||||
}
|
||||
selectedPlatformExpertNameMap.value[id] = String(item?.expertName || "").trim() || `涓撳#${id}`;
|
||||
selectedPlatformExpertNameMap.value[id] = String(item?.expertName || "").trim() || `专家#${id}`;
|
||||
}
|
||||
selectedPlatformExpertIds.value = profiles
|
||||
.map((item: any) => Number(item?.expertId || 0))
|
||||
@ -2875,7 +2875,7 @@ const handleBindExperts = async () => {
|
||||
await bindMeetingExperts(meetingId, {
|
||||
expertIds: selectedPlatformExpertIds.value,
|
||||
});
|
||||
ElMessage.success("涓撳缁戝畾鎴愬姛");
|
||||
ElMessage.success("专家绑定成功");
|
||||
await loadBoundExperts(meetingId);
|
||||
bindExpertVisible.value = false;
|
||||
};
|
||||
@ -2890,9 +2890,9 @@ const handleUnbindExpert = async (row: any) => {
|
||||
}
|
||||
const confirm = await ElMessageBox.confirm(
|
||||
`确认解绑专家「${row?.expertName || row?.expertId || ""}」吗?`,
|
||||
"瑙g粦纭",
|
||||
"解绑确认",
|
||||
{
|
||||
confirmButtonText: "纭畾",
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "鍙栨秷",
|
||||
type: "warning",
|
||||
},
|
||||
@ -2903,7 +2903,7 @@ const handleUnbindExpert = async (row: any) => {
|
||||
try {
|
||||
const targetId = Number(row?.expertId || 0);
|
||||
await unbindMeetingExpert(selectedExpertManageMeetingId.value, targetId);
|
||||
ElMessage.success("瑙g粦鎴愬姛");
|
||||
ElMessage.success("解绑成功");
|
||||
await loadBoundExperts(selectedExpertManageMeetingId.value);
|
||||
removeSelectedPlatformExpertLocal(targetId);
|
||||
} catch (_e) {
|
||||
@ -2928,10 +2928,10 @@ const pollMeetingLaborAgreementExtract = async (meetingId: number, taskId: strin
|
||||
return data;
|
||||
}
|
||||
if (status === "FAILED") {
|
||||
throw new Error(String(data?.reason || "鍔冲姟鍗忚鎶藉彇澶辫触"));
|
||||
throw new Error(String(data?.reason || "劳务协议抽取失败"));
|
||||
}
|
||||
}
|
||||
throw new Error("鍔冲姟鍗忚鎶藉彇瓒呮椂锛岃绋嶅悗閲嶈瘯");
|
||||
throw new Error("劳务协议抽取超时,请稍后重试");
|
||||
};
|
||||
|
||||
const openMeetingLaborAgreementExtractConfirm = (
|
||||
@ -3025,7 +3025,7 @@ const handleMeetingLaborAgreementFilePicked = async (event: Event) => {
|
||||
warnMeetingMaterialReadonly();
|
||||
return;
|
||||
}
|
||||
if (!validateMaterialFile(file, "鍔冲姟鍗忚", 50)) {
|
||||
if (!validateMaterialFile(file, "劳务协议", 50)) {
|
||||
return;
|
||||
}
|
||||
meetingLaborAgreementUploading.value = true;
|
||||
@ -3048,7 +3048,7 @@ const handleMeetingLaborAgreementFilePicked = async (event: Event) => {
|
||||
if (!taskId) {
|
||||
throw new Error("未获取到OCR任务号");
|
||||
}
|
||||
ElMessage.info("鍔冲姟鍗忚宸蹭笂浼狅紝姝e湪鎶藉彇涓撳淇℃伅");
|
||||
ElMessage.info("劳务协议已上传,正在抽取专家信息");
|
||||
const extracted = await pollMeetingLaborAgreementExtract(meetingId, taskId);
|
||||
await applyMeetingLaborAgreementExtractFlow(meetingId, taskId, extracted);
|
||||
} catch (error: any) {
|
||||
@ -3098,11 +3098,11 @@ const handleUnbindExpertGuarded = async (row: any) => {
|
||||
};
|
||||
|
||||
const moduleTitleMap: Record<string, string> = {
|
||||
BASIC_INFO: "浼氳鍩烘湰淇℃伅妯″潡",
|
||||
WRITE_OFF_DOCS: "鏍搁攢鏉愭枡妯″潡",
|
||||
EXPERT_PROFILE: "涓撳绠€浠?涓插満妯″潡",
|
||||
EXPERT_LIST: "涓撳鍒楄〃妯″潡",
|
||||
MEETING_INVOICE: "浼氳鍙戠エ妯″潡",
|
||||
BASIC_INFO: "会议基本信息模块",
|
||||
WRITE_OFF_DOCS: "核销材料模块",
|
||||
EXPERT_PROFILE: "专家简介/串场模块",
|
||||
EXPERT_LIST: "专家列表模块",
|
||||
MEETING_INVOICE: "会议发票模块",
|
||||
};
|
||||
type BackendMaterialModuleCode = "BASIC_INFO" | "WRITE_OFF_DOCS" | "EXPERT_PROFILE" | "EXPERT_LIST" | "MEETING_INVOICE";
|
||||
const resolveBackendMaterialModuleCode = (moduleCode: MaterialModuleCode): BackendMaterialModuleCode => {
|
||||
@ -3136,8 +3136,8 @@ const isMaterialLoadActive = (
|
||||
};
|
||||
|
||||
const prepareMaterialModuleLoad = (moduleCode: MaterialModuleCode) => {
|
||||
materialDialogTitle.value = moduleTitleMap[moduleCode] || "浼氳璧勬枡妯″潡";
|
||||
materialReviewNotice.value = "瀹℃牳淇℃伅鍔犺浇涓?..";
|
||||
materialDialogTitle.value = moduleTitleMap[moduleCode] || "会议资料模块";
|
||||
materialReviewNotice.value = "审核信息加载中...";
|
||||
};
|
||||
|
||||
const extractExt = (fileName: string) => {
|
||||
@ -3405,7 +3405,7 @@ const validateImageFile = (file: File | null, label: string, maxSizeMb = MATERIA
|
||||
return false;
|
||||
}
|
||||
if (Number(file.size || 0) > maxSizeMb * 1024 * 1024) {
|
||||
ElMessage.warning(`${label}澶у皬涓嶈兘瓒呰繃${maxSizeMb}MB`);
|
||||
ElMessage.warning(`${label}大小不能超过${maxSizeMb}MB`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -3415,7 +3415,7 @@ const validateMaterialFile = (file: File | null, label: string, maxSizeMb = MATE
|
||||
return false;
|
||||
}
|
||||
if (!isMaterialUploadAllowed(file)) {
|
||||
ElMessage.warning(`${label}浠呮敮鎸佸浘鐗囨垨PDF鏂囦欢`);
|
||||
ElMessage.warning(`${label}仅支持图片或PDF文件`);
|
||||
return false;
|
||||
}
|
||||
if (Number(file.size || 0) > maxSizeMb * 1024 * 1024) {
|
||||
@ -3433,17 +3433,17 @@ const validateExpertProfileFile = (file: File | null, maxSizeMb = MATERIAL_MAX_F
|
||||
const isPptMime = mime === "application/vnd.ms-powerpoint"
|
||||
|| mime === "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
||||
if (!EXPERT_PROFILE_ACCEPT_EXT.has(ext) && mime !== "application/pdf" && !isPptMime) {
|
||||
ElMessage.warning("涓撳绠€浠?涓插満浠呮敮鎸丳DF鎴朠PT鏂囦欢");
|
||||
ElMessage.warning("专家简介/串场仅支持PDF或PPT文件");
|
||||
return false;
|
||||
}
|
||||
if (Number(file.size || 0) > maxSizeMb * 1024 * 1024) {
|
||||
ElMessage.warning(`涓撳绠€浠?涓插満鏂囦欢澶у皬涓嶈兘瓒呰繃${maxSizeMb}MB`);
|
||||
ElMessage.warning(`专家简介/串场文件大小不能超过${maxSizeMb}MB`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const beforeAgendaUpload = (rawFile: any, maxSizeMb?: number) => {
|
||||
if (!validateMaterialFile((rawFile as File) || null, "浼氳鏃ョ▼", maxSizeMb)) {
|
||||
if (!validateMaterialFile((rawFile as File) || null, "会议日程", maxSizeMb)) {
|
||||
return false;
|
||||
}
|
||||
if (agendaDocRows.value.length >= 5) {
|
||||
@ -3455,23 +3455,23 @@ const beforeAgendaUpload = (rawFile: any, maxSizeMb?: number) => {
|
||||
const beforeSignInUpload = (rawFile: any, maxSizeMb?: number) =>
|
||||
validateMaterialFile((rawFile as File) || null, "签到表", maxSizeMb);
|
||||
const beforeThemePhotoUpload = (rawFile: any, maxSizeMb?: number) =>
|
||||
validateImageFile((rawFile as File) || null, "涓婚鐓х墖", maxSizeMb);
|
||||
validateImageFile((rawFile as File) || null, "主题照片", maxSizeMb);
|
||||
const beforeInvitationUpload = (rawFile: any, maxSizeMb?: number) =>
|
||||
validateMaterialFile((rawFile as File) || null, "閭€璇峰嚱", maxSizeMb);
|
||||
validateMaterialFile((rawFile as File) || null, "邀请函", maxSizeMb);
|
||||
const beforePhotoUpload: UploadProps["beforeUpload"] = (rawFile) =>
|
||||
validateMaterialFile((rawFile as File) || null, "鐜板満鐓х墖");
|
||||
validateMaterialFile((rawFile as File) || null, "现场照片");
|
||||
const beforeLaborProtocolUpload: UploadProps["beforeUpload"] = (rawFile) =>
|
||||
validateMaterialFile((rawFile as File) || null, "鍗忚鏂囦欢");
|
||||
validateMaterialFile((rawFile as File) || null, "协议文件");
|
||||
const beforeLaborInvoiceUpload: UploadProps["beforeUpload"] = (rawFile) =>
|
||||
validateMaterialFile((rawFile as File) || null, "鍔冲姟鍙戠エ");
|
||||
validateMaterialFile((rawFile as File) || null, "劳务发票");
|
||||
const beforeMeetingInvoiceUpload: UploadProps["beforeUpload"] = (rawFile) =>
|
||||
validateMaterialFile((rawFile as File) || null, "浼氳鍙戠エ闄勪欢");
|
||||
validateMaterialFile((rawFile as File) || null, "会议发票附件");
|
||||
const beforeExpertProfileUpload = (rawFile: any, maxSizeMb?: number) =>
|
||||
validateExpertProfileFile((rawFile as File) || null, maxSizeMb);
|
||||
|
||||
const onAgendaFileChange = (uploadFile: any) => {
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
agendaFile.value = validateMaterialFile(file, "浼氳鏃ョ▼") ? file : null;
|
||||
agendaFile.value = validateMaterialFile(file, "会议日程") ? file : null;
|
||||
};
|
||||
|
||||
const onSignInFileChange = (uploadFile: any) => {
|
||||
@ -3481,7 +3481,7 @@ const onSignInFileChange = (uploadFile: any) => {
|
||||
|
||||
const onInvitationFileChange = (uploadFile: any) => {
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
invitationFile.value = validateMaterialFile(file, "閭€璇峰嚱") ? file : null;
|
||||
invitationFile.value = validateMaterialFile(file, "邀请函") ? file : null;
|
||||
};
|
||||
|
||||
const handleAgendaPictureChange = async (uploadFile: any, uploadFiles: any, maxSizeMb?: number) => {
|
||||
@ -3490,7 +3490,7 @@ const handleAgendaPictureChange = async (uploadFile: any, uploadFiles: any, maxS
|
||||
return;
|
||||
}
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
agendaFile.value = validateMaterialFile(file, "浼氳鏃ョ▼", maxSizeMb) ? file : null;
|
||||
agendaFile.value = validateMaterialFile(file, "会议日程", maxSizeMb) ? file : null;
|
||||
if (!agendaFile.value) {
|
||||
return;
|
||||
}
|
||||
@ -3516,7 +3516,7 @@ const handleThemePhotoPictureChange = async (uploadFile: any, uploadFiles: any,
|
||||
return;
|
||||
}
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
themePhotoFile.value = validateImageFile(file, "涓婚鐓х墖", maxSizeMb) ? file : null;
|
||||
themePhotoFile.value = validateImageFile(file, "主题照片", maxSizeMb) ? file : null;
|
||||
if (!themePhotoFile.value) {
|
||||
return;
|
||||
}
|
||||
@ -3525,7 +3525,7 @@ const handleThemePhotoPictureChange = async (uploadFile: any, uploadFiles: any,
|
||||
|
||||
const handleInvitationPictureChange = async (uploadFile: any, uploadFiles: any, maxSizeMb?: number) => {
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
invitationFile.value = validateMaterialFile(file, "閭€璇峰嚱", maxSizeMb) ? file : null;
|
||||
invitationFile.value = validateMaterialFile(file, "邀请函", maxSizeMb) ? file : null;
|
||||
if (!invitationFile.value) {
|
||||
return;
|
||||
}
|
||||
@ -3553,7 +3553,7 @@ const handleExpertProfileFileChange = async (uploadFile: any, uploadFiles: any,
|
||||
await putToSignedUrl(uploadUrl, file, signResp?.data?.contentType || file.type);
|
||||
expertProfileForm.value.fileName = file.name;
|
||||
expertProfileForm.value.ossKey = objectKey;
|
||||
ElMessage.success("涓撳绠€浠?涓插満鏂囦欢涓婁紶鎴愬姛");
|
||||
ElMessage.success("专家简介/串场文件上传成功");
|
||||
};
|
||||
const handleExpertProfileFilePreview: UploadProps["onPreview"] = async (uploadFile) => {
|
||||
const ossKey = String(expertProfileForm.value.ossKey || "").trim();
|
||||
@ -3673,7 +3673,7 @@ const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invit
|
||||
? themePhotoFile.value
|
||||
: invitationFile.value;
|
||||
if (!file) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鏂囦欢");
|
||||
ElMessage.warning("请先选择文件");
|
||||
return;
|
||||
}
|
||||
const signResp = await fetchMeetingMaterialUploadSign(selectedMeetingId.value, "WRITE_OFF_DOCS", {
|
||||
@ -3711,7 +3711,7 @@ const uploadDocFile = async (target: "agenda" | "signIn" | "themePhoto" | "invit
|
||||
|
||||
const onPhotoFileChange = async (uploadFile: any) => {
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
if (!validateMaterialFile(file, "鐜板満鐓х墖") || !file) {
|
||||
if (!validateMaterialFile(file, "现场照片") || !file) {
|
||||
return;
|
||||
}
|
||||
const exists = photoUploadFiles.value.some((x) => x.name === file.name && x.size === file.size && x.lastModified === file.lastModified);
|
||||
@ -3737,7 +3737,7 @@ const onLaborProtocolFileChange = async (uploadFile: any) => {
|
||||
return;
|
||||
}
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
laborProtocolUploadFile.value = validateMaterialFile(file, "鍗忚鏂囦欢") ? file : null;
|
||||
laborProtocolUploadFile.value = validateMaterialFile(file, "协议文件") ? file : null;
|
||||
if (!laborProtocolUploadFile.value || laborProtocolAutoUploading.value) {
|
||||
return;
|
||||
}
|
||||
@ -3755,7 +3755,7 @@ const onLaborInvoiceFileChange = async (uploadFile: any) => {
|
||||
return;
|
||||
}
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
if (!validateMaterialFile(file, "鍔冲姟鍙戠エ") || !file) {
|
||||
if (!validateMaterialFile(file, "劳务发票") || !file) {
|
||||
return;
|
||||
}
|
||||
const exists = laborInvoiceUploadFiles.value.some((x) => x.name === file.name && x.size === file.size && x.lastModified === file.lastModified);
|
||||
@ -3777,7 +3777,7 @@ const onLaborInvoiceFileChange = async (uploadFile: any) => {
|
||||
|
||||
const onInvoiceFileChange = async (uploadFile: any) => {
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
if (!validateMaterialFile(file, "鍙戠エ闄勪欢") || !file) {
|
||||
if (!validateMaterialFile(file, "发票附件") || !file) {
|
||||
return;
|
||||
}
|
||||
const exists = invoiceUploadFiles.value.some((x) => x.name === file.name && x.size === file.size && x.lastModified === file.lastModified);
|
||||
@ -3811,7 +3811,7 @@ const onMeetingInvoiceSectionFileChange = async (
|
||||
return;
|
||||
}
|
||||
const file = (uploadFile?.raw as File) || null;
|
||||
if (!validateMaterialFile(file, "浼氳鍙戠エ闄勪欢") || !file || !selectedMeetingId.value) {
|
||||
if (!validateMaterialFile(file, "会议发票附件") || !file || !selectedMeetingId.value) {
|
||||
return;
|
||||
}
|
||||
const uploadTaskKey = `${sectionCode}:${fieldKey}`;
|
||||
@ -3841,7 +3841,7 @@ const onMeetingInvoiceSectionFileChange = async (
|
||||
ocr: fieldKey === "invoiceFile" ? { status: "idle" } : undefined,
|
||||
});
|
||||
await cacheDocPreviewUrl(objectKey);
|
||||
ElMessage.success("浼氳鍙戠エ闄勪欢涓婁紶鎴愬姛");
|
||||
ElMessage.success("会议发票附件上传成功");
|
||||
if (fieldKey === "invoiceFile") {
|
||||
await runMeetingInvoiceOcr(sectionCode, fieldKey);
|
||||
}
|
||||
@ -3971,7 +3971,7 @@ const uploadPhotoFile = async () => {
|
||||
return;
|
||||
}
|
||||
if (photoUploadFiles.value.length === 0) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鐓х墖");
|
||||
ElMessage.warning("请先选择照片");
|
||||
return;
|
||||
}
|
||||
const expertId = Number(selectedExpertMaterialId.value);
|
||||
@ -3998,7 +3998,7 @@ const uploadPhotoFile = async () => {
|
||||
successCount++;
|
||||
}
|
||||
photoUploadFiles.value = [];
|
||||
ElMessage.success(`鐜板満鐓х墖涓婁紶鎴愬姛锛${successCount}寮狅級`);
|
||||
ElMessage.success(`现场照片上传成功(${successCount}张)`);
|
||||
};
|
||||
|
||||
const uploadLaborProtocolFile = async () => {
|
||||
@ -4006,7 +4006,7 @@ const uploadLaborProtocolFile = async () => {
|
||||
return;
|
||||
}
|
||||
if (!laborProtocolUploadFile.value) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鍗忚鏂囦欢");
|
||||
ElMessage.warning("请先选择协议文件");
|
||||
return;
|
||||
}
|
||||
const signResp = await fetchMeetingMaterialUploadSign(selectedMeetingId.value, "EXPERT_LIST", {
|
||||
@ -4035,7 +4035,7 @@ const uploadLaborProtocolFile = async () => {
|
||||
}
|
||||
}
|
||||
laborProtocolUploadFile.value = null;
|
||||
ElMessage.success("鍔冲姟鍗忚涓婁紶鎴愬姛");
|
||||
ElMessage.success("劳务协议上传成功");
|
||||
};
|
||||
|
||||
const uploadLaborInvoiceFile = async () => {
|
||||
@ -4043,7 +4043,7 @@ const uploadLaborInvoiceFile = async () => {
|
||||
return;
|
||||
}
|
||||
if (laborInvoiceUploadFiles.value.length === 0) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鍔冲姟鍙戠エ");
|
||||
ElMessage.warning("请先选择劳务发票");
|
||||
return;
|
||||
}
|
||||
const localFile = laborInvoiceUploadFiles.value[0];
|
||||
@ -4076,7 +4076,7 @@ const uploadLaborInvoiceFile = async () => {
|
||||
row.invoicePreviewUrl = previewUrl;
|
||||
}
|
||||
laborInvoiceUploadFiles.value.shift();
|
||||
ElMessage.success("鍔冲姟鍙戠エ涓婁紶鎴愬姛");
|
||||
ElMessage.success("劳务发票上传成功");
|
||||
if (objectKey) {
|
||||
await runLaborInvoiceOcr(objectKey);
|
||||
}
|
||||
@ -4087,11 +4087,11 @@ const uploadInvoiceFile = async () => {
|
||||
return;
|
||||
}
|
||||
if (invoiceUploadFiles.value.length === 0) {
|
||||
ElMessage.warning("璇峰厛閫夋嫨鍙戠エ闄勪欢");
|
||||
ElMessage.warning("请先选择发票附件");
|
||||
return;
|
||||
}
|
||||
if (!invoiceDraft.value.invoiceNo.trim()) {
|
||||
ElMessage.warning("璇峰~鍐欏彂绁ㄥ彿");
|
||||
ElMessage.warning("请填写发票号");
|
||||
return;
|
||||
}
|
||||
const expertId = Number(selectedExpertMaterialId.value);
|
||||
@ -4124,8 +4124,8 @@ const uploadInvoiceFile = async () => {
|
||||
invoiceDraft.value.invoiceNo = "";
|
||||
invoiceDraft.value.amountCent = 0;
|
||||
invoiceDraft.value.taxCent = 0;
|
||||
invoiceDraft.value.expenseType = "鍏朵粬";
|
||||
ElMessage.success(`鍙戠エ闄勪欢涓婁紶鎴愬姛锛${successCount}寮狅級`);
|
||||
invoiceDraft.value.expenseType = "其他";
|
||||
ElMessage.success(`发票附件上传成功(${successCount}张)`);
|
||||
};
|
||||
|
||||
const removeSelectedExpertPhoto = (index: number) => {
|
||||
@ -4196,7 +4196,7 @@ const removeMeetingInvoiceSectionFile = (
|
||||
|
||||
const handleViewOss = async (ossKey: string) => {
|
||||
if (!ossKey) {
|
||||
ElMessage.warning("OSSKey 涓虹┖");
|
||||
ElMessage.warning("OSSKey 为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@ -4205,10 +4205,10 @@ const handleViewOss = async (ossKey: string) => {
|
||||
if (signedUrl) {
|
||||
window.open(signedUrl, "_blank");
|
||||
} else {
|
||||
ElMessage.warning("鏈幏鍙栧埌鏌ョ湅閾炬帴");
|
||||
ElMessage.warning("未获取到查看链接");
|
||||
}
|
||||
} catch (_e) {
|
||||
ElMessage.error("鏌ョ湅澶辫触锛岃妫€鏌?file.download 鏉冮檺");
|
||||
ElMessage.error("查看失败,请检查 file.download 权限");
|
||||
}
|
||||
};
|
||||
|
||||
@ -4325,7 +4325,7 @@ const loadMaterialReviews = async (
|
||||
return;
|
||||
}
|
||||
}
|
||||
materialReviewNotice.value = "褰撳墠妯″潡鏆傛棤鏉$洰瀹℃牳鏄庣粏";
|
||||
materialReviewNotice.value = "当前模块暂无条目审核明细";
|
||||
} catch (_e) {
|
||||
if (typeof requestId === "number" && !isMaterialLoadActive(requestId, meetingId, moduleCode)) {
|
||||
return;
|
||||
@ -4364,7 +4364,7 @@ const loadMaterialModule = async (
|
||||
) => {
|
||||
const backendModuleCode = resolveBackendMaterialModuleCode(moduleCode);
|
||||
selectedModuleCode.value = moduleCode;
|
||||
materialDialogTitle.value = moduleTitleMap[moduleCode] || "浼氳璧勬枡妯″潡";
|
||||
materialDialogTitle.value = moduleTitleMap[moduleCode] || "会议资料模块";
|
||||
resetMaterialForms();
|
||||
if (moduleCode === "EXPERT_LIST") {
|
||||
await loadBasicInfoForMaterial(meetingId, requestId);
|
||||
@ -4809,7 +4809,7 @@ const validateMeetingInvoiceRequired = () => {
|
||||
const amountCent = toCent(amount);
|
||||
if (amountCent > maxCateringCent) {
|
||||
ElMessage.warning(
|
||||
`鈥滈楗槑缁嗏€濋噾棰濅笉鑳借秴杩囦細璁绠?椁愯垂鍗犳瘮锛堜笂闄${toYuan(maxCateringCent)}鍏冿級`,
|
||||
`“餐饮明细”金额不能超过会议预算 × 餐费占比(上限${toYuan(maxCateringCent)}元)`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -4823,7 +4823,7 @@ const validateExpertProfileRequired = () => {
|
||||
return true;
|
||||
}
|
||||
if (!String(expertProfileForm.value.ossKey || "").trim()) {
|
||||
ElMessage.warning("璇蜂笂浼犱笓瀹剁畝浠?涓插満鏂囦欢");
|
||||
ElMessage.warning("请上传专家简介/串场文件");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -5019,7 +5019,7 @@ const handleSaveMaterial = async () => {
|
||||
remark: materialForm.value.remark,
|
||||
},
|
||||
);
|
||||
ElMessage.success("妯″潡淇濆瓨鎴愬姛");
|
||||
ElMessage.success("模块保存成功");
|
||||
initialMaterialContentJson.value = buildContentJson();
|
||||
return true;
|
||||
} catch (e) {
|
||||
@ -5055,7 +5055,7 @@ const handleSubmitMaterial = async () => {
|
||||
remark: materialForm.value.remark,
|
||||
},
|
||||
);
|
||||
ElMessage.success("妯″潡鎻愪氦鎴愬姛");
|
||||
ElMessage.success("模块提交成功");
|
||||
materialDialogVisible.value = false;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user