Contacts 字段设计
目的:对照 Contacts UI 设计和数据指标需求,逐字段分析数据来源,确定
PhoneBook表
字段放置原则: PhoneBook 表的定位是客户级别的判定和标记,尽量不重复存储其他表已有的数据。
通话数据 → 查 call-analysis Lead 数据 → 查 LeadTracking-v2 SMS 数据 → 查 MessageStore / Conversations 客户级别的聚合判定(温度、意图、分类、分配、标签) → 存 PhoneBook
分析范围说明:本次改版已对生命周期的 Lead 阶段进行了全面的数据源分析和字段设计。Member 和 Churned 阶段暂未进行详细分析(见 1.3、1.4 标注),因此文档中涉及这两个阶段的字段多为预留或待定状态,后续迭代再细化。
一、Contacts 信息分析
1.1 通用信息(所有 Stage 共用)
1.2 Lead 专属信息(仅 stage = Lead 时适用)
1.3 Member 专属信息(仅 stage = Member 时适用)
⏳ 本次改版暂不涉及 Member 阶段,以下内容仅作规划参考,不纳入当前分析和实现范围。
⚠️ 合同信息、使用行为、客户价值、附加消费、体测进展依赖会员管理 / 排课签到 / 交易系统,V1 暂无数据源。
1.4 Churned 专属信息(仅 stage = Churned 时适用)
⏳ 本次改版暂不涉及 Churned 阶段,以下内容仅作规划参考,不纳入当前分析和实现范围。
二、Contacts 字段数据分析和设计
2.1 身份信息
对应 1.1 身份信息:姓名、电话、邮箱、性别、地址、工作、生日/年龄、作息模式
⚠️ 第 4-8 项在 V1 中暂无数据源,PhoneBook 表预留字段位置。未来可能的写入方式:AI 从通话内容中提取、员工手动录入、或对接第三方 CRM/表单系统。
2.2 生命周期
对应 1.1 生命周期:stage 生命阶段、state 活跃状态 详细定义见 客户生命周期管理
现有数据源分析:
数据库中有两个近似字段,但都不直接等同于"生命阶段(lifecycleStage)":
- LeadTracking-v2
leadType(值:Web Lead、Online Intro等)— 这是 Lead 的来源渠道,描述客户从哪个入口进来,不是生命阶段。归入后续运营信息分析。- call-analysis
customer_type(值:prospective_client/existing_member/other)— 这是 AI 对单通电话的判定,表示本次通话中对方是潜在客户还是现有会员。它是单次通话粒度的,不是客户级别的状态。lifecycleStage 判定逻辑:
员工可手动覆盖系统判定。
lifecycleState 判定逻辑:
Lead 阶段的 State 可从
leadStatus推导;Member 和 Churned 阶段的 State 判定逻辑在生命周期管理文档中已有清晰定义,待对应数据源接入后即可实现。Stage × State 的完整组合和流转路径见 客户生命周期管理 §2.4。
2.3 运营信息
对应 1.1 运营信息:分配给谁、员工备注、自定义标签、doNotContact (DNC)
说明:运营信息全部为员工操作产生的数据,当前数据库中没有现成数据源,均为 PhoneBook 新字段。
为什么叫 Owner:沿用 CRM 行业惯例(Salesforce 叫
OwnerId,HubSpot 叫Contact Owner)。Owner 不绑定具体角色——Lead 阶段的 Owner 可能是 BDR,Member 阶段可能是客户经理,Churned 阶段可能是留存专员,通用性更好。当前owner存储员工姓名(String),暂无独立的 Owner 表。未来如果做任务分配功能,可能会建立独立的 Owner 表存储员工详细信息(姓名、角色、门店归属等),届时可改为ownerId作为外键关联。call-analysis 中有staff_name字段(接听员工姓名),但这是单通电话的接听人,不等同于 Owner——owner是客户级别的责任归属,由管理层分配。
2.4 活动数据
对应 1.1 活动数据:来源渠道、获取日期、首次尝试联系时间、首次触达时间、通话次数、短信次数、最后活动时间
说明:除来源渠道外,其余字段均有现成数据源,但源数据分散在多个表且粒度为单条记录。PhoneBook 存储的是客户级别的聚合值(如 callCount 是总次数,lastActivityAt 是最新时间),由各数据管道在写入源表时同步更新 PhoneBook。
关于 LeadTracking-v2
leadType:该字段值为Web Lead、Online Intro,描述的是 Lead 表单的提交类型(网页留资 vs 线上预约体验课),不是来源渠道。真正的来源渠道(Facebook / Instagram / Google / Walk-in / 转介绍等)需要对接广告平台或 CRM 系统,当前 LeadTracking-v2 中没有存储。leadType已在 2.2 生命周期中分析过,不属于活动数据。关于 LeadTracking-v2
receivedAt:当前数据库中同一号码存在多条记录(未去重),receivedAt记录的可能是最近一次提交时间,这是不对的。Lead 入库管道首先应去重,重复提交的数据不再存入,这样receivedAt才是真正的首次获取时间。为什么 PhoneBook 叫
acquiredAt而不是receivedAt:LeadTracking-v2 的字段叫receivedAt(收到 Lead 表单),但 PhoneBook 改名为acquiredAt,原因:"acquired" 更通用——walk-in、主动来电等 non-Lead 路径客户不是 "received" 来的.为什么 PhoneBook 要保留自己的时间字段:活动数据中的 4 个时间字段(
acquiredAt、firstAttemptedAt、firstConnectedAt、lastActivityAt)在 LeadTracking-v2 和 PhoneBook 中都存储。原因有二:
- 非 Lead 路径客户没有 LeadTracking-v2 记录:walk-in、主动来电、转介绍等场景下客户直接进入系统,不经过 Lead 提交流程。这类客户的时间数据无法从 LeadTracking-v2 获取,只能由 PhoneBook 自身记录。
- PhoneBook 是客户级别的统一视图:即使是 Lead 路径客户,PhoneBook 也需要自己的时间字段来支撑列表排序、筛选、温度衰减等功能,避免每次都跨表查询 LeadTracking-v2。
2.5 联系偏好
对应 1.1 联系偏好:联系响应模式、最佳联系时段、偏好联系渠道
数据源分析:
三个字段当前都没有直接数据源。原始信号分散在 call-analysis(接通率、通话时段、call_state)和 MessageStore(回复率、回复时段)中,需要跨多条记录聚合分析才能得出结论。
写入方式:Layer 2 Daily Batch AI 写入(与
aiSummary、actionNeeded、suggestedActions同一管道)。员工可手动覆盖。
2.6 健身画像
对应 1.1 健身画像:核心需求、感兴趣的课程类型、偏好时段、健身经验(含过往经历)、当前运动习惯、关注点
数据源分析:
七个字段当前都没有直接数据源。但 call-analysis 的
executive_summary中已经包含健身相关信号(如 "tread 50 class"、"first class experience"、"membership pricing"),只是以自然语言形式散落在摘要中,未被结构化提取。写入方式:Layer 2 Daily Batch AI 写入。AI 从该客户所有通话的 transcript + executive_summary + SMS 内容中提取健身画像信息,结构化后写入 PhoneBook。员工可手动补充或覆盖。
2.7 通讯记录
对应 1.1 通讯记录:SMS 内容、通话录音(音频回放)、逐句对话记录(Conversation Data,分 Speaker + 时间戳)、语音信箱、系统备注
⚠️ 与 2.1–2.6 不同:通讯记录是原始事件流,不存入 PhoneBook。通过统一的
ActivityLog索引表按时间倒序渲染为 Communication Timeline。
数据源概览
ActivityLog — 统一 Timeline 索引表 已废弃
::: warning 架构决策 (2026-03-09):不再建独立 ActivityLog DynamoDB 表
结论:计划将 call-analysis、MessageStore、LeadTracking-v2 全量迁移到 Neon PostgreSQL 后,用 UNION ALL VIEW 替代 ActivityLog。
原因:ActivityLog 的唯一动机是 DynamoDB 无法跨表查询。PostgreSQL 原生支持 UNION ALL + ORDER BY + LIMIT,三张表的时间线在数据库层合并,无需预建索引表。
替代方案:在 Neon 中创建 contact_timeline VIEW(calls UNION ALL sms_messages UNION ALL leads),每张表加 (phone, created_at DESC) 索引。预期延迟 <50ms。
参考:GitLab 在 PostgreSQL 上明确禁止 polymorphic events 表,采用分表 + UNION ALL;HubSpot 用分表 JOIN 而非独立 timeline 表。
::: 以下为原始设计(保留供参考,不实施)。
原设计背景:通讯记录分散在多个源表(call-analysis、MessageStore、系统操作),如果 Timeline UI 每次加载都要查多张表再合并排序,查询复杂且性能差。ActivityLog 作为预建索引,让 UI 只查一张表就能拿到所有事件的时间线。
原设计工作方式:各数据管道在写入源表的同时,同步写入一条轻量索引记录到 ActivityLog。每条记录只存展示摘要 + 源表引用键,不重复存储完整数据。
表设计:
metadata 示例:
写入方式:
查询方式:Timeline UI 查询 ActivityLog(PK=phone,SK 倒序),一次查询拿到所有事件。用户点击某条记录展开详情时,根据 ref 去源表(call-analysis / MessageStore)加载完整数据(录音、转录、完整短信等)。
系统备注(System Note,待建)
人工或系统触发的操作事件,在 Timeline 中穿插显示,帮助员工了解客户旅程的关键节点。不包含 AI 通话分析推导出的信息(那些属于 2.8/2.9)。
CRM 对接后扩展(当前无数据源,未来接入 CRM 系统后可增加):
说明:系统备注直接以
type=system写入 ActivityLog,不需要独立的源表——ActivityLog 本身就是系统备注的存储位置。各业务管道在执行操作时(Lead 入库、员工改 Owner/DNC/Tag/Stage、CRM 回调等)同步写入一条type=system记录。
2.8 AI 通话分析(Per-Call)
对应 1.1 AI通话分析:通话摘要(AI 摘要、follow_up_needed、follow_up_reasons)· 关键信息(主分类、子分类、次要话题、通话结果分类、是否获取信用卡、营收优先级)· 通话详情(接听结果、通话方向、通话时长等)
⚠️ 与 2.7 一样,不存入 PhoneBook。这些是 call-analysis 表中每通电话的 AI 分析字段,存储在 call-analysis DynamoDB + S3。用户在 Timeline(ActivityLog)中点击某通电话,通过
ref(telephonySessionId)查询 call-analysis 获取完整分析数据并展示。
2.9 AI 跨通话分析(Cross-Call)
对应 1.1 AI跨通话分析:客户摘要(customerSummary)、是否需要跟进(actionNeeded,跨通话综合判断)、建议动作、建议截止时间、建议优先级
⚠️ 与 2.7/2.8 不同:2.9 字段存入 PhoneBook。这是 Layer 2(Daily Batch)读取该客户所有通话的 2.8 分析数据后,跨通话聚合生成的客户级别判断。
数据源分析:
四个字段当前都没有数据源,均为 PhoneBook 新字段。
写入方式:Layer 2 Daily Batch AI 写入。每日批量读取该客户在 call-analysis 中的所有通话记录(2.8 字段)+ MessageStore 中的 SMS 记录,综合分析后写入 PhoneBook。员工可手动覆盖。
与 2.5/2.6 的关系:2.5(联系偏好)、2.6(健身画像)也是 Layer 2 写入的 PhoneBook 字段,但它们提取的是具体的结构化数据(偏好时段、健身目标等)。2.9 产出的是高层判断:这个客户整体情况如何(
customerSummary)、是否需要行动(actionNeeded)、具体做什么(suggestedActions,每个 action 内含 priority)、最晚什么时候做(suggestedFollowUpBy)。
2.10 Lead 跟进(Lead 专属)
对应 1.2 Lead 跟进:leadStatus、temperature
⚠️ 仅在
lifecycleStage = Lead时适用,同时存入 PhoneBook + LeadTracking-v2。
写入方式:
关于
Duplicate和Invalid Number:不属于leadStatus——它们是数据质量判定,与跟进状态是两个独立维度。应在 LeadTracking-v2 中以独立字段标记(如isDuplicate、isValidNumber),不写入 PhoneBook,用于计算有效率等指标。
2.11 Lead 分析(Lead 专属)
对应 1.2 Lead 分析:意向等级、提交次数
⚠️ 仅在
lifecycleStage = Lead时适用,同时存入 PhoneBook + LeadTracking-v2。
写入方式:
关于
submissionCount:LeadTracking-v2 中没有现成的提交次数字段,但同一手机号确实存在多条记录(5,078 条记录中有 678 个手机号重复提交,最多达 11 次)。Lead 入库管道在写入时统计同一 phone 的记录数,写入 LeadTracking-v2,同步更新 PhoneBook。
2.12 消费决策(Lead 专属)
对应 1.2 消费决策:预算区间、价格敏感度、决策风格、决策周期
⚠️ 仅在
lifecycleStage = Lead时适用,同时存入 PhoneBook + LeadTracking-v2。
写入方式:Layer 2 Daily Batch AI 写入。AI 从通话 transcript + SMS 中提取消费决策信号,结构化后写入 PhoneBook。员工可手动补充或覆盖。
2.13 决策障碍(Lead 专属)
对应 1.2 决策障碍:objections
⚠️ 仅在
lifecycleStage = Lead时适用,同时存入 PhoneBook + LeadTracking-v2。
写入方式:员工手动输入 或 AI 从通话中自动提取。
2.14 条件性拒绝原因(Lead 专属)
对应 1.2 条件性拒绝:rejectionReasons
⚠️ 仅在
lifecycleStage = Lead时适用,同时存入 PhoneBook + LeadTracking-v2。
写入方式:AI 从通话中识别明确拒绝信号后写入,员工确认或手动标记。
objectionsvsrejectionReasons的区别:
objections:客户还在犹豫,有挽回空间("太贵了" → 可以介绍优惠方案)rejectionReasons:客户已明确拒绝,挽回可能性低("太远了" → 无法改变地理位置)
rejectionReasons仅在leadStatus = bad_timing时适用——客户因具体条件拒绝(太远、时间冲突、已有会籍等),条件可能变化。not_interested是无条件拒绝,不记录具体原因。
三、PhoneBook 最终表设计
主表 (PhoneBook-{env})
跳过 2.7(通讯记录)和 2.8(AI 通话分析)——它们不存入 PhoneBook,通过 ActivityLog 索引表查询。email 不存入 PhoneBook,查询时从 LeadTracking-v2 读取;邮箱反查客户使用辅助表
PhoneBook-EmailMapping。
共 47 个字段(系统 3 + 身份 7 + 生命周期 2 + 运营 4 + 活动 7 + 联系偏好 3 + 健身画像 7 + AI 跨通话 4 + Lead 跟进 2 + Lead 分析 2 + 消费决策 4 + 决策障碍 1 + 条件性拒绝 1)
GSI 索引
共 5 个 GSI
辅助表
独立表(非 PhoneBook 字段,但 Contacts 页面依赖)
四、不存入 PhoneBook 的展示数据
以下数据在 Contacts 页面中展示,但不存入 PhoneBook 表,由 API 从其他表实时获取:
五、写入管道
管道设计原则:
- 写入轻量化:管道 1-3 只写计数器和时间戳(原子
ADD+SET),单次写入成本极低 - 数据一致性:PhoneBook 不冗余存储明细数据(call 详情、SMS 内容),避免与源表不一致
- AI 管道集中:Layer 2 一次性写入所有 AI 提取字段(联系偏好 + 健身画像 + 跨通话分析 + Lead 分析 + 消费决策 + 决策障碍/拒绝),减少写入次数
- 双写同步:Lead 专属字段(2.10–2.14)同时写入 PhoneBook + LeadTracking-v2,保证两张表数据一致
六、Contacts 页面结构
Contacts 页面由三个核心区域组成,通过两种视图模式切换布局:
6.1 三大区域
6.2 两种视图模式
- 列表模式:左侧为名单表格(主区域),右侧侧边栏上下排列用户详情和通讯记录
- 详情模式:左侧为用户详情面板(完整展示),右侧为通讯记录(全屏展开),名单列表隐藏
6.3 通讯记录 Communication Log 详细结构
按日期分组的时间线,每条事件根据类型有不同的展示样式:
6.3.1 事件类型
通讯记录卡片左右位置规则:
- 左侧:客户发起的信息(客户来电、客户发送的SMS、 客户的Voicemail)
- 右侧:系统/门店发起的信息(门店外呼、门店发送的SMS、门店的Voicemail、System Note)
6.3.2 通话卡片(Call Card)
通话卡片默认展示以下信息:
6.3.3 通话展开详情(Hide/Show Details)
点击通话卡片的展开按钮后,按 AI 分析结论 → 通话元数据 → 原始对话 的顺序展示:
1. Key Information(AI 分析结论)
2. Call Details(通话元数据)
3. Transcript(原始对话)
Conversation Data:逐句对话记录,分 Speaker 标注 + 时间戳,Speaker 1(系统/客户)和 Speaker 2(员工)交替展示
6.4 信息展示分布
基于「一、客户信息分析」的分类,将每类信息分配到三个区域:
设计逻辑:
- 名单列表:只放可排序/可筛选的客户级别关键列,用于快速扫描和批量操作
- 用户详情:完整的客户画像,是名单列表的超集;列表模式下摘要展示,详情模式下完全展开
- 通讯记录:按日期分组的时间线,展示四种事件类型(System Note / SMS / Call / Voicemail);点击通话卡片弹出详情弹窗