feat: 增加全平台核心跨端数据契约与 TypeScript 类型体系

这个提交包含在:
wikiboss
2026-09-20 17:12:40 +08:00
父节点 9fa1d1fbd0
当前提交 27e053afad
共有 3 个文件被更改,包括 678 次插入 和 0 次删除

254
admin/src/types/omni.ts 普通文件
查看文件

@@ -0,0 +1,254 @@
/**
* OmniCard AI (CRMmp) - 全平台跨端核心数据契约与 TypeScript 类型体系
*
* 遵循出海 SaaS 规范、Bento Grid 便当盒美学与 RFC 6350 国际标准。
* 供 后端服务 (Cool-Admin) 与 管理后台 (Arco Pro React) 共享镜像复用。
* 严格类型安全,杜绝 any。
*/
// ==========================================
// 1. 名片与微官网契约 (Card Profile & Bento)
// ==========================================
/**
* 名片生命周期状态
*/
export type CardStatus = 'draft' | 'published' | 'archived';
/**
* CardProfile - 名片基础资料契约
*/
export interface CardProfile {
/** 名片主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 关联用户账号 ID */
userId: string | number;
/** 姓名 */
name: string;
/** 职业头衔/职位 */
title: string;
/** 所属企业/组织名称 */
company: string;
/** 个人签名 / 品牌 Slogan */
slogan?: string;
/** 头像 / 形象照 URL */
avatarUrl?: string;
/** 国际电话号码 (E.164 规范) */
phone?: string;
/** 电子邮箱 */
email?: string;
/** WhatsApp 国际直达账号/号码 */
whatsapp?: string;
/** LinkedIn 个人/企业主页链接 */
linkedin?: string;
/** 所在地时区 (如 'UTC+8', 'America/New_York') */
timezone?: string;
/** 姓名双语发音音频 URL (RFC 6350 语音扩展) */
audioPronunciationUrl?: string;
/** 名片状态 */
status: CardStatus;
/** 主题样式代码 (如 'corporate_navy', 'tech_dark', 'gold_luxe') */
themeCode?: string;
}
/**
* Bento Grid 网格块类型
*/
export type BentoBlockType = 'hero' | 'case' | 'article' | 'social' | 'video' | 'form';
/**
* Bento Grid 列跨度 (1列 / 2列满宽)
*/
export type BentoColSpan = 1 | 2;
/**
* Bento Grid 行跨度 (1行 / 2行加高)
*/
export type BentoRowSpan = 1 | 2;
/**
* BentoBlock - Bento Grid 网格块契约
*/
export interface BentoBlock {
/** 网格块主键 ID */
id: string | number;
/** 所属名片 ID */
cardId: string | number;
/** 组件类型 */
type: BentoBlockType;
/** 栅格跨列 (1 | 2) */
colSpan: BentoColSpan;
/** 栅格跨行 (1 | 2) */
rowSpan: BentoRowSpan;
/** 排序序号 (从小到大排列) */
sortOrder: number;
/** 块标题 */
title?: string;
/** 块正文 / 描述 / 嵌入内容 */
content?: string;
/** 多媒体资源 URL (图片/视频封面/音频) */
mediaUrl?: string;
/** 目标跳转外链 URL */
linkUrl?: string;
/** 扩展元数据 JSON (支持序列化字符串或键值对字典,禁止 any) */
metaJson?: string | Record<string, unknown>;
}
// ==========================================
// 2. 访客雷达与轻量级出海 CRM 契约 (Radar & Lead)
// ==========================================
/**
* 潜客线索全生命周期跟进状态
*/
export type LeadStatus = 'new' | 'contacted' | 'hot' | 'won' | 'archived';
/**
* 线索触达来源渠道
*/
export type LeadSource = 'nfc' | 'qr' | 'link' | 'ai_chat';
/**
* LeadEntity - 潜客线索关系模型契约
*/
export interface LeadEntity {
/** 线索主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 来源名片 ID */
cardId: string | number;
/** 访客唯一追踪指纹 ID */
visitorId: string;
/** 客户姓名 */
name: string;
/** 客户所属企业名称 */
company?: string;
/** 联系电话 */
phone?: string;
/** 电子邮箱 */
email?: string;
/** 跟进状态 */
status: LeadStatus;
/** 意向度评分 (0 - 100) */
intentScore: number;
/** 触达来源途径 */
source: LeadSource;
/** 跟进备忘录 / 需求备注 */
notes?: string;
}
/**
* 访客触碰/打开途径
*/
export type TouchType = 'nfc' | 'qr' | 'link';
/**
* RadarTrack - 实时访客足迹契约
*/
export interface RadarTrack {
/** 轨迹记录主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 访问的目标名片 ID */
cardId: string | number;
/** 访客唯一追踪指纹 ID */
visitorId: string;
/** 访客公网 IP 地址 */
ip: string;
/** 访客所在国家/地区 */
country: string;
/** 访客所在城市 */
city: string;
/** 触碰方式途径 */
touchType: TouchType;
/** 页面停留时长 (毫秒) */
stayDurationMs: number;
/** 页面最大滚动深度百分比 (0 - 100) */
scrollDepth: number;
/** 浏览过的 Bento 组件块标识列表 */
viewedBlocks: string[];
/** 访问时间戳 */
createdAt: string | Date;
}
// ==========================================
// 3. NFC 实体卡设备台账契约 (NFC Fleet)
// ==========================================
/**
* NFC 卡片实体物理材质
*/
export type NFCMaterial = 'wood' | 'metal' | 'pvc';
/**
* NFC 硬件设备生命周期状态
*/
export type NFCStatus = 'active' | 'suspended' | 'unbound';
/**
* NFC 场景模式
*/
export type NFCSceneMode = 'business' | 'social';
/**
* NFCRecord - NFC 实体卡设备台账契约
*/
export interface NFCRecord {
/** 台账主键 ID */
id: string | number;
/** 硬件唯一识别芯片 UID (如 '04:7A:B2:8F:1C:6D:80') */
uid: string;
/** 所属企业租户 ID */
tenantId: string | number;
/** 当前绑定的名片 ID (未绑定时为 null 或空) */
cardId?: string | number | null;
/** 硬件制造/下发批次号 */
batchNo: string;
/** 物理材质 */
material: NFCMaterial;
/** 设备状态 */
status: NFCStatus;
/** 场景模式 (如白天商务/夜晚社交) */
sceneMode: NFCSceneMode;
/** 最后一次被触碰扫描时间 */
lastScannedAt?: string | Date | null;
}
// ==========================================
// 4. 企业租户与品牌 VI 契约 (Tenant & BrandKit)
// ==========================================
/**
* 租户订阅商业版本套餐
*/
export type TenantPlanType = 'free' | 'pro' | 'enterprise';
/**
* 品牌 VI 规范套件
*/
export interface BrandKit {
/** 官方企业 Logo 图标 URL */
logoUrl: string;
/** 品牌标准主色调 (Hex 颜色代码,如 '#0B5CFF') */
primaryColor: string;
}
/**
* TenantProfile - 企业租户及品牌 VI 契约
*/
export interface TenantProfile {
/** 租户主键 ID */
id: string | number;
/** 企业/团队官方名称 */
companyName: string;
/** 商业订阅版本 */
planType: TenantPlanType;
/** 自定义独立主域名 (如 'me.brand.com') */
customDomain?: string | null;
/** 统一品牌 VI 套件 */
brandKit: BrandKit;
}

查看文件

@@ -0,0 +1,254 @@
/**
* OmniCard AI (CRMmp) - 全平台跨端核心数据契约与 TypeScript 类型体系
*
* 遵循出海 SaaS 规范、Bento Grid 便当盒美学与 RFC 6350 国际标准。
* 供 后端服务 (Cool-Admin) 与 管理后台 (Arco Pro React) 共享镜像复用。
* 严格类型安全,杜绝 any。
*/
// ==========================================
// 1. 名片与微官网契约 (Card Profile & Bento)
// ==========================================
/**
* 名片生命周期状态
*/
export type CardStatus = 'draft' | 'published' | 'archived';
/**
* CardProfile - 名片基础资料契约
*/
export interface CardProfile {
/** 名片主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 关联用户账号 ID */
userId: string | number;
/** 姓名 */
name: string;
/** 职业头衔/职位 */
title: string;
/** 所属企业/组织名称 */
company: string;
/** 个人签名 / 品牌 Slogan */
slogan?: string;
/** 头像 / 形象照 URL */
avatarUrl?: string;
/** 国际电话号码 (E.164 规范) */
phone?: string;
/** 电子邮箱 */
email?: string;
/** WhatsApp 国际直达账号/号码 */
whatsapp?: string;
/** LinkedIn 个人/企业主页链接 */
linkedin?: string;
/** 所在地时区 (如 'UTC+8', 'America/New_York') */
timezone?: string;
/** 姓名双语发音音频 URL (RFC 6350 语音扩展) */
audioPronunciationUrl?: string;
/** 名片状态 */
status: CardStatus;
/** 主题样式代码 (如 'corporate_navy', 'tech_dark', 'gold_luxe') */
themeCode?: string;
}
/**
* Bento Grid 网格块类型
*/
export type BentoBlockType = 'hero' | 'case' | 'article' | 'social' | 'video' | 'form';
/**
* Bento Grid 列跨度 (1列 / 2列满宽)
*/
export type BentoColSpan = 1 | 2;
/**
* Bento Grid 行跨度 (1行 / 2行加高)
*/
export type BentoRowSpan = 1 | 2;
/**
* BentoBlock - Bento Grid 网格块契约
*/
export interface BentoBlock {
/** 网格块主键 ID */
id: string | number;
/** 所属名片 ID */
cardId: string | number;
/** 组件类型 */
type: BentoBlockType;
/** 栅格跨列 (1 | 2) */
colSpan: BentoColSpan;
/** 栅格跨行 (1 | 2) */
rowSpan: BentoRowSpan;
/** 排序序号 (从小到大排列) */
sortOrder: number;
/** 块标题 */
title?: string;
/** 块正文 / 描述 / 嵌入内容 */
content?: string;
/** 多媒体资源 URL (图片/视频封面/音频) */
mediaUrl?: string;
/** 目标跳转外链 URL */
linkUrl?: string;
/** 扩展元数据 JSON (支持序列化字符串或键值对字典,禁止 any) */
metaJson?: string | Record<string, unknown>;
}
// ==========================================
// 2. 访客雷达与轻量级出海 CRM 契约 (Radar & Lead)
// ==========================================
/**
* 潜客线索全生命周期跟进状态
*/
export type LeadStatus = 'new' | 'contacted' | 'hot' | 'won' | 'archived';
/**
* 线索触达来源渠道
*/
export type LeadSource = 'nfc' | 'qr' | 'link' | 'ai_chat';
/**
* LeadEntity - 潜客线索关系模型契约
*/
export interface LeadEntity {
/** 线索主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 来源名片 ID */
cardId: string | number;
/** 访客唯一追踪指纹 ID */
visitorId: string;
/** 客户姓名 */
name: string;
/** 客户所属企业名称 */
company?: string;
/** 联系电话 */
phone?: string;
/** 电子邮箱 */
email?: string;
/** 跟进状态 */
status: LeadStatus;
/** 意向度评分 (0 - 100) */
intentScore: number;
/** 触达来源途径 */
source: LeadSource;
/** 跟进备忘录 / 需求备注 */
notes?: string;
}
/**
* 访客触碰/打开途径
*/
export type TouchType = 'nfc' | 'qr' | 'link';
/**
* RadarTrack - 实时访客足迹契约
*/
export interface RadarTrack {
/** 轨迹记录主键 ID */
id: string | number;
/** 所属企业租户 ID */
tenantId: string | number;
/** 访问的目标名片 ID */
cardId: string | number;
/** 访客唯一追踪指纹 ID */
visitorId: string;
/** 访客公网 IP 地址 */
ip: string;
/** 访客所在国家/地区 */
country: string;
/** 访客所在城市 */
city: string;
/** 触碰方式途径 */
touchType: TouchType;
/** 页面停留时长 (毫秒) */
stayDurationMs: number;
/** 页面最大滚动深度百分比 (0 - 100) */
scrollDepth: number;
/** 浏览过的 Bento 组件块标识列表 */
viewedBlocks: string[];
/** 访问时间戳 */
createdAt: string | Date;
}
// ==========================================
// 3. NFC 实体卡设备台账契约 (NFC Fleet)
// ==========================================
/**
* NFC 卡片实体物理材质
*/
export type NFCMaterial = 'wood' | 'metal' | 'pvc';
/**
* NFC 硬件设备生命周期状态
*/
export type NFCStatus = 'active' | 'suspended' | 'unbound';
/**
* NFC 场景模式
*/
export type NFCSceneMode = 'business' | 'social';
/**
* NFCRecord - NFC 实体卡设备台账契约
*/
export interface NFCRecord {
/** 台账主键 ID */
id: string | number;
/** 硬件唯一识别芯片 UID (如 '04:7A:B2:8F:1C:6D:80') */
uid: string;
/** 所属企业租户 ID */
tenantId: string | number;
/** 当前绑定的名片 ID (未绑定时为 null 或空) */
cardId?: string | number | null;
/** 硬件制造/下发批次号 */
batchNo: string;
/** 物理材质 */
material: NFCMaterial;
/** 设备状态 */
status: NFCStatus;
/** 场景模式 (如白天商务/夜晚社交) */
sceneMode: NFCSceneMode;
/** 最后一次被触碰扫描时间 */
lastScannedAt?: string | Date | null;
}
// ==========================================
// 4. 企业租户与品牌 VI 契约 (Tenant & BrandKit)
// ==========================================
/**
* 租户订阅商业版本套餐
*/
export type TenantPlanType = 'free' | 'pro' | 'enterprise';
/**
* 品牌 VI 规范套件
*/
export interface BrandKit {
/** 官方企业 Logo 图标 URL */
logoUrl: string;
/** 品牌标准主色调 (Hex 颜色代码,如 '#0B5CFF') */
primaryColor: string;
}
/**
* TenantProfile - 企业租户及品牌 VI 契约
*/
export interface TenantProfile {
/** 租户主键 ID */
id: string | number;
/** 企业/团队官方名称 */
companyName: string;
/** 商业订阅版本 */
planType: TenantPlanType;
/** 自定义独立主域名 (如 'me.brand.com') */
customDomain?: string | null;
/** 统一品牌 VI 套件 */
brandKit: BrandKit;
}

查看文件

@@ -0,0 +1,170 @@
import {
CardProfile,
CardStatus,
BentoBlock,
BentoBlockType,
BentoColSpan,
BentoRowSpan,
LeadEntity,
LeadStatus,
LeadSource,
RadarTrack,
TouchType,
NFCRecord,
NFCMaterial,
NFCStatus,
NFCSceneMode,
TenantProfile,
TenantPlanType,
BrandKit,
} from '../../src/comm/types/omni';
describe('OmniCard AI 核心跨端数据契约与 TypeScript 类型体系测试', () => {
it('应正确支持 CardProfile 契约及其字段与状态枚举', () => {
const cardStatus: CardStatus = 'published';
const card: CardProfile = {
id: 'card_1001',
tenantId: 'tenant_888',
userId: 'user_001',
name: 'Alex Rivera',
title: 'Global VP of Business Development',
company: 'OmniCard Global Ltd.',
slogan: 'Empowering global trade with AI',
avatarUrl: 'https://cdn.omnicard.ai/avatars/alex.jpg',
phone: '+1-555-892-0199',
email: 'alex@omnicard.ai',
whatsapp: '+15558920199',
linkedin: 'https://linkedin.com/in/alex-rivera-global',
timezone: 'UTC+8',
audioPronunciationUrl: 'https://cdn.omnicard.ai/audio/alex.mp3',
status: cardStatus,
themeCode: 'corporate_navy',
};
expect(card.id).toBe('card_1001');
expect(card.name).toBe('Alex Rivera');
expect(card.status).toBe('published');
expect(card.themeCode).toBe('corporate_navy');
});
it('应正确支持 BentoBlock 契约与尺寸、网格类型约束', () => {
const blockType: BentoBlockType = 'hero';
const colSpan: BentoColSpan = 2;
const rowSpan: BentoRowSpan = 1;
const block: BentoBlock = {
id: 101,
cardId: 1001,
type: blockType,
colSpan,
rowSpan,
sortOrder: 0,
title: 'Hero Profile',
content: 'Leading AI-driven digital identity across MENA and APAC markets.',
mediaUrl: 'https://cdn.omnicard.ai/media/hero.png',
linkUrl: 'https://omnicard.ai',
metaJson: {
accentColor: '#0B5CFF',
badge: 'Top Speaker',
},
};
expect(block.type).toBe('hero');
expect(block.colSpan).toBe(2);
expect(block.rowSpan).toBe(1);
expect(typeof block.sortOrder).toBe('number');
});
it('应正确支持 LeadEntity 潜客线索契约与意向评分、状态流转', () => {
const leadStatus: LeadStatus = 'hot';
const leadSource: LeadSource = 'nfc';
const lead: LeadEntity = {
id: 'lead_5001',
tenantId: 'tenant_888',
cardId: 'card_1001',
visitorId: 'vis_ae_9921',
name: 'Tariq Mansour',
company: 'Dubai Energy Holding',
phone: '+971-50-1234567',
email: 'tariq@dubaienergy.ae',
status: leadStatus,
intentScore: 92,
source: leadSource,
notes: 'Met at GITEX 2026. Very interested in enterprise NFC fleet and multi-tenant branding.',
};
expect(lead.status).toBe('hot');
expect(lead.intentScore).toBe(92);
expect(lead.source).toBe('nfc');
expect(lead.company).toBe('Dubai Energy Holding');
});
it('应正确支持 RadarTrack 实时访客足迹契约与时空数据追踪', () => {
const touch: TouchType = 'qr';
const now = new Date();
const track: RadarTrack = {
id: 'radar_8001',
tenantId: 'tenant_888',
cardId: 'card_1001',
visitorId: 'vis_de_4432',
ip: '194.12.88.4',
country: 'Germany',
city: 'Frankfurt',
touchType: touch,
stayDurationMs: 185000,
scrollDepth: 88,
viewedBlocks: ['hero', 'case_energy', 'article_ai_2026'],
createdAt: now,
};
expect(track.touchType).toBe('qr');
expect(track.country).toBe('Germany');
expect(track.stayDurationMs).toBeGreaterThan(0);
expect(track.viewedBlocks).toHaveLength(3);
});
it('应正确支持 NFCRecord 实体卡设备台账契约与生命周期状态', () => {
const material: NFCMaterial = 'metal';
const status: NFCStatus = 'active';
const sceneMode: NFCSceneMode = 'business';
const nfcCard: NFCRecord = {
id: 'nfc_9001',
uid: '04:7A:B2:8F:1C:6D:80',
tenantId: 'tenant_888',
cardId: 'card_1001',
batchNo: 'BATCH-2026-Q1-METAL',
material,
status,
sceneMode,
lastScannedAt: '2026-09-20T14:30:00.000Z',
};
expect(nfcCard.material).toBe('metal');
expect(nfcCard.status).toBe('active');
expect(nfcCard.sceneMode).toBe('business');
expect(nfcCard.uid).toBe('04:7A:B2:8F:1C:6D:80');
});
it('应正确支持 TenantProfile 企业租户与 BrandKit 品牌 VI 契约', () => {
const planType: TenantPlanType = 'enterprise';
const brandKit: BrandKit = {
logoUrl: 'https://cdn.omnicard.ai/brands/omnitech-logo.svg',
primaryColor: '#0B5CFF',
};
const tenant: TenantProfile = {
id: 'tenant_888',
companyName: 'OmniTech Global Inc.',
planType,
customDomain: 'vip.omnitech.com',
brandKit,
};
expect(tenant.planType).toBe('enterprise');
expect(tenant.brandKit.primaryColor).toBe('#0B5CFF');
expect(tenant.customDomain).toBe('vip.omnitech.com');
});
});