feat: sync OneTalk customer profiles

This commit is contained in:
YBF
2026-09-01 18:44:32 +08:00
parent b9e671a374
commit a1dae83d78
64 changed files with 4536 additions and 61 deletions
+19 -13
View File
@@ -6,6 +6,8 @@
>
> 本文记录一次对真实 Chromium 页面运行时的只读探查结果,重点是如何获取会话对应的客户姓名、公司、登录 ID、阿里 ID 等资料,以及如何继续刷新客户详情。页面和静态 bundle 版本可能变化,生产代码必须保留特征检测、超时和字段白名单。
> **当前任务边界(2026-08-31)**:本文是历史探查证据,不是当前跨层实现合同。当前第一阶段只允许 MAIN world 读取已经加载的白名单基础资料,并通过现有 Bright WebSocket 投递;详情刷新、邮箱、注册时间、买家标签、DOM 适配和群聊成员属于未来范围。文中出现的 token、加密 ID 和内部详情调用只用于说明探查结果,禁止进入页面桥、Service Worker、Bright、Mind、日志或持久化。
## 1. 结论
当前 OneTalk 页面有三层资料入口:
@@ -14,11 +16,11 @@
会话列表模块已经把客户资料放在这个全局对象中。对于已经加载到会话列表的联系人,不需要额外请求,就能取得 `aliId``loginId`、姓名、公司等字段。
2. **补刷新`conversationServiceHttp.getConversationContactDetailList()`**
2. **延期的详情刷新探查`conversationServiceHttp.getConversationContactDetailList()`**
`window.IcbuIM.IMBaaSSDK` 中具体的 `IcbuConversationServiceImpl` 实例带有内部 HTTP 适配器。该适配器可以用页面已有的加密 ID 和 chat token 刷新联系人资料。
3. **完整客户详情:客户详情微应用自己的 `contactMemberInfo` 请求**
3. **延期的完整客户详情:客户详情微应用自己的 `contactMemberInfo` 请求**
右侧“客户详情”面板中的邮箱、注册时间等字段不在当前基础联系人对象中。静态 bundle 显示客户详情微应用会调用 `/message/contact/detail/contactMemberInfo.htm`。这部分应优先通过页面微应用已有逻辑或已渲染 DOM 获取,不要在插件 Service Worker 中自行拼接 CRM 请求。
@@ -31,7 +33,7 @@ window.__conversationListData__
→ 发送给 Mind
```
缺资料时再走:
缺资料时再走(历史探查建议,当前任务禁止)
```text
IcbuConversationServiceImpl.getInstance()
@@ -564,7 +566,9 @@ channelAccountId + aliId
- 群聊:会话标题不是联系人资料;需要使用成员列表服务逐个得到成员,再分别匹配 `aliId/loginId`
- 当前 `getConversationContactDetailList` 可以批量传多个联系人对象,但每个联系人仍必须带自己的加密 ID和页面 token。
## 7. 向 Mind 发送的建议数据契约
## 7. 向 Mind 发送的历史建议(不是当前实现契约
以下结构保留作 2026-08-27 探查记录。当前实现以共享 OneTalk contract、profile page envelope、Bright frame 和 Mind profile HTTP 规范为准,不使用本节的旧顶层字段结构。
客户资料应作为独立资料事件发送,不要附加到消息正文,也不要把原始会话对象当作 payload:
@@ -610,19 +614,19 @@ apps/chrome-extension/src/onetalk/main-page/contact-observer/
1. 读取 `window.__conversationListData__` 初始快照;
2. 订阅 `im-conversation-list:syncData`
3. 对资料缺失的会话调用 `conversationServiceHttp.getConversationContactDetailList`
4. 对邮箱、注册时间等完整详情使用页面微应用状态或 DOM 补充;
3. **未来范围**对资料缺失的会话调用 `conversationServiceHttp.getConversationContactDetailList`
4. **未来范围**对邮箱、注册时间等完整详情使用页面微应用状态或 DOM 补充;
5. 对返回对象执行字段白名单清洗;
6. 通过已有 page bridge / Service Worker 发送给 Mind
7.`channelAccountId + aliId` 去重;
8. 对每个联系人记录成功、部分成功、超时和 ID 不匹配状态。
推荐采集策略:
上面的详情刷新策略是未来范围。当前第一阶段策略:
```text
实时会话列表更新 → 立即采集基础资料
用户打开会话 → 按需刷新完整资料
显式回填客户资料” → 对缺资料会话批量补采集
实时会话列表更新 → 立即采集已加载的白名单基础资料
首次有效页面 hello → 请求当前已加载单聊 snapshot
邮箱/注册时间/买家标签/显式回填 → 另立 task
```
不要对每一条消息重复请求客户资料;应按联系人去重。
@@ -669,9 +673,9 @@ CSRF
完整原始响应
```
### 9.3 页面离线
### 9.3 页面离线与未来详情刷新
本次第一次调用外层空 Promise 时没有任何请求;改用内部 HTTP 适配器后能收到 200 响应。若页面自身网络状态为断开,内部方法可能长时间不完成,因此必须在插件侧设置明确超时,并把结果标记为 `timeout`,不能无限等待
本次第一次调用外层空 Promise 时没有任何请求;改用内部 HTTP 适配器后能收到 200 响应。这是历史探查结果,不是当前任务的调用授权。若未来任务重新启用详情刷新,必须另行定义 endpoint、token 边界和超时;当前 profile snapshot 命令本身是 fire-and-forget,不能阻塞消息 bootstrap
## 10. 验证记录
@@ -691,7 +695,9 @@ CSRF
| 右侧 DOM | 包含公司、邮箱、注册时间、买家标签 |
| 基础 SDK 返回邮箱/注册时间 | 当前未包含 |
## 11. 最小可用实现示例
## 11. 历史最小示例(不可直接用于当前任务)
本节代码展示当时探查到的内部详情刷新方式,故意保留为未来任务的证据。当前实现不得调用其中的 HTTP 详情方法,也不得让 chatToken 或加密 ID 离开 MAIN world。
下面是只返回安全字段的最小示例。它应当在 OneTalk 页面 MAIN world 中执行: