import * as ExcelJS from 'exceljs'; import type { CellValue } from './imports.types'; export function parseJson(raw: string | null | undefined): T | null { if (!raw) return null; try { return JSON.parse(raw) as T; } catch { return null; } } export function textValue(value: CellValue): string { if (value === null || value === undefined) return ''; return String(value).trim(); } export function normalizeHeader(value: string): string { return value .trim() .toLowerCase() .replace(/[\s()()]/g, ''); } export function headerMatches(header: string, alias: string): boolean { const h = normalizeHeader(header); const a = normalizeHeader(alias); if (!h || !a) return false; // 只允许“表头包含别名”的单向匹配,避免短表头(如“宿舍号”) // 被长复合别名(如“原宿舍号/新宿舍号”)反向包含而误判。 return h === a || h.includes(a); } export function cellValue(cell: ExcelJS.Cell | undefined): CellValue { if (!cell) return null; const value = cell.value; if (value === null || value === undefined) return null; if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return value; } if (value instanceof Date) return value; if (typeof value === 'object') { const candidate = value as { text?: unknown; result?: unknown }; if (typeof candidate.text === 'string') return candidate.text; if (typeof candidate.result === 'string' || typeof candidate.result === 'number') { return candidate.result; } if (candidate.result instanceof Date) return candidate.result; } return null; } export function parseDateValue(value: CellValue): string | null { if (value instanceof Date && !Number.isNaN(value.getTime())) { const year = value.getFullYear(); const month = String(value.getMonth() + 1).padStart(2, '0'); const day = String(value.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } const raw = textValue(value); if (!raw) return null; const match = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})/.exec(raw); if (!match) return null; const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); const date = new Date(Date.UTC(year, month - 1, day)); if ( date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day ) { return null; } return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; } export function safeError(error: unknown): string { if (error instanceof Error) return error.message.slice(0, 120); return '未知错误'; } export function applyString(target: object, key: string, value: CellValue): void { const text = textValue(value); if (text) (target as Record)[key] = text; } export function optionalNumber(value: CellValue): number | null { const text = textValue(value); if (!text) return null; const parsed = Number(text); return Number.isFinite(parsed) ? parsed : null; } export function csvCell(value: string): string { return `"${value.replace(/"/g, '""')}"`; }