跳至主要内容

群發(Broadcast)與進線原因(InboundReason)規格說明書

版本: v1.0
最後更新: 2026-06-13
服務範圍: aile-service-tenant(核心)、aile-service-room(協同)


第一部分:群發(Broadcast)

1. 概述

群發(Broadcast)是 Aile 提供的批量消息推送能力,允許服務號向符合特定條件(標籤篩選或指定客戶列表)的客戶群發送訊息。群發支援定時發送、渠道過濾和結果統計。


2. BroadcastModel(群發持久化模型)

2.1 資料結構

MongoDB 集合:aile.tenant.servicenumber.broadcast

// aile-api/aile-tenant-api/.../model/servicenumber/BroadcastModel.java
@Document("aile.tenant.servicenumber.broadcast")
@CompoundIndexes({
@CompoundIndex(name = "serviceNumberId", def = "{'serviceNumberId': 1}"),
@CompoundIndex(name = "serviceNumberId_1_status_1_updateTime_1",
def = "{'serviceNumberId': 1, 'status': 1, 'updateTime': 1}")
})
public class BroadcastModel extends BaseModel {
String name; // 任務標題
String remark; // 備註
String tenantId; // 租戶 ID
String accountId; // 操作者帳號 ID
String memberId; // 操作者客服 memberId
String serviceNumberId; // 服務號 ID
Long broadcastTime; // 預定發送時間
List<String> labelIds; // 目標標籤 ID 列表(選填)
List<String> customerIds; // 目標客戶 ID 列表(選填)
LabelMatchLogic matchLogic; // 標籤匹配邏輯(AND / OR)
List<BroadcastBody> content; // 群發內容
BroadcastStatus status; // 狀態
Channel channel; // 目標渠道
Integer totalCount; // 目標總數
Integer successCount; // 成功數
Integer failCount; // 失敗數
}

2.2 狀態機

// aile-api/aile-tenant-api/.../enums/servicenumber/BroadcastStatus.java
public enum BroadcastStatus {
Will, // 待發送
Doing, // 發送中
Done, // 已完成
Delete // 已刪除
}
Will ──→ Doing ──→ Done
│ │
└──→ Delete └──→ Delete

3. 群發服務實現

3.1 BroadcastServiceImpl

位置:aile-service/aile-service-tenant/.../service/servicenumber/impl/BroadcastServiceImpl.java

核心方法:

方法說明
create(dto)建立群發任務
update(dto)更新任務(僅 Will 狀態可更新)
start(broadcastId)啟動發送(Will → Doing)
complete(broadcastId)完成發送(Doing → Done)
delete(broadcastId)刪除任務(軟刪除)
list(dto)分頁查詢群發任務

3.2 目標受眾計算

BroadcastServiceImpl.start()

├── 若有 labelIds
│ ├── 依 matchLogic(AND/OR)查詢符合標籤的客戶列表
│ └── 交叉過濾 customerIds(如有指定)

├── 若僅有 customerIds
│ └── 直接使用指定客戶列表

├── 渠道過濾
│ └── 僅向指定 channel 的客戶發送

├── 計算 totalCount = 目標客戶數

└── 逐個客戶發送消息
├── 成功 → successCount++
└── 失敗 → failCount++(記錄日誌)

4. 消息發送機制

4.1 BroadcastMessageUtil

位置:aile-service/aile-service-room/.../message/BroadcastMessageUtil.java

群發消息透過 Room 服務發送:

BroadcastServiceImpl

└── MessageFeign.sendServiceMessage(dto) [跨服務調用]

└── aile-service-room

└── BroadcastMessageUtil.sendBroadcastMessage()
├── 建立 MessageModel
├── 寫入對應 Services Room
└── 透過 GatewayFeign 外發

4.2 廣播內容格式

// BroadcastBody(內嵌於 BroadcastModel)
public class BroadcastBody {
MessageType type; // 消息類型(Text / Image / Template 等)
String text; // 文字內容
String fileUrl; // 媒體文件 URL
// Template 消息
TemplateMessage template; // 模板消息(包含 Action 按鈕等)
}

5. 群發 API

路由:/servicenumber/broadcast/

方法路徑說明
POST/broadcast/create建立群發任務
POST/broadcast/update更新群發任務
POST/broadcast/start啟動發送
POST/broadcast/complete標記完成
POST/broadcast/delete刪除任務
POST/broadcast/list查詢任務列表
GET/broadcast/detail?broadcastId=查詢任務詳情
POST/broadcast/target-batch批量查詢目標受眾

6. 定時發送

群發支援預約發送,透過 broadcastTime 欄位指定未來時間:

BroadcastModel.broadcastTime

└── 定時任務掃描 (Cron / OnceScheduleManager)
├── 檢查 broadcastTime ≤ now
├── 檢查 status = Will
└── 自動調用 start()

第二部分:進線原因(InboundReason)

7. 概述

進線原因(InboundReason)是 Aile 提供的客戶進線來源標記系統,用於追蹤客戶是從哪個業務場景進入客服對話的。支援兩種模式:

模式說明
預設來源(Preset)管理員預先配置的進線原因,客戶進線時透過 URL 參數或 API 指定
即時原因(RealTime)客戶進線時動態傳入的進線原因資料

8. ServiceInboundReasonModel(進線原因配置)

8.1 資料結構

MongoDB 集合:aile.tenant.inbound.reason

// aile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonModel.java
@Document("aile.tenant.inbound.reason")
@CompoundIndexes({
@CompoundIndex(name = "tenantId", def = "{'tenantId': 1}")
})
public class ServiceInboundReasonModel extends BaseModel {
String tenantId; // 租戶 ID
String sourceName; // 來源名稱(如「官網首頁」)
ServiceInboundReasonTypeEnum sourceType; // 來源類型
String description; // 進線原因描述
String businessId; // 業務 ID(關聯特定業務場景)
Long validityPeriod; // 有效期(null 或 0 表示永久有效)
Boolean status; // 啟用/禁用
}

8.2 進線原因類型枚舉

// aile-api/aile-tenant-api/.../enums/ServiceInboundReasonTypeEnum.java
public enum ServiceInboundReasonTypeEnum {
SCAN_QR_CODE("qrcode", "掃碼進線"), // 門店、海報、線下活動
PRODUCT_CONSULT("product", "商品咨詢"), // 商品詳情頁、商品列表
PROMOTION_CONSULT("activity", "活動咨詢"), // 促銷活動卡片、活動頁面
SIGNATURE("signature", "簽名檔進線"), // 員工郵件簽名檔連接
CUSTOMER_SUPPORT("support", "客服支持"), // 幫助中心、聯繫我們
PRICING_CONSULT("pricing", "定價咨詢"), // 定價頁面、價格表
CUSTOM("custom", "自定義") // 業務自定義場景
}

9. ServiceInboundReasonSessionModel(進線原因-會話關聯)

9.1 資料結構

MongoDB 集合:aile.tenant.servicenumber.inbound.reason.session

// aile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonSessionModel.java
@Document("aile.tenant.servicenumber.inbound.reason.session")
@CompoundIndexes({
@CompoundIndex(name = "sourceId", def = "{'sourceId': 1}"),
@CompoundIndex(name = "sessionId", def = "{'sessionId': 1}"),
@CompoundIndex(name = "serviceNumberId_sourceId", def = "{'serviceNumberId': 1, 'sourceId': 1}"),
@CompoundIndex(name = "serviceNumberId_sourceId_transferToAgent",
def = "{'serviceNumberId': 1, 'sourceId': 1, 'transferToAgent': 1}")
})
public class ServiceInboundReasonSessionModel extends BaseModel {
String tenantId; // 租戶 ID
String serviceNumberId; // 服務號 ID
String sessionId; // 會話 ID
String roomId; // 聊天室 ID
String customerId; // 客戶 ID
String sourceId; // 進線原因 ID(關聯 ServiceInboundReasonModel)
Boolean transferToAgent; // 是否轉人工
ServiceInboundReasonOrigin originType; // 來源類型:Preset / RealTime
String sourceData; // 即時原因資料(JSON 字串,originType=RealTime 時使用)
String sourceName; // 來源名稱快照(建立關聯時的來源名稱)
ServiceInboundReasonTypeEnum sourceType; // 來源類型快照
}

10. 進線原因來源類型

// aile-api/aile-tenant-api/.../enums/ServiceInboundReasonOrigin.java
public enum ServiceInboundReasonOrigin {
Preset, // 預設來源(管理員配置的進線原因)
RealTime // 即時原因(客戶進線時動態傳入)
}
類型說明使用場景
Preset預先配置好的進線原因掃碼進線、商品頁面進線、活動頁面進線
RealTime進線時動態指定的原因自定義業務場景、外部系統傳入的臨時原因

11. 進線原因服務

11.1 ServiceInboundReasonService

位置:aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonService.java

提供進線原因配置的 CRUD:

方法說明
create(dto)建立進線原因配置
update(dto)更新配置
delete(id)刪除配置
list(dto)分頁查詢配置列表
enable(id) / disable(id)啟用/停用

11.2 ServiceInboundReasonSessionService

位置:aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonSessionService.java

提供進線原因與會話的綁定:

public interface ServiceInboundReasonSessionService extends BaseMongoService<ServiceInboundReasonSessionModel> {
void bindSession(ServiceInboundReasonSessionBindDto bindDto);
void markTransferToAgent(String sessionId);
}

12. 進線原因綁定流程

客戶進線(攜帶進線原因參數)

├── 透過 URL 參數 ?sourceId=xxx 指定預設原因
│ 或
├── 透過 API 傳入即時原因資料

└── ServiceInboundReasonServiceImpl

├── 查詢 ServiceInboundReasonModel(若 sourceId 有效)
├── 建立 ServiceSession(會話)
└── ServiceInboundReasonSessionService.bindSession(bindDto)

├── 建立 ServiceInboundReasonSessionModel
│ ├── originType = Preset(若使用預設原因)
│ │ = RealTime(若動態傳入)
│ ├── sourceName = 快照當前的來源名稱
│ └── sourceData = 即時原因的 JSON 資料(RealTime 時)

└── 關聯 sessionId ↔ sourceId

13. 轉人工標記

ServiceInboundReasonSessionService.markTransferToAgent(sessionId)

└── 更新 ServiceInboundReasonSessionModel.transferToAgent = true

此標記用於統計:哪些進線原因的客戶最終轉了人工客服。


14. 進線原因統計

基於 ServiceInboundReasonSessionModel 的聚合查詢:

統計維度說明
按來源類型各來源類型的進線量、轉人工量
按預設原因每個預設配置的進線量
按即時原因按 sourceName 分組的即時原因進線量
轉人工率transferToAgent=true 的比例

15. 進線原因 API

15.1 進線原因配置 API

路由:/inboundreason/

方法路徑說明
POST/inboundreason/create建立進線原因
POST/inboundreason/update更新進線原因
POST/inboundreason/delete刪除進線原因
POST/inboundreason/list查詢進線原因列表
GET/inboundreason/detail?inboundReasonId=查詢詳情

15.2 進線原因關聯查詢 API

方法路徑說明
GET/inboundreason/session/list?sessionId=查詢會話的進線原因
GET/inboundreason/session/statistics進線原因統計

16. 業務場景示例

16.1 掃碼進線

1. 管理員配置進線原因:
sourceName = "台北門市",sourceType = SCAN_QR_CODE
2. 生成帶參數的二維碼 URL:
https://line.me/R/ti/p/@xxx?sourceId=INB_001
3. 客戶掃碼後進線:
→ 自動綁定 sourceId="INB_001"
→ originType=Preset
→ 記錄進線原因快照

16.2 即時原因

1. 外部系統呼叫進線 API,附帶:
{ sourceName: "訂單 #12345 查詢", sourceType: "custom", sourceData: { orderId: "12345" } }
2. 系統建立進線原因關聯:
→ originType=RealTime
→ sourceData = {"orderId":"12345"}
→ 客服端顯示「進線原因:訂單 #12345 查詢」

17. 群發與進線原因的關聯

群發任務可以透過進線原因數據進行精準投放:

BroadcastServiceImpl(選擇目標受眾時)

├── 可選:篩選有特定進線原因的客戶
│ ├── 查詢 ServiceInboundReasonSessionModel
│ │ └── sourceId = "INB_001"(掃碼進線的客戶)
│ └── 取得 customerId 列表

└── 將篩選結果作為群發目標

18. 關鍵檔案索引

群發(Broadcast)

層級檔案說明
API Modelaile-api/aile-tenant-api/.../model/servicenumber/BroadcastModel.java群發持久化模型
API Enumaile-api/aile-tenant-api/.../enums/servicenumber/BroadcastStatus.java群發狀態枚舉
Serviceaile-service/aile-service-tenant/.../service/servicenumber/impl/BroadcastServiceImpl.java群發服務實現
Room Utilaile-service/aile-service-room/.../message/BroadcastMessageUtil.java群發消息工具

進線原因(InboundReason)

層級檔案說明
API Modelaile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonModel.java進線原因配置模型
API Modelaile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonSessionModel.java進線原因-會話關聯模型
API Enumaile-api/aile-tenant-api/.../enums/ServiceInboundReasonTypeEnum.java進線原因類型枚舉
API Enumaile-api/aile-tenant-api/.../enums/ServiceInboundReasonOrigin.java來源類型枚舉
API DTOaile-api/aile-tenant-api/.../dto/inboundreason/ServiceInboundReasonSessionBindDto.java會話綁定 DTO
Serviceaile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonService.java進線原因服務接口
Serviceaile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonSessionService.java關聯服務接口
Service Implaile-service/aile-service-tenant/.../service/inboundreason/impl/ServiceInboundReasonServiceImpl.java進線原因服務實現
Service Implaile-service/aile-service-tenant/.../service/inboundreason/impl/ServiceInboundReasonSessionServiceImpl.java關聯服務實現
Redis Keyaile-api/aile-tenant-api/.../constant/ServiceInboundReasonRedisKey.java進線原因 Redis Key