/** * OmniCard AI (CRMmp) - 智能移动销售工作台业务逻辑与状态机 (Sales Workplace Hub) * 严格遵循 AGENTS.md 规范与 uts 强类型设计 */ import { CardProfile, LeadEntity, WorkplaceKpi, WorkplaceOverviewResult, WorkplaceRadarItem, } from '../../../common/types.uts'; import { fetchCardQrcodeSvg, fetchOwnerCardPage, fetchOwnerLeadPage, fetchWorkplaceOverview, } from '../../../common/api.uts'; import { getCurrentLocale } from '../../../common/locale.uts'; export interface WorkplaceState { loading: boolean; errorMessage: string; activeCard: CardProfile | null; cardList: CardProfile[]; activeQrSvg: string; activeShareUrl: string; kpis: WorkplaceKpi; hotRadarItem: WorkplaceRadarItem | null; recentLeads: LeadEntity[]; radarOnline: boolean; } export function createWorkplaceState(): WorkplaceState { return { loading: true, errorMessage: '', activeCard: null, cardList: [], activeQrSvg: '', activeShareUrl: '', kpis: { tapCount: 0, viewCount: 0, newLeadCount: 0, conversionRate: 0, tapDelta: 0, viewDelta: 0, newLeadDelta: 0, }, hotRadarItem: null, recentLeads: [], radarOnline: true, }; } export async function loadWorkplaceData(state: WorkplaceState): Promise { state.loading = true; state.errorMessage = ''; try { // 1. 并行获取工作台概览、名片列表、最新待跟进线索 const overviewPromise = fetchWorkplaceOverview(5).then((data: WorkplaceOverviewResult) => { state.radarOnline = true; return data; }).catch(() => { state.radarOnline = false; const emptyKpi: WorkplaceKpi = { tapCount: 0, viewCount: 0, newLeadCount: 0, conversionRate: 0, tapDelta: 0, viewDelta: 0, newLeadDelta: 0, }; const emptyResult: WorkplaceOverviewResult = { kpis: emptyKpi, radarFeed: [], }; return emptyResult; }); const cardsPromise = fetchOwnerCardPage({ page: 1, size: 10 }).catch(() => null); const leadsPromise = fetchOwnerLeadPage({ page: 1, size: 3 }).catch(() => null); const [overview, cardPage, leadPage] = await Promise.all([ overviewPromise, cardsPromise, leadsPromise, ]); // 2. 赋值 KPI 与雷达高光 if (overview != null && overview.kpis != null) { state.kpis = overview.kpis; } state.hotRadarItem = null; if (overview != null && overview.radarFeed != null && overview.radarFeed.length > 0) { state.hotRadarItem = overview.radarFeed[0]; } if (leadPage != null && leadPage.list != null) { state.recentLeads = leadPage.list; } else { state.recentLeads = []; } if (cardPage != null && cardPage.list != null && cardPage.list.length > 0) { state.cardList = cardPage.list; const published = cardPage.list.find((c: CardProfile) => c.status === 'published'); state.activeCard = published != null ? published : cardPage.list[0]; } else { state.activeCard = null; state.cardList = []; state.activeQrSvg = ''; state.activeShareUrl = ''; } if (state.activeCard != null) { state.activeQrSvg = ''; state.activeShareUrl = ''; try { const slugOrId = state.activeCard!.slug || String(state.activeCard!.id); const qrRes = await fetchCardQrcodeSvg(slugOrId); if (qrRes != null && qrRes.svg != null && qrRes.svg !== '') { state.activeQrSvg = qrRes.svg; } else { state.activeQrSvg = ''; } if (qrRes != null && qrRes.url != null && qrRes.url !== '') { state.activeShareUrl = qrRes.url; } else if (state.activeCard!.url != null && state.activeCard!.url !== '') { state.activeShareUrl = state.activeCard!.url!; } } catch (_e) { state.activeQrSvg = ''; state.activeShareUrl = ''; } } else { state.activeQrSvg = ''; state.activeShareUrl = ''; } if (state.activeCard == null && state.recentLeads.length === 0 && state.radarOnline === false) { state.errorMessage = resolveWorkplaceText('workplace.load_error'); } } catch (_err) { state.errorMessage = resolveWorkplaceText('workplace.load_error'); state.activeQrSvg = ''; state.activeShareUrl = ''; } finally { state.loading = false; } } export function buildPortalPreviewUrl(card: CardProfile): string { if (card.slug != null && card.slug !== '') { return `/pages/portal/index?slug=${card.slug}&mode=owner`; } if (card.id != null) { return `/pages/portal/index?id=${card.id}&mode=owner`; } return '/pages/portal/index?mode=owner'; } export function openCardPreview(card: CardProfile): void { uni.navigateTo({ url: buildPortalPreviewUrl(card), }); } export function openCardQrcode(card: CardProfile): void { const targetId = card.slug || String(card.id || ''); uni.navigateTo({ url: `/pages/owner/card/qrcode?id=${targetId}`, }); } export function openLeadDetail(leadId: string | number): void { uni.navigateTo({ url: `/pages/owner/leads-detail?id=${leadId}`, }); } export function openRadarPage(): void { uni.switchTab({ url: '/pages/owner/radar', }); } export function openCardsPage(): void { uni.switchTab({ url: '/pages/owner/card/index', }); } export function openLeadsPage(): void { uni.switchTab({ url: '/pages/owner/leads', }); } export function resolveWorkplaceText(key: string, locale?: string): string { const targetLocale = locale != null ? locale : getCurrentLocale(); const isZh = targetLocale.startsWith('zh'); const dict: Record> = { 'workplace.title': { zh: '销售工作台', en: 'Sales Workplace', }, 'workplace.greeting': { zh: '今日业务概况与线索跟进', en: 'Today business overview & lead follow-up', }, 'workplace.radar_active': { zh: '雷达在线监测中', en: 'Radar Live Active', }, 'workplace.quick_showcase': { zh: '出示名片', en: 'Show Card', }, 'workplace.view_portal': { zh: '预览微官网', en: 'View Micro-Site', }, 'workplace.copy_link': { zh: '复制直链', en: 'Copy Link', }, 'workplace.link_copied': { zh: '名片直链已复制', en: 'Card link copied to clipboard', }, 'workplace.nfc_active': { zh: 'NFC 展会模式就绪', en: 'NFC Business Mode Ready', }, 'workplace.kpi_title': { zh: '今日数据', en: 'Today KPIs', }, 'workplace.kpi_taps': { zh: '触碰/扫码', en: 'Taps & Scans', }, 'workplace.kpi_visitors': { zh: '官网访客数', en: 'Visitors', }, 'workplace.kpi_leads': { zh: '新增线索', en: 'New Leads', }, 'workplace.kpi_conversion': { zh: '意向转化率', en: 'Intent Rate', }, 'workplace.radar_pulse_title': { zh: '实时访客', en: 'Live Visitors', }, 'workplace.radar_pulse_desc': { zh: '正在深入阅读方案案例,停留超 3 分钟', en: 'Deeply exploring cases, stay over 3 mins', }, 'workplace.radar_action_whatsapp': { zh: '立即联系', en: 'Contact Now', }, 'workplace.leads_todo_title': { zh: '今日待办商机', en: 'Actionable Leads', }, 'workplace.leads_view_all': { zh: '查看全部', en: 'View All', }, 'workplace.ai_tip_title': { zh: '跟进建议', en: 'Follow-up Suggestion', }, 'workplace.ai_tip_desc': { zh: '近期重点客户对解决方案案例关注度上升,建议及时跟进。', en: 'Prospect engagement on solution cases is rising. Follow-up recommended.', }, 'workplace.primary_cta': { zh: '出示名片码', en: 'Show Card QR', }, 'workplace.qr_empty': { zh: '暂无二维码', en: 'QR code unavailable', }, 'workplace.empty_card': { zh: '还没有名片', en: 'No card yet', }, 'workplace.empty_leads': { zh: '今天还没有要跟进的线索', en: 'No leads to follow up', }, 'workplace.empty_radar': { zh: '还没有新的访客', en: 'No new visitors', }, 'workplace.switch_card': { zh: '切换', en: 'Switch', }, 'workplace.published': { zh: '已发布', en: 'Published', }, 'workplace.load_error': { zh: '工作台暂时没加载出来', en: 'Workplace could not be loaded', }, 'workplace.score': { zh: '意向', en: 'Intent', }, }; const item = dict[key]; if (item != null) { return isZh ? item.zh : item.en; } return key; }