/** * OmniCard AI (CRMmp) - 用户端跨端核心数据契约与 TypeScript / UTS 类型体系 * 严格遵循 AGENTS.md 规范与出海 SaaS 契约,与 backend / admin 镜像对齐 */ export type CardStatus = 'draft' | 'published' | 'archived'; export type BentoBlockType = 'hero' | 'case' | 'article' | 'social' | 'video' | 'form'; export type BentoColSpan = 1 | 2; export type BentoRowSpan = 1 | 2; export interface BentoBlockPublic { id: number | string; cardId: number | string; type: BentoBlockType; colSpan: BentoColSpan; rowSpan: BentoRowSpan; sortOrder: number; title?: string; content?: string; mediaUrl?: string; linkUrl?: string; metaJson?: string | Record; } export interface BrandKit { logoUrl: string; primaryColor: string; } export interface CardPortalDetail { id: number | string; slug?: string; name: string; title: string; company: string; slogan?: string; avatarUrl?: string; phone?: string; email?: string; whatsapp?: string; linkedin?: string; timezone?: string; audioPronunciationUrl?: string; themeCode?: string; status: CardStatus; bentoBlocks: BentoBlockPublic[]; brandKit?: BrandKit; cachedAt?: number; } export type LeadStatus = 'new' | 'contacted' | 'hot' | 'won' | 'archived'; export type LeadSource = 'nfc' | 'qr' | 'link' | 'ai_chat'; export interface LeadEntity { id: string | number; tenantId?: string | number; cardId: string | number; visitorId?: string; name: string; company?: string; phone?: string; email?: string; status: LeadStatus; intentScore: number; source: LeadSource; notes?: string; } export interface SubmitLeadParams { cardId: string | number; name: string; company?: string; phone?: string; email?: string; source?: string; notes?: string; visitorId?: string; [key: string]: any; } export type TouchType = 'nfc' | 'qr' | 'link'; export interface RadarTrack { id: string | number; tenantId?: string | number; cardId: string | number; visitorId: string; ip?: string; country?: string; city?: string; touchType: TouchType; stayDurationMs: number; scrollDepth: number; viewedBlocks: string[]; createdAt?: string | Date; } export interface RecordRadarTrackParams { cardId: string | number; visitorId: string; touchType?: string; stayDurationMs?: number; scrollDepth?: number; viewedBlocks?: string[]; ip?: string; country?: string; city?: string; [key: string]: any; } export interface ApiResponse { code: number; message: string; data: T; }