feat(1.0):调整未读列表

This commit is contained in:
summer 2025-10-20 14:11:27 +08:00
parent a6ac558680
commit ba0630b2da
10 changed files with 65 additions and 103 deletions

View File

@ -924,6 +924,11 @@ const docTemplate = `{
},
"/admin/messages/latest": {
"get": {
"security": [
{
"LoginVerifyToken": []
}
],
"description": "管理端根据appid获取最新消息记录包含已读未读状态访问时自动标记为已读",
"consumes": [
"application/json"
@ -1788,26 +1793,6 @@ const docTemplate = `{
"app.latestMessageData": {
"type": "object",
"properties": {
"content": {
"description": "消息内容",
"type": "string"
},
"is_read": {
"description": "是否已读(0:未读 1:已读)",
"type": "integer"
},
"message_id": {
"description": "消息ID",
"type": "integer"
},
"msg_type": {
"description": "消息类型(1:文本 2:图片)",
"type": "integer"
},
"receiver_id": {
"description": "接收人ID",
"type": "string"
},
"send_time": {
"description": "发送时间",
"type": "string"

View File

@ -916,6 +916,11 @@
},
"/admin/messages/latest": {
"get": {
"security": [
{
"LoginVerifyToken": []
}
],
"description": "管理端根据appid获取最新消息记录包含已读未读状态访问时自动标记为已读",
"consumes": [
"application/json"
@ -1780,26 +1785,6 @@
"app.latestMessageData": {
"type": "object",
"properties": {
"content": {
"description": "消息内容",
"type": "string"
},
"is_read": {
"description": "是否已读(0:未读 1:已读)",
"type": "integer"
},
"message_id": {
"description": "消息ID",
"type": "integer"
},
"msg_type": {
"description": "消息类型(1:文本 2:图片)",
"type": "integer"
},
"receiver_id": {
"description": "接收人ID",
"type": "string"
},
"send_time": {
"description": "发送时间",
"type": "string"

View File

@ -275,21 +275,6 @@ definitions:
type: object
app.latestMessageData:
properties:
content:
description: 消息内容
type: string
is_read:
description: 是否已读(0:未读 1:已读)
type: integer
message_id:
description: 消息ID
type: integer
msg_type:
description: 消息类型(1:文本 2:图片)
type: integer
receiver_id:
description: 接收人ID
type: string
send_time:
description: 发送时间
type: string
@ -1414,6 +1399,8 @@ paths:
description: Bad Request
schema:
$ref: '#/definitions/code.Failure'
security:
- LoginVerifyToken: []
summary: 根据appid获取最新消息记录
tags:
- 管理端.小程序

View File

@ -10,6 +10,7 @@ type handler struct {
logger logger.CustomLogger
writeDB *dao.Query
readDB *dao.Query
db mysql.Repo
}
func New(logger logger.CustomLogger, db mysql.Repo) *handler {
@ -17,5 +18,6 @@ func New(logger logger.CustomLogger, db mysql.Repo) *handler {
logger: logger,
writeDB: dao.Use(db.GetDbW()),
readDB: dao.Use(db.GetDbR()),
db: db,
}
}

View File

@ -3,6 +3,7 @@ package app
import (
"fmt"
"net/http"
"time"
"mini-chat/internal/code"
"mini-chat/internal/pkg/core"
@ -17,15 +18,10 @@ type latestMessageByAppIdRequest struct {
}
type latestMessageData struct {
MessageID int32 `json:"message_id"` // 消息ID
SendTime string `json:"send_time"` // 发送时间
SenderID string `json:"sender_id"` // 发送人ID
SenderName string `json:"sender_name"` // 发送人昵称
SenderAvatar string `json:"sender_avatar"` // 发送人头像
ReceiverID string `json:"receiver_id"` // 接收人ID
Content string `json:"content"` // 消息内容
MsgType int32 `json:"msg_type"` // 消息类型(1:文本 2:图片)
IsRead int32 `json:"is_read"` // 是否已读(0:未读 1:已读)
UnreadCount int64 `json:"unread_count"` // 未读数量
}
@ -48,6 +44,7 @@ type latestMessageByAppIdResponse struct {
// @Success 200 {object} latestMessageByAppIdResponse
// @Failure 400 {object} code.Failure
// @Router /admin/messages/latest [get]
// @Security LoginVerifyToken
func (h *handler) LatestMessageByAppId() core.HandlerFunc {
return func(ctx core.Context) {
req := new(latestMessageByAppIdRequest)
@ -78,37 +75,54 @@ func (h *handler) LatestMessageByAppId() core.HandlerFunc {
return
}
query := h.readDB.AppMessageLog.WithContext(ctx.RequestContext()).
Where(h.readDB.AppMessageLog.AppID.Eq(req.AppID))
type unreadMessageResult struct {
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name"`
SendTime time.Time `json:"send_time"`
AvatarURL string `json:"avatar_url"`
UnreadCount int64 `json:"unread_count"`
}
// 查询总数
total, err := query.Count()
if err != nil {
var results []unreadMessageResult
var total int64
countErr := h.db.GetDbR().Table("app_message_log m").
Select("m.send_time, m.sender_id, m.sender_name, u.user_avatar as avatar_url, COUNT(*) as unread_count").
Joins("LEFT JOIN app_user u ON m.sender_id = u.user_id").
Where("m.app_id = ? AND m.sender_id != ? AND m.is_read = 1", req.AppID, "888888").
Group("m.sender_id").
Count(&total).
Error
if countErr != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ListMessageError,
fmt.Sprintf("%s%s", code.Text(code.ListMessageError), err.Error())),
fmt.Sprintf("%s%s", code.Text(code.ListMessageError), countErr.Error())),
)
return
}
// 分页查询指定小程序的最新消息
resultData, err := query.
Order(h.readDB.AppMessageLog.SendTime.Asc()).
resultErr := h.db.GetDbR().Table("app_message_log m").
Select("max(m.send_time) as send_time, m.sender_id, max(m.sender_name) as sender_name, max(u.user_avatar) as avatar_url, COUNT(*) as unread_count").
Joins("LEFT JOIN app_user u ON m.sender_id = u.user_id").
Where("m.app_id = ? AND m.sender_id != ? AND m.is_read = 1", req.AppID, "888888").
Group("m.sender_id").
Order("unread_count DESC").
Offset((req.Page - 1) * req.PageSize).
Limit(req.PageSize).
Find()
if err != nil {
Find(&results).
Error
if resultErr != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ListMessageError,
fmt.Sprintf("%s%s", code.Text(code.ListMessageError), err.Error())),
fmt.Sprintf("%s%s", code.Text(code.ListMessageError), resultErr.Error())),
)
return
}
// 自动标记该appid下的所有消息为已读管理端访问时
_, err = h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()).
_, err := h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()).
Where(h.writeDB.AppMessageLog.AppID.Eq(req.AppID)).
Where(h.writeDB.AppMessageLog.IsRead.Eq(0)).
Update(h.writeDB.AppMessageLog.IsRead, 1)
@ -120,27 +134,15 @@ func (h *handler) LatestMessageByAppId() core.HandlerFunc {
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = total
res.List = make([]latestMessageData, len(resultData))
for k, v := range resultData {
// 计算该用户在该应用下的未读消息总数
unreadCount, _ := h.readDB.AppMessageLog.WithContext(ctx.RequestContext()).
Where(h.readDB.AppMessageLog.AppID.Eq(req.AppID)).
Where(h.readDB.AppMessageLog.ReceiverID.Eq(v.ReceiverID)).
Where(h.readDB.AppMessageLog.IsRead.Eq(0)).
Count()
res.List = make([]latestMessageData, len(results))
for k, v := range results {
res.List[k] = latestMessageData{
MessageID: v.ID,
SendTime: timeutil.FriendlyTime(v.SendTime),
SenderID: v.SenderID,
SenderName: v.SenderName,
SenderAvatar: "", // TODO: 需要从用户表获取头像信息
ReceiverID: v.ReceiverID,
Content: v.Content,
MsgType: v.MsgType,
IsRead: v.IsRead, // 直接使用消息表中的 is_read 字段
UnreadCount: unreadCount,
SenderAvatar: v.AvatarURL,
UnreadCount: v.UnreadCount,
}
}

View File

@ -8,13 +8,13 @@ import (
"net/http"
"time"
"github.com/DanPlayer/randomname"
"mini-chat/internal/code"
"mini-chat/internal/pkg/core"
"mini-chat/internal/pkg/httpclient"
"mini-chat/internal/pkg/validation"
"mini-chat/internal/repository/mysql/model"
"github.com/DanPlayer/randomname"
)
type miniprogramLoginRequest struct {

View File

@ -4,11 +4,12 @@ import (
"bytes"
"encoding/json"
"fmt"
"mini-chat/internal/pkg/core"
"mini-chat/internal/pkg/httpclient"
"net/http"
"sync"
"time"
"mini-chat/internal/pkg/core"
"mini-chat/internal/pkg/httpclient"
)
// AccessTokenRequest 获取 access_token 请求参数