function normalizeText(value) { if (typeof value === 'string') { return value.trim() } if (value === null || value === undefined) { return '' } return String(value).trim() } function resolveOperationLabelFromSource(source) { switch (normalizeText(source).toLowerCase()) { case 'onlyoffice': return '在线编辑保存' case 'content-import': return '导入表格' case 'upload': return '上传表格' case 'restore': return '恢复历史版本' case 'review-submit': return '提交审核固化' case 'preview': return '预览版本' default: return '' } } export function resolveSpreadsheetOperationLabel(record) { const explicitLabel = normalizeText(record?.operationLabel) if (explicitLabel) { return explicitLabel } const sourceLabel = resolveOperationLabelFromSource(record?.spreadsheetMeta?.source) if (sourceLabel) { return sourceLabel } const note = normalizeText(record?.note).toLowerCase() if (note.includes('onlyoffice')) { return '在线编辑保存' } if (note.includes('导入')) { return '导入表格' } if (note.includes('恢复')) { return '恢复历史版本' } if (note.includes('上传')) { return '上传表格' } return '表格修改' } function normalizeChangeRecord(record) { const version = normalizeText(record?.version) if (!version) { return null } return { version, operationLabel: resolveSpreadsheetOperationLabel(record), operationActor: normalizeText(record?.operationActor || record?.createdBy || record?.spreadsheetMeta?.updated_by) || '系统', note: normalizeText(record?.note) || '用户修改了表格内容。', time: normalizeText(record?.time || record?.createdAt || record?.spreadsheetMeta?.updated_at), isWorking: record?.isWorking !== false, isPendingLocalEdit: Boolean(record?.isPendingLocalEdit), disabledReason: normalizeText(record?.disabledReason) } } function toTimestamp(value) { const normalized = normalizeText(value) if (!normalized) { return 0 } const parsed = Date.parse(normalized) return Number.isNaN(parsed) ? 0 : parsed } function dedupeChangeRecords(records) { const seen = new Set() return records.filter((item) => { const key = [item.version, item.operationLabel, item.note].join('::') if (seen.has(key)) { return false } seen.add(key) return true }) } export function buildSpreadsheetChangeRecords({ history = [], localRecords = [], publishedVersion = '', limit = 5 } = {}) { const normalizedPublishedVersion = normalizeText(publishedVersion) const normalizedHistoryRecords = Array.isArray(history) ? history.map(normalizeChangeRecord).filter(Boolean) : [] const normalizedLocalRecords = Array.isArray(localRecords) ? localRecords.map(normalizeChangeRecord).filter(Boolean) : [] const unpublishedHistoryRecords = normalizedHistoryRecords.filter( (item) => item.version !== normalizedPublishedVersion ) const preferredHistoryRecords = unpublishedHistoryRecords.length || !normalizedPublishedVersion ? unpublishedHistoryRecords : normalizedHistoryRecords return dedupeChangeRecords([...normalizedLocalRecords, ...preferredHistoryRecords]) .sort((left, right) => toTimestamp(right.time) - toTimestamp(left.time)) .slice(0, limit) }