补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor <cursoragent@cursor.com>
662 行
19 KiB
Plaintext
662 行
19 KiB
Plaintext
/**
|
|
* OmniCard AI (CRMmp) - 名片主个人中心与消息通知配置业务驱动层
|
|
* 严格按照 AGENTS.md 规范与 uts 强类型约束
|
|
*/
|
|
|
|
import {
|
|
OmniLocale,
|
|
PORTAL_LOCALE_STORAGE_KEY,
|
|
getCurrentLocale,
|
|
setAppLocale,
|
|
getOmniText,
|
|
} from '../../../common/locale.uts';
|
|
import {
|
|
CardProfile,
|
|
OwnerPageData,
|
|
OwnerPageQuery,
|
|
} from '../../../common/types.uts';
|
|
import { fetchOwnerCardPage } from '../../../common/api.uts';
|
|
|
|
export { PORTAL_LOCALE_STORAGE_KEY };
|
|
|
|
export type UserProfileAccount = {
|
|
name: string;
|
|
company: string;
|
|
department: string;
|
|
avatar: string;
|
|
cardId: string;
|
|
cardSlug: string;
|
|
};
|
|
|
|
export type NotificationSettings = {
|
|
radarPush: boolean;
|
|
leadNotice: boolean;
|
|
};
|
|
|
|
export type ProfileMetrics = {
|
|
cardsCount: number;
|
|
visitorsCount: number;
|
|
leadsCount: number;
|
|
};
|
|
|
|
export type ProfileState = {
|
|
account: UserProfileAccount;
|
|
notifications: NotificationSettings;
|
|
metrics: ProfileMetrics;
|
|
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';
|
|
export const PROFILE_METRICS_STORAGE_KEY = 'omni_owner_profile_metrics';
|
|
|
|
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: '',
|
|
company: '',
|
|
department: '',
|
|
avatar: '',
|
|
cardId: '',
|
|
cardSlug: '',
|
|
};
|
|
}
|
|
|
|
export type LoadProfileAccountApi = {
|
|
fetchOwnerCardPage: (
|
|
query: OwnerPageQuery
|
|
) => Promise<OwnerPageData<CardProfile>>;
|
|
};
|
|
|
|
/**
|
|
* 读取接口可选组织字段:仅 trim,缺失或空白一律空串
|
|
*/
|
|
export function readOptionalOrgText(value: string | null | undefined): string {
|
|
if (value == null) {
|
|
return '';
|
|
}
|
|
return String(value).trim();
|
|
}
|
|
|
|
/**
|
|
* 公司/部门展示:有值原样返回,缺失或空串走 i18n 空态
|
|
*/
|
|
export function displayOrgField(value: string | null | undefined): string {
|
|
const text = readOptionalOrgText(value);
|
|
if (text === '') {
|
|
return resolveProfileText('empty');
|
|
}
|
|
return text;
|
|
}
|
|
|
|
/**
|
|
* 接口失败或无数据时清空公司与部门,禁止保留上次/示例值
|
|
*/
|
|
export function clearOrgFields(state: ProfileState): void {
|
|
state.account.company = '';
|
|
state.account.department = '';
|
|
}
|
|
|
|
function readDepartmentFromCard(card: CardProfile): string {
|
|
const extra = card as CardProfile & { department?: string | null };
|
|
return readOptionalOrgText(extra.department);
|
|
}
|
|
|
|
/**
|
|
* 从名片分页接口拉取当前用户公司/部门(仅使用接口返回字段)
|
|
*/
|
|
export async function loadOwnerProfileAccount(
|
|
state: ProfileState,
|
|
api?: LoadProfileAccountApi
|
|
): Promise<boolean> {
|
|
const fetchPage =
|
|
api != null ? api.fetchOwnerCardPage : fetchOwnerCardPage;
|
|
state.loading = true;
|
|
try {
|
|
const data = await fetchPage({ page: 1, size: 1 } as OwnerPageQuery);
|
|
const list = data.list != null ? data.list : [];
|
|
if (list.length === 0) {
|
|
clearOrgFields(state);
|
|
state.account.cardId = '';
|
|
state.account.cardSlug = '';
|
|
state.errorMessage = '';
|
|
state.loading = false;
|
|
return true;
|
|
}
|
|
const card = list[0];
|
|
state.account.company = readOptionalOrgText(card.company);
|
|
state.account.department = readDepartmentFromCard(card);
|
|
state.account.cardId = card.id != null ? String(card.id) : '';
|
|
const slugText = card.slug != null ? String(card.slug).trim() : '';
|
|
state.account.cardSlug = slugText;
|
|
if (card.name != null && String(card.name).trim() !== '') {
|
|
state.account.name = String(card.name).trim();
|
|
}
|
|
if (card.avatarUrl != null && String(card.avatarUrl).trim() !== '') {
|
|
state.account.avatar = String(card.avatarUrl).trim();
|
|
}
|
|
state.errorMessage = '';
|
|
state.loading = false;
|
|
return true;
|
|
} catch (err: unknown) {
|
|
clearOrgFields(state);
|
|
state.account.cardId = '';
|
|
state.account.cardSlug = '';
|
|
const msg = err instanceof Error && err.message !== ''
|
|
? err.message
|
|
: resolveProfileText('error');
|
|
state.errorMessage = msg;
|
|
state.loading = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function getDefaultNotifications(): NotificationSettings {
|
|
return {
|
|
radarPush: true,
|
|
leadNotice: true,
|
|
};
|
|
}
|
|
|
|
export function getDefaultMetrics(): ProfileMetrics {
|
|
return {
|
|
cardsCount: 0,
|
|
visitorsCount: 0,
|
|
leadsCount: 0,
|
|
};
|
|
}
|
|
|
|
export function loadProfileMetrics(storage?: StorageApi): ProfileMetrics {
|
|
const store = storage != null ? storage : defaultStorage();
|
|
try {
|
|
const raw = store.getStorageSync(PROFILE_METRICS_STORAGE_KEY);
|
|
const parsed = safeParseJson<Record<string, unknown>>(raw);
|
|
if (parsed != null && typeof parsed === 'object') {
|
|
const defaultM = getDefaultMetrics();
|
|
const cards = typeof parsed.cardsCount === 'number' ? parsed.cardsCount : defaultM.cardsCount;
|
|
const visitors = typeof parsed.visitorsCount === 'number' ? parsed.visitorsCount : defaultM.visitorsCount;
|
|
const leads = typeof parsed.leadsCount === 'number' ? parsed.leadsCount : defaultM.leadsCount;
|
|
return {
|
|
cardsCount: cards,
|
|
visitorsCount: visitors,
|
|
leadsCount: leads,
|
|
};
|
|
}
|
|
} catch (_e) {}
|
|
return getDefaultMetrics();
|
|
}
|
|
|
|
export function saveProfileMetrics(metrics: ProfileMetrics, storage?: StorageApi): boolean {
|
|
const store = storage != null ? storage : defaultStorage();
|
|
try {
|
|
store.setStorageSync(PROFILE_METRICS_STORAGE_KEY, JSON.stringify(metrics));
|
|
return true;
|
|
} catch (_e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function createProfileState(locale?: OmniLocale): ProfileState {
|
|
const currentLocale = locale != null ? locale : getCurrentLocale();
|
|
return {
|
|
account: getDefaultAccount(),
|
|
notifications: getDefaultNotifications(),
|
|
metrics: getDefaultMetrics(),
|
|
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 safeName = typeof parsedAccount.name === 'string'
|
|
? parsedAccount.name.trim()
|
|
: '';
|
|
const safeCompany = typeof parsedAccount.company === 'string'
|
|
? parsedAccount.company.trim()
|
|
: '';
|
|
const safeDept = typeof parsedAccount.department === 'string'
|
|
? parsedAccount.department.trim()
|
|
: '';
|
|
const safeAvatar = typeof parsedAccount.avatar === 'string'
|
|
? parsedAccount.avatar.trim()
|
|
: '';
|
|
const safeCardId = typeof parsedAccount.cardId === 'string'
|
|
? parsedAccount.cardId.trim()
|
|
: '';
|
|
const safeCardSlug = typeof parsedAccount.cardSlug === 'string'
|
|
? parsedAccount.cardSlug.trim()
|
|
: '';
|
|
|
|
state.account = {
|
|
name: safeName,
|
|
company: safeCompany,
|
|
department: safeDept,
|
|
avatar: safeAvatar,
|
|
cardId: safeCardId,
|
|
cardSlug: safeCardSlug,
|
|
};
|
|
}
|
|
} 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();
|
|
state.metrics = loadProfileMetrics(store);
|
|
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)
|
|
);
|
|
saveProfileMetrics(state.metrics, store);
|
|
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 = '';
|
|
}
|
|
|
|
/**
|
|
* 计算配额使用百分比 (0-100),防溢出与除零防御
|
|
*/
|
|
export function calculateQuotaPercent(used: number, limit: number): number {
|
|
if (limit <= 0) {
|
|
return 100;
|
|
}
|
|
if (used <= 0) {
|
|
return 0;
|
|
}
|
|
const pct = Math.round((used / limit) * 100);
|
|
if (pct > 100) {
|
|
return 100;
|
|
}
|
|
return pct;
|
|
}
|
|
|
|
/**
|
|
* 瑞士国际主义多语言文案解析器,无 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');
|
|
}
|
|
if (key === 'empty') {
|
|
return getOmniText(locale, 'common.empty');
|
|
}
|
|
|
|
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 'tierPro':
|
|
return isZh ? '商业专业版' : 'Pro Plan';
|
|
case 'tierBadge':
|
|
return 'PRO';
|
|
case 'previewPortal':
|
|
return isZh ? '预览微官网' : 'Preview site';
|
|
case 'metricsCards':
|
|
return isZh ? '活跃名片' : 'Active Cards';
|
|
case 'metricsVisitors':
|
|
return isZh ? '雷达访客' : 'Radar Visitors';
|
|
case 'metricsLeads':
|
|
return isZh ? '沉淀线索' : 'Captured Leads';
|
|
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 ? '设备与团队' : 'Hardware & Team';
|
|
case 'cardStudioSection':
|
|
return isZh ? '名片内容管理' : 'Digital Card Studio';
|
|
case 'myCards':
|
|
return isZh ? '我的数字名片' : 'Digital Cards';
|
|
case 'cardEdit':
|
|
return isZh ? '名片编辑' : 'Edit Card';
|
|
case 'productCases':
|
|
return isZh ? '产品相册与案例' : 'Portfolio & Cases';
|
|
case 'articleDynamics':
|
|
return isZh ? '文章与商务动态' : 'Insights & News';
|
|
case 'sharePoster':
|
|
return isZh ? '分享海报' : 'Share Poster';
|
|
case 'exchangeHall':
|
|
return isZh ? '互换大厅' : 'Exchange Hall';
|
|
case 'editProfile':
|
|
return isZh ? '编辑资料' : 'Edit';
|
|
case 'nfcSection':
|
|
return isZh ? 'NFC 设备' : 'NFC Fleet';
|
|
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.';
|
|
case 'upgradeQuota':
|
|
return isZh ? '升级扩容' : 'Upgrade Plan';
|
|
case 'planActive':
|
|
return isZh ? '生效中' : 'Active';
|
|
case 'confirmLogoutTitle':
|
|
return isZh ? '确认退出' : 'Sign Out';
|
|
case 'confirmLogoutContent':
|
|
return isZh ? '确定要退出当前账号吗?' : 'Are you sure you want to sign out?';
|
|
case 'myCardsSub':
|
|
return isZh ? '查看和切换名片' : 'View and switch cards';
|
|
case 'cardEditSub':
|
|
return isZh ? '改姓名、职位和联系方式' : 'Name, role, and contact details';
|
|
case 'productCasesSub':
|
|
return isZh ? '名片上展示的案例' : 'Cases shown on your card';
|
|
case 'articleDynamicsSub':
|
|
return isZh ? '名片上展示的文章' : 'Articles shown on your card';
|
|
case 'sharePosterSub':
|
|
return isZh ? '全屏出示二维码' : 'Full-screen QR';
|
|
case 'exchangeHallSub':
|
|
return isZh ? '当面交换名片' : 'Exchange in person';
|
|
case 'nfcScanSub':
|
|
return isZh ? '把实体卡绑到名片' : 'Bind a physical card';
|
|
case 'nfcModeSub':
|
|
return isZh ? '更换这张卡打开的页面' : 'Choose what the card opens';
|
|
case 'nfcSecuritySub':
|
|
return isZh ? '卡片丢失时远程停用' : 'Freeze a lost card';
|
|
case 'teamBriefingSub':
|
|
return isZh ? '团队今天的获客' : "Today's team results";
|
|
case 'avatarActionSheetTitle':
|
|
return isZh ? '头像管理' : 'Avatar Options';
|
|
case 'avatarActionPreview':
|
|
return isZh ? '查看大图' : 'View Full Photo';
|
|
case 'avatarActionChoose':
|
|
return isZh ? '从相册更换头像' : 'Change from Photos';
|
|
case 'avatarActionRemove':
|
|
return isZh ? '移除当前头像' : 'Remove Avatar';
|
|
case 'aboutApp':
|
|
return isZh ? '关于 OmniCard' : 'About OmniCard';
|
|
case 'aboutBody':
|
|
return isZh ? '数字名片、微官网和访客雷达' : 'Digital cards, microsites, and visitor radar';
|
|
case 'confirm':
|
|
return isZh ? '知道了' : 'OK';
|
|
case 'appVersion':
|
|
return 'OmniCard';
|
|
case 'securitySafe':
|
|
return isZh ? '保护中' : 'Protected';
|
|
case 'livePulse':
|
|
return isZh ? '实时' : 'Live';
|
|
default:
|
|
return key;
|
|
}
|
|
}
|