/** * OmniCard AI (CRMmp) - 名片主个人中心与消息通知配置业务驱动层 * 严格按照 AGENTS.md 规范与 uts 强类型约束 */ import { OmniLocale, PORTAL_LOCALE_STORAGE_KEY, getCurrentLocale, setAppLocale, getOmniText, } from '../../../common/locale.uts'; export { PORTAL_LOCALE_STORAGE_KEY }; export type UserProfileAccount = { name: string; company: string; department: string; avatar: string; }; export type NotificationSettings = { radarPush: boolean; leadNotice: boolean; }; export type ProfileState = { account: UserProfileAccount; notifications: NotificationSettings; locale: OmniLocale; saving: boolean; loading: boolean; errorMessage: string; }; export type StorageApi = { getStorageSync: (key: string) => unknown; setStorageSync: (key: string, value: unknown) => void; }; export const PROFILE_ACCOUNT_STORAGE_KEY = 'omni_owner_profile_account'; export const PROFILE_NOTIFICATIONS_STORAGE_KEY = 'omni_owner_profile_notifications'; function defaultStorage(): StorageApi { return { getStorageSync: (key: string): unknown => { try { if (typeof uni !== 'undefined' && uni.getStorageSync != null) { return uni.getStorageSync(key); } } catch (_e) {} return ''; }, setStorageSync: (key: string, value: unknown): void => { try { if (typeof uni !== 'undefined' && uni.setStorageSync != null) { uni.setStorageSync(key, value); } } catch (err: unknown) { throw err; } }, }; } export function getDefaultAccount(): UserProfileAccount { return { name: 'Alex Vance', company: 'Nexus Tech Global', department: 'Overseas Business Dept', avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?auto=format&fit=crop&w=256&q=80', }; } export function getDefaultNotifications(): NotificationSettings { return { radarPush: true, leadNotice: true, }; } export function createProfileState(locale?: OmniLocale): ProfileState { const currentLocale = locale != null && locale !== '' ? locale : getCurrentLocale(); return { account: getDefaultAccount(), notifications: getDefaultNotifications(), locale: currentLocale, saving: false, loading: false, errorMessage: '', }; } function safeParseJson(raw: unknown): T | null { if (raw == null || typeof raw !== 'string') { return null; } const trimmed = raw.trim(); if (trimmed === '' || (!trimmed.startsWith('{') && !trimmed.startsWith('['))) { return null; } try { return JSON.parse(trimmed) as T; } catch (_e) { return null; } } /** * 从本地存储加载个人名片主资料与通知设置,具备完整防御性容错 */ export function loadProfileSettings(storage?: StorageApi): ProfileState { const store = storage != null ? storage : defaultStorage(); const state = createProfileState(); try { const rawAccount = store.getStorageSync(PROFILE_ACCOUNT_STORAGE_KEY); const parsedAccount = safeParseJson>(rawAccount); if (parsedAccount != null && typeof parsedAccount === 'object') { const defaultAcc = getDefaultAccount(); const safeName = typeof parsedAccount.name === 'string' && parsedAccount.name.trim() !== '' ? parsedAccount.name.trim() : defaultAcc.name; const safeCompany = typeof parsedAccount.company === 'string' && parsedAccount.company.trim() !== '' ? parsedAccount.company.trim() : defaultAcc.company; const safeDept = typeof parsedAccount.department === 'string' && parsedAccount.department.trim() !== '' ? parsedAccount.department.trim() : defaultAcc.department; const safeAvatar = typeof parsedAccount.avatar === 'string' && parsedAccount.avatar.trim() !== '' ? parsedAccount.avatar.trim() : defaultAcc.avatar; state.account = { name: safeName, company: safeCompany, department: safeDept, avatar: safeAvatar, }; } } catch (_e) { // 降级使用默认账户 state.account = getDefaultAccount(); } try { const rawNotice = store.getStorageSync(PROFILE_NOTIFICATIONS_STORAGE_KEY); const parsedNotice = safeParseJson>(rawNotice); if (parsedNotice != null && typeof parsedNotice === 'object') { const defaultNotif = getDefaultNotifications(); state.notifications = { radarPush: typeof parsedNotice.radarPush === 'boolean' ? parsedNotice.radarPush : defaultNotif.radarPush, leadNotice: typeof parsedNotice.leadNotice === 'boolean' ? parsedNotice.leadNotice : defaultNotif.leadNotice, }; } } catch (_e) { // 降级使用默认通知 state.notifications = getDefaultNotifications(); } state.locale = getCurrentLocale(); return state; } /** * 保存名片主资料与通知设置到本地存储 */ export function saveProfileSettings(state: ProfileState, storage?: StorageApi): boolean { const store = storage != null ? storage : defaultStorage(); try { store.setStorageSync( PROFILE_ACCOUNT_STORAGE_KEY, JSON.stringify(state.account) ); store.setStorageSync( PROFILE_NOTIFICATIONS_STORAGE_KEY, JSON.stringify(state.notifications) ); state.errorMessage = ''; return true; } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Storage save failed'; state.errorMessage = msg; return false; } } /** * 更新账户资料字段,具备非空与空格修剪防御保护 */ export function updateAccount( state: ProfileState, patch: Partial ): void { if (patch == null) { return; } if (typeof patch.name === 'string' && patch.name.trim() !== '') { state.account.name = patch.name.trim(); } if (typeof patch.company === 'string' && patch.company.trim() !== '') { state.account.company = patch.company.trim(); } if (typeof patch.department === 'string' && patch.department.trim() !== '') { state.account.department = patch.department.trim(); } if (typeof patch.avatar === 'string' && patch.avatar.trim() !== '') { state.account.avatar = patch.avatar.trim(); } } /** * 切换雷达即时推送通知开关,并同步记忆持久化 */ export function toggleRadarPush( state: ProfileState, value?: boolean, storage?: StorageApi ): boolean { const store = storage != null ? storage : defaultStorage(); const nextVal = value !== undefined ? Boolean(value) : !state.notifications.radarPush; state.notifications.radarPush = nextVal; try { store.setStorageSync( PROFILE_NOTIFICATIONS_STORAGE_KEY, JSON.stringify(state.notifications) ); state.errorMessage = ''; } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Failed to persist radar push'; state.errorMessage = msg; } return nextVal; } /** * 切换新线索提醒开关,并同步记忆持久化 */ export function toggleLeadNotice( state: ProfileState, value?: boolean, storage?: StorageApi ): boolean { const store = storage != null ? storage : defaultStorage(); const nextVal = value !== undefined ? Boolean(value) : !state.notifications.leadNotice; state.notifications.leadNotice = nextVal; try { store.setStorageSync( PROFILE_NOTIFICATIONS_STORAGE_KEY, JSON.stringify(state.notifications) ); state.errorMessage = ''; } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Failed to persist lead notice'; state.errorMessage = msg; } return nextVal; } /** * 切换首选语言并记忆持久化 */ export function setPreferredLocale( state: ProfileState, locale: string, storage?: StorageApi ): OmniLocale { const safeLocales: OmniLocale[] = [ 'zh-CN', 'en-US', 'ar-SA', 'es-ES', 'de-DE', 'fr-FR', 'ja-JP', ]; let targetLocale: OmniLocale = 'zh-CN'; if (locale != null) { const found = safeLocales.find((l: OmniLocale) => l === locale); if (found != null) { targetLocale = found; } else { const lower = locale.toLowerCase(); if (lower.startsWith('en')) { targetLocale = 'en-US'; } } } state.locale = targetLocale; setAppLocale(targetLocale); if (storage != null) { try { storage.setStorageSync(PORTAL_LOCALE_STORAGE_KEY, targetLocale); } catch (_e) {} } return targetLocale; } /** * 预览个人头像 */ export function previewAccountAvatar(state: ProfileState): void { if (state.account.avatar !== '') { // #ifndef UNI-APP-X-TEST try { if (typeof uni !== 'undefined' && typeof uni.previewImage === 'function') { uni.previewImage({ urls: [state.account.avatar], current: state.account.avatar, }); } } catch (_e) {} // #endif } } /** * 移除个人头像 */ export function removeAccountAvatar(state: ProfileState): void { state.account.avatar = ''; } /** * 瑞士国际主义多语言文案解析器,无 emoji */ export function resolveProfileText(key: string): string { const locale = getCurrentLocale(); if (key === 'save') { return getOmniText(locale, 'common.save'); } if (key === 'saved') { return getOmniText(locale, 'common.success'); } if (key === 'loading') { return getOmniText(locale, 'common.loading'); } if (key === 'error') { return getOmniText(locale, 'common.error'); } const isZh = locale === 'zh-CN'; switch (key) { case 'title': return isZh ? '个人中心' : 'Profile'; case 'subtitle': return isZh ? '管理名片主信息与系统通知' : 'Manage account and notifications'; case 'accountSection': return isZh ? '基本资料' : 'Account'; case 'nameLabel': return isZh ? '姓名' : 'Name'; case 'companyLabel': return isZh ? '所属企业' : 'Company'; case 'departmentLabel': return isZh ? '部门' : 'Department'; case 'avatarLabel': return isZh ? '头像' : 'Avatar'; case 'notificationsSection': return isZh ? '消息通知' : 'Notifications'; case 'radarPushTitle': return isZh ? '雷达即时推送' : 'Radar Push'; case 'radarPushDesc': return isZh ? '海外客商访问名片时立即通知' : 'Instant alert when visitors view card'; case 'leadNoticeTitle': return isZh ? '新线索提醒' : 'Lead Notice'; case 'leadNoticeDesc': return isZh ? '客商留资或互换名片时实时触达' : 'Real-time notice for new leads'; case 'languageSection': return isZh ? '偏好设置' : 'Preferences'; case 'languageLabel': return isZh ? '界面语言' : 'Display Language'; default: return key; } }