文件
OmniCard/mpuniapp/pages/owner/profile/useProfile.uts
wikiboss eec259a3a7 feat: 完成全系统30个功能点开发与E2E全链路验收 (8轮调度32个子代理闭环)
- 模块一: 出海案例作品集、博客动态发布、人名发音语音条、RTL阿语多语言切换
- 模块二: AI顾问人设配置、行业术语库润色、RAG切片沙盒调试、流式会话与意向留资卡片
- 模块三: 全球访客雷达大屏、多维加权意向算分、外部CRM对接推送、团队公海池流转
- 模块四: 移动端NFC安全挂失、NFC动态路由规则配置、动态防伪验签、展会制卡Zip批量导出
- 模块五: 组织架构与名片分配、移动端个人中心设置、离职交接与历史线索迁移、安全审计日志
- 模块六: Stripe国际信用卡订阅Webhook、独立二级域名与SSL检测、坐席配额预警、多币种发票
- 模块七: 纸质名片OCR解析入库、国际商务日程RFC 5545 ICS日历、微官网离线SWR预加载、展会实时排行榜大屏
- 模块八: 全球出海SEO OpenGraph元标签注入与社交爬虫探测、30点端到端全链路业务流集成测试套件
2026-09-20 23:47:47 +08:00

366 行
10 KiB
Plaintext

/**
* 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<T>(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<Record<string, unknown>>(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<Record<string, unknown>>(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<UserProfileAccount>
): 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;
}
/**
* 瑞士国际主义多语言文案解析器,无 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;
}
}