bindbox-game/internal/api/message/message_mark_read.go
邹方成 1a285f4e23 feat(消息状态): 添加消息已读状态功能
- 新增消息已读状态表结构及模型
- 实现用户端标记消息为已读接口
- 添加管理端获取最新消息记录接口
- 实现微信小程序登录功能
- 更新相关API文档和路由配置
2025-10-18 18:24:42 +08:00

115 lines
3.2 KiB
Go

package message
import (
"fmt"
"net/http"
"time"
"mini-chat/internal/code"
"mini-chat/internal/pkg/core"
"mini-chat/internal/pkg/validation"
"mini-chat/internal/repository/mysql/model"
)
type markMessageReadRequest struct {
AppID string `json:"app_id" binding:"required"` // 小程序ID
UserID string `json:"user_id" binding:"required"` // 用户ID
MessageID int32 `json:"message_id" binding:"required"` // 消息ID
}
type markMessageReadResponse struct {
Message string `json:"message"`
}
// MarkMessageRead 标记消息为已读
// @Summary 标记消息为已读
// @Description 标记指定消息为已读状态
// @Tags 用户端
// @Accept json
// @Produce json
// @Param RequestBody body markMessageReadRequest true "请求参数"
// @Success 200 {object} markMessageReadResponse
// @Failure 400 {object} code.Failure
// @Router /app/messages/read [post]
func (h *handler) MarkMessageRead() core.HandlerFunc {
return func(ctx core.Context) {
req := new(markMessageReadRequest)
res := new(markMessageReadResponse)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ParamBindError,
validation.Error(err)),
)
return
}
// 检查消息是否存在
message, err := h.readDB.AppMessageLog.WithContext(ctx.RequestContext()).
Where(h.readDB.AppMessageLog.ID.Eq(req.MessageID)).
Where(h.readDB.AppMessageLog.AppID.Eq(req.AppID)).
First()
if err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ListMessageError,
fmt.Sprintf("消息不存在:%s", err.Error())),
)
return
}
// 检查用户是否有权限标记此消息为已读(只有接收者可以标记)
if message.ReceiverID != req.UserID {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ListMessageError,
"只有消息接收者可以标记消息为已读"),
)
return
}
// 检查是否已经标记为已读
existingReadStatus, _ := h.readDB.AppMessageReadStatus.WithContext(ctx.RequestContext()).
Where(h.readDB.AppMessageReadStatus.AppID.Eq(req.AppID)).
Where(h.readDB.AppMessageReadStatus.MessageID.Eq(req.MessageID)).
Where(h.readDB.AppMessageReadStatus.UserID.Eq(req.UserID)).
First()
now := time.Now()
if existingReadStatus != nil {
// 如果已存在记录,更新为已读状态
_, err = h.writeDB.AppMessageReadStatus.WithContext(ctx.RequestContext()).
Where(h.writeDB.AppMessageReadStatus.ID.Eq(existingReadStatus.ID)).
Updates(map[string]interface{}{
"is_read": 1,
"read_time": &now,
"updated_at": now,
})
} else {
// 如果不存在记录,创建新的已读状态记录
newReadStatus := &model.AppMessageReadStatus{
AppID: req.AppID,
MessageID: req.MessageID,
UserID: req.UserID,
IsRead: 1,
ReadTime: &now,
CreatedAt: now,
UpdatedAt: now,
}
err = h.writeDB.AppMessageReadStatus.WithContext(ctx.RequestContext()).Create(newReadStatus)
}
if err != nil {
ctx.AbortWithError(core.Error(
http.StatusBadRequest,
code.ListMessageError,
fmt.Sprintf("标记消息已读失败:%s", err.Error())),
)
return
}
res.Message = "消息已标记为已读"
ctx.Payload(res)
}
}