feat: 同步管理端、用户端与后端业务,并接通线上 Web 接口
补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor <cursoragent@cursor.com>
这个提交包含在:
@@ -57,13 +57,18 @@ test('3. 大屏页面必须存在且使用 Arco Design 官方核心组件', () =
|
||||
assert.ok(content.includes('Progress'), '必须使用 Arco Progress 展示占比进度条');
|
||||
});
|
||||
|
||||
test('4. 大屏页面必须对接雷达聚合分析 API 且只设置 1 个主 CTA', () => {
|
||||
test('4. 大屏页面必须对接雷达热力聚合 API 且只设置 1 个主 CTA', () => {
|
||||
const content = fs.readFileSync(radarMapPagePath, 'utf-8');
|
||||
|
||||
// 接口校验
|
||||
// 国家/地区分布必须来自已有热力聚合接口(analytics 内含 countryDistribution,或独立 distribution)
|
||||
assert.ok(
|
||||
content.includes('/api/admin/crm/radar/analytics') || content.includes('/api/admin/crm/radar/distribution'),
|
||||
'必须对接雷达分析或国家分布 API'
|
||||
content.includes('/api/admin/crm/radar/analytics') ||
|
||||
content.includes('/api/admin/crm/radar/distribution'),
|
||||
'必须对接雷达热力聚合 analytics 或 distribution API'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('countryDistribution') || content.includes('/radar/distribution'),
|
||||
'国家/地区分布必须绑定接口返回的 countryDistribution(或 distribution)'
|
||||
);
|
||||
|
||||
// 瑞士国际主义与一屏单主 CTA 原则: 统计 type="primary" 按钮数量
|
||||
@@ -75,6 +80,63 @@ test('4. 大屏页面必须对接雷达聚合分析 API 且只设置 1 个主 CT
|
||||
);
|
||||
});
|
||||
|
||||
test('4b. 国家分布禁止写死占比;请求失败或无数据必须空态', () => {
|
||||
const content = fs.readFileSync(radarMapPagePath, 'utf-8');
|
||||
const localeContent = fs.readFileSync(radarMapLocalePath, 'utf-8');
|
||||
|
||||
// 禁止演示用硬编码国家名与写死占比
|
||||
const bannedCountries = [
|
||||
'United States',
|
||||
'United Kingdom',
|
||||
'Singapore',
|
||||
'Germany',
|
||||
'Japan',
|
||||
'China',
|
||||
'Dubai',
|
||||
'Saudi Arabia',
|
||||
];
|
||||
for (const name of bannedCountries) {
|
||||
assert.ok(!content.includes(name), `禁止硬编码国家/地区名: ${name}`);
|
||||
}
|
||||
assert.ok(
|
||||
!/percentage\s*:\s*\d+/.test(content),
|
||||
'禁止在页面中写死 percentage 国家占比'
|
||||
);
|
||||
assert.ok(
|
||||
!/visitorCount\s*:\s*[1-9]/.test(content),
|
||||
'禁止在页面中写死非零 visitorCount 演示数据'
|
||||
);
|
||||
|
||||
// 失败或非 1000 必须清空分布,不得残留假占比
|
||||
assert.ok(
|
||||
content.includes('countryDistribution: []') ||
|
||||
content.includes('EMPTY_ANALYTICS') ||
|
||||
content.includes('emptyAnalytics'),
|
||||
'必须具备空的 countryDistribution 初始/空态结构'
|
||||
);
|
||||
assert.ok(
|
||||
/setAnalyticsData\(\s*(EMPTY_ANALYTICS|emptyAnalytics)/.test(content) ||
|
||||
/setAnalyticsData\(\s*\{\s*[\s\S]*countryDistribution\s*:\s*\[\s*\]/.test(content),
|
||||
'接口失败必须 setAnalyticsData 清空为国家空分布'
|
||||
);
|
||||
|
||||
// 空态文案走 locale
|
||||
assert.ok(
|
||||
content.includes('radarMap.status.empty') || content.includes("t['radarMap.status.empty']"),
|
||||
'空态必须引用 radarMap.status.empty'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('Empty') || content.includes('noDataElement'),
|
||||
'无数据必须使用 Empty 或 Table noDataElement'
|
||||
);
|
||||
assert.ok(localeContent.includes('radarMap.status.empty'), 'locale 必须包含空态文案');
|
||||
assert.ok(localeContent.includes('radarMap.status.loadFailed'), 'locale 必须包含加载失败文案');
|
||||
assert.ok(
|
||||
localeContent.includes('radarMap.country.unknown'),
|
||||
'locale 必须包含未知国家/地区文案'
|
||||
);
|
||||
});
|
||||
|
||||
test('5. 必须使用设计 Token 系统且保持严谨纯粹 (零 any、零 emoji)', () => {
|
||||
const content = fs.readFileSync(radarMapPagePath, 'utf-8');
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户