版本: v1.0\ 最後更新: 2026-06-13\ 服務範圍: aile-service-tenant(核心)、aile-service-room(協同)
群發(Broadcast)是 Aile 提供的批量消息推送能力,允許服務號向符合特定條件(標籤篩選或指定客戶列表)的客戶群發送訊息。群發支援定時發送、渠道過濾和結果統計。
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; // 失敗數
}// aile-api/aile-tenant-api/.../enums/servicenumber/BroadcastStatus.java
public enum BroadcastStatus {
Will, // 待發送
Doing, // 發送中
Done, // 已完成
Delete // 已刪除
}Will ──→ Doing ──→ Done
│ │
└──→ Delete └──→ Delete位置: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) | 分頁查詢群發任務 |
BroadcastServiceImpl.start()
│
├── 若有 labelIds
│ ├── 依 matchLogic(AND/OR)查詢符合標籤的客戶列表
│ └── 交叉過濾 customerIds(如有指定)
│
├── 若僅有 customerIds
│ └── 直接使用指定客戶列表
│
├── 渠道過濾
│ └── 僅向指定 channel 的客戶發送
│
├── 計算 totalCount = 目標客戶數
│
└── 逐個客戶發送消息
├── 成功 → successCount++
└── 失敗 → failCount++(記錄日誌)位置:aile-service/aile-service-room/.../message/BroadcastMessageUtil.java
群發消息透過 Room 服務發送:
BroadcastServiceImpl
│
└── MessageFeign.sendServiceMessage(dto) [跨服務調用]
│
└── aile-service-room
│
└── BroadcastMessageUtil.sendBroadcastMessage()
├── 建立 MessageModel
├── 寫入對應 Services Room
└── 透過 GatewayFeign 外發// BroadcastBody(內嵌於 BroadcastModel)
public class BroadcastBody {
MessageType type; // 消息類型(Text / Image / Template 等)
String text; // 文字內容
String fileUrl; // 媒體文件 URL
// Template 消息
TemplateMessage template; // 模板消息(包含 Action 按鈕等)
}路由:/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 | 批量查詢目標受眾 |
群發支援預約發送,透過 broadcastTime 欄位指定未來時間:
BroadcastModel.broadcastTime
│
└── 定時任務掃描 (Cron / OnceScheduleManager)
├── 檢查 broadcastTime ≤ now
├── 檢查 status = Will
└── 自動調用 start()進線原因(InboundReason)是 Aile 提供的客戶進線來源標記系統,用於追蹤客戶是從哪個業務場景進入客服對話的。支援兩種模式:
| 模式 | 說明 |
|---|---|
| 預設來源(Preset) | 管理員預先配置的進線原因,客戶進線時透過 URL 參數或 API 指定 |
| 即時原因(RealTime) | 客戶進線時動態傳入的進線原因資料 |
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; // 啟用/禁用
}// 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", "自定義") // 業務自定義場景
}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; // 來源類型快照
}// aile-api/aile-tenant-api/.../enums/ServiceInboundReasonOrigin.java
public enum ServiceInboundReasonOrigin {
Preset, // 預設來源(管理員配置的進線原因)
RealTime // 即時原因(客戶進線時動態傳入)
}
| 類型 | 說明 | 使用場景 |
|---|---|---|
Preset | 預先配置好的進線原因 | 掃碼進線、商品頁面進線、活動頁面進線 |
RealTime | 進線時動態指定的原因 | 自定義業務場景、外部系統傳入的臨時原因 |
位置:aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonService.java
提供進線原因配置的 CRUD:
| 方法 | 說明 |
|---|---|
create(dto) | 建立進線原因配置 |
update(dto) | 更新配置 |
delete(id) | 刪除配置 |
list(dto) | 分頁查詢配置列表 |
enable(id) / disable(id) | 啟用/停用 |
位置:aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonSessionService.java
提供進線原因與會話的綁定:
public interface ServiceInboundReasonSessionService extends BaseMongoService<ServiceInboundReasonSessionModel> {
void bindSession(ServiceInboundReasonSessionBindDto bindDto);
void markTransferToAgent(String sessionId);
}客戶進線(攜帶進線原因參數)
│
├── 透過 URL 參數 ?sourceId=xxx 指定預設原因
│ 或
├── 透過 API 傳入即時原因資料
│
└── ServiceInboundReasonServiceImpl
│
├── 查詢 ServiceInboundReasonModel(若 sourceId 有效)
├── 建立 ServiceSession(會話)
└── ServiceInboundReasonSessionService.bindSession(bindDto)
│
├── 建立 ServiceInboundReasonSessionModel
│ ├── originType = Preset(若使用預設原因)
│ │ = RealTime(若動態傳入)
│ ├── sourceName = 快照當前的來源名稱
│ └── sourceData = 即時原因的 JSON 資料(RealTime 時)
│
└── 關聯 sessionId ↔ sourceIdServiceInboundReasonSessionService.markTransferToAgent(sessionId)
│
└── 更新 ServiceInboundReasonSessionModel.transferToAgent = true此標記用於統計:哪些進線原因的客戶最終轉了人工客服。
基於 ServiceInboundReasonSessionModel 的聚合查詢:
| 統計維度 | 說明 |
|---|---|
| 按來源類型 | 各來源類型的進線量、轉人工量 |
| 按預設原因 | 每個預設配置的進線量 |
| 按即時原因 | 按 sourceName 分組的即時原因進線量 |
| 轉人工率 | transferToAgent=true 的比例 |
路由:/inboundreason/
| 方法 | 路徑 | 說明 |
|---|---|---|
POST | /inboundreason/create | 建立進線原因 |
POST | /inboundreason/update | 更新進線原因 |
POST | /inboundreason/delete | 刪除進線原因 |
POST | /inboundreason/list | 查詢進線原因列表 |
GET | /inboundreason/detail?inboundReasonId= | 查詢詳情 |
| 方法 | 路徑 | 說明 |
|---|---|---|
GET | /inboundreason/session/list?sessionId= | 查詢會話的進線原因 |
GET | /inboundreason/session/statistics | 進線原因統計 |
1. 管理員配置進線原因:
sourceName = "台北門市",sourceType = SCAN_QR_CODE
2. 生成帶參數的二維碼 URL:
https://line.me/R/ti/p/@xxx?sourceId=INB_001
3. 客戶掃碼後進線:
→ 自動綁定 sourceId="INB_001"
→ originType=Preset
→ 記錄進線原因快照1. 外部系統呼叫進線 API,附帶:
{ sourceName: "訂單 #12345 查詢", sourceType: "custom", sourceData: { orderId: "12345" } }
2. 系統建立進線原因關聯:
→ originType=RealTime
→ sourceData = {"orderId":"12345"}
→ 客服端顯示「進線原因:訂單 #12345 查詢」群發任務可以透過進線原因數據進行精準投放:
BroadcastServiceImpl(選擇目標受眾時)
│
├── 可選:篩選有特定進線原因的客戶
│ ├── 查詢 ServiceInboundReasonSessionModel
│ │ └── sourceId = "INB_001"(掃碼進線的客戶)
│ └── 取得 customerId 列表
│
└── 將篩選結果作為群發目標| 層級 | 檔案 | 說明 |
|---|---|---|
| API Model | aile-api/aile-tenant-api/.../model/servicenumber/BroadcastModel.java | 群發持久化模型 |
| API Enum | aile-api/aile-tenant-api/.../enums/servicenumber/BroadcastStatus.java | 群發狀態枚舉 |
| Service | aile-service/aile-service-tenant/.../service/servicenumber/impl/BroadcastServiceImpl.java | 群發服務實現 |
| Room Util | aile-service/aile-service-room/.../message/BroadcastMessageUtil.java | 群發消息工具 |
| 層級 | 檔案 | 說明 |
|---|---|---|
| API Model | aile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonModel.java | 進線原因配置模型 |
| API Model | aile-api/aile-tenant-api/.../model/inboundreason/ServiceInboundReasonSessionModel.java | 進線原因-會話關聯模型 |
| API Enum | aile-api/aile-tenant-api/.../enums/ServiceInboundReasonTypeEnum.java | 進線原因類型枚舉 |
| API Enum | aile-api/aile-tenant-api/.../enums/ServiceInboundReasonOrigin.java | 來源類型枚舉 |
| API DTO | aile-api/aile-tenant-api/.../dto/inboundreason/ServiceInboundReasonSessionBindDto.java | 會話綁定 DTO |
| Service | aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonService.java | 進線原因服務接口 |
| Service | aile-service/aile-service-tenant/.../service/inboundreason/ServiceInboundReasonSessionService.java | 關聯服務接口 |
| Service Impl | aile-service/aile-service-tenant/.../service/inboundreason/impl/ServiceInboundReasonServiceImpl.java | 進線原因服務實現 |
| Service Impl | aile-service/aile-service-tenant/.../service/inboundreason/impl/ServiceInboundReasonSessionServiceImpl.java | 關聯服務實現 |
| Redis Key | aile-api/aile-tenant-api/.../constant/ServiceInboundReasonRedisKey.java | 進線原因 Redis Key |