---
# System prepended metadata

title: 2-1.分類列表：分類列表頁、借書 & 歸還API

---

---
tags: NeutecLife App
---

# 2-1.分類列表：分類列表頁、借書＆歸還 API

:::info
目錄：
<a href="https://hackmd.io/FStSBTFdRhac3tsDr8OyiA">0.登入功能相關 API 文件</a>
<a href="https://hackmd.io/coOyibBDRYqJpluQIQFYmg">1.首頁功能相關 API 文件</a>
<a href="https://hackmd.io/-A3kGYJ8SHyjegBROlwJow">2-1.分類列表：分類列表頁、借書＆歸還 API 文件</a>
<a href="https://hackmd.io/boCGrFpsR0CciLYEXS-kxw">2-2.分類列表：借物 API 文件</a>
<a href="https://hackmd.io/jBWDb0OaT_KV-_ducdzqsQ">2-3.分類列表：會議室＆英文課 API 文件</a>
<a href="https://hackmd.io/FhZ89ZDxSbOK8oYslEXuCA">3.最新消息 API 文件</a>
<a href="https://hackmd.io/SSAxobFGQEC8lyHiu485iQ">4.通知 API 文件</a>
<a href="https://hackmd.io/Fz8d0LtbS2iwhuI3QmmzYQ">5.我的 API 文件</a>

> [time=Jan 4, 2024]
* `更新`  Document init
> [time=May 16, 2024]
* `更新`  所有borrow命名修改成loan
> [time=Jun 12, 2024]
* `更新` 統一型態：不使用0與1代表Bool，將number修正為int型態
> [time=Jun 17, 2024]
* `更新` 修正借書相關API參數命名與結構
> [time=Jun 19, 2024]
* `更新` 欄位更名：commentNum更名為ratingNum，中文說明更正為「評價總數」
* `更新` 欄位更名：loanStatus更名為loanPanelStatus
* `更新` 新增「借書狀態8」loanPanelStatus 第8種狀態
* `更新` 新增「[狀態代碼](#狀態代碼)」1012 Blacklist.
* `更新` 資料型態變更：star資料型態由string變更為float
* `更新` 欄位更名：commentNum更名為ratingNum
> [time=Jun 25, 2024]
* `更新` 新增「借物狀態6」loanPanelStatus 第6種狀態
> [time=Jun 26, 2024]
* `新增` [socket對話資料處理型態](#socket對話資料處理型態)
* `更新` 各API修改[資料處理型態](#socket對話資料處理型態)(type)值
> [time=Jul 02, 2024]
* `更新` [bookDetailPage](#bookDetailPage)與[itemDetailPage](#itemDetailPage)縮減與整合content內容
* `新增` [itemSearchPage](#itemSearchPage)，與bookSearchPage做區別。
> [time=Jul 08, 2024]
* `更新` [bookDetailPage](#bookDetailPage)與[itemDetailPage](#itemDetailPage)在content module增加isLoaned辨識此物是否曾經被借用過
> [time=Jul 26, 2024]
* `更新` [bookDetailPage](#bookDetailPage)與[itemDetailPage](#itemDetailPage)在loanPanel module增加isPositive辨識toast icon的顏色
* `更新` [bookDetailPage](#bookDetailPage)與[itemDetailPage](#itemDetailPage)在loanPanel module增加nextCanLoanDate與nextExpectReturnDate欄位，並移除expectLoanDate欄位
* `更新` [bookDetailPage](#bookDetailPage)與[itemDetailPage](#itemDetailPage)新增location(物品位置)欄位
> [time=Jul 29, 2024]
* `更新` 日期格式統一採用 yyyy/M/
> [time=Aug 8, 2024]
* `更新` 圖片路徑將不帶入domain，App端將預設domain帶入
> [time=Aug 13, 2024]
* `更新` bookPage與itemPage的filter排序修正為1:上架新到舊、2:評價高到低、3:借閱多到少，上架新到舊為預設值
> [time=Aug 14, 2024]
* `更新` favorite收藏功能修改，由App實做大部分的工，Server端僅透過minePage.favoriteList回傳
> [time=Aug 28, 2024]
* `更新` returnPage-return歸還功能request格式簡化
> [time=Nov 4, 2024]
* `新增` 所有websocket API皆可額外帶入timeout參數
> [time=Nov 14, 2024]
* `更新` [bookDetailPage](#bookDetailPage)在reserve module (type=add)增加isLoanButton欄位
> [time=Dec 2, 2024]
* `更新` 錯誤代碼
> [time=Feb 25, 2025]
* `更新` itemGroupId更名為functionId
* `更新` bookSearchPage request新增functionId
> [time=Nov 21, 2025]
* `更新` 電玩 更名為 動漫電玩
----
:::

```
所有websocket API皆可額外帶入timeout參數做測試用途：

參數名稱：timeout
值：0-9 代表延遲回應的秒數，可模擬網路不穩回應變慢的情況
   99 代表Server端出現未知的錯誤，可模擬Server端某功能出現異常的情況
   
 ```

## 2. 分類列表 API

### ✅ functionListPage

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `分類列表頁資訊`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65ddacbd2c17a4b71e803e41">`zeplin前端畫面`</a>
#### Remark
```
1. 八項功能的圖片icon以靜態方式儲存在App端
 ```

**Request** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "functionListPage",
  "module": "all",
  "type": "select",
  "data": {}
}
```

**Response**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | string | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y  | 手機畫面名稱  |
| info      | string | Y  | 手機畫面資訊 |
| module    | string | Y  | 手機畫面區塊名稱 |
| status    | int    | Y  | [狀態代碼](#狀態代碼) |
| errorMsg  | string |    | 錯誤訊息 |
| type      | string | Y  | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y  | 資料筆數 |
| data      | array  | Y  | 資料內容 |
| functionId| int    | Y  | 分類列表id(1~8固定：1書籍、2會議室、3其他設備、4英文課、5電動、6露營裝備、7桌遊、8其他)|
| title     | string | Y  | 功能名稱 |
| isNew     | bool   | Y  | 是否有新資訊<br>書籍：是否有新書上架於7日內<br>會議室：無，永遠保持false<br>其他設備：是否有新物品上架於7日內<br>英文課：是否開放選課<br>動漫電玩：是否有新物品上架於7日內<br>露營裝備：是否有新物品上架於7日內<br>桌遊：是否有新物品上架於7日內<br>其他：是否有新物品上架於7日內|
| group     | int    | Y  | 功能群組名稱 (1:公司資源/2:社團資產) |
| datetime  | string | Y  | 資料發佈時間 |


```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"functionListPage",
  "info": [
    {
      "module": "functionList",
      "status": 200,
      "type": "list",
      "num": 8,
      "data": [
        {
          "functionId": 1,
          "title": "書籍",
          "isNew": true,
          "group": 1
        },
        {
          "functionId": 2,
          "title": "會議室",
          "isNew": true,
          "group": 1
        },
        {
          "functionId": 3,
          "title": "其他設備",
          "isNew": true,
          "group": 1
        },
        {
          "functionId": 4,
          "title": "英文課",
          "isNew": 1,
          "group": 1
        },
        {
          "functionId": 5,
          "title": "動漫電玩",
          "isNew": true,
          "group": 2
        },
        {
          "functionId": 6,
          "title": "露營裝備",
          "isNew": true,
          "group": 2
        },
        {
          "functionId": 7,
          "title": "桌遊",
          "isNew": true,
          "group": 2
        },
        {
          "functionId": 8,
          "title": "其他",
          "isNew": true,
          "group": 2
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

</br>

### ✅ bookPage

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `借閱書籍入口頁資訊`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cb945441dc749debcae">`zeplin前端畫面`</a>

#### Remark
```
1. 若該書籍分類底下無任何書籍，就不列出；確保每個分類底下至少有一項資
料。

2. 本月新書區塊一定要有資料，當API要建立newBookList這個module時，抓取最新推薦月份的書籍資料。
 ```

**Request** 
| Parameter     | Type     | Require | Description |
| -----------   | -------- | ------- | ----------- |
| requestId     | string   | Y       | 對話id  |
| page          | string   | Y       | 手機畫面名稱 |
| module        | string   | Y       | 功能區塊名稱 |
| type          | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data          | object   | Y       | 參數資料 |
| categoryId    | int      | Y       | bookList的書籍分類id<br>0:代表全部，「全部」這個分類由App端加入 |
| sort          | int      | Y       | bookList的排序方式 (都只有降冪DESC方式)<br>1:上架新到舊(預設值)<br>2: 評價高到低<br>3: 借閱多到少 |
| lastId        | int      |         | bookList的分頁機制：帶入目前資料的最後一筆itemId，API將回傳此itemId之後的30筆資料。若不帶此參數則提供最前面的30筆資料。 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookPage",
  "module": "all",
  "type": "select",
  "data": {
      "categoryId":0,
      "sort":1,
      "lastId": 30
  }
}
```
**Response**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |

<br>

**promoteTextList 推廣文字區塊（則數限制1~10筆）**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| title       | string | Y | 推廣文字大標題(限單行)  |
| subTitle    | string | Y | 推廣文字小標題(至多兩行)<br><font color='red'>需將\<br\>轉換成\r</font>輸出給App |

<br>

**newBookList 本月新書區塊**
| Parameter      | Type     | Require | Description |
| -----------    | -------- | ------- | ---------- |
| itemId         | int      | Y | 書籍id  |
| title          | string   | Y | 書名 |
| author         | string   | Y | 作者 |
| categoryId     | int      | Y | 書籍分類id |
| isNew          | bool     | Y | 是否為新書(新上架7日內為1) |
| isFavorite     | bool     | Y | 是否被選定為我的最愛 |
| imgUrl         | string   | Y | 圖片路徑 |
| star           | float    | Y | 星等平均(四捨五入，小數點1位，零也要出現。ex:5.0) |
| ratingNum      | int      | Y | 評價總數 |

#### Remark
```
1. 若該書籍分類底下無任何書籍，就不列出；確保每個分類底下至少有一項資料。
2. 既定的分類與index如下：
商業理財        1 
心理勵志        2 
藝術設計        3 
人文社會        4 
文學小說        5 
電腦資訊        6 
生活旅遊        7 
親子教養        8 
飲食保健        9 
自然科普        10 
漫畫圖文        11
```

<br>
 
**bookCategory 書籍分類選單**
| Parameter      | Type     | Require | Description |
| -----------    | -------- | ------- | ----------- |
| categoryId     | int      | Y | 書籍分類id  |
| name           | string   | Y | 書籍分類名稱 |

<br>

**bookList 書籍列表區塊**
| Parameter      | Type     | Require | Description |
| -----------    | -------- | ------- | ----------- |
| itemId         | int      | Y | 書籍id  |
| title          | string   | Y | 書名 |
| author         | string   | Y | 作者 |
| categoryId     | int      | Y | 書籍分類id |
| isNew          | bool     | Y | 是否為新書(新上架7日內為true) |
| isFavorite     | bool     | Y | 是否被選定為我的最愛 |
| imgUrl         | string   | Y | 圖片路徑 |
| star           | float    | Y | 星等平均(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| ratingNum      | int      | Y | 評價總數 |

<br>
 
**wishUrl 我要許願區塊**
| Parameter  | Type    | Require | Description |
| ---------- | --------| ------- | ----------- |
| url        | string  | Y | 我要許願google form表單連結 |

<br>

    
```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "bookPage",
  "info": [
    {
      "module": "promoteTextList",
      "status":200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "title": "與書為友，閱讀人生",
          "subTitle": "借閱書籍，帶你走遍千山萬水，探索無盡的知識之海"
        },
        {
          "title": "書香陣陣飄，暖意滿心房",
          "subTitle": "書像一座寶庫，潛藏着無數寶藏",
        },
      ],
      "datetime":"2024/6/26 12:38:11"
    },
    {
      "module": "newBookList",
      "status":200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "itemId": 1,
          "title": "奧本海默",
          "author":"凱・博得、馬丁・薛",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": true,
          "imgUrl": "/img/book/1.png",
          "star": 4.7,
          "ratingNum": 99
        },
        {
          "itemId": 2,
          "title": "哈利波特",
          "author":"J.K.,Rowlling",
          "categoryId": 2,
          "isNew": true,
          "isFavorite": false,
          "imgUrl": "/img/book/2.png",
          "star": 4.7,
          "ratingNum": 99
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    },
    {
      "module": "bookCategory",
      "status":200,
      "type": "list",
      "num": 11,
      "data": [
        {
          "categoryId": 1,
          "name": "商業理財"
        },
        {
          "categoryId": 2,
          "name": "心理勵志"
        },
        {
          "categoryId": 3,
          "name": "藝術設計"
        },
        {
          "categoryId": 4,
          "name": "人文社會"
        },
        {
          "categoryId": 5,
          "name": "文學小說"
        },
        {
          "categoryId": 6,
          "name": "電腦資訊"
        },
        {
          "categoryId": 7,
          "name": "生活旅遊"
        },
        {
          "categoryId": 8,
          "name": "親子教養"
        },
        {
          "categoryId": 9,
          "name": "飲食保健"
        },
        {
          "categoryId": 10,
          "name": "自然科普"
        },
        {
          "categoryId": 11,
          "name": "漫畫圖文"
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    },
    {
      "module": "bookList",
      "status":200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "itemId": 1,
          "title": "奧本海默",
          "author":"凱・博得、馬丁・薛",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": true,
          "imgUrl": "/img/book/1.png",
          "star": 4.7,
          "ratingNum": 99
        },
        {
          "itemId": 2,
          "title": "哈利波特",
          "author":"J.K.,Rowlling",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": false,
          "imgUrl": "/img/book/2.png",
          "star": 4.1,
          "ratingNum": 199
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    },
    {
      "module": "wishUrl",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "url": "https://forms.gle/96PdDNsgMNFFJ25n7",
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    }
  ],
  "datetime": "2024/6/26 12:38:11"
}
```
</br>

### ✅ bookPage-bookList 分頁機制

**Request for bookList Module 書籍列表區塊(第二頁為例)** 
| Parameter     | Type     | Require | Description |
| -----------   | -------- | ------- | ----------- |
| requestId     | string   | Y       | 對話id  |
| page          | string   | Y       | 手機畫面名稱 |
| module        | string   | Y       | 功能區塊名稱 |
| type          | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data          | object   | Y       | 參數資料 |
| categoryId    | int      | Y       | bookList的書籍分類id<br>0:代表全部，「全部」這個分類由App端加入 |
| sort          | int      | Y       | bookList的排序方式 (都只有降冪DESC方式)<br>1:上架新到舊(預設值)<br>2: 評價高到低<br>3: 借閱多到少 |
| lastId        | int      |         | bookList的分頁機制：帶入目前資料的最後一筆itemId，API將回傳此itemId之後的30筆資料。若不帶此參數則提供最前面的30筆資料。 |
#### Remark
```
以下為要求bookList第二頁的範例
 ```
```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookPage",
  "module": "bookList",
  "type": "select",
  "data": {
      "categoryId":0,
      "sort":1,
      "lastId": 30
  }
}
```

<br>

**Response for bookList Module 書籍列表區塊(第二頁為例)**

| Parameter  | Type   | Require | Description |
| --------   | -------| ------- | ----------- |
| itemId     | int    |    Y    | 書籍id  |
| title      | string |    Y    | 書名 |
| author     | string |    Y    | 作者 |
| categoryId | int    |    Y    | 書籍分類id |
| isNew      | bool   |    Y    | 是否為新書(新上架7日內為true) |
| isFavorite | bool   |    Y    | 是否被選定為我的最愛 |
| imgUrl     | string |    Y    | 圖片路徑 |
| star       | float  |    Y    | 星等平均(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| ratingNum  | int    |    Y    | 評價總數 |
```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "bookPage",
  "info": [
    {
      "module": "bookList",
      "status":200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "itemId": 1,
          "title": "奧本海默",
          "author":"凱・博得、馬丁・薛",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": true,
          "imgUrl": "/img/book/1.png",
          "star": 4.7,
          "ratingNum": 99
        },
        {
          "itemId": 2,
          "title": "哈利波特",
          "author":"J.K.,Rowlling",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": false,
          "imgUrl": "/img/book/2.png",
          "star": 4.1,
          "ratingNum": 199
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    },
  ],
  "datetime": "2024/6/26 12:38:11"
}
```

<br>


### bookPage-bookList 資料更新異動通知
**Response for bookList Module 書籍列表區塊**

| Parameter  | Type   | Require | Description |
| --------   | -------| ------- | ----------- |
| itemId     | int    |    Y    | 書籍id  |
| title      | string |    Y    | 書名 |
| author     | string |    Y    | 作者 |
| categoryId | int    |    Y    | 書籍分類id |
| isNew      | bool   |    Y    | 是否為新書(新上架7日內為true) |
| isFavorite | bool   |    Y    | 是否被選定為我的最愛 |
| imgUrl     | string |    Y    | 圖片路徑 |
| star       | float  |    Y    | 星等平均(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| ratingNum  | int    |    Y    | 評價總數 |
| nextId     | int    |    Y    | 該筆資料的下一筆itemId，若此資料為最後一筆，該值顯示空值。<br><font color=red>這裏的nextId會根據排序(sort)來得知，並非僅是itemId+1這個單一邏輯。</font>|
#### Remark
```
主動通知時requestId為空
 ```
```json=
{
  "requestId": "",
  "status": 200,
  "page": "bookPage",
  "info": [
    {
      "module": "bookList",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "itemId": 606,
          "title": "奧本海默",
          "author":"凱・博得、馬丁・薛",
          "categoryId": 1,
          "isNew": true,
          "isFavorite": true,
          "imgUrl": "/img/book/1.png",
          "star": 4.7,
          "ratingNum": 99,
          "nextId": 607
        }
      ],
      "datetime":"2024/6/26 12:38:11"
    },
  ],
  "datetime": "2024/6/26 12:38:11"
}
```

<br>



### ✅ bookPage-favorite

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍列表頁-收藏/取消收藏排隊 動作`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cb945441dc749debcae">`zeplin前端畫面`</a>

#### Remark
```
1.本月新書區塊中的書籍，也會出現在書籍列表裡。
因此當使用者按下本月新書的收藏，書籍列表的愛心按鈕也需要同步亮起。
此部分為App端實作。

2.收藏有異動時，API僅回傳minePage.favoriteList。
 ```
 
 ![NeutecLife收藏機制0813.drawio](https://hackmd.io/_uploads/HJ7wOZ59R.png)
<a href="https://dl.dropboxusercontent.com/scl/fi/5k0g19yajw2yaljxhs9gy/NeutecLife-240813.drawio.png?rlkey=f6toj7w7ynrag218k3ifymqec&st=ms7p2zcf&dl=0" target="_blank">查看收藏流程原圖</a>
 
**Request for 新增收藏動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookPage",
  "module": "favorite",
  "type": "insert",
  "data": {
      "itemId":1
  }
}
```
**Response for 新增收藏成功**

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |
| type        | int      | Y       | 項目型態<br>1:書籍/物品<br> <font color=lightgray>[Phase2] 2:活動/意見調查</font> |
| functionId | int      | Y       | 分類列表id（1書籍、3其他設備、5電動、6露營裝備、7桌遊、8其他）  |
| id       | int   | Y       | 如果type == 1 or 2，id代表itemId<br><font color=lightgray>[Phase2] 若type==2，id代表eventId</font> |
| title       | string   | Y       | 借用項目標題(書名/品名/活動名稱) |
| subtitle    | string   | Y       | functionId為1＝author(書籍作者)；<br>functionId為3~8=teamName(物品所屬單位的名稱)|
| iconUrl     | string   | Y       | 借用項目圖片連結  |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",  
  "status":200,
  "page":"minePage",
  "info": [
    {
      "module": "favoriteList",
      "status": 200,
      "type": "add",
      "num": 1,
      "data": [
        {
          "type":1,
          "functionId":1,
          "id":1,
          "title":"奧本海默",
          "subTitle":"凱・博得、馬丁・薛",
          "iconUrl":"/img/book/1.png"
        }
      ],
      "datetime": "2024/7/2 12:38:11"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

<br>

**Request for 取消收藏動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookPage",
  "module": "favorite",
  "type": "delete",
  "data": {
      "itemId":1
  }
}
```
**Response for 取消收藏成功**

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |
| type        | int      | Y       | 項目型態<br>1:書籍/物品<br> <font color=lightgray>[Phase2] 2:活動/意見調查</font> |
| functionId | int      | Y       | 分類列表id（1書籍、3其他設備、5電動、6露營裝備、7桌遊、8其他）  |
| title       | string   | Y       | 借用項目標題(書名/品名/活動名稱) |
| subtitle    | string   | Y       | functionId為1＝author(書籍作者)；<br>functionId為3~8=teamName(物品所屬單位的名稱)|
| iconUrl     | string   | Y       | 借用項目圖片連結  |
```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",  
  "status":200,
  "page":"minePage",
  "info": [
    {
      "module": "favoriteList",
      "status": 200,
      "type": "remove",
      "num": 1,
      "data": [
        {
          "type":1,
          "functionId":1,
          "id":1,
          "title":"奧本海默",
          "subTitle":"凱・博得、馬丁・薛",
          "iconUrl":"/img/book/1.png"
        }
      ],
      "datetime": "2024/7/2 12:38:11"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

### ✅ bookDetailPage

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍內容頁資訊`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cb5a1f5bd7e37bb7e94">`zeplin前端畫面`</a>

**Request** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id       |
| page        | string   | Y       | 手機畫面名稱  |
| module      | string   | Y       | 功能區塊名稱  |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態)  |
| data        | object   | Y       | 資料參數      |
| itemId      | int      | Y       | 書籍id       |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "all",
  "type": "select",
  "data": {
      "itemId": 1
  }
}
```
**Response**
| Parameter | Type     | Require | Description |
| ----------| -------- | ------- | ----------- |
| requestId | string   | Y       | 對話id  |
| status    | int      | Y       | [狀態代碼](#狀態代碼) |
| page      | string   | Y       | 手機畫面名稱  |
| info      | array    | Y       | 手機畫面資訊 |
| module    | string   | Y       | 手機畫面區塊名稱 |
| status    | int      | Y       | [狀態代碼](#狀態代碼) 
| errorMsg  | string   |         | 錯誤訊息 |
| type      | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| num       | int      | Y       | 資料筆數 |
| data      | array    | Y       | 資料內容 |

<br>

**Response bookContent module**
| Parameter      | Type     | Require | Description |
| -----------    | -------- | ------- | ----------- |
| itemId         | int      | Y | 書籍編號 |
| imgUrl         | array    | Y | 書籍圖片URL，1或2張圖片 |
| title          | string   | Y | 書名 |
| author         | string   | Y | 作者 |
| categoryName   | string   | Y | 書籍分類名稱 |
| publisher      | string   | Y | 出版社名稱 |
| serialNo       | string   | Y | 書籍編號 |
| location       | string   | Y | 書籍位置 |
| isNew          | bool     | Y | 是否為新書(新上架7日內為1) |
| isFavorite     | bool     | Y | 是否被選定為我的最愛 |
| desc           | string   | Y | 書籍介紹 |
| star           | float    | Y | 星等(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| ratingNum      | int      | Y | 評價總數 |
| loanRule       | string   | Y | 借用規則文字內容 |
| returnRule     | string   | Y | 歸還與展延文字內容 |
| isLoaned       | bool     | Y | 是否曾經借用過<br>true:曾借用 false:不曾借用<br>(用來判斷是否出現評分及評論表單) |

<br>

**Response commentList module**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| name        | string   | Y       | 評論者<br>(匿名留言格式：匿名<br>實名留言格式：NE097-Bruce Huang)|
| star        | float    | Y       | 星等(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| comment     | string   | Y       | 評論內容(API判斷是否有輸入留言：去除半形空白與全形空白後為空值則為「無評論」) |

<br>

**Response loanPanel module 借書版面狀態**
```
module loanPanel在下方一併說明
 ```


```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "bookDetailPage",
  "info": [
    {
      "module": "bookContent",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "itemId":1,
          "imgUrl":["/img/book/1-1.png", "/img/book/1-2.png"],
          "title": "奧本海默",
          "author":"凱・博得、馬丁・薛",
          "categoryName":"藝術設計",
          "publisher":"避風港文化有限公司",
          "serialNo":"B3028",
          "location":"17F咖啡廳書櫃",
          "isNew": true,
          "isFavorite": true,
          "desc": "書本介紹有很多字",
          "star": 4.7,
          "ratingNum": 99,
          "loanRule":"借用規則文字內容",
          "returnRule":"歸還與展延文字內容",
          "isLoaned":true
        }
      ],
      "datetime": "2024/7/2 12:38:11"
    },
    {
      "module": "commentList",
      "status": 200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "name": "NE097-Bruce Huang",
          "comment": "太好看！！",
          "star": 5.0
        },
        {
          "name": "匿名",
          "comment": "太好看！！",
          "star": 5.0
        }
      ],
      "datetime": "2024/7/2 12:38:11"
    },
    {
      "module": "loanPanel",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":1,
          "itemId":1,
          "nextCanLoanDate": "2023/6/10",
          "nextExpectReturnDate": "2023/6/16",
          "loanedDate": "",
          "expectReturnDate": "",
          "loanWorkDays": 0,
          "leftDays": 0,
          "extendWorkDays": 0,
          "expectExtendReturnDate":""
        }
      ],
      "datetime": "2024/7/2 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}

```

#### 借書狀態1: 此書無人借閱情況的loanPanel
![截圖 2024-01-24 晚上10.32.29](https://hackmd.io/_uploads/r1z2yiCFT.png)
![截圖 2024-01-24 晚上10.35.27](https://hackmd.io/_uploads/r1GSgiRYa.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus| int      | Y | 借用板塊狀態=1 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate   | string   | Y | 借用時間=系統今日日期(這裡的值不是真的借出的時間，因為還沒借) |
| expectReturnDate| string| Y | 預計歸還日期=今日＋60個工作天(根據書籍借用規則) |
| loanWorkDays    | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還=60 |
| extendWorkDays   | int      | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate| string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":1,
      "itemId":1,
      "nextCanLoanDate": "2023/6/10",
      "nextExpectReturnDate": "2023/6/16",
      "loanedDate": "",
      "expectReturnDate": "",
      "loanWorkDays": 0,
      "leftDays": 0,
      "extendWorkDays": 0,
      "expectExtendReturnDate":""
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```


#### 借書狀態2: 外借中＆尚未可以展延情況的loanPanel
![截圖 2024-01-24 晚上10.44.51](https://hackmd.io/_uploads/ryeYfsCYT.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus| int    | Y | 借用板塊狀態=2 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate   | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還=60 |
| extendWorkDays| int     | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate  | string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":2,
      "itemId":1,
      "nextCanLoanDate": "",
      "nextExpectReturnDate": "",
      "loanedDate":"2024/1/17",
      "expectReturnDate":"2024/4/9",
      "loanWorkDays": 0,
      "leftDays": 45,
      "extendWorkDays": 0,
      "expectExtendReturnDate":""
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```
#### 借書狀態3: 外借中＆開放展延、無人排隊情況的loanPanel
![截圖 2024-01-24 晚上10.57.07](https://hackmd.io/_uploads/SkJvHjAY6.png)
![截圖 2024-01-25 上午10.20.23](https://hackmd.io/_uploads/SJftrHk9a.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus| int    | Y | 借用板塊狀態=3 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate   | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還 |
| extendWorkDays| int     | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate  | string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":3,
      "itemId":1,
      "nextCanLoanDate": "",
      "nextExpectReturnDate": "",
      "loanedDate":"2024/1/17",
      "expectReturnDate":"2024/4/9",
      "loanWorkDays": 0,
      "leftDays": 45,
      "extendWorkDays": 15,
      "expectExtendReturnDate":"2024/4/24"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

#### 借書狀態4: 外借中＆開放展延、有人排隊情況的loanPanel
![截圖 2024-01-25 上午10.22.16](https://hackmd.io/_uploads/SyIe8r15T.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus| int    | Y | 借用板塊狀態=4 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate   | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還 |
| extendWorkDays| int     | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate  | string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":4,
      "itemId":1,
      "nextCanLoanDate": "",
      "nextExpectReturnDate": "",
      "loanedDate":"2024/1/17",
      "expectReturnDate":"2024/4/9",
      "loanWorkDays": 0,
      "leftDays": 45,
      "extendWorkDays": 0,
      "expectExtendReturnDate":
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

#### 借書狀態5: A君已借閱，B君尚未按下(或已取消)排隊按鈕，B君所看到的loanPanel
![截圖 2024-01-25 上午10.31.13](https://hackmd.io/_uploads/HywDOBJqT.png)
![截圖 2024-09-05 上午11.48.58](https://hackmd.io/_uploads/ryIZsiI3R.png)


| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus| int    | Y | 借用板塊狀態=5 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate   | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還 |
| extendWorkDays| int     | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate| string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":5,
      "itemId":1,
      "nextCanLoanDate": "2024/6/20",
      "nextExpectReturnDate": "",
      "loanedDate":"",
      "expectReturnDate":"",
      "loanWorkDays": 0,
      "leftDays": 0,
      "extendWorkDays": 0,
      "expectExtendReturnDate":""
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

<br>

#### 借書狀態6: A君已排隊，A君所看到的loanPanel
![截圖 2024-05-17 下午6.44.27](https://hackmd.io/_uploads/r10SKFrXA.png)
![截圖 2024-01-26 下午5.02.55](https://hackmd.io/_uploads/Sk48Bxb96.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus   | int      | Y | 借用板塊狀態=6 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate     | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays     | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還 |
| extendWorkDays   | int      | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate| string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":6,
      "itemId":1,
      "nextCanLoanDate": "2024/10/25",
      "nextExpectReturnDate": "",
      "loanedDate":"",
      "expectReturnDate":"",
      "loanWorkDays": 0,
      "leftDays": 0,
      "extendWorkDays": 0,
      "expectExtendReturnDate":"",
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

#### 借書狀態7: A君已借閱，A君已展延，A君所看到的loanPanel
![截圖 2024-08-06 下午6.30.17](https://hackmd.io/_uploads/S1AwhdycC.jpg)


| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus   | int      | Y | 借用板塊狀態=7 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate     | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還 |
| extendWorkDays   | int      | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate| string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":7,
      "itemId":1,
      "nextCanLoanDate": "",
      "nextExpectReturnDate": "",
      "loanedDate":"2024/1/17",
      "expectReturnDate":"",
      "loanWorkDays": 0,
      "leftDays": 98,
      "extendWorkDays": 0,
      "expectExtendReturnDate":"2024/4/24",
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

#### 借書狀態8: A君已借閱，A君已逾期，A君所看到的loanPanel
![截圖 2024-06-19 下午5.03.16](https://hackmd.io/_uploads/r1jajDgLC.png)

| Parameter    | Type     | Require | Description |
| -----------  | -------- | ------- | ----------- |
| loanPanelStatus   | int      | Y | 借用板塊狀態=8 |
| itemId       | int      | Y | 書籍id |
| nextCanLoanDate| string   | Y | 預計可借用日期(排隊時顯示用) |
| nextExpectReturnDate| string   | Y | 預計可借用的歸還日期=nextCanLoanDate＋loanWorkDays＋holidays |
| loanedDate     | string   | Y | 借用時間 |
| expectReturnDate| string| Y | 預計歸還日期 |
| loanWorkDays | int      | Y | 書籍可借用工作天數=60(根據書籍借用規則) |
| leftDays     | int      | Y | 剩餘幾日須歸還<br><font color='red'>逾期天數的值也來自leftDays，若是逾期1天，leftDays的值為-1。</font> |
| extendWorkDays   | int      | Y | 可展延工作天數=15(根據書籍借用規則) |
| expectExtendReturnDate| string | Y | 預計展延後歸還日期 |

```json=
{
  "module": "loanPanel",
  "status":200,
  "type": "list",
  "num": 1,
  "data": [
    {
      "loanPanelStatus":8,
      "itemId":1,
      "nextCanLoanDate": "",
      "nextExpectReturnDate": "",
      "loanedDate":"2024/1/17",
      "expectReturnDate":"2024/4/9",
      "loanWorkDays": 0,
      "leftDays": -1,
      "extendWorkDays": 15,
      "expectExtendReturnDate":"2024/4/24"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

<br>

#### Response for 失敗(書籍被刪除或下架)
| Parameter | Type   | Require | Description |
| ----------| -------| ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| errorMsg  | string | Y       | 錯誤訊息 |
| datetime  | string | Y       | 資料回應時間 |

<img src="https://hackmd.io/_uploads/rkx0M9ZdQge.png" width="250" />

<br>

```
當書籍被刪除或下架時再透過「舊通知」或「舊蒐藏」點擊，將會看見錯誤訊息Dialog。
```

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "bookDetailPage",
  "info": [
    {
      "module": "bookContent",
      "status": 1021,
      "errorMsg": "查無此書籍",
      "detetime": "2025/8/13 12:38:11"
    }
    
  ],
  "datetime": "2025/8/13 12:38:11"
}
```
</br>

### ✅ bookDetailPage-loan,extend,reserve

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍內容頁資訊-借閱、展延、排隊/取消排隊 動作`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cb5a1f5bd7e37bb7e94">`zeplin前端畫面`</a>

#### Remark
```
1.當完成動作後，將需要立即更新loanPanel的module資訊
2.做loan, extend & reserve三個動作前，API需先判斷借用者是否在黑名單中。
 ```
**Request for loan module 借閱動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |

```
Step1(app request). App在做借用時，會先做reserve insert，再做loan insert
```
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| isLoanButton      | bool      | Y       | 按鈕借用來源判斷 備註(false:我要排隊 true:我要借用) |
```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "page": "bookDetailPage",
  "module": "reserve",
  "type": "insert",
  "data": {
      "itemId":1,
      "isLoanButton":false
  }
}
```
```
Step1(api response). API將回傳bookDetailPage.reserve，data為空值，因為此時並非一般的「排隊」
```
```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "reserve",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [],
      "datetime": "2023/11/1 12:38:11"
    }
  "datetime": "2023/11/1 12:38:11"
}
```

```
Step2. 當App收到response為bookDetailPage.reserve.status (requestId需要有對應)為200時，再繼續執行loan insert借用動作
```
```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "loan",
  "type": "insert",
  "data": {
      "itemId":1
  }
}
```
**Response for loan module 借閱動作-成功**

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |
| location  | string | Y | 取書位置 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "loan",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "location": "17F書架"
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "loanPanel",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":2,
          "itemId":1,
          "nextCanLoanDate": "",
          "nextExpectReturnDate": "",
          "loanedDate":"2024/1/17",
          "expectReturnDate":"2024/4/9",
          "loanWorkDays": 60,
          "leftDays": 45,
          "extendWorkDays": 15,
          "expectExtendReturnDate":""
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

**Response for loan module 借閱動作-失敗 (因黑名單失敗為例)**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y  | 對話id  |
| status    | int    | Y  | [狀態代碼](#狀態代碼)  |
| page      | string | Y  | 手機畫面名稱  |
| info      | array  | Y  | 手機畫面資訊 |
| module    | string | Y  | 手機畫面區塊名稱 |
| status    | int    | Y  | [狀態代碼](#狀態代碼) |
| errorMsg  | string |    | 錯誤訊息 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "loan",
      "status": 1012,
      "errorMsg": "blacklist",
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "loanPanel",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":1,
          "itemId":1,
          "nextCanLoanDate": "",
          "nextExpectReturnDate": "",
          "loanedDate": "2024/1/17",
          "expectReturnDate": "2024/4/9",
          "loanWorkDays": 60,
          "leftDays": 60,
          "extendWorkDays": 15,
          "expectExtendReturnDate":""
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

<hr>

**Request for extend module 展延動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "extend",
  "type": "update",
  "data": {
      "itemId":1
  }
}
```
**Response for extend module 展延動作**
| Parameter | Type     | Require | Description |
| --------- | -------- | ------- | ----------- |
| requestId | string   | Y  | 對話id  |
| status    | int      | Y  | [狀態代碼](#狀態代碼)  |
| page      | string   | Y  | 手機畫面名稱  |
| info      | array    | Y  | 手機畫面資訊 |
| module    | string   | Y  | 手機畫面區塊名稱 |
| status    | int      | Y  | [狀態代碼](#狀態代碼) |
| errorMsg  | string   |    | 錯誤訊息 |
| type      | string   | Y  | [資料處理型態](#socket對話資料處理型態) |
| num       | int      | Y  | 資料筆數 |
| data      | array    | Y  | 資料內容 |
| toast     | string   | Y  | 回應訊息 |
| isPositive| bool     | Y  | 回應訊息是否為積極行為，true:icon顏色為藍色, false:icon顏色為白色 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "extend",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "toast": "已展延至2024/4-/4",
          "isPositive":true
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "loanPanel",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":7,
          "itemId":1,
          "nextCanLoanDate": "",
          "nextExpectReturnDate": "",
          "loanedDate":"2024/1/17",
          "expectReturnDate":"2024/4/9",
          "loanWorkDays": 60,
          "leftDays": 45,
          "extendWorkDays": 15,
          "expectExtendReturnDate":"2024/4/24"
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```
<hr>

**Request for reserve module 排隊動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |
| isLoanButton      | bool      | Y       | 按鈕借用來源判斷 備註(false:我要排隊 true:我要借用) |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "reserve",
  "type": "insert",
  "data": {
      "itemId":1,
      "isLoanButton":false
  }
}
```
**Response for reserve module 排隊動作**
| Parameter | Type   | Require | Description |
| ----------| -------| ------- | ----------- |
| requestId | string | Y  | 對話id  |
| status    | int    | Y  | [狀態代碼](#狀態代碼)  |
| page      | string | Y  | 手機畫面名稱  |
| info      | array  | Y  | 手機畫面資訊 |
| module    | string | Y  | 手機畫面區塊名稱 |
| status    | int    | Y  | [狀態代碼](#狀態代碼) |
| errorMsg  | string |    | 錯誤訊息 |
| type      | string | Y  | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y  | 資料筆數 |
| data      | array  | Y  | 資料內容 |
| toast     | string | Y  | 回應訊息 |
| isPositive| bool   | Y  | 回應訊息是否為積極行為，true:icon顏色為藍色, false:icon顏色為白色 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "reserve",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "toast": "排隊成功",
          "isPositive": true
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "loanPanel",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":6,
          "itemId":1,
          "nextCanLoanDate": "2024/6/20",
          "nextExpectReturnDate": "",
          "loanedDate":"2024/1/17",
          "expectReturnDate":"2024/4/9",
          "loanWorkDays": 60,
          "leftDays": 45,
          "extendWorkDays": 15,
          "expectExtendReturnDate":""
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

<hr>

**Request for reserve module (type=delete) 取消排隊動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "reserve",
  "type": "delete",
  "data": {
      "itemId":1
  }
}
```
**Response for reserve module (type=delete) 取消排隊動作**
| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | string | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |
| toast     | string | Y | 回應訊息 |
| isPositive| bool   | Y | 回應訊息是否為積極行為，true:icon顏色為藍色, false:icon顏色為白色 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",  
  "status":200,
  "page":"bookDetailPage",
  "info": [
    {
      "module": "reserve",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "toast": "排隊已取消",
          "isPositive": false
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "loanPanel",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "loanPanelStatus":5,
          "itemId":1,
          "nextCanLoanDate": "2024/6/20",
          "nextExpectReturnDate": "",
          "loanedDate":"",
          "expectReturnDate":"",
          "loanWorkDays": 60,
          "leftDays": 45,
          "extendWorkDays": 15,
          "expectExtendReturnDate":""
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

### ✅ bookDetailPage-favorite

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍內容頁-收藏/取消收藏 動作`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cb5a1f5bd7e37bb7e94">`zeplin前端畫面`</a>

#### Remark
```

收藏異動的同時，有訂閱的頁面(ex:minePage or bookPage)也需要同步資料。
 ```
**Request for 新增收藏動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "favorite",
  "type": "insert",
  "data": {
      "itemId":1
  }
}
```
**Response for 新增收藏成功**

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",  
  "status":200,
  "page":"minePage",
  "info": [
    {
      "module": "favoriteList",
      "status": 200,
      "type": "add",
      "num": 1,
      "data": [
        {
          "type":1,
          "functionId":1,
          "id":11,
          "title":"地球編年史完全指南",
          "subTitle":"凱・博得、馬丁・薛",
          "iconUrl":"/img/book/11.png"
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

<br>

**Request for 取消收藏動作** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料參數 |
| itemId      | int      | Y       | 書籍id |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookDetailPage",
  "module": "favorite",
  "type": "delete",
  "data": {
      "itemId":1
  }
}
```
**Response for 取消收藏成功**

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId | string | Y | 對話id  |
| status    | int    | Y | [狀態代碼](#狀態代碼)  |
| page      | string | Y | 手機畫面名稱  |
| info      | array  | Y | 手機畫面資訊 |
| module    | string | Y | 手機畫面區塊名稱 |
| status    | int    | Y | [狀態代碼](#狀態代碼) |
| errorMsg  | string |   | 錯誤訊息 |
| type      | string | Y | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y | 資料筆數 |
| data      | array  | Y | 資料內容 |

```json=

{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",  
  "status":200,
  "page":"minePage",
  "info": [
    {
      "module": "favoriteList",
      "status": 200,
      "type": "remove",
      "num": 1,
      "data": [
        {
          "type":1,
          "functionId":1,
          "id":11,
          "title":"地球編年史完全指南",
          "subTitle":"凱・博得、馬丁・薛",
          "iconUrl":"/img/book/11.png"
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2024/7/2 12:38:11"
}
```

<br>

### ✅ bookSearchPage

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍搜尋頁資訊`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/662f74f00f2aea14a503c8a5">`zeplin前端畫面`</a>
#### Remark
```
1. 當App送出關鍵字後才會發出該請求
2. API將模糊比對「書名」、「作者」與「內容資訊」三欄位，並將書籍資料回傳
```
**Request** 
| Parameter     | Type     | Require | Description |
| -----------   | -------- | ------- | ----------- |
| requestId     | string   | Y       | 對話id  |
| page          | string   | Y       | 手機畫面名稱 |
| module        | string   | Y       | 功能區塊名稱 |
| type          | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data          | object   | Y       | 參數資料 |
| functionId    | int      |         | 分類列表id（1代表書籍）|
| keyword       | string   | Y       | 關鍵字 |
| lastId        | int      |         | 分頁機制：帶入目前資料的最後一筆itemId，API將回傳此itemId之後的30筆資料。<br>若不帶此參數則提供最前面的30筆資料。 |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "bookSearchPage",
  "module": "all",
  "type": "select",
  "data": {
      "functionId": 1,
      "keyword":"David Macey"
  }
}
```
**Response**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y | 對話id  |
| status      | int      | Y | [狀態代碼](#狀態代碼) |
| page        | string   | Y | 手機畫面名稱  |
| info        | array    | Y | 手機畫面資訊 |
| module      | string   | Y | 手機畫面區塊名稱 |
| status      | int      | Y | [狀態代碼](#狀態代碼) |
| errorMsg    | string   |   | 錯誤訊息 |
| type        | string   | Y | [資料處理型態](#socket對話資料處理型態) |
| num         | int      | Y | 資料筆數 |
| data        | array    | Y | 資料內容 |

<br>

**bookList 書籍列表區塊**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| itemId      | int      | Y       | 書籍id  |
| title       | string   | Y       | 書名 |
| author      | string   | Y       | 作者 |
| categoryId  | int      | Y       | 書籍分類id |
| isNew       | bool     | Y       | 是否為新書(新上架7日內為1) |
| isFavorite  | bool     | Y       | 是否被選定為我的最愛 |
| imgUrl      | string   | Y       | 圖片路徑 |
| star        | float    | Y       | 星等平均(四捨五入，小數點1位，點零也要出現。ex:5.0) |
| ratingNum   | int      | Y       | 評價總數 |

<br>

**wishUrl 書籍我要許願區塊**
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| wishUrl     | string   | Y       | 我要許願 google form 連結  |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "bookSearchPage",
  "info": [
    {
      "module": "bookList",
      "status":200,
      "type": "list",
      "num": 2,
      "data": [
        {
          "itemId": 1,
          "title": "奧本海默",
          "author":"David Macey",
          "categoryId": 4,
          "isNew": true,
          "isFavorite": true,
          "imgUrl": "/img/book/1.png",
          "star": 4.7,
          "ratingNum": 99
        },
        {
          "itemId": 2,
          "title": "哈利波特",
          "author":"David Macey",
          "categoryId": 4,
          "isNew": true,
          "isFavorite": false,
          "imgUrl": "/img/book/2.png",
          "star": 4.1,
          "ratingNum": 199
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    },
    {
      "module": "wishUrl",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "url": "https://forms.gle/96PdDNsgMNFFJ25n7",
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2024/6/25 12:38:11"
}
```
</br>


### ❇️ returnPage

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍/物品 歸還入口頁資訊（從Scanner通道進入，將會顯示所有該區的已借用書籍/物品）`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cc0556504bcf8a97ad0">`zeplin前端畫面`</a>

#### Remark
```
1. 目前僅完成「書籍部分」，物品部分尚未建置。
 ```

**Request** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | --------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object   | Y       | 資料 |
| returnLocationId | int | Y       | 歸還地id |



```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "returnPage",
  "module": "all",
  "type": "select",
  "data": {
      "returnLocationId":1
  }
}
```
**Response for 書籍/物品情況**
| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       |[狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| errorMsg  | string |         | 錯誤訊息 |
| type      | string | Y       | [資料處理型態](#socket對話資料處理型態) |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容 |
| returnType  | int  | Y       | 歸還物型態(1:書籍/2:物品)   |
| itemId    | int    | Y       | 書籍/物品id |
| title     | string | Y       | 書籍/物品名稱 |
| subtitle  | string | Y       | 書籍作者/物品擁有單位<br>(returnType為1時，subtitle為書籍作者；returnType為2時，subtitle為物品擁有單位，如桌遊社) |
| imgUrl    | string | Y       | 圖片連結 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "returnPage",
  "info": [
    {
      "module": "loanList",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
          {
              "returnType":1,
              "returnList":[
                  {
                    "itemId": 1,
                    "title": "社畜的財務自由計畫",
                    "subtitle": "九把刀",
                    "imgUrl": "/book/1.png"
                  },
                  {
                    "itemId": 2,
                    "title": "哈利波特-神秘的魔法石",
                    "subtitle": "J.K羅琳",
                    "imgUrl": "/book/2.png"
                  }
              ]
          
          }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

<br>


### ❇️ returnPage-return

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍/物品 歸還頁 歸還動作，資訊包含之後評論popup的頁面內容`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/65dc5cc0f0747b2e48f5d0b9">`zeplin前端畫面`</a>

#### Remark
```
1. 歸還地只會有一種型態，不是書就是物
2. 歸還完畢後的toast，app端要等待POPUP視窗收下後才顯示
3. 若一次歸還多筆資料，其中一筆出現問題，將rollback所有資料並顯示error給前端
4. 目前僅完成「書籍部分」，物品部分尚未建置。
 ```


**Request for 書籍/物品** 
| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id      |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | [資料處理型態](#socket對話資料處理型態) |
| data        | object    | Y       | 資料參數    |
| returnLocationId | int | Y       | 歸還地id    |
| returnItemIds  | array | Y       | 歸還物itemId清單   |


```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "returnPage",
  "module": "return",
  "type": "update",
  "data": {
      "returnLocationId":1,
      "returnItemIds":[1,2]
  }
}
```

**Response**
| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string |    Y    | 對話id  |
| status    | int    |    Y    | [狀態代碼](#狀態代碼) |
| page      | string |    Y    | 手機畫面名稱  |
| info      | array  |    Y    | 手機畫面資訊 |
| module    | string |    Y    | 手機畫面區塊名稱 |
| status    | int    |    Y    | [狀態代碼](#狀態代碼) |
| errorMsg  | string |         | 錯誤訊息 |
| type      | string |    Y    | [資料處理型態](#socket對話資料處理型態) |
| num       | int    |    Y    | 資料筆數 |
| data      | array  |    Y    | 資料內容 |
| isSuccess | bool   |    Y    | 是否成功歸還 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "returnPage",
  "info": [
    {
      "module": "return",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "toast": "歸還成功",
          "isPositive": true
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

### ❇️ returnPage-rating

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `書籍/物品 歸還頁-評價動作`

App Screen: <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/66349b6f5560160624feea53">`歸還當下直接評價`</a> ＆ <a href="https://app.zeplin.io/project/65d8474dc2c129ce739d5420/screen/6634995f6c4546ad2a8d96d6">`歸還後回到bookDetailPage才評價`</a>

#### Remark
```
1.API一次僅接收單筆 書籍/物品 的評價資料
2.有兩個畫面分別會使用此API，一種是歸還當下、另一種則是歸還後返回書籍內容頁評價
3.該員曾借用過才可以評價，且可以無限重複評價
4. 目前僅完成「書籍部分」，物品部分尚未建置。
 ```

**Request** 
| Parameter   | Type   | Require | Description |
| ----------- | -------| ------- | ----------- |
| requestId   | string |    Y    | 對話id  |
| page        | string |    Y    | 手機畫面名稱  |
| module      | string |    Y    | 手機畫面區塊名稱 |
| type        | string |    Y    | [資料處理型態](#socket對話資料處理型態) |
| data        | object |    Y    | 資料參數 |
| itemId      | int    |    Y    | 書籍/物品id      |
| star        | int    |    Y    | 星等(四捨五入小數點1位) |
| comment     | string |    Y    | 評論內容(API判斷是否有輸入留言：去除半形空白與全形空白後為空值則為「無評論」) |
| isAnonymous | bool   |    Y    | 是否匿名評價(true:匿名 false:實名) |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "returnPage",
  "module": "rating",
  "type": "update",
  "data": {
        "itemId": 1,
        "star": 5,
        "comment": "太好看了！",
        "isAnonymous": false
  }
}
```

**Response for 評價成功**
| Parameter   | Type   | Require | Description |
| ----------- | -------| ------- | ----------- |
| requestId   | string | Y       | 對話id  |
| status      | int    | Y       | [狀態代碼](#狀態代碼) |
| page        | string | Y       | 手機畫面名稱  |
| info        | array  | Y       | 手機畫面資訊 |
| module      | string | Y       | 手機畫面區塊名稱 |
| type        | string | Y       | [資料處理型態](#socket對話資料處理型態) |
| num         | int    | Y       | 資料筆數 |
| data        | array  | Y       | 資料內容 |
| toast       | string | Y       | toast內容  |
| isPositive| bool     | Y  | 回應訊息是否為積極行為，true:icon顏色為藍色, false:icon顏色為白色 |

```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "returnPage",
  "info": [
    {
      "module": "rating",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "toast": "已發佈評分及評論",
          "isPositive":true
        }
      ],
      "datetime": "2023/11/1 12:38:11"
    }
  ],
  "datetime": "2023/11/1 12:38:11"
}
```

**Response for 評價失敗**
| Parameter   | Type   | Require | Description |
| ----------- | -------| ------- | ----------- |
| requestId   | string | Y       | 對話id  |
| status      | int    | Y       | [狀態代碼](#狀態代碼) |
| page        | string | Y       | 手機畫面名稱  |
| info        | array  | Y       | 手機畫面資訊 |
| module      | string | Y       | 手機畫面區塊名稱 |
| status      | int    | Y       | [狀態代碼](#狀態代碼) |
| errorMsg    | string |         | 錯誤訊息 |
| datetime    | string | Y       | 時間 |


```json=
{
  "requestId": "1fb7d801-4a05-0b1d-ea16-de1d32c97d6c",
  "status": 200,
  "page": "returnPage",
  "info": [
    {
      "module": "rating",
      "status": 1005,
      "errorMsg": "Data processing error.",
      "datetime": "2025/8/13 12:38:11"
    }
    
  ],
  "datetime": "2025/8/13 12:38:11"
}
```


### ✅ itemReturnLocationRedirect
URL:`https://{domain name}/api/guest/itemReturnLocationRedirect/redirectReturnUrl`

Method: `GET`

Descirption: `提供給手機相機app掃描後，歸還地點轉址API`

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| urlScheme   | string   | Y       | app所能解析的url scheme(需做url encode) |

```
Request 範例：
https://{domain}/api/guest/itemReturnLocationRedirect/redirectReturnUrl?urlScheme=neuteclife%3A%2F%2FreturnPage%2Fall%2Fselect%2F%3FreturnLocationId%3D165
```

<br>

**Response**
```
操作流程：
1. 取得參數urlscheme的值，並url decode
2. validate - 確認開頭是neuteclife://，否則將 header 404 status code
3. 轉址 - 直接轉址至urlscheme的值，ex: neuteclife://returnPage/all/select/?returnLocationId=165
```
</br>





---
</br>
<iframe src="https://hackmd.io/zqx1OcNuTKSHCI89YIHMOw?view" width="100%" height="500"></iframe>

<!--
### 狀態代碼

| status | description |
| -----  |-------------|
| 200    | Success |
| 1001   | Not found this page or module. |
| 1003   | Not found this DATA. |
| 1004   | DATA parameter error. |
| 1005   | Data processing error. |
| 1006   | 您輸入的帳號或密碼錯誤，請重新輸入 |
| 1008   | Your account has been logged in another device. |
| 1009   | Touch too fast. |
| 1010   | Unknow error. |
| 1011   | 身份驗證失敗，請重新登入 |
| 1012   | Blacklist. |
| 1013   | Not found this lastId. |
| 1014   | 已超過書籍借用2本上限 |
| 1015   | 此書籍正在借閱中，借閱失敗 |
| 1016   | 書籍有人排隊預約，展延失敗 |
| 1017   | 時段衝突，此時段已有人預約 |
| 1018   | 物品已進入借用狀態，無法取消 |
| 1030   | 已有他人在此時段預約\r請重新選擇起訖時間 |
| 1031   | 會議時段衝突\r請重新選擇循環時段 |

<br>

### socket對話資料處理型態
| type   | description |
| -----  |-------------|
| select | App端請求「顯示用」資料。<br>ex:需要顯示書籍列表時。 |
| insert | App端請求「新增」動作。<br>ex:使用者按下借用按鈕時。 |
| update | App端請求「更新」動作。<br>ex:使用者更換快速入口項目時。 |
| delete | App端請求「刪除」動作。<br>ex:使用者按下取消收藏按鈕時。 |
| list   | Server端請求刷新整個區塊資料，或僅告知事件已處理完成。<br>ex:需要顯示書籍列表時。 |
| add    | Server端請求新增資料到區塊中。<br>ex:當後台新增了一筆通知時。 |
| modify | Server端請求更新畫面中的某筆資料。<br>ex:當後台修改了某一筆已發出通知的錯字時。 |
| remove | App端請求「刪除」動作。<br>ex:大樓消防演練通知會在演練結束後自動在App端移除消失。  |


-->