php 站內信,訊息未讀已讀,資料表設計思路與方案值得揣摩!

Weiwen發表於2022-11-22

站內信,訊息已讀未讀,這種功能我們經常見到,但是能認真思考一下這種功能是如何設計的應該不多吧。網上找了很多教程檢視,覺得還是太過於老套了。
這裡有一篇值得推薦的,設計思路與方案值得學習一下。主要是有思路,再到資料庫的設計都有!這樣寫程式碼也是清晰明瞭了。

站內信通常需要解決兩個需求:

1 使用者對使用者的站內信,管理員對使用者的站內信:即一對一傳送
2 管理員對多使用者、使用者組、全站的站內信:即一對多傳送(還有一種是使用者對產品的站內信,例如對某個模組的反饋、疑問之類的)

我們目前的需求是:

1 管理員對多使用者傳送站內信要求:對使用者真實性不做校驗,對標題長度、內容長度進行限制(分別是45個位元組、150個位元組,對應中文字元15個、50個),對收件人的拼音長度進行限制(最長50個位元組)。
2 使用者可以檢視自己的站內信按“全部、已讀、未讀”過濾按訊息來源分類:工單平臺、資源管理、自動裝機、漏洞平臺、故障平臺
3 使用者可以刪除、批次刪除站內信
4 使用者可以已閱、批次已閱、全部標記為已讀 站內信
5 運維平臺頁面頂部的訊息圖示展示未讀訊息數,超過99顯示 99+ ;滑鼠放上去,會有下拉框,展示最近10條未讀訊息(展示“時間”,“訊息來源”,“標題”);

下拉框的底部有兩個按鈕:“更多”,載入更多未讀訊息;“檢視全部”,跳轉到站內信列表頁面(最好另開一個視窗);
點選下拉框裡的未讀訊息,透過彈出框展示詳情;然後在未讀列表裡刪除該記錄,在資料庫裡標記為已讀,訊息圖示的未讀訊息數量減一。

系統設計與流程

  • 功能設計
  • 系統流程
  • 傳送站內信
  • 讀取POST請求的request body
  • 校驗長度
  • 插入資料庫
  • 返回

獲取站內信列表呼叫子模組,插入傳送給全站或我所屬使用者組的站內信;根據查詢條件,返回資料庫資料.
獲取未讀站內信數量呼叫子模組,插入傳送給全站或我所屬使用者組的站內信; 返回數量
批次已閱檢查messageId是不是屬於當前使用者;
inbox_message表裡把 read 置為1,修改update_time
全部已閱

update inbox_message set “read”=1, 
“update_time”=now where 
“receiver_name”=currentUser() 
and “read” = 0

批次刪除
檢查messageId是不是屬於當前使用者inbox_message表裡把 deleted 置為1,修改update_time

全部刪除

update inbox_message set “deleted”=1, “update_time”=now where “receiver_name”=currentUser() and “deleted” = 0

資料庫設計
*站內信內容表 *

CREATE TABLE `inbox_message_text` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `title` varchar(128) NOT NULL DEFAULT '',
  `content` longtext NOT NULL,
  `create_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  `send_type` tinyint(4) NOT NULL DEFAULT '0',
  `creator_name` varchar(255) NOT NULL DEFAULT '',
  `deleted` tinyint(4) NOT NULL DEFAULT '0',
  `module_id` bigint(20) NOT NULL,
  `link` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

站內信本身除了訊息來源(module_name),還有一個緯度的描述,叫訊息型別(message_type),例如安全訊息、活動訊息、服務訊息等,每一大類裡,又可以劃分子類,例如活動訊息-優惠活動。訊息來源和訊息型別可以是正交關係,即工單平臺也可以有活動訊息;訊息來源也可以是訊息型別的一種,稱為“產品訊息”。
站內信傳送表

CREATE TABLE `inbox_message` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `message_text_id` bigint(20) NOT NULL,
  `receiver_name` varchar(255) NOT NULL DEFAULT '',
  `read` tinyint(4) NOT NULL DEFAULT '0',
  `deleted` tinyint(4) NOT NULL DEFAULT '0',
  `create_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `inbox_message_receiver_name_deleted_read_id` (`receiver_name`,`deleted`,`read`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

訊息來源表

CREATE TABLE `inbox_module` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `code` varchar(128) NOT NULL DEFAULT '',
  `name` varchar(128) NOT NULL DEFAULT '',
  `create_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `code` (`code`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

*API設計 *
傳送站內信:POST /v1/message

request body Content-Type: application/json
{
"title": "工單審批",
"content": "XXX提交了變更申請,請審批",
"to": "sunzhongyuan,shenli,wangya",
"module_name": "工單平臺",
"link": "xxx"

}
response
{
"code": 200,
"data": 32,
"msg": "OK"
}

獲取站內信列表:GET /v1/message User-Id: xxx

http://127.0.0.1:10085/v1/message?query=message_text_id.module_id.name:xxx&limit=1
{
"code": 200,
"data": {
"data": [
{
"id": 1,
"message_text": {
"id": 1,
"title": "title 2",
"content": "content 2",
"create_time": "2018-01-12 11:13:48",
"update_time": "2018-01-12 11:13:48",
"send_type": 1,
"creator_name": "sysadmin",
"deleted": 0,
"link": "xxx",
"Messages": null,
"module": {
"id": 4,
"code": "secure",
"name": "xxx",
"create_time": "2018-01-11 15:38:01",
"update_time": "2018-01-11 15:38:01",
"MessageTexts": null

}
},
"receiver_name": "xxx",
"read": 0,
"deleted": 0,
"create_time": "2018-01-12 11:13:48",
"update_time": "2018-01-12 11:13:48"

}
],
"total": 2

},
"msg": "OK"

}

注:
返回資料的個數是由 limit 限制,而 total 是符合query條件的總數(用於分頁)
目前沒有傳送使用者組、全站的行為,如果有的話,在獲取列表介面裡,增加一步“插入所有傳送給我所在使用者組,或發給全站的,且我自己的站內信列表裡沒有記錄到的站內信”

獲取未讀站內信數量:GET /v1/message/unread_count
response

{
"code": 200,
"data": 29,
"msg": "OK"

}

獲取單個站內信內容:GET /v1/message/:id

{
"code": 200,
"data": {
"id": 2,
"message_text": {
"id": 2,
"title": "title 2",
"content": "content 3",
"create_time": "2018-01-12 11:37:54",
"update_time": "2018-01-12 11:37:54",
"send_type": 1,
"creator_name": "sysadmin",
"deleted": 0,
"link": "",
"Messages": null,
"module": {
"id": 4,
"code": "secure",
"name": "xxx",
"create_time": "2018-01-11 15:38:01",
"update_time": "2018-01-11 15:38:01",
"MessageTexts": null

}
},
"receiver_name": "xxx",
"read": 1,
"deleted": 0,
"create_time": "2018-01-12 11:37:54",
"update_time": "2018-01-22 17:33:20"

},
"msg": "OK"

}

已閱、批次已閱站內信:PUT /v1/read_messages/:messageIds
response

{
"code": 200,
"data": "OK",
"msg": "OK"

}

全部已閱 PUT:/v1/read_all_messages
response 同上
刪除、批次刪除站內信:PUT /v1/delete_messages/:messageIds
response 同上
全部刪除站內信:PUT /v1/delete_all_messages
response 同上
獲取訊息來源列表:GET /v1/module
response

{
"code": 200,
"data": [
{
"id": 1,
"code": "worksheet",
"name": "工單平臺",
"create_time": "2018-01-11 15:21:38",
"update_time": "2018-01-11 15:21:38",
"MessageTexts": null

},
{
"id": 2,
"code": "cmdb",
"name": "資源管理",
"create_time": "2018-01-11 15:22:28",
"update_time": "2018-01-11 15:22:28",
"MessageTexts": null

},
...
],
"msg": "OK"

}

測試注意點

1、傳送站內信

  • 純介面
  • 收件使用者以逗號分割,真實性不做校驗
  • 收件使用者有長度校驗,50個位元組
  • title content 有長度校驗,分別是45,150個位元組
  • module_name 是一個列表,必須從這裡選一個

2、其他介面都可以透過前端頁面測試最佳化

  • 未讀列表可以加上粗體顯示,已讀則是普通字型。
  • 對站內信進行分類,打上不同緯度的標籤,方便過濾、搜尋、遮蔽。
  • 使用者可以設定允許接收的站內信的訊息來源。管理員可以對全站訊息、全站人員、全站的訊息屬性進行增刪改查,比如撤銷某個站內信,讓所有人都看不見。
  • 管理員可以統計站內信的傳送數量、各產品的使用情況、訊息被讀的比例、訊息被讀的時間、訊息被讀的方式(點開還是批次操作)等。

原文連結:juejin.cn/post/7168715142446727182

本作品採用《CC 協議》,轉載必須註明作者和本文連結
最美的不是下雨天,而是和你一起躲過的屋簷!

相關文章