Files
EchoChat/backend/go-service/app/admin/dao/message_manage_dao.go

243 lines
6.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package dao 提供 admin 模块的数据库访问操作
package dao
import (
"context"
"fmt"
"time"
"github.com/echochat/backend/app/dto"
imModel "github.com/echochat/backend/app/im/model"
"github.com/echochat/backend/pkg/logs"
"go.uber.org/zap"
"gorm.io/gorm"
)
// MessageManageDAO 管理端消息数据访问对象
type MessageManageDAO struct {
db *gorm.DB
}
// NewMessageManageDAO 创建 MessageManageDAO 实例
func NewMessageManageDAO(db *gorm.DB) *MessageManageDAO {
return &MessageManageDAO{db: db}
}
// ListMessages 分页查询消息列表(支持多条件筛选)
func (d *MessageManageDAO) ListMessages(ctx context.Context, req *dto.AdminMessageListRequest) ([]imModel.Message, int64, error) {
funcName := "dao.message_manage_dao.ListMessages"
logs.Debug(ctx, funcName, "查询消息列表")
query := d.db.WithContext(ctx).Model(&imModel.Message{})
if req.Keyword != "" {
query = query.Where("content ILIKE ?", fmt.Sprintf("%%%s%%", req.Keyword))
}
if req.Type != nil {
query = query.Where("type = ?", *req.Type)
}
if req.SenderID != nil {
query = query.Where("sender_id = ?", *req.SenderID)
}
if req.ConversationID != nil {
query = query.Where("conversation_id = ?", *req.ConversationID)
}
if req.Status != nil {
query = query.Where("status = ?", *req.Status)
}
if req.StartTime != "" {
if t, err := time.Parse("2006-01-02", req.StartTime); err == nil {
query = query.Where("created_at >= ?", t)
}
}
if req.EndTime != "" {
if t, err := time.Parse("2006-01-02", req.EndTime); err == nil {
query = query.Where("created_at < ?", t.AddDate(0, 0, 1))
}
}
var total int64
if err := query.Count(&total).Error; err != nil {
logs.Error(ctx, funcName, "统计消息总数失败", zap.Error(err))
return nil, 0, err
}
page := req.Page
if page <= 0 {
page = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
var messages []imModel.Message
err := query.Order("id DESC").
Offset((page - 1) * pageSize).
Limit(pageSize).
Find(&messages).Error
if err != nil {
logs.Error(ctx, funcName, "查询消息列表失败", zap.Error(err))
return nil, 0, err
}
return messages, total, nil
}
// GetMessageByID 根据 ID 查询单条消息
func (d *MessageManageDAO) GetMessageByID(ctx context.Context, id int64) (*imModel.Message, error) {
var msg imModel.Message
err := d.db.WithContext(ctx).First(&msg, id).Error
if err != nil {
return nil, err
}
return &msg, nil
}
// UpdateMessageStatus 更新消息状态
func (d *MessageManageDAO) UpdateMessageStatus(ctx context.Context, id int64, status int) error {
return d.db.WithContext(ctx).
Model(&imModel.Message{}).
Where("id = ?", id).
Update("status", status).Error
}
// GetTotalCount 获取消息总数
func (d *MessageManageDAO) GetTotalCount(ctx context.Context) (int64, error) {
var count int64
err := d.db.WithContext(ctx).Model(&imModel.Message{}).Count(&count).Error
return count, err
}
// GetTodayCount 获取今日消息数
func (d *MessageManageDAO) GetTodayCount(ctx context.Context) (int64, error) {
var count int64
today := time.Now().Truncate(24 * time.Hour)
err := d.db.WithContext(ctx).Model(&imModel.Message{}).
Where("created_at >= ?", today).Count(&count).Error
return count, err
}
// GetTypeDistribution 获取消息类型分布
func (d *MessageManageDAO) GetTypeDistribution(ctx context.Context) ([]dto.TypeDistItem, error) {
type row struct {
Type int `gorm:"column:type"`
Count int64 `gorm:"column:count"`
}
var rows []row
err := d.db.WithContext(ctx).
Model(&imModel.Message{}).
Select("type, count(*) as count").
Group("type").
Order("count DESC").
Find(&rows).Error
if err != nil {
return nil, err
}
result := make([]dto.TypeDistItem, 0, len(rows))
for _, r := range rows {
result = append(result, dto.TypeDistItem{
Type: r.Type,
Count: r.Count,
})
}
return result, nil
}
// GetDailyTrend 获取每日消息趋势
func (d *MessageManageDAO) GetDailyTrend(ctx context.Context, days int) ([]dto.DailyTrendItem, error) {
startDate := time.Now().AddDate(0, 0, -days).Truncate(24 * time.Hour)
type row struct {
Date string `gorm:"column:date"`
Count int64 `gorm:"column:count"`
}
var rows []row
err := d.db.WithContext(ctx).
Model(&imModel.Message{}).
Select("TO_CHAR(created_at, 'YYYY-MM-DD') as date, count(*) as count").
Where("created_at >= ?", startDate).
Group("date").
Order("date ASC").
Find(&rows).Error
if err != nil {
return nil, err
}
result := make([]dto.DailyTrendItem, 0, len(rows))
for _, r := range rows {
result = append(result, dto.DailyTrendItem{Date: r.Date, Count: r.Count})
}
return result, nil
}
// GetActiveUsers 获取活跃用户排行Top 10
func (d *MessageManageDAO) GetActiveUsers(ctx context.Context, days int) ([]dto.ActiveUserItem, error) {
startDate := time.Now().AddDate(0, 0, -days).Truncate(24 * time.Hour)
type row struct {
UserID int64 `gorm:"column:sender_id"`
Nickname string `gorm:"column:nickname"`
Count int64 `gorm:"column:count"`
}
var rows []row
err := d.db.WithContext(ctx).
Raw(`SELECT m.sender_id, u.nickname, count(*) as count
FROM im_messages m
JOIN auth_users u ON u.id = m.sender_id
WHERE m.created_at >= ? AND m.sender_id > 0
GROUP BY m.sender_id, u.nickname
ORDER BY count DESC
LIMIT 10`, startDate).
Scan(&rows).Error
if err != nil {
return nil, err
}
result := make([]dto.ActiveUserItem, 0, len(rows))
for _, r := range rows {
result = append(result, dto.ActiveUserItem{
UserID: r.UserID,
Nickname: r.Nickname,
Count: r.Count,
})
}
return result, nil
}
// GetActiveGroups 获取活跃群组排行Top 10
func (d *MessageManageDAO) GetActiveGroups(ctx context.Context, days int) ([]dto.ActiveGroupItem, error) {
startDate := time.Now().AddDate(0, 0, -days).Truncate(24 * time.Hour)
type row struct {
GroupID int64 `gorm:"column:id"`
Name string `gorm:"column:name"`
Count int64 `gorm:"column:count"`
}
var rows []row
err := d.db.WithContext(ctx).
Raw(`SELECT g.id, g.name, count(*) as count
FROM im_messages m
JOIN im_conversations c ON c.id = m.conversation_id
JOIN im_groups g ON g.conversation_id = c.id
WHERE m.created_at >= ? AND c.type = 2
GROUP BY g.id, g.name
ORDER BY count DESC
LIMIT 10`, startDate).
Scan(&rows).Error
if err != nil {
return nil, err
}
result := make([]dto.ActiveGroupItem, 0, len(rows))
for _, r := range rows {
result = append(result, dto.ActiveGroupItem{
GroupID: r.GroupID,
Name: r.Name,
Count: r.Count,
})
}
return result, nil
}