---
title: 前後台客服信息部分API及前端邏輯
tags: 股神
---
:::danger
每支 api,前端每個頁面,請記得做錯誤處理
:::
# 前台 H5 所需 API 們
## 0. 共用格式
| 項目 | 值 |
| ------ | ----------- |
| Method | POST |
| Type | FormData |
| param | SessionCode |
```typescript=1
// 回傳示例
{
code: 0,
message: 'success',
// result為下面API們的回傳範例,這裡用checkStatus做示範
result: {
isRead: false,
isBlacklisted: false
}
}
```
## 1. 確認該 customer 狀態,ex.是否有未讀的新訊息/是否已被黑名單
| 項目 | 值 |
| ----- | ------------ |
| URL | /checkStatus |
| table | sys_dialogue + 黑名單的table |
- isRead邏輯: ==sys_dialogue==這張 table,同個**customer id**底下的==isRated = 0==, **最多**只會有 1 個
- 如果有一個,且該"話題編號"的 isRead 也是 0,則回傳 false
- 其他狀況都回傳 true
ex.如果該 customer id 底下,完全沒有==isRated = false==,代表完全沒有未結束的話題,所以回傳 true
- isBlacklisted邏輯: 如果該customerId有被黑名單,回傳isBlacklisted = true
- API 因為是被動的,無法主動知道資料有沒有被更新,所以必須每隔一段時間去 call checkStatus API
- 回傳欄位
```typescript=1
interface ICheckStatus {
isRead: boolean;
isBlacklisted: boolean;
}
// 回傳示例
{
isRead: false,
isBlacklisted: false
}
```
## 2. 撈取客服組別名稱
| 項目 | 值 |
| ----- | -------------- |
| URL | /kefuGroupName |
| table | ?? |
- 回傳該 customerId 對應的客服組別名稱
- 回傳欄位
```typescript=
interface IKefuGroupName {
kefuGroupName: string;
}
// 回傳示例
{
kefuGroupName:
'A公司'
}
```
## 3. 發送話題(新話題/當前話題)
| 項目 | 值 |
| ----- | ----------------------------------- |
| URL | /postTopic |
| param | 如發送欄位所示 |
| table | sys_dialogue + sys_dialogue_message |
- 新話題時,前端**不帶** topicId, 帶 ==groupId, groupName, message==
- 當前話題時,前端帶==topicId==及==message==
- ==這支 API 為前台 H5 傳送,寫入 sys_dialogue_message, type 一律為'Q'==
:::info
後端邏輯
- 如果前端沒傳 topicId(話題編號) - 新話題
- 後端生成 topicId(話題編號), sys_dialogue 依照欄位寫入資訊, 因為無法預知會是哪個客服回覆,由 H5 傳送的,kefuName 可以不寫入資料
- 後端針對每個 message 生成 messageId(信息編號), sys_dialogue_message 依照欄位寫入資訊
- 如果前端有傳 topicId(話題編號) - 當前話題
- sys_dialogue 依照欄位更新資訊 ex. lastMessage 及 updateTime
- 後端針對每個 message 生成 messageId(信息編號), sys_dialogue_message 依照欄位寫入資訊
:::
* 發送欄位
```typescript=
interface IPostTopic {
topicId: string; // 話題編號 (唯一值)
groupId: string; // 用戶的話題id text_config.js設定
groupName: string; // 用戶的話題名稱 text_config.js設定
message: string; // 使用者輸入的留言=> 防呆: 只有該topicId對應的isFinished=false,才可寫入db,否則回傳錯誤
score: 1|2|3|4|5; // 使用者的評分=> 防呆: 只有該topicId對應的isRated=false,才可寫入db,否則回傳錯誤 分數為1(最低),2,3,4,5(最高)
}
// 發送示例 (新增)
{
groupId: 'A01',
groupName: '黃金',
message: '請問黃金交易手續費怎麼算?'
}
// 發送示例 (當前話題)
{
topicId: '69462295-6c41-425f-a33f-fadb6310d7ba',
message: '請問什麼時候可以拿到出金'
}
```
- 回傳欄位
```typescript=
// 回傳示例
{
code: 0,
message: 'success'
}
```
## 4. 發送評分
| 項目 | 值 |
| ----- | ----------------------------------- |
| URL | /updateScore |
| param | 如發送欄位所示 |
| table | sys_dialogue + sys_dialogue_message |
- 前端帶==topicId==及==score==
- ==若使用者 24 小時無評分,後端必須把 sys_dialogue 對應的 topicId 的 isRated 改成 1, 以及補上 score 為 5==
- 發送欄位
```typescript=
interface IUpdateScore {
topicId: string; // 話題編號 (唯一值)
score: 1|2|3|4|5; // 使用者的評分=> 防呆: 只有該topicId對應的isRated=false,才可寫入db,否則回傳錯誤 分數為1(最低),2,3,4,5(最高)
}
// 發送示例 (評分)
{
topicId: '69462295-6c41-425f-a33f-fadb6310d7ba',
score: 5
}
```
- 回傳欄位
```typescript=
// 回傳示例
{
code: 0,
message: 'success'
}
```
## 5. 撈取新話題/當前話題
| 項目 | 值 |
| ----- | ----------------------------------- |
| URL | /getTopic |
| table | sys_dialogue + sys_dialogue_message |
- sys_dialogue,同個**customer id**底下的==isRated = 0==, **最多**只會有 1 個
- API 只需回傳這一個==isRated = 0==的資料給前端,若沒有,則回傳==null==
- 如果有資料,回傳對應的 topicId,sys_dialogue_message 裡面的所有對話
- order by ==time==, 舊到新
- 需要確保回傳的值,只會是==null==或者==一個 object==
- 回傳欄位
```typescript=1
interface IMessage {
customerName: string; // user暱稱
kefuName: string; // 客服暱稱
time: string; // 留言時間 格式: 2021-07-16 15:43
message: string; // 如果多行,請保留 \n,前端才知道什麼時候要斷行
type: 'Q' | 'A'; // Q: customer寫的, A: 客服寫的
}
interface IGetTopic {
history: IMessage[];
topicId: string; // 話題編號 (唯一值)
topicTime: string; // 此話題編號的 update time 格式: 2021-07-16 15:43
groupId: string; // 用戶的話題id text_config.js設定
groupName: string; // 用戶的話題名稱 text_config.js設定
isFinished: boolean; // 此話題是否已結束? true:已結束 false:尚未結束
isRated: boolean; // 此話題是否已評分? true:已評分 false:尚未評分
isRead: boolean; // 此話題是否所有訊息,都已被user讀取
}
// 回傳示例
{
history: [
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:43',
message: '請問抽到新股,什麼時候知道結果?',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:48',
message: '可是我不想讓你知道結果',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:53',
message: '你這客服怎麼可以這麼優秀',
type: 'Q'
}
],
topicId: '69462295-6c41-425f-a33f-fadb6310d7ba',
topicTime: '2021-07-16 15:53',
groupId: 'A04',
groupName: '其他',
isFinished: false,
isRated: false,
isRead: true,
}
```
- 示意圖

## 6. 撈取歷史話題
| 項目 | 值 |
| ----- | ----------------------------------- |
| URL | /history |
| param | groupId ==非必填== |
| table | sys_dialogue + sys_dialogue_message |
- ==groupId==未填, 則回傳所有歷史話題
- ==array 回傳排序,topicTime 新->舊 (topicTime 是 sys_dialogue 的 createTime); 但是話題裡面的 history , time 舊->新==
- 在 db 裡面,所有的歷史話題,table 對應的資訊,應該都會是==isFinished = true 而且 isRated = true==
```typescript=1
interface IMessage {
customerName: string; // user暱稱
kefuName: string; // 客服暱稱
time: string; // 留言時間 格式: 2021-07-16 15:53
message: string; // 如果多行,請保留 \n,前端才知道什麼時候要斷行
type: 'Q' | 'A'; // Q: customer寫的, A: 客服寫的
}
interface IHistory {
history: IMessage[];
topicId: string; // 話題編號 (唯一值)
topicTime: string; // 此話題編號的 update time 格式: 2021-07-16 15:53
groupId: string; // 用戶的話題id text_config.js設定
groupName: string; // 用戶的話題名稱 text_config.js設定
}
// API回傳的格式會是以 IGetHistory 組成的 array
// 回傳示例
[
{
history: [
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:43',
message: '請問抽到新股,什麼時候知道結果?',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:48',
message: '可是我不想讓你知道結果',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:53',
message: '你這客服怎麼可以這麼優秀',
type: 'Q'
}, {
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:54',
message: '不優秀要怎麼當客服',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:55',
message: '我不知道要說什麼了',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:56',
message: '請問還有問題嗎?如果沒有問題我就結束話題了',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-16 15:58',
message: '好的~掰掰',
type: 'Q'
}
],
topicId: '23702224-febe-4443-a03f-e926a1bb0556',
topicTime: '2021-07-16 15:58',
groupId: 'G03',
groupName: '其他'
},
{
history: [
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:20',
message: '您好,我是股神客服001,很高興為您服務,有任何問題請給我留言,我將盡快給你答覆!',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:20',
message: '請問我是誰?',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:25',
message: '牛仔很忙,不要找我聊天',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:28',
message: '那不吵你了',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:35',
message: '請問還有問題嗎?如果沒有問題我就結束話題了',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-15 11:58',
message: '好的,掰掰',
type: 'Q'
},
],
topicId: '69462295-6c41-425f-a33f-fadb6310d7ba',
topicTime: '2021-07-15 11:58',
groupId: 'G03',
groupName: '其他'
},
{
history: [
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 08:43',
message: '您好,我是股神客服001,很高興為您服務,有任何問題請給我留言,我將盡快給你答覆!',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 08:43',
message: '請問抽到新股,什麼時候知道結果?',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 08:48',
message: '可是我不想讓你知道結果',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 09:03',
message: '你這客服怎麼可以這麼優秀',
type: 'Q'
}, {
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 09:04',
message: '不優秀要怎麼當客服',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 09:05',
message: '我不知道要說什麼了',
type: 'Q'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 09:06',
message: '請問還有問題嗎?如果沒有問題我就結束話題了',
type: 'A'
},
{
customerName: 'user暱稱',
kefuName: '客服001',
time: '2021-07-13 09:08',
message: '好的~掰掰',
type: 'Q'
}
],
topicId: '23892224-aabb-4443-a03f-e926a1bb0556',
topicTime: '2021-07-13 09:08',
groupId: 'G03',
groupName: '其他'
},
];
```
- 示意圖

# 前台 H5 邏輯
## H5 首頁
- 在首頁且 login 後,才打 checkStatus api
- 頻率: 跟==策略消息==同時撈取
- 若 checkStatus api 回傳==isRead = false==, 表示未讀,需顯示紅點
## H5 客服留言
- 進入預設選擇==新話題/當前話題==
### 新話題/當前話題
- 剛進畫面,打 getTopic api
- api 回傳==null==: 可開啟新話題
- api 回傳==object==: 依照回傳 object,顯示當前話題
- 新話題 getTopic api
- 回傳 null 時顯示
- 打 template api, template='招呼模板的編號', 將撈回的模板顯示在畫面上
- 話題必選/內容必填,才可送出,若其中一個未填,顯示紅字提示
- 送出中, 請顯示送出中
- 當前話題 getTopic api
- isRated = false, isFinished= false, 顯示輸入框
- isRated = false, isFinished= true, 顯示評分畫面,不會有輸入框
- 不會有其他狀況, 其他狀況代表有問題
- 內容必填,才可送出,若未填或小於 5 字,顯示紅字提示
- 送出中, 請顯示送出中
- 使用者按完送出或評分後
- 若成功, 則跳轉頁面
- 若失敗, 則停留原畫面, 並顯示原因
### 歷史話題
- 剛進畫面,打 history api
- 下拉選單預設都不選(所以撈回所有話題)
- 頻率: 只有==每次點擊歷史話題按鈕==or 更改下拉選單,才打 api,不做頻繁更新
# 後台所需的 API 們
## 0. 共用格式
| 項目 | 值 |
| ------ | -------------- |
| Type | JSON |
| cookie | token ==必填== |
## 1. 列表頁
| 項目 | 值 |
| ------ | ------------------------- |
| URL | /sys/dialogue/list |
| Method | GET |
| params | 搜尋列的條件們+分頁條件們 |
| table | sys_dialogue |
- 針對前端給的 params 以及 token 拿到的 userId,可以找出 userId 對應的==客服組別==,後端對==sys_dialogue==下 query,回傳對應的結果
- 分頁以及多個 params 的串法,請參照後台其他 API
- 示意圖

## 2. 刪除某話題編號對應的所有資料
| 項目 | 值 |
| ------ | ----------------------------------- |
| URL | /sys/dialogue/delete |
| Method | POST |
| params | ==topicId== |
| table | sys_dialogue + sys_dialogue_message |
- 請先從 token,確定該 userId 有刪除的權限,才需要做下述事情
- 刪除 sys_dialogue_message 該 ==topicId== 底下所有資料
- 刪除 sys_dialogue 該 ==topicId==資料
## 3. 撈取某話題編號(彈窗內的所有資料)
| 項目 | 值 |
| ------ | ---------------------------------------------------------------------------- |
| URL | /sys/dialogue/{topicId} |
| Method | GET |
| params | ==topicId== |
| table | sys_dialogue + sys_dialogue_message + customer_info(撈取 Mobile 及 NickName) |
- 回傳==sys_dialogue==及==sys_dialogue_message==對應的==topicId==,組成以下資料
- 回傳欄位
```json=
{
history: [
{
customerName: "aki_test",
kefuName: "超级管理员",
time: "2021-08-05 11:24",
message: "请问我是谁?",
type: "Q"
},
{
customerName: "aki_test",
kefuName: "超级管理员",
time: "2021-08-05 13:01",
message: "牛仔很忙,不要找我聊天",
type: "A"
},
{
customerName: "aki_test",
kefuName: "超级管理员",
time: "2021-08-06 09:52",
message: "那不吵你",
type: "Q"
},
{
customerName: "aki_test",
kefuName: "超级管理员",
time: "2021-08-06 11:53",
message: "请问还有问题吗?如果没有问题我就结束话题了",
type: "A"
},
{
customerName: "aki_test",
kefuName: "超级管理员",
time: "2021-08-06 13:05",
message: "没有了,谢谢",
type: "Q"
}
],
topicId: "23702224-febe-4443-a03f-e926a1bb0556",
topicTime: "2021-08-05 11:24",
customerName: "aki_test", // customer_info NickName
mobile: "19876543210", // customer_info Mobile
groupId: "G03",
groupName: "其他",
isFinished: true
}
```
- 示意圖


## 4. 客服回覆/結束話題
| 項目 | 值 |
| ------ | ----------------------------------- |
| URL | /sys/dialogue/update |
| Method | POST |
| params | 如==傳送欄位==所示 |
| table | sys_dialogue + sys_dialogue_message |
- sys_dialogue 更新欄位資訊
- 必定更新: updateTime, isRead 要改成 0, isReplied 要改成 1
- 可能更新: ==isFinish 改成 1== 或 ==更新 lastMessage==
- sys_dialogue_message 依照欄位寫入資訊
- ==這支 API 為後台客服傳送,寫入 sys_dialogue_message, type 一律為'A'==
* 前端傳送欄位
```json=
// 發送示例 (回覆)
{
topicId: "23702224-febe-4443-a03f-e926a1bb0556",
message: "请问还有问题吗?如果没有问题我就结束话题了"
}
// 發送示例 (結束話題)
{
topicId: "23702224-febe-4443-a03f-e926a1bb0556",
isFinished: true
}
```