refactor(mpuniapp): 彻底重构个人中心为现代商务条状入口,集成商业资产罗盘看板并优化高管交互质感
这个提交包含在:
文件差异内容过多而无法显示
加载差异
@@ -25,9 +25,16 @@ export type NotificationSettings = {
|
||||
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;
|
||||
@@ -41,6 +48,7 @@ export type StorageApi = {
|
||||
|
||||
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 {
|
||||
@@ -80,11 +88,50 @@ export function getDefaultNotifications(): NotificationSettings {
|
||||
};
|
||||
}
|
||||
|
||||
export function getDefaultMetrics(): ProfileMetrics {
|
||||
return {
|
||||
cardsCount: 6,
|
||||
visitorsCount: 128,
|
||||
leadsCount: 24,
|
||||
};
|
||||
}
|
||||
|
||||
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 !== '' ? locale : getCurrentLocale();
|
||||
return {
|
||||
account: getDefaultAccount(),
|
||||
notifications: getDefaultNotifications(),
|
||||
metrics: getDefaultMetrics(),
|
||||
locale: currentLocale,
|
||||
saving: false,
|
||||
loading: false,
|
||||
@@ -166,6 +213,7 @@ export function loadProfileSettings(storage?: StorageApi): ProfileState {
|
||||
}
|
||||
|
||||
state.locale = getCurrentLocale();
|
||||
state.metrics = loadProfileMetrics(store);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -183,6 +231,7 @@ export function saveProfileSettings(state: ProfileState, storage?: StorageApi):
|
||||
PROFILE_NOTIFICATIONS_STORAGE_KEY,
|
||||
JSON.stringify(state.notifications)
|
||||
);
|
||||
saveProfileMetrics(state.metrics, store);
|
||||
state.errorMessage = '';
|
||||
return true;
|
||||
} catch (err: unknown) {
|
||||
@@ -416,13 +465,13 @@ export function resolveProfileText(key: string): string {
|
||||
case 'logout':
|
||||
return isZh ? '退出登录' : 'Log out';
|
||||
case 'workspaceSection':
|
||||
return isZh ? '智能硬件与团队' : 'Hardware & Team';
|
||||
return isZh ? '设备与团队' : 'Hardware & Team';
|
||||
case 'cardStudioSection':
|
||||
return isZh ? '名片与微官网工作室' : 'Digital Card Studio';
|
||||
return isZh ? '名片内容管理' : 'Digital Card Studio';
|
||||
case 'myCards':
|
||||
return isZh ? '我的数字名片' : 'Digital Cards';
|
||||
case 'cardEdit':
|
||||
return isZh ? '极速资料维护' : 'Quick Profile';
|
||||
return isZh ? '名片编辑' : 'Edit Card';
|
||||
case 'productCases':
|
||||
return isZh ? '产品相册与案例' : 'Portfolio & Cases';
|
||||
case 'articleDynamics':
|
||||
@@ -434,7 +483,7 @@ export function resolveProfileText(key: string): string {
|
||||
case 'editProfile':
|
||||
return isZh ? '编辑资料' : 'Edit';
|
||||
case 'nfcSection':
|
||||
return isZh ? 'NFC 智能硬件' : 'NFC Fleet';
|
||||
return isZh ? 'NFC 设备' : 'NFC Fleet';
|
||||
case 'nfcScan':
|
||||
return isZh ? 'NFC 贴卡激活' : 'Activate NFC card';
|
||||
case 'nfcMode':
|
||||
@@ -442,7 +491,7 @@ export function resolveProfileText(key: string): string {
|
||||
case 'nfcSecurity':
|
||||
return isZh ? 'NFC 挂失' : 'Freeze NFC card';
|
||||
case 'teamBriefing':
|
||||
return isZh ? '展会战报' : 'Team briefing';
|
||||
return isZh ? '展会数据' : 'Team briefing';
|
||||
case 'quotaSection':
|
||||
return isZh ? '套餐与配额' : 'Plan & Quota';
|
||||
case 'quotaCards':
|
||||
@@ -457,6 +506,42 @@ export function resolveProfileText(key: string): string {
|
||||
return isZh ? '确认退出' : 'Sign Out';
|
||||
case 'confirmLogoutContent':
|
||||
return isZh ? '确定要退出当前账号吗?' : 'Are you sure you want to sign out?';
|
||||
case 'myCardsSub':
|
||||
return isZh ? '查看与出示专属数字名片' : 'View and present digital cards';
|
||||
case 'cardEditSub':
|
||||
return isZh ? '修改履历、职业信息与社交矩阵' : 'Update profile and social links';
|
||||
case 'productCasesSub':
|
||||
return isZh ? '展示产品与案例' : 'Portfolio and cases';
|
||||
case 'articleDynamicsSub':
|
||||
return isZh ? '发布业务动态与文章' : 'Publish dynamic posts';
|
||||
case 'sharePosterSub':
|
||||
return isZh ? '展会专属扫码展台与立牌' : 'Expo QR poster and stand';
|
||||
case 'exchangeHallSub':
|
||||
return isZh ? '面对面扫码或碰卡互换' : 'Face-to-face card exchange';
|
||||
case 'nfcScanSub':
|
||||
return isZh ? '新实体卡贴碰写入绑定' : 'Tap and bind new NFC card';
|
||||
case 'nfcModeSub':
|
||||
return isZh ? '展会与拜访场景切换' : 'Switch expo and meeting modes';
|
||||
case 'nfcSecuritySub':
|
||||
return isZh ? '防盗刷保护与远程紧急冻结' : 'Remote freeze and theft protection';
|
||||
case 'teamBriefingSub':
|
||||
return isZh ? '全员名片分发与获客大盘战报' : 'Team leads and distribution briefing';
|
||||
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 'appVersion':
|
||||
return isZh ? '企业旗舰版 v1.2.0' : 'Enterprise v1.2.0';
|
||||
case 'securitySafe':
|
||||
return isZh ? '保护中' : 'Protected';
|
||||
case 'livePulse':
|
||||
return isZh ? '实时' : 'Live';
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -78,3 +78,20 @@ test('8. profile/index.uvue 必须符合 Bento Grid、漫反射软阴影与极
|
||||
assert.ok(content.includes('linear-gradient'), '必须包含品牌微渐变或极光流光微效果');
|
||||
});
|
||||
|
||||
test('9. 业务入口必须为条状入口 (Grouped Inset Cell Rows),杜绝玩具方块网格', () => {
|
||||
const content = fs.readFileSync(profileUvuePath, 'utf-8');
|
||||
|
||||
assert.ok(content.includes('bento-list-group'), '必须使用 bento-list-group 分组条状容器');
|
||||
assert.ok(content.includes('bento-row-item'), '必须使用 bento-row-item 条状列表项');
|
||||
assert.equal(content.includes('workspace-grid'), false, '必须彻底移除 workspace-grid 玩具方块网格');
|
||||
assert.equal(content.includes('grid-item-head'), false, '必须彻底移除 grid-item-head 网格头部');
|
||||
});
|
||||
|
||||
test('10. 头像交互必须优雅沉浸,杜绝破坏高管形象的右上角突兀红色大叉', () => {
|
||||
const content = fs.readFileSync(profileUvuePath, 'utf-8');
|
||||
|
||||
assert.equal(content.includes('avatar-remove-badge'), false, '严禁在头像角部悬挂突兀红色大叉删除标');
|
||||
assert.ok(content.includes('onAvatarClick'), '头像必须支持点击交互呼出操作面板');
|
||||
});
|
||||
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户