/** 海报 side:male=/hb-n 男方,female=/hb-nv 女方 */ export const POSTER_SIDES = [ { key: 'male', route: '/hb-n', label: '男方', short: 'n' }, { key: 'female', route: '/hb-nv', label: '女方', short: 'nv' }, ] export function resolvePosterSide(input) { const v = String(input || '').trim().toLowerCase() if (v === 'female' || v === 'nv' || v === 'f' || v === 'bride') return 'female' if (v === 'male' || v === 'n' || v === 'm' || v === 'groom') return 'male' return '' } function baseFields() { return { enabled: true, heroImg: '', title: '婚礼邀请函', footer: '—诚挚邀请 ♥ 恭请光临—', loadingEffect: 'redSeal', enterEffect: 'fadeUp', showInviteButton: true, inviteButtonText: '打开请柬', invitePath: '/', } } /** 男方默认文案 */ export function defaultMalePosterConfig() { return { ...baseFields(), sonLabel: '儿子:', sonName: '张浩强', daughterInLawLabel: '儿媳:', daughterInLawName: '刘佳怡', lines: [ '各位亲朋好友', '吾家有喜 儿子结婚', '良辰已定 吉日待访', '兹定于2026年10月3日 星期日', '农历九月初八 中午11:08分', '为儿子儿媳举办结婚典礼', '敬备喜宴 诚邀您携家人光临', '地址:幸福大酒店二楼宴会厅', '张国栋 & 陈晓玲 夫 妇 敬邀', ], } } /** 女方默认文案 */ export function defaultFemalePosterConfig() { return { ...baseFields(), sonLabel: '女儿:', sonName: '刘佳怡', daughterInLawLabel: '女婿:', daughterInLawName: '张浩强', lines: [ '各位亲朋好友', '吾家有喜 女儿出嫁', '良辰已定 吉日待访', '兹定于2026年10月3日 星期日', '农历九月初八 中午11:08分', '为女儿女婿举办结婚典礼', '敬备喜宴 诚邀您携家人光临', '地址:幸福大酒店二楼宴会厅', '刘建国 & 王秀兰 夫 妇 敬邀', ], } } /** @deprecated 兼容旧调用,等同男方默认 */ export function defaultPosterConfig() { return defaultMalePosterConfig() } export function defaultPosterBundle() { return { male: defaultMalePosterConfig(), female: defaultFemalePosterConfig(), } } export const LOADING_EFFECTS = [ { value: 'fade', label: '淡入加载' }, { value: 'redSeal', label: '红印囍字' }, { value: 'goldShimmer', label: '金字微光' }, ] export const ENTER_EFFECTS = [ { value: 'fadeUp', label: '上浮淡入' }, { value: 'scaleIn', label: '缩放进入' }, { value: 'curtain', label: '金幕拉开' }, ] /** 是否为旧版扁平配置(未分男女方) */ function isLegacyFlatPoster(raw) { if (!raw || typeof raw !== 'object') return false if (raw.male || raw.female) return false return 'title' in raw || 'lines' in raw || 'heroImg' in raw || 'sonName' in raw } export function normalizePosterConfig(raw, side = 'male') { const s = resolvePosterSide(side) || 'male' const base = s === 'female' ? defaultFemalePosterConfig() : defaultMalePosterConfig() const loaded = raw && typeof raw === 'object' ? raw : {} const lines = Array.isArray(loaded.lines) ? loaded.lines.map((l) => String(l ?? '')) : base.lines return { ...base, ...loaded, lines: lines.length ? lines : base.lines, enabled: loaded.enabled !== false, showInviteButton: loaded.showInviteButton !== false, loadingEffect: LOADING_EFFECTS.some((e) => e.value === loaded.loadingEffect) ? loaded.loadingEffect : base.loadingEffect, enterEffect: ENTER_EFFECTS.some((e) => e.value === loaded.enterEffect) ? loaded.enterEffect : base.enterEffect, invitePath: loaded.invitePath || '/', inviteButtonText: loaded.inviteButtonText || base.inviteButtonText, } } /** 归一化整包 { male, female };兼容旧扁平数据迁入 male */ export function normalizePosterBundle(raw) { const loaded = raw && typeof raw === 'object' ? raw : {} if (isLegacyFlatPoster(loaded)) { return { male: normalizePosterConfig(loaded, 'male'), female: defaultFemalePosterConfig(), } } return { male: normalizePosterConfig(loaded.male, 'male'), female: normalizePosterConfig(loaded.female, 'female'), } } export function pickPosterSide(bundle, side) { const normalized = normalizePosterBundle(bundle) const s = resolvePosterSide(side) || 'male' return normalized[s] }