Merge branch 'fe/review-meeting-edit-bugs' into feature/review-ai-panel

# Conflicts:
#	src/views/review/meeting/MeetingEdit.vue
pull/874/head
Codewoc 2026-04-01 17:34:37 +08:00
commit 8e85d4b768
2 changed files with 146 additions and 0 deletions

View File

@ -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')

View File

@ -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
}