/** * OmniCard AI (CRMmp) - 用户端跨端核心数据契约与 TypeScript / UTS 类型体系 * 严格遵循 AGENTS.md 规范与全球数字名片 SaaS 契约,与 backend / admin 镜像对齐 */ export type CardStatus = 'draft' | 'published' | 'archived'; export interface CardProfile { id?: string | number; tenantId?: string | number; userId?: string | number; name: string; title?: string; company?: string; slogan?: string; avatarUrl?: string; phone?: string; email?: string; whatsapp?: string; linkedin?: string; telegram?: string; twitter?: string; wechat?: string; timezone?: string; audioPronunciationUrl?: string; audioPronounceUrl?: string; status?: CardStatus; themeCode?: string; url?: string; address?: string; city?: string; country?: string; meetingUrl?: string; [key: string]: any; } export type BentoBlockType = 'hero' | 'case' | 'article' | 'social' | 'video' | 'form' | 'appointment'; 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 MeetingInviteOptions { summary?: string; title?: string; description?: string; location?: string; startTime: Date | string | number; endTime: Date | string | number; organizerName?: string; organizerEmail?: string; } export interface CalendarInviteBundle { googleUrl: string; outlookUrl: string; icsUrl: 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; telegram?: string; twitter?: string; wechat?: string; timezone?: string; audioPronunciationUrl?: string; audioPronounceUrl?: string; themeCode?: string; status: CardStatus; bentoBlocks: BentoBlockPublic[]; brandKit?: BrandKit; meetingUrl?: string; cachedAt?: number; } export type LeadStatus = 'new' | 'contacted' | 'hot' | 'won' | 'archived'; export type LeadSource = 'nfc' | 'qr' | 'link' | 'ai_chat' | 'exchange'; export type CardContactSource = 'exchange' | 'collect' | 'scan' | 'event'; export type CardEventStatus = 'active' | 'ended'; export interface CardEvent { id?: string | number; code: string; name: string; status: CardEventStatus; } export interface CardEventMember { id?: string | number; eventId: number; userId: number; cardId: number; } export interface CardEventJoinResult { event: CardEvent; member: CardEventMember; } export interface TeamRankItem { memberId: number; memberName: string; leads: number; touches: number; score: number; rank: number; } export interface CardContact { id?: string | number; ownerUserId: number; ownerCardId?: number | null; peerCardId: number; source: CardContactSource; leadId?: number | null; peerName?: string; peerTitle?: string; peerCompany?: string; peerAvatarUrl?: string; peerSlug?: string; } 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 RadarViewedContent { key: string; title?: string; } 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[]; viewedContents?: RadarViewedContent[]; visitorName?: string; visitorCompany?: string; avatarUrl?: string; cardTitle?: string; createdAt?: string | Date; createTime?: string | Date; } export interface RadarHotInbox { unread: number; list: RadarTrack[]; } 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; } export type NFCMaterial = 'wood' | 'metal' | 'pvc'; export type NFCStatus = 'active' | 'suspended' | 'unbound'; export type NFCSceneMode = 'business' | 'social'; export interface NFCRecord { id: string | number; uid: string; tenantId: string | number; cardId?: string | number | null; batchNo: string; material: NFCMaterial; status: NFCStatus; sceneMode: NFCSceneMode; lastScannedAt?: string | Date | null; } export interface NfcBindParams { uid: string; cardId: number; } export interface NfcUidParams { uid: string; } export interface OwnerPageQuery { page: number; size: number; keyWord?: string; status?: LeadStatus; cardId?: string | number; visitorId?: string; } export interface QuotaCheckResult { used: number; limit: number; remaining: number; percentage: number; warning: boolean; exceeded: boolean; plan?: string; } export type OwnerPagePagination = { page: number; size: number; total: number; }; export interface OwnerPageData { list: T[]; pagination: OwnerPagePagination; } export type AiChatRole = 'user' | 'assistant' | 'system'; export type ChatMessageType = 'text' | 'lead_card'; export interface ChatLeadPayload { title: string; description: string; name: string; contact: string; submitted: boolean; submitting?: boolean; successMessage?: string; errorMessage?: string; } export interface ChatMessage { role: AiChatRole; content: string; type?: ChatMessageType; cardPayload?: ChatLeadPayload; } export interface AiChatMessage { role: AiChatRole; content: string; type?: ChatMessageType; cardPayload?: ChatLeadPayload; } export interface AiChatRequest { cardId: string | number; locale?: string; messages: AiChatMessage[]; } export interface AiChatReply { reply: string; locale: string; shouldCollectLead: boolean; } export interface CardCase { id?: string | number; tenantId?: string | number; cardId: string | number; title: string; client?: string; duration?: string; metrics?: string; coverImage?: string; pdfUrl?: string; description?: string; metaJson?: string; sortOrder?: number; createTime?: string | Date; updateTime?: string | Date; } export interface CardArticle { id?: string | number; cardId: string | number; title: string; summary?: string; content: string; coverImage?: string; isPublished: boolean; ogMeta?: Record; createTime?: Date | string; updateTime?: Date | string; } export interface WorkplaceKpi { tapCount: number; viewCount: number; newLeadCount: number; conversionRate: number; tapDelta: number; viewDelta: number; newLeadDelta: number; } export interface WorkplaceRadarItem { id: number | string; cardId: number | string; cardTitle?: string; visitorId?: string; country: string; city: string; touchType: TouchType; stayDurationMs: number; viewedBlocks: string[]; intentScore?: number; isLocal?: boolean; createTime: Date | string; } export interface WorkplaceOverviewResult { kpis: WorkplaceKpi; radarFeed: WorkplaceRadarItem[]; }