文件
OmniCard/mpuniapp/pages/owner/profile/useProfile.uts

409 行
11 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;
}
/**
* 预览个人头像
*/
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';
case 'logout':
return isZh ? '退出登录' : 'Log out';
case 'workspaceSection':
return isZh ? '工作台' : 'Workspace';
case 'nfcScan':
return isZh ? 'NFC 贴卡激活' : 'Activate NFC card';
case 'nfcMode':
return isZh ? 'NFC 场景切换' : 'NFC scene mode';
case 'nfcSecurity':
return isZh ? 'NFC 挂失' : 'Freeze NFC card';
case 'teamBriefing':
return isZh ? '展会战报' : 'Team briefing';
case 'quotaSection':
return isZh ? '套餐配额' : 'Plan quota';
case 'quotaCards':
return isZh ? '名片用量' : 'Card usage';
case 'quotaUpgrade':
return isZh ? '已达上限,请升级套餐' : 'Limit reached. Upgrade to continue.';
default:
return key;
}
}