diff --git a/scripts/reviewMeetingEditHelpers.check.ts b/scripts/reviewMeetingEditHelpers.check.ts new file mode 100644 index 000000000..b08e7c717 --- /dev/null +++ b/scripts/reviewMeetingEditHelpers.check.ts @@ -0,0 +1,53 @@ +import assert from 'node:assert/strict' +import { + buildProjectTimeBatchPayload, + mapCopiedProjectItems, + mapPersistedProjectItems, + shouldSyncPersistedProjectTimes +} from '../src/views/review/meeting/meetingEditHelpers' + +const baseProject = { + id: 101, + seqNo: 1, + startTime: '09:00', + endTime: '09:15', + agendaCategory: '项目申报论证', + projectTitle: '项目A', + reporter: '张三', + reporterUnit: '软件学院', + reviewDate: '2026-04-01' +} + +const persistedProjects = mapPersistedProjectItems([baseProject]) +assert.equal( + persistedProjects[0].sourceProjectId, + undefined, + '编辑已有会议时,不应该把现有项目 id 回填到 sourceProjectId' +) + +const copiedProjects = mapCopiedProjectItems([baseProject]) +assert.equal(copiedProjects[0].sourceProjectId, 101, '复制会议时,应该保留源项目 id 用于首次复制资料') + +assert.equal( + shouldSyncPersistedProjectTimes({ + isEdit: true, + isProjectsModified: false, + originalMeetingStart: 1711942800000, + currentMeetingStart: 1711944600000, + projects: [baseProject] + }), + true, + '编辑已有会议且仅修改会议开始时间时,应该同步已落库项目时间' +) + +assert.deepEqual(buildProjectTimeBatchPayload([baseProject]), { + items: [ + { + id: 101, + startTime: '09:00', + endTime: '09:15' + } + ] +}) + +console.log('reviewMeetingEditHelpers checks passed') diff --git a/src/views/review/meeting/meetingEditHelpers.ts b/src/views/review/meeting/meetingEditHelpers.ts new file mode 100644 index 000000000..ed54219f2 --- /dev/null +++ b/src/views/review/meeting/meetingEditHelpers.ts @@ -0,0 +1,93 @@ +export type MeetingEditProjectItem = { + id?: number + sourceProjectId?: number + seqNo: number + startTime?: string + endTime?: string + agendaCategory: string + projectTitle: string + reporter: string + reporterUnit: string + reviewDate?: string +} + +export type MeetingProjectSource = { + id?: number + seqNo?: number + startTime?: string + endTime?: string + agendaCategory?: string + projectTitle?: string + reporter?: string + reporterUnit?: string + reviewDate?: string + sourceProjectId?: number +} + +export type ProjectTimeBatchPayload = { + items: Array<{ + id: number + startTime: string + endTime: string + }> +} + +type PersistedProjectScheduleSyncArgs = { + isEdit: boolean + isProjectsModified: boolean + originalMeetingStart?: string | number + currentMeetingStart?: string | number + projects: MeetingProjectSource[] +} + +const mapProjectItems = (projects: MeetingProjectSource[], copySourceProjectId: boolean): MeetingEditProjectItem[] => + (projects || []).map((item) => ({ + id: item.id, + sourceProjectId: copySourceProjectId ? (item.sourceProjectId ?? item.id) : item.sourceProjectId, + seqNo: item.seqNo || 0, + startTime: item.startTime, + endTime: item.endTime, + agendaCategory: item.agendaCategory || '', + projectTitle: item.projectTitle || '', + reporter: item.reporter || '', + reporterUnit: item.reporterUnit || '', + reviewDate: item.reviewDate + })) + +export const mapPersistedProjectItems = (projects: MeetingProjectSource[] = []): MeetingEditProjectItem[] => + mapProjectItems(projects, false) + +export const mapCopiedProjectItems = (projects: MeetingProjectSource[] = []): MeetingEditProjectItem[] => + mapProjectItems(projects, true) + +const normalizeComparableValue = (value?: string | number) => + value === undefined || value === null || value === '' ? undefined : String(value) + +export const shouldSyncPersistedProjectTimes = ({ + isEdit, + isProjectsModified, + originalMeetingStart, + currentMeetingStart, + projects +}: PersistedProjectScheduleSyncArgs) => { + if (!isEdit || isProjectsModified) { + return false + } + if (!projects.some((item) => typeof item.id === 'number')) { + return false + } + return normalizeComparableValue(originalMeetingStart) !== normalizeComparableValue(currentMeetingStart) +} + +export const buildProjectTimeBatchPayload = ( + projects: MeetingProjectSource[] = [] +): ProjectTimeBatchPayload | undefined => { + const items = projects + .filter((item) => item.id && item.startTime && item.endTime) + .map((item) => ({ + id: item.id as number, + startTime: item.startTime as string, + endTime: item.endTime as string + })) + return items.length > 0 ? { items } : undefined +}