refactor(i18n): 全工程面向国际用户与全球现代商务重构,彻底清理出海跨境等单向视角表达并对齐自动化测试
这个提交包含在:
@@ -5,7 +5,7 @@ import {
|
||||
ChannelAttributionEvent,
|
||||
} from '../../../src/modules/crm/service/attribution';
|
||||
|
||||
describe('Point 46: 访客雷达多渠道来源归因与出海转化漏斗分析', () => {
|
||||
describe('Point 46: 访客雷达多渠道来源归因与转化漏斗分析', () => {
|
||||
let service: RadarAttributionService;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -18,7 +18,7 @@ describe('Point 46: 访客雷达多渠道来源归因与出海转化漏斗分析
|
||||
expect(normalizeTrafficChannel('booth', 'qrcode')).toBe('booth_qr');
|
||||
});
|
||||
|
||||
it('应精准识别 WhatsApp 与 LinkedIn 社交出海渠道', () => {
|
||||
it('应精准识别 WhatsApp 与 LinkedIn 国际社交渠道', () => {
|
||||
expect(normalizeTrafficChannel('whatsapp', 'im')).toBe('whatsapp_chat');
|
||||
expect(normalizeTrafficChannel('linkedin', 'social')).toBe('linkedin_share');
|
||||
expect(normalizeTrafficChannel('email', 'sig')).toBe('email_signature');
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
TrafficFilterResult,
|
||||
} from '../../../src/modules/crm/service/bot-filter';
|
||||
|
||||
describe('Point 63 (P2): 访客雷达异常流量与出海社交抓取机器爬虫清洗过滤', () => {
|
||||
describe('Point 63 (P2): 访客雷达异常流量与社交抓取机器爬虫清洗过滤', () => {
|
||||
let service: RadarBotFilterService;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AdminCrmLeadController } from '../../../src/modules/crm/controller/admi
|
||||
import { CrmLeadEntity } from '../../../src/modules/crm/entity/lead';
|
||||
import { RadarTrack } from '../../../src/comm/types/omni';
|
||||
|
||||
describe('【BTP-20】线索流转自动化与出海 Webhook / 实时推送集成测试', () => {
|
||||
describe('【BTP-20】线索流转自动化与外部 Webhook / 实时推送集成测试', () => {
|
||||
let syncService: CrmSyncService;
|
||||
let pushService: CrmRadarPushService;
|
||||
let mockLead: CrmLeadEntity;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
GdprUserDataBundle,
|
||||
} from '../../../src/modules/crm/service/compliance';
|
||||
|
||||
describe('Point 53: 海外合规 GDPR / CCPA 访客数据匿名化脱敏与被遗忘权导出', () => {
|
||||
describe('Point 53: 国际合规 GDPR / CCPA 访客数据匿名化脱敏与被遗忘权导出', () => {
|
||||
let service: ComplianceGdprService;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
CompanyProfileResult,
|
||||
} from '../../../src/modules/crm/service/enrichment';
|
||||
|
||||
describe('Point 49: 出海潜客企业邮箱域名解析与商业主页自动富化', () => {
|
||||
describe('Point 49: 潜客企业邮箱域名解析与商业主页自动富化', () => {
|
||||
let service: LeadCompanyEnrichmentService;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('Point 55: 全球访客雷达国家城市坐标聚合与热力散点引
|
||||
service = new RadarGeoHeatmapService();
|
||||
});
|
||||
|
||||
describe('1. resolveCityCoordinates (出海核心商务枢纽城市经纬度解析)', () => {
|
||||
describe('1. resolveCityCoordinates (全球核心商务枢纽城市经纬度解析)', () => {
|
||||
it('应精准解析迪拜、利雅得、新加坡与伦敦经纬度', () => {
|
||||
const dubai = resolveCityCoordinates('AE', 'Dubai');
|
||||
expect(dubai).toEqual([55.27, 25.20]);
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
LeadBehaviorTrigger,
|
||||
} from '../../../src/modules/crm/service/lead-automation';
|
||||
|
||||
describe('Point 58 (P1): 出海潜客线索行为自动化阶段推进引擎', () => {
|
||||
describe('Point 58 (P1): 潜客线索行为自动化阶段推进引擎', () => {
|
||||
let service: LeadStageAutomationService;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('多租户安全闭环: 公开留资与雷达足迹自动绑定名片
|
||||
it('公开留资未显式传入 tenantId 时,必须根据 cardId 自动追溯绑定归属名片的 tenantId 和 userId', async () => {
|
||||
const lead = await leadService.submitLead({
|
||||
cardId: 101,
|
||||
name: '海外采购商',
|
||||
name: '国际采购商',
|
||||
phone: '+971-50-9876543',
|
||||
company: 'Dubai Trading LLC',
|
||||
});
|
||||
@@ -68,7 +68,7 @@ describe('多租户安全闭环: 公开留资与雷达足迹自动绑定名片
|
||||
const lead = await leadService.submitLead({
|
||||
cardId: 101,
|
||||
tenantId: 999,
|
||||
name: '海外采购商',
|
||||
name: '国际采购商',
|
||||
phone: '+971-50-9876543',
|
||||
} as any);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
LeadWebhookPayload,
|
||||
} from '../../../src/modules/crm/service/webhook-dispatcher';
|
||||
|
||||
describe('Point 51: 出海商机实时 Webhook 触发器与 HMAC-SHA256 签名分发', () => {
|
||||
describe('Point 51: 商机实时 Webhook 触发器与 HMAC-SHA256 签名分发', () => {
|
||||
let dispatcher: LeadWebhookDispatcher;
|
||||
const mockSecret = 'whsec_8f9a2b4c6e1d7g5h3j8k9l0m';
|
||||
const mockPayload: LeadWebhookPayload = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { AdminCrmRadarController } from '../../../src/modules/crm/controller/admin/radar';
|
||||
import {
|
||||
buildWorkplaceOverview,
|
||||
calculateTrackIntentScore,
|
||||
CrmRadarService,
|
||||
} from '../../../src/modules/crm/service/radar';
|
||||
import { CrmTrackEntity } from '../../../src/modules/crm/entity/track';
|
||||
@@ -152,4 +153,97 @@ describe('商务概览工作台聚合 (getWorkplaceOverview)', () => {
|
||||
expect(res.data.kpis.viewCount).toBe(2);
|
||||
expect(controller.crmRadarService.getWorkplaceOverview).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('数据专家重构:科学意向度与会话降噪增强', () => {
|
||||
it('科学意向分算法 (calculateTrackIntentScore) 必须符合多因子阶梯模型', () => {
|
||||
// 1. 直链 0 秒跳出,无任何浏览与滚动:低意向分 (10分)
|
||||
const bounceScore = calculateTrackIntentScore({
|
||||
touchType: 'link',
|
||||
stayDurationMs: 0,
|
||||
scrollDepth: 0,
|
||||
viewedBlocks: [],
|
||||
});
|
||||
expect(bounceScore).toBe(10);
|
||||
|
||||
// 2. NFC 面对面触碰初始分:天然高权重 (35分)
|
||||
const nfcInitialScore = calculateTrackIntentScore({
|
||||
touchType: 'nfc',
|
||||
stayDurationMs: 0,
|
||||
});
|
||||
expect(nfcInitialScore).toBe(35);
|
||||
|
||||
// 3. QR 扫码 + 30秒研读 + 2个模块 + 深度滚动:高意向买家 (25 + 20 + 10 + 10 = 65分)
|
||||
const engagedScore = calculateTrackIntentScore({
|
||||
touchType: 'qr',
|
||||
stayDurationMs: 30000,
|
||||
viewedBlocks: ['hero', 'products'],
|
||||
scrollDepth: 75,
|
||||
});
|
||||
expect(engagedScore).toBe(65);
|
||||
|
||||
// 4. NFC 触碰 + 150秒深读 + 4个模块 + 深度滚动:极高意向买家 (封顶 99分)
|
||||
const hotScore = calculateTrackIntentScore({
|
||||
touchType: 'nfc',
|
||||
stayDurationMs: 150000,
|
||||
viewedBlocks: ['hero', 'products', 'cases', 'contact'],
|
||||
scrollDepth: 95,
|
||||
});
|
||||
expect(hotScore).toBe(99);
|
||||
});
|
||||
|
||||
it('buildWorkplaceOverview 应实现会话去噪与合并,并填充名片名称和本地标记', () => {
|
||||
const cardList = [
|
||||
{ id: 1, name: 'Alex Chen', title: '全球商务总监' },
|
||||
];
|
||||
|
||||
// 同一访客 vis_101 先产生了 0 秒 PV,又更新了 45 秒有效停留
|
||||
const t1 = track({
|
||||
id: 10,
|
||||
cardId: 1,
|
||||
touchType: 'link',
|
||||
country: 'Local',
|
||||
city: 'Local',
|
||||
stayDurationMs: 0,
|
||||
createTime: new Date('2026-09-21T10:00:00'),
|
||||
});
|
||||
t1.visitorId = 'vis_101';
|
||||
|
||||
const t2 = track({
|
||||
id: 11,
|
||||
cardId: 1,
|
||||
touchType: 'link',
|
||||
country: 'Local',
|
||||
city: 'Local',
|
||||
stayDurationMs: 45000,
|
||||
viewedBlocks: ['products'],
|
||||
createTime: new Date('2026-09-21T10:01:00'),
|
||||
});
|
||||
t2.visitorId = 'vis_101';
|
||||
|
||||
const result = buildWorkplaceOverview(
|
||||
[t1, t2],
|
||||
[],
|
||||
now,
|
||||
10,
|
||||
cardList
|
||||
);
|
||||
|
||||
// 验证 1:去噪合并后同一会话只保留 1 条记录
|
||||
expect(result.radarFeed).toHaveLength(1);
|
||||
const feedItem = result.radarFeed[0];
|
||||
|
||||
// 验证 2:停留时长采用合并后的最高值 45 秒
|
||||
expect(feedItem.stayDurationMs).toBe(45000);
|
||||
expect(feedItem.viewedBlocks).toContain('products');
|
||||
|
||||
// 验证 3:名片名称正确注入
|
||||
expect(feedItem.cardTitle).toBe('Alex Chen · 全球商务总监');
|
||||
|
||||
// 验证 4:识别为本地环境
|
||||
expect(feedItem.isLocal).toBe(true);
|
||||
|
||||
// 验证 5:意向分由后端自动算出并大于 0 秒跳出分
|
||||
expect(feedItem.intentScore).toBeGreaterThan(10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
在新工单中引用
屏蔽一个用户