---
# System prepended metadata

title: 前後台客服信息部分API及前端邏輯
tags: [股神]

---

---
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,
}
```

- 示意圖
  ![](https://i.imgur.com/CvlskD3.jpg)

## 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: '其他'
  },
];
```

- 示意圖
  ![](https://i.imgur.com/rQt47vT.jpg)
  


# 前台 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
- 示意圖

![](https://i.imgur.com/Nakptoe.jpg)

## 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
}
```

- 示意圖
  ![](https://i.imgur.com/NIs4ER8.jpg)

![](https://i.imgur.com/xGRMmlR.jpg)

## 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
}
```
