feat: 同步管理端、用户端与后端业务,并接通线上 Web 接口
补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。 Co-authored-by: Cursor <cursoragent@cursor.com>
这个提交包含在:
@@ -184,5 +184,63 @@ test('8. 实时雷达数据专家重构:相对时间、本地环境优雅降
|
||||
assert.ok(!/\bany\b/.test(content), '严禁使用 any');
|
||||
});
|
||||
|
||||
test('9. P32: KPI 必须来自 workplace 统计接口,禁止演示假数,失败回退 0/空态', () => {
|
||||
const content = fs.readFileSync(pagePath, 'utf-8');
|
||||
const localeContent = fs.readFileSync(localePath, 'utf-8');
|
||||
|
||||
assert.ok(
|
||||
content.includes('/api/admin/crm/radar/workplace'),
|
||||
'KPI 必须请求 /api/admin/crm/radar/workplace'
|
||||
);
|
||||
assert.ok(content.includes('kpis.tapCount'), '触碰量必须绑定接口 kpis.tapCount');
|
||||
assert.ok(content.includes('kpis.viewCount'), '浏览量必须绑定接口 kpis.viewCount');
|
||||
assert.ok(content.includes('kpis.newLeadCount'), '新线索必须绑定接口 kpis.newLeadCount');
|
||||
assert.ok(
|
||||
content.includes('kpis.conversionRate'),
|
||||
'转化率必须绑定接口 kpis.conversionRate'
|
||||
);
|
||||
|
||||
// 禁止渠道/KPI 演示假数(空 feed 时不得回退 50/30/20)
|
||||
assert.ok(
|
||||
!/nfc:\s*50/.test(content) && !/qr:\s*30/.test(content) && !/link:\s*20/.test(content),
|
||||
'渠道分布禁止硬编码 50/30/20 假数'
|
||||
);
|
||||
assert.ok(!content.includes('14500'), '禁止硬编码演示 KPI 数字');
|
||||
assert.ok(!content.includes('Vanguard'), '禁止硬编码演示客户名');
|
||||
assert.ok(!/\b210\b/.test(content), '页面禁止硬编码演示停留秒数');
|
||||
assert.ok(
|
||||
!localeContent.includes('210'),
|
||||
'语言包禁止硬编码演示停留秒数假数'
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
content.includes('code !== 1000') || content.includes('code === 1000'),
|
||||
'必须按 Cool-Admin 约定校验 code === 1000'
|
||||
);
|
||||
|
||||
// 失败或无数据时必须回退 EMPTY_KPI / 全 0,不得保留假数
|
||||
assert.ok(content.includes('EMPTY_KPI'), '必须定义 EMPTY_KPI 作为空态/失败回退');
|
||||
assert.ok(
|
||||
content.includes('kpis: EMPTY_KPI, radarFeed: []'),
|
||||
'接口失败或无效响应时必须 setOverview 回退 EMPTY_KPI'
|
||||
);
|
||||
|
||||
// 漏斗 meta 与渠道/预警空态必须走 locale
|
||||
const localeKeys = [
|
||||
'workplace.funnel.metaBase',
|
||||
'workplace.funnel.metaTapView',
|
||||
'workplace.funnel.metaViewInteract',
|
||||
'workplace.funnel.metaInteractLead',
|
||||
'workplace.channel.empty',
|
||||
'workplace.alerts.empty',
|
||||
];
|
||||
for (const key of localeKeys) {
|
||||
assert.ok(localeContent.includes(key), `语言包必须包含: ${key}`);
|
||||
assert.ok(content.includes(key), `页面必须引用 locale key: ${key}`);
|
||||
}
|
||||
|
||||
assert.ok(!EMOJI_RE.test(content), '页面严禁 emoji');
|
||||
assert.ok(!EMOJI_RE.test(localeContent), '语言包严禁 emoji');
|
||||
assert.ok(!/\bany\b/.test(content), '严禁 any');
|
||||
});
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户