refactor(i18n): 全工程面向国际用户与全球现代商务重构,彻底清理出海跨境等单向视角表达并对齐自动化测试

这个提交包含在:
wikiboss
2026-09-21 15:24:36 +08:00
父节点 ad9df7a7a4
当前提交 17882ca1cb
共有 135 个文件被更改,包括 12928 次插入 和 1653 次删除

查看文件

@@ -34,6 +34,15 @@ type ArticleDetailState = {
description: string;
image: string;
};
authorName?: string;
authorTitle?: string;
authorCompany?: string;
authorAvatar?: string;
readTimeMinutes?: number;
summaryText?: string;
scrollDepth?: number;
enterTime?: number;
visitorId?: string;
};
type ArticleShareFields = {
@@ -65,6 +74,15 @@ type ArticleDetailModule = {
getArticleShareFields: (state: ArticleDetailState, pageUrl: string) => ArticleShareFields;
loadArticleDetail: (state: ArticleDetailState) => Promise<BentoBlockFixture | null>;
copyArticleShareLink: (state: ArticleDetailState, pageUrl?: string) => boolean;
resolveArticleDetailText: (key: string, locale?: string) => string;
updateArticleScrollDepth: (
state: ArticleDetailState,
scrollTop: number,
scrollHeight: number,
windowHeight: number
) => number;
reportArticleStay: (state: ArticleDetailState, scrollDepth?: number) => Promise<unknown>;
navToAuthorPortal: (state: ArticleDetailState) => void;
};
type UniToastOption = {
@@ -453,4 +471,112 @@ describe('OmniCard AI 用户端文章详情业务逻辑测试 (useArticleDetail.
expect(toastCalls.length).toBeGreaterThan(0);
});
});
describe('4. 专栏作者微展台与核心摘要导读', () => {
it('4.1 加载文章时能一并解析名片作者信息与核心摘要', async () => {
const {
createArticleDetailState,
applyArticleDetailOptions,
loadArticleDetail,
} = loadUseArticleDetail();
const state = createArticleDetailState();
applyArticleDetailOptions(state, { cardId: 'card-101', blockId: '3' });
await loadArticleDetail(state);
expect(state.authorName).toBe('Alex Vance');
expect(state.authorTitle).toBe('Managing Director & Global Partner');
expect(state.authorCompany).toBe('Nexus Tech Global Ltd');
expect(state.readTimeMinutes).toBeGreaterThanOrEqual(1);
expect(state.summaryText?.length).toBeGreaterThan(0);
});
});
describe('5. 阅读滑屏深度计算与雷达停留时长上报', () => {
it('5.1 updateArticleScrollDepth 正确计算并单调递增滑屏百分比', () => {
const { createArticleDetailState, updateArticleScrollDepth } = loadUseArticleDetail();
const state = createArticleDetailState();
expect(state.scrollDepth).toBe(0);
// 顶部
updateArticleScrollDepth(state, 0, 2000, 600);
expect(state.scrollDepth).toBe(0);
// 中间 (scrollTop = 700 / maxScroll = 1400 => 50%)
updateArticleScrollDepth(state, 700, 2000, 600);
expect(state.scrollDepth).toBe(50);
// 向上回滚时保持最大深度
updateArticleScrollDepth(state, 200, 2000, 600);
expect(state.scrollDepth).toBe(50);
// 触底 (100%)
updateArticleScrollDepth(state, 1400, 2000, 600);
expect(state.scrollDepth).toBe(100);
});
it('5.2 reportArticleStay 将停留时长与阅读深度正确上报至雷达', async () => {
const {
createArticleDetailState,
applyArticleDetailOptions,
loadArticleDetail,
reportArticleStay,
} = loadUseArticleDetail();
const state = createArticleDetailState();
applyArticleDetailOptions(state, { cardId: 'card-101', blockId: '3' });
await loadArticleDetail(state);
mockRequestResponse = {
statusCode: 200,
data: {
code: 1000,
message: 'success',
data: {
id: 'track-1',
cardId: 'card-101',
visitorId: 'vis-test',
touchType: 'link',
stayDurationMs: 1200,
scrollDepth: 75,
viewedBlocks: ['3'],
},
},
};
state.enterTime = Date.now() - 1500;
state.scrollDepth = 75;
await reportArticleStay(state, 75);
expect(lastRequestOptions?.url).toContain('/open/crm/radar/track');
const body = lastRequestOptions?.data as Record<string, unknown>;
expect(body.cardId).toBe('card-101');
expect(body.touchType).toBe('link');
expect(body.scrollDepth).toBe(75);
expect(body.viewedBlocks).toEqual(['3']);
});
});
describe('6. 多语言本地化文案体系', () => {
it('6.1 覆盖 zh-CN, en-US, ar-SA, es-ES 等语种的核心文案', () => {
const { resolveArticleDetailText } = loadUseArticleDetail();
expect(resolveArticleDetailText('kicker', 'zh-CN')).toBe('深度洞见');
expect(resolveArticleDetailText('summary', 'zh-CN')).toBe('核心导读');
expect(resolveArticleDetailText('author', 'zh-CN')).toBe('专栏作者');
expect(resolveArticleDetailText('viewPortal', 'zh-CN')).toBe('查看微官网');
expect(resolveArticleDetailText('kicker', 'en-US')).toBe('Thought Leadership');
expect(resolveArticleDetailText('summary', 'en-US')).toBe('Key Takeaways');
expect(resolveArticleDetailText('author', 'en-US')).toBe('Author');
expect(resolveArticleDetailText('viewPortal', 'en-US')).toBe('View Profile');
expect(resolveArticleDetailText('kicker', 'ar-SA')).toBe('رؤى متعمقة');
expect(resolveArticleDetailText('summary', 'ar-SA')).toBe('أبرز النقاط');
expect(resolveArticleDetailText('kicker', 'es-ES')).toBe('Perspectivas');
expect(resolveArticleDetailText('summary', 'es-ES')).toBe('Puntos clave');
});
});
});

查看文件

@@ -47,6 +47,12 @@ type MockBentoBlock = {
metrics?: CaseKpi[];
pdfUrl?: string;
youtubeUrl?: string;
client?: string;
industry?: string;
region?: string;
challenge?: string;
solution?: string;
[key: string]: unknown;
};
};
@@ -89,6 +95,8 @@ type UseCaseDetailModule = {
buildExchangePath: (cardId: string) => string;
openCaseExchange: (cardId: string) => void;
goCaseBack: () => void;
copyCaseExternalLink: (url: string) => boolean;
resolveCaseDetailText: (key: string) => string;
};
function loadUseCaseDetail(): UseCaseDetailModule {
@@ -371,4 +379,72 @@ describe('OmniCard AI 用户端案例详情业务逻辑测试 (useCaseDetail.uts
expect(navigateBackCount).toBe(1);
});
});
describe('5. Bento Grid 模块化结构化数据与国际化解析', () => {
it('5.1 支持从 metaJson 解析 client, industry, region, challenge, solution', () => {
const { createCaseDetailState, applyCaseDetailOptions, applyPortalCase } =
loadUseCaseDetail();
const card = buildMockPortal();
card.bentoBlocks[1].metaJson = {
client: 'Global Logistics Corp',
industry: 'Supply Chain IoT',
region: 'Middle East & North Africa',
challenge: 'High latency in cross-border tracking and data silos.',
solution: 'Deployed dual-frequency NFC sensors and cloud-native mesh.',
kpis: [{ label: 'On-time Delivery', value: '99.8%' }],
};
const state = createCaseDetailState();
applyCaseDetailOptions(state, { cardId: 'card-101', blockId: '2' });
applyPortalCase(state, card);
expect((state as any).client).toBe('Global Logistics Corp');
expect((state as any).industry).toBe('Supply Chain IoT');
expect((state as any).region).toBe('Middle East & North Africa');
expect((state as any).challenge).toBe(
'High latency in cross-border tracking and data silos.'
);
expect((state as any).solution).toBe(
'Deployed dual-frequency NFC sensors and cloud-native mesh.'
);
expect(state.kpis).toEqual([{ label: 'On-time Delivery', value: '99.8%' }]);
});
it('5.2 resolveCaseDetailText 正确解析新增的 Bento 模组词条', () => {
const { resolveCaseDetailText } = loadUseCaseDetail();
expect(resolveCaseDetailText('badge')).toBeDefined();
expect(resolveCaseDetailText('overview')).toBeDefined();
expect(resolveCaseDetailText('challenge')).toBeDefined();
expect(resolveCaseDetailText('solution')).toBeDefined();
expect(resolveCaseDetailText('kpis')).toBeDefined();
expect(resolveCaseDetailText('resources')).toBeDefined();
expect(resolveCaseDetailText('pdfAction')).toBeDefined();
expect(resolveCaseDetailText('videoAction')).toBeDefined();
});
it('5.3 copyCaseExternalLink 触发 uni.setClipboardData 与 Toast 提示', () => {
let clipboardText = '';
let toastCalled = false;
(global as { uni?: Record<string, unknown> }).uni = {
setClipboardData: (opts: { data: string; success?: () => void }) => {
clipboardText = opts.data;
opts.success?.();
},
showToast: () => {
toastCalled = true;
},
};
const { copyCaseExternalLink } = loadUseCaseDetail();
const res = copyCaseExternalLink('https://cdn.omnicard.ai/doc.pdf');
expect(res).toBe(true);
expect(clipboardText).toBe('https://cdn.omnicard.ai/doc.pdf');
expect(toastCalled).toBe(true);
const emptyRes = copyCaseExternalLink('');
expect(emptyRes).toBe(false);
});
});
});

查看文件

@@ -3,7 +3,7 @@
* 严格遵循 TDD 测试驱动规范
*/
describe('Point 56: 移动端 App / H5 出海名片 Universal Link 深度链接路由分发解析器', () => {
describe('Point 56: 移动端 App / H5 智能数字名片 Universal Link 深度链接路由分发解析器', () => {
let router: any;
beforeEach(() => {

查看文件

@@ -1,6 +1,6 @@
/**
* OmniCard AI (CRMmp) - 访客端多语言动态切换与 RTL 镜像契约测试 (TDD)
* 严格按照 AGENTS.md 与出海国际化 WCAG 标准规范
* 严格按照 AGENTS.md 与国际化 WCAG 标准规范
*/
import * as fs from 'fs';
@@ -173,7 +173,7 @@ describe('Point 04: 访客端多语言动态切换与 RTL 镜像无感适配', (
});
describe('4. 默认 GeoIP 语言回退 (resolveGeoLocale)', () => {
it('根据出海访客的国家码准确映射主流语言或回退 en-US', () => {
it('根据访客的国家码准确映射主流语言或回退 en-US', () => {
const { resolveGeoLocale } = require(LOCALE_UTS) as {
resolveGeoLocale: (countryCode?: string, fallback?: string) => string;
};

查看文件

@@ -1,6 +1,6 @@
/**
* OmniCard AI (CRMmp) - 移动微官网离线 LocalStorage 极速预加载与骨架屏单测套件 (TDD)
* 严格遵循 AGENTS.md 规范与出海高性能架构契约
* 严格遵循 AGENTS.md 规范与高性能架构契约
*/
export interface MockBentoBlock {

查看文件

@@ -19,7 +19,7 @@ describe('uni-app 框架自带原生 tabBar 规范测试 (TDD Red -> Green)', ()
// 关键规范:tabBar.list[0].pagePath 必须与 pages[0].path 一致,原生 tabBar 才能在首屏正常加载
expect(config.tabBar.list[0].pagePath).toBe(config.pages[0].path);
expect(config.tabBar.list[0].text).toBe('官网');
expect(config.tabBar.list[0].text).toBe('名片');
// 校验颜色 Token
expect(config.tabBar.color.toLowerCase()).toBe('#667085');