本文引用的文件
通话模块 call 是调查数据模型中的基础通信维度,负责存储和查询与电话、号码相关的调查实体。它主要覆盖以下五类数据:
| 实体 | 说明 | 典型用途 |
|---|---|---|
| 通话记录 | 一次主叫或被叫的通话明细 | 查某人通话、查双方关系、时间分布 |
| 夜间通话 | 在设定夜间时段内的通话统计 | 发现异常作息、隐蔽联络 |
| 连续通话 | 按月份判断两人是否持续保持联系 | 识别长期稳定关系 |
| 敏感通话 | 高频或重点对象的通话预警 | 敏感对象预警、关系热点 |
| 开放信息 | 号码开户、归属地、入网销户等元数据 | 补全号码身份、校验活跃状态 |
该模块与人员 person 的关系非常直接:通话记录的“本方”通常对应案件中的目标人员,而“对方”可能是同案人、联系人、涉案号码或其他无关号码。通过本方与对方的姓名、证件号、电话号码,可以把通话记录与人、交易、轨迹、治理树串联起来,形成“谁在什么时间、以什么方式、和谁发生了多少次关联”的调查证据链。
通话模块在后端 Java 项目中采用典型的分层结构:
graph TB
subgraph "控制器层"
C1["CallRecordController"]
C2["CallNightController"]
C3["CallContinuousController"]
C4["CallSensitiveController"]
end
subgraph "服务层"
S1["CallRecordService"]
S2["CallNightService"]
S3["CallContinuousService"]
S4["CallSensitiveService"]
S5["CallOpenInfoService"]
end
subgraph "映射层"
M1["CallRecordMapper"]
M2["CallNightMapper"]
M3["CallContinuousMapper"]
M4["CallSensitiveMapper"]
M5["CallOpenInfoMapper"]
M6["UseOpenInfoCallRecordMapper"]
M7["CallRecordAllMapper"]
end
subgraph "公共模型"
E1["CallRecord"]
E2["CallRecordAll"]
E3["UseOpenInfoCallRecord"]
E4["CallOpenInfo"]
Q1["CallRecordQuery"]
Q2["CallNightQuery"]
Q3["CallContinuousQuery"]
Q4["CallSensitiveQuery"]
D1["CallNightDTO"]
D2["CallContinuousDTO"]
D3["CallSensitiveDTO"]
end
subgraph "数据库表"
T1["call_record"]
T2["call_record_all"]
T3["use_open_info_call_record"]
T4["call_opening_info"]
end
C1 --> S1
C2 --> S2
C3 --> S3
C4 --> S4
S1 --> M1
S2 --> M2
S3 --> M3
S4 --> M4
S5 --> M5
M1 --> T1
M2 --> T1
M3 --> T1
M4 --> T1
M5 --> T4
M6 --> T3
M7 --> T2
图示来源
从现有代码可见,通话模块包含:
| 层次 | 职责 |
|---|---|
| 控制器 | 暴露 HTTP 接口,如通话记录分页查询、夜间通话、连续通话、敏感通话、开放信息等 |
| 服务 | 封装通话分析逻辑,包括时间范围过滤、号码匹配、去重、分页、聚合统计 |
| 映射器 | 对接 MyBatis,访问底层数据库表 |
| 公共模型 | 定义通话实体、查询参数、分析结果 DTO |
| 数据库 | 定义通话明细、合并记录、使用方通话记录、号码开户信息 |
此外,通话模块还作为 AI Agent 工具的数据源之一。CallAnalysisTool 通过注入 CallRecordService 等组件,对外暴露获取通话记录、夜间通话、连续通话、敏感通话等工具能力,供智能分析流程调用。
章节来源
CallRecord 映射到 call_record 表,表示一条原始通话记录。关键字段可归纳为四类:
| 字段类别 | 字段示例 | 含义 |
|---|---|---|
| 本方身份 | personName、personPhone、personCertNo |
本方姓名、手机号、证件号 |
| 位置信息 | personRegionId、personCellId、personStationName、经度、纬度 |
本方基站大区、小区、名称和坐标 |
| 通话事实 | callDateTime、callDate、callTime、duration、callDirection、callType |
通话时间、时长、主被叫、通话类型 |
| 对方身份 | otherName、otherPhone、otherPhoneArea、otherCertNo |
对方姓名、手机号、归属地、证件号 |
CallRecord 继承自通用清洗基类,并支持序列化;同时提供字符串化方法,用于日志或导出时拼接关键字段。
章节来源
| 实体 | 表名 | 主要用途 |
|---|---|---|
CallRecordAll |
call_record_all |
汇总或合并后的通话记录,字段口径与 CallRecord 基本一致 |
UseOpenInfoCallRecord |
use_open_info_call_record |
与开放信息关联的通话记录视图或中间表 |
CallOpenInfo |
call_opening_info |
号码开户信息,含运营商、归属省、市、入网销户时间、首次通话时间等 |
其中,CallOpenInfo 更偏向号码维度的静态档案,而通话记录更偏向行为维度。两者可通过 personPhone 关联,用于判断号码是否有效、是否已销户、归属地是否与通话归属地一致等。
章节来源
erDiagram
CALL_RECORD {
bigint id PK
bigint fileId
bigint sheetId
varchar personName
varchar personPhone
varchar personPhoneArea
varchar personCertNo
varchar personRegionId
varchar personCellId
varchar personStationName
varchar personStationLongitude
varchar personStationLatitude
varchar operatorId
timestamp callDateTime
date callDate
time callTime
integer duration
varchar callDirection
varchar callType
varchar otherName
varchar otherPhone
varchar otherPhoneArea
varchar otherCertNo
varchar remark
varchar personLibId
varchar callLocal
}
CALL_RECORD_ALL {
bigint id PK
bigint fileId
bigint sheetId
varchar personName
varchar personPhone
varchar personPhoneArea
varchar personCertNo
varchar personRegionId
varchar personCellId
varchar personStationName
varchar personStationLongitude
varchar personStationLatitude
varchar operatorId
timestamp callDateTime
date callDate
time callTime
integer duration
varchar callDirection
varchar callType
varchar otherName
varchar otherPhone
varchar otherPhoneArea
varchar otherCertNo
varchar remark
varchar personLibId
varchar callLocal
}
USE_OPEN_INFO_CALL_RECORD {
bigint id PK
bigint fileId
bigint sheetId
varchar personName
varchar personPhone
varchar personPhoneArea
varchar personCertNo
varchar personRegionId
varchar personCellId
varchar personStationName
varchar personStationLongitude
varchar personStationLatitude
varchar operatorId
timestamp callDateTime
date callDate
time callTime
integer duration
varchar callDirection
varchar callType
varchar otherName
varchar otherPhone
varchar otherPhoneArea
varchar otherCertNo
varchar remark
varchar personLibId
varchar callLocal
}
CALL_OPENING_INFO {
bigint id PK
bigint fileId
bigint sheetId
varchar phoneType
varchar operatorId
varchar personPhone
varchar personType
varchar personName
varchar personCertNo
varchar personCertAddress
varchar mailingAddress
varchar province
varchar city
varchar phoneStatus
timestamp activationDateTime
timestamp closingDateTime
timestamp firstCallDateTime
timestamp lastSuspensionDateTime
}
PERSON_CALL_STAT {
varchar personName PK
integer personPhoneCount
timestamp firstCallDateTime
timestamp lastCallDateTime
integer totalCallCount
integer totalCallDuration
integer outCallCount
integer inCallCount
}
PHONE_CALL_STAT {
varchar personPhone PK
varchar personName
varchar personCertNo
varchar operator
timestamp firstCallDateTime
timestamp lastCallDateTime
integer callContactCount
integer totalCallDuration
integer totalCallCount
integer outCallDuration
integer outCallCount
integer inCallDuration
integer inCallCount
}
图示来源
classDiagram
class CallRecord {
+String personName
+String personPhone
+String operatorId
+String personPhoneArea
+String personCertNo
+String personRegionId
+String personCellId
+String personStationName
+String personStationLongitude
+String personStationLatitude
+LocalDateTime callDateTime
+LocalDate callDate
+LocalTime callTime
+Integer duration
+String callDirection
+String callType
+String otherName
+String otherPhone
+String otherPhoneArea
+String otherCertNo
+String remark
+String personLibId
+String callLocal
}
class CallRecordAll {
+String personName
+String personPhone
+String operatorId
+String personPhoneArea
+String personCertNo
+String personRegionId
+String personCellId
+String personStationName
+String personStationLongitude
+String personStationLatitude
+LocalDateTime callDateTime
+LocalDate callDate
+LocalTime callTime
+Integer duration
+String callDirection
+String callType
+String otherName
+String otherPhone
+String otherPhoneArea
+String otherCertNo
+String remark
+String personLibId
+String callLocal
}
class UseOpenInfoCallRecord {
+String personName
+String personPhone
+String operatorId
+String personPhoneArea
+String personCertNo
+String personRegionId
+String personCellId
+String personStationName
+String personStationLongitude
+String personStationLatitude
+LocalDateTime callDateTime
+LocalDate callDate
+LocalTime callTime
+Integer duration
+String callDirection
+String callType
+String otherName
+String otherPhone
+String otherPhoneArea
+String otherCertNo
+String remark
+String personLibId
+String callLocal
}
class CallOpenInfo {
+String phoneType
+String operatorId
+String personPhone
+String personType
+String personName
+String personCertNo
+String personCertAddress
+String mailingAddress
+String province
+String city
+String phoneStatus
+LocalDateTime activationDateTime
+LocalDateTime closingDateTime
+LocalDateTime firstCallDateTime
+LocalDateTime lastSuspensionDateTime
}
CallRecordAll --> CallRecord : "字段口径相近"
UseOpenInfoCallRecord --> CallRecord : "语义相近"
CallOpenInfo --> CallRecord : "通过 personPhone 关联"
图示来源
CallRecordQuery 是通话记录分页查询的主要输入对象,继承自通用查询基类,因此除自身字段外,还支持分页、排序等通用能力。其核心过滤条件包括:
| 条件 | 类型 | 说明 |
|---|---|---|
id、ids |
Long、Long 列表 | 按单条或批量主键过滤 |
fileId、sheetId |
Long | 按数据来源文件和工作表过滤 |
personPhones |
String 列表 | 按本方号码集合过滤 |
operatorId |
String | 按运营商过滤 |
personPhoneArea |
String | 按本方号码归属地过滤 |
personCertNo |
String | 按本方证件号过滤 |
personRegionId、personCellId |
String | 按基站大区、小区过滤 |
duration |
Integer | 按通话时长过滤 |
callDirection |
String | 按主叫或被叫过滤 |
callType |
String | 按通话类型过滤 |
otherName |
String | 按对方姓名模糊或精确过滤 |
otherPhones、otherPhone |
String 列表、String | 按对方号码集合或单个号码过滤 |
startTime、endTime |
String | 按时间范围过滤 |
symbol |
String | 当前查询对象中作为时间比较符号使用 |
注意:CallRecordQuery 中只定义了 personPhones 列表,没有 personPhone 单值字段;但 personName 等常用字段并未出现在查询对象中。实际工程中如果需要按姓名查询,应优先确认服务层是否对 personName 做了扩展处理,或者改用证件号、号码等唯一性更强的字段。
章节来源
CallNightQuery 用于夜间通话分析,包含:
| 字段 | 含义 |
|---|---|
nightStart |
夜间开始小时 |
nightEnd |
夜间结束小时 |
monthVal |
月份阈值或筛选条件 |
otherName |
对方姓名 |
otherPhone |
对方号码 |
夜间通话的核心逻辑是以 callTime 的小时区间为基础,结合月份维度做聚合,输出时间段、对方信息、通话次数、跨月跨度等结果。
章节来源
CallContinuousQuery 用于识别两个人之间是否在某段时间内持续保持联系,包含:
| 字段 | 含义 |
|---|---|
monthVal |
连续月份阈值,例如超过该值的连续通话才保留 |
otherName |
对方姓名 |
otherPhone |
对方号码 |
连续通话的关键不是单次通话,而是“按月观察”:如果两人在多个相邻月份都有通话,则认为他们存在连续关系;若中间有断月,则可能拆成多段连续区间。
章节来源
CallSensitiveQuery 用于敏感通话预警,包含:
| 字段 | 含义 |
|---|---|
otherPhone |
对方号码 |
otherName |
对方姓名 |
敏感通话通常关注两类场景:一是与重点监控对象的通话;二是与某些号码发生异常高频通话。结果由 CallSensitiveDTO 表达,包括对方信息、通话次数等。
章节来源
通话记录中的“本方”通常对应案件中的目标人员,而“对方”可能是:
因此,通话记录不能只看 personPhone,还必须结合:
personName、personCertNo:确认本方真实身份。otherName、otherPhone、otherCertNo:识别对方是谁。callDirection:判断是本方拨打还是接听。callDateTime、callDate、callTime、duration:还原通话时间和强度。personLibId:关联案件中的卡库或人员库。在调查分析中,建议将通话记录视为“边”,人员视为“点”。同一案件中,一个人可能既是多条边的起点,也可能是多条边的终点。
| 关联维度 | 通话的作用 |
|---|---|
| 交易 | 通话频繁的人往往与资金往来有关联;可用通话频次辅助判断交易对手是否可信 |
| 轨迹 | 通话时的基站位置可与活动轨迹对照,判断通话是否发生在异常地点 |
| 治理树 | 通话关系可作为治理树中的社会关系补充,帮助构建人物关系图谱 |
| 账户开户 | 通过 call_opening_info 校验号码是否实名、是否已销户、归属地是否合理 |
通话数据中的号码可能存在格式不一致问题,例如前缀、空格、分隔符差异。推荐匹配策略:
personName、personCertNo。call_opening_info 验证号码状态、归属地、入网时间。通话记录去重应考虑以下维度:
| 去重维度 | 适用场景 |
|---|---|
主键 id |
数据库级唯一标识,最可靠 |
personPhone + otherPhone + callDateTime |
同一天内同一方向通话 |
personPhone + otherPhone + callDate |
忽略分钟级重复,按天去重 |
personPhone + otherPhone + callTime |
同一时刻不同天的重复记录 |
文件级 fileId + sheetId |
同一数据源的重复导入 |
建议在入库阶段基于 fileId、sheetId、id 做幂等控制;在分析阶段根据业务需要选择不同粒度的去重策略。
通话记录分页由 CallRecordController 暴露 getCallRecord 接口,返回分页结果。服务层通常结合 MyBatis Plus 的分页插件完成分页。
聚合统计方面,系统还定义了预统计表:
| 统计表 | 作用 |
|---|---|
person_call_stat |
按人员汇总通话次数、通话时长、主被叫次数 |
phone_call_stat |
按号码汇总通话接触人数、通话时长、主被叫次数 |
这些表适合做快速概览统计,但要注意它们可能是离线计算结果,不一定实时反映最新通话数据。
章节来源
通话模块的整体请求链路如下:
sequenceDiagram
participant Client as "调用方"
participant Controller as "CallRecordController"
participant Service as "CallRecordService"
participant Mapper as "CallRecordMapper"
participant DB as "call_record 表"
Client->>Controller: POST /cr/getCallRecord
Controller->>Service: getCallRecord(query)
Service->>Mapper: 执行分页查询
Mapper->>DB: 按条件检索通话记录
DB-->>Mapper: 返回分页数据
Mapper-->>Service: 返回 Page<CallRecord>
Service-->>Controller: 返回 Result<Page<CallRecord>>
Controller-->>Client: 返回 JSON 响应
图示来源
AI Agent 侧的调用路径类似,只是入口变为工具方法:
sequenceDiagram
participant Agent as "Agent 工具调用方"
participant Tool as "CallAnalysisTool"
participant Service as "CallRecordService"
participant Night as "CallNightService"
participant Continuous as "CallContinuousService"
participant Sensitive as "CallSensitiveService"
Agent->>Tool: getCallRecords()
Tool->>Service: getCallRecord(query)
Agent->>Tool: stat_call_night_summary()
Tool->>Night: 查询夜间通话统计
Agent->>Tool: stat_call_continuous_summary()
Tool->>Continuous: 查询连续通话统计
Agent->>Tool: stat_call_sensitive_summary()
Tool->>Sensitive: 查询敏感通话统计
图示来源
CallRecordController 暴露了 /cr/getCallRecord 接口,接收 CallRecordQuery,返回 Result<Page<CallRecord>>。这是一个简洁的 REST 接口设计,把具体查询逻辑交给 CallRecordService。
CallRecordService 继承 MyBatis Plus 的 ServiceImpl,说明它复用通用 CRUD 和分页能力,再叠加通话业务逻辑。
章节来源
夜间通话分析由 CallNightService 处理,输入是 CallNightQuery,输出是 CallNightDTO。典型输出包括:
| 字段 | 含义 |
|---|---|
time |
时间段标识,例如夜间某个小时区间 |
otherName、personName |
对方和本方姓名 |
otherPhone |
对方号码集合,可能以逗号分隔 |
callCount |
该时间段通话次数 |
totalMonthCount |
跨越的月份总数 |
startHour、endHour |
夜间时段起止小时 |
夜间通话的价值在于发现非正常作息下的联络行为,例如深夜频繁通话、长期只在夜间联系的固定关系。
章节来源
连续通话分析由 CallContinuousService 处理,输入是 CallContinuousQuery,输出是 CallContinuousDTO。核心输出包括:
| 字段 | 含义 |
|---|---|
personName、personPhone |
本方信息 |
otherName、otherPhone、otherPhones |
对方信息,可能合并多个号码 |
pairContMonthCount |
连续通话月份数 |
pairTotalCalls |
该关系总通话次数 |
continuousStartMonth、continuousEndMonth |
连续区间起止月份 |
连续通话常用于判断两人是否存在长期稳定的社交关系。例如,连续六个月以上每月都有通话,比短期高频通话更能体现关系稳定性。
章节来源
敏感通话分析由 CallSensitiveService 处理,输入是 CallSensitiveQuery,输出是 CallSensitiveDTO。敏感通话的重点是“对方”是否值得关注:
| 字段 | 含义 |
|---|---|
personName |
本方姓名 |
otherName |
对方姓名 |
otherPhone |
对方号码 |
callCount |
通话次数 |
敏感通话可以结合外部黑名单、重点关注名单、历史案件线索进行筛选。
章节来源
CallOpenInfoService 管理号码开户信息,对应 call_opening_info 表。关键字段包括:
| 字段 | 含义 |
|---|---|
phoneType |
号码类型 |
operatorId |
运营商 |
personPhone |
号码 |
personType |
用户类型 |
personName |
使用人姓名 |
personCertNo |
使用人证件号 |
province、city |
归属省、市 |
phoneStatus |
号码状态 |
activationDateTime |
入网时间 |
closingDateTime |
销户时间 |
firstCallDateTime |
首次通话时间 |
lastSuspensionDateTime |
最后停机时间 |
开放信息适合用来:
章节来源
通话模块内部依赖关系如下:
graph LR
A["CallRecordController"] --> B["CallRecordService"]
C["CallNightController"] --> D["CallNightService"]
E["CallContinuousController"] --> F["CallContinuousService"]
G["CallSensitiveController"] --> H["CallSensitiveService"]
I["CallOpenInfoService"] --> J["CallOpenInfoMapper"]
B --> K["CallRecordMapper"]
D --> L["CallNightMapper"]
F --> M["CallContinuousMapper"]
H --> N["CallSensitiveMapper"]
K --> O["call_record"]
L --> O
M --> O
N --> O
J --> P["call_opening_info"]
图示来源
外部依赖主要包括:
CallAnalysisTool 暴露通话分析能力章节来源
通话记录表已创建以下索引:
| 索引名 | 列 | 作用 |
|---|---|---|
idx_call_record_person_name |
personName |
按本方姓名查询 |
idx_call_record_person_phone |
personPhone |
按本方号码查询 |
idx_call_record_other_name |
otherName |
按对方姓名查询 |
idx_call_record_other_phone |
otherPhone |
按对方号码查询 |
开放信息表已创建:
| 索引名 | 列 | 作用 |
|---|---|---|
idx_call_opening_info_person_phone |
personPhone |
按号码查开户信息 |
idx_call_opening_info_person_name |
personName |
按姓名查开户信息 |
章节来源
对于大数据量通话模块,建议增加以下索引:
| 建议索引 | 列组合 | 原因 |
|---|---|---|
| 时间范围索引 | callDate、callDateTime |
绝大多数查询会带时间范围 |
| 主被叫组合索引 | callDirection、personPhone |
常见于按本方号码和主被叫方向查询 |
| 对方关系索引 | otherPhone、otherName |
支持对方号码、对方姓名的联合查询 |
| 基站索引 | personRegionId、personCellId |
支持按基站区域或小区定位通话 |
| 文件来源索引 | fileId、sheetId |
支持按数据源隔离查询 |
时间范围查询如果没有 callDate 或 callDateTime 索引,容易退化为全表扫描,尤其在通话记录达到千万级时影响显著。
如果通话记录数据量很大,可按时间分区:
| 分区方式 | 优点 | 缺点 |
|---|---|---|
| 按月分区 | 与连续通话、夜间通话按月分析契合 | 维护分区较多 |
| 按日分区 | 适合高频增量写入 | 分区过多 |
| 按年份分区 | 结构简单 | 时间粒度粗 |
推荐优先按“年+月”或“月”分区,配合 callDate 索引,使时间范围查询既能走分区裁剪,又能走索引扫描。
startTime、endTime,可能扫描整表。personPhone、personCertNo、id 优于 personName。%xxx% 形式,难以命中索引。person_call_stat、phone_call_stat,明细用 call_record。可能原因:
fileId、sheetId。排查建议:
id 或 personPhone 精确查询。callDirection 是否为主叫或被叫。fileId、sheetId。可能原因:
nightStart、nightEnd 配置不合理。callTime 为空或格式异常。排查建议:
callTime 分布。otherName、otherPhone 过滤。可能原因:
monthVal 过高。排查建议:
monthVal 阈值。CallContinuousDTO 中的连续起止月份。可能原因:
排查建议:
call_opening_info 验证号码有效性。章节来源
通话模块 call 是整个调查数据体系中的重要基础模块。它以通话记录为核心,向上支撑夜间通话、连续通话、敏感通话等业务分析,向外与人员、交易、轨迹、治理树产生交叉关系,向内通过开放信息完善号码身份。
在实际使用中,应重点关注:
这样,通话模块不仅能回答“某人打过哪些电话”,还能进一步回答“他和谁建立了稳定关系”“是否存在异常夜间联络”“是否频繁联系敏感对象”,从而服务于更完整的调查分析。