refactor: update repository interfaces and improve dependency injection
All checks were successful
Build Backend / build (push) Successful in 12m45s
Build Backend / build-docker (push) Successful in 2m40s

- Refactored repository structures to use interfaces instead of concrete types, enhancing flexibility and testability.
- Updated various repository methods to accept interfaces, allowing for better dependency management.
- Modified wire generation to accommodate new repository interfaces, ensuring proper service injection throughout the application.
- Enhanced handler methods to utilize DTOs for filtering and data handling, improving code clarity and maintainability.
This commit is contained in:
lafay
2026-03-26 18:14:16 +08:00
parent 7b41dfeb00
commit c6848aba06
50 changed files with 1034 additions and 663 deletions

View File

@@ -25,12 +25,12 @@ type AdminCommentService interface {
// adminCommentServiceImpl 管理端评论服务实现
type adminCommentServiceImpl struct {
commentRepo *repository.CommentRepository
postRepo *repository.PostRepository
commentRepo repository.CommentRepository
postRepo repository.PostRepository
}
// NewAdminCommentService 创建管理端评论服务
func NewAdminCommentService(commentRepo *repository.CommentRepository, postRepo *repository.PostRepository) AdminCommentService {
func NewAdminCommentService(commentRepo repository.CommentRepository, postRepo repository.PostRepository) AdminCommentService {
return &adminCommentServiceImpl{
commentRepo: commentRepo,
postRepo: postRepo,

View File

@@ -28,21 +28,21 @@ type AdminDashboardService interface {
// adminDashboardServiceImpl 管理端仪表盘服务实现
type adminDashboardServiceImpl struct {
db *gorm.DB
userRepo *repository.UserRepository
postRepo *repository.PostRepository
commentRepo *repository.CommentRepository
userRepo repository.UserRepository
postRepo repository.PostRepository
commentRepo repository.CommentRepository
groupRepo repository.GroupRepository
activityRepo *repository.UserActivityRepository
activityRepo repository.UserActivityRepository
}
// NewAdminDashboardService 创建管理端仪表盘服务
func NewAdminDashboardService(
db *gorm.DB,
userRepo *repository.UserRepository,
postRepo *repository.PostRepository,
commentRepo *repository.CommentRepository,
userRepo repository.UserRepository,
postRepo repository.PostRepository,
commentRepo repository.CommentRepository,
groupRepo repository.GroupRepository,
activityRepo *repository.UserActivityRepository,
activityRepo repository.UserActivityRepository,
) AdminDashboardService {
return &adminDashboardServiceImpl{
db: db,

View File

@@ -30,13 +30,13 @@ type AdminGroupService interface {
// adminGroupServiceImpl 管理端群组服务实现
type adminGroupServiceImpl struct {
groupRepo repository.GroupRepository
userRepo *repository.UserRepository
userRepo repository.UserRepository
}
// NewAdminGroupService 创建管理端群组服务
func NewAdminGroupService(
groupRepo repository.GroupRepository,
userRepo *repository.UserRepository,
userRepo repository.UserRepository,
) AdminGroupService {
return &adminGroupServiceImpl{
groupRepo: groupRepo,

View File

@@ -34,13 +34,13 @@ type AdminPostService interface {
// adminPostServiceImpl 管理端帖子服务实现
type adminPostServiceImpl struct {
postRepo *repository.PostRepository
postRepo repository.PostRepository
cache cache.Cache
logService *LogService
}
// NewAdminPostService 创建管理端帖子服务
func NewAdminPostService(postRepo *repository.PostRepository, cacheBackend cache.Cache) AdminPostService {
func NewAdminPostService(postRepo repository.PostRepository, cacheBackend cache.Cache) AdminPostService {
return &adminPostServiceImpl{
postRepo: postRepo,
cache: cacheBackend,

View File

@@ -20,11 +20,11 @@ type AdminUserService interface {
// adminUserServiceImpl 管理端用户服务实现
type adminUserServiceImpl struct {
userRepo *repository.UserRepository
userRepo repository.UserRepository
}
// NewAdminUserService 创建管理端用户服务
func NewAdminUserService(userRepo *repository.UserRepository) AdminUserService {
func NewAdminUserService(userRepo repository.UserRepository) AdminUserService {
return &adminUserServiceImpl{
userRepo: userRepo,
}

View File

@@ -11,7 +11,6 @@ import (
"carrot_bbs/internal/repository"
"go.uber.org/zap"
"gorm.io/gorm"
)
// AsyncLogConfig 异步日志配置
@@ -31,7 +30,6 @@ type AsyncLogManager struct {
dataChangeChan chan *model.DataChangeLog
cfg *AsyncLogConfig
db *gorm.DB
wg sync.WaitGroup
ctx context.Context
cancel context.CancelFunc
@@ -42,10 +40,9 @@ type AsyncLogManager struct {
// NewAsyncLogManager 创建异步日志管理器
func NewAsyncLogManager(
db *gorm.DB,
operationRepo *repository.OperationLogRepository,
loginRepo *repository.LoginLogRepository,
dataChangeRepo *repository.DataChangeLogRepository,
operationRepo repository.OperationLogRepository,
loginRepo repository.LoginLogRepository,
dataChangeRepo repository.DataChangeLogRepository,
logger *zap.Logger,
cfg *AsyncLogConfig,
) *AsyncLogManager {
@@ -56,7 +53,6 @@ func NewAsyncLogManager(
loginChan: make(chan *model.LoginLog, cfg.BufferSize),
dataChangeChan: make(chan *model.DataChangeLog, cfg.BufferSize),
cfg: cfg,
db: db,
ctx: ctx,
cancel: cancel,
logger: logger,
@@ -90,9 +86,9 @@ func NewAsyncLogManager(
// worker 处理协程
func (m *AsyncLogManager) worker(
id int,
operationRepo *repository.OperationLogRepository,
loginRepo *repository.LoginLogRepository,
dataChangeRepo *repository.DataChangeLogRepository,
operationRepo repository.OperationLogRepository,
loginRepo repository.LoginLogRepository,
dataChangeRepo repository.DataChangeLogRepository,
) {
opBatch := make([]*model.OperationLog, 0, m.cfg.BatchSize)
loginBatch := make([]*model.LoginLog, 0, m.cfg.BatchSize)
@@ -164,9 +160,9 @@ func (m *AsyncLogManager) flushBatches(
ops []*model.OperationLog,
logins []*model.LoginLog,
changes []*model.DataChangeLog,
operationRepo *repository.OperationLogRepository,
loginRepo *repository.LoginLogRepository,
dataChangeRepo *repository.DataChangeLogRepository,
operationRepo repository.OperationLogRepository,
loginRepo repository.LoginLogRepository,
dataChangeRepo repository.DataChangeLogRepository,
) {
if len(ops) == 0 && len(logins) == 0 && len(changes) == 0 {
return
@@ -194,17 +190,17 @@ func (m *AsyncLogManager) flushBatches(
}
// flushOperationLogs 刷新操作日志
func (m *AsyncLogManager) flushOperationLogs(logs []*model.OperationLog, repo *repository.OperationLogRepository) error {
func (m *AsyncLogManager) flushOperationLogs(logs []*model.OperationLog, repo repository.OperationLogRepository) error {
return repo.BatchCreateOperationLogs(context.Background(), logs)
}
// flushLoginLogs 刷新登录日志
func (m *AsyncLogManager) flushLoginLogs(logs []*model.LoginLog, repo *repository.LoginLogRepository) error {
func (m *AsyncLogManager) flushLoginLogs(logs []*model.LoginLog, repo repository.LoginLogRepository) error {
return repo.BatchCreateLoginLogs(context.Background(), logs)
}
// flushDataChangeLogs 刷新数据变更日志
func (m *AsyncLogManager) flushDataChangeLogs(logs []*model.DataChangeLog, repo *repository.DataChangeLogRepository) error {
func (m *AsyncLogManager) flushDataChangeLogs(logs []*model.DataChangeLog, repo repository.DataChangeLogRepository) error {
return repo.BatchCreateDataChangeLogs(context.Background(), logs)
}

View File

@@ -21,11 +21,11 @@ type ChannelService interface {
}
type channelServiceImpl struct {
channelRepo *repository.ChannelRepository
channelRepo repository.ChannelRepository
cache cache.Cache
}
func NewChannelService(channelRepo *repository.ChannelRepository, c cache.Cache) ChannelService {
func NewChannelService(channelRepo repository.ChannelRepository, c cache.Cache) ChannelService {
return &channelServiceImpl{channelRepo: channelRepo, cache: c}
}

View File

@@ -56,9 +56,8 @@ type ChatService interface {
// chatServiceImpl 聊天服务实现
type chatServiceImpl struct {
db *gorm.DB
repo *repository.MessageRepository
userRepo *repository.UserRepository
repo repository.MessageRepository
userRepo repository.UserRepository
sensitive SensitiveService
sseHub *sse.Hub
@@ -69,9 +68,8 @@ type chatServiceImpl struct {
// NewChatService 创建聊天服务
func NewChatService(
db *gorm.DB,
repo *repository.MessageRepository,
userRepo *repository.UserRepository,
repo repository.MessageRepository,
userRepo repository.UserRepository,
sensitive SensitiveService,
sseHub *sse.Hub,
cacheBackend cache.Cache,
@@ -90,7 +88,6 @@ func NewChatService(
)
return &chatServiceImpl{
db: db,
repo: repo,
userRepo: userRepo,
sensitive: sensitive,
@@ -538,13 +535,9 @@ func (s *chatServiceImpl) GetAllUnreadCount(ctx context.Context, userID string)
// RecallMessage 撤回消息2分钟内
func (s *chatServiceImpl) RecallMessage(ctx context.Context, messageID string, userID string) error {
// 获取消息
var message model.Message
err := s.db.First(&message, "id = ?", messageID).Error
message, err := s.repo.GetMessageByID(messageID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("message not found")
}
return fmt.Errorf("failed to get message: %w", err)
return errors.New("message not found")
}
// 验证是否是消息发送者
@@ -563,10 +556,7 @@ func (s *chatServiceImpl) RecallMessage(ctx context.Context, messageID string, u
}
// 更新消息状态为已撤回,并清空原始消息内容,仅保留撤回占位
err = s.db.Model(&message).Updates(map[string]interface{}{
"status": model.MessageStatusRecalled,
"segments": model.MessageSegments{},
}).Error
err = s.repo.RecallMessage(messageID, userID)
if err != nil {
return fmt.Errorf("failed to recall message: %w", err)
}
@@ -604,22 +594,15 @@ func (s *chatServiceImpl) RecallMessage(ctx context.Context, messageID string, u
// DeleteMessage 删除消息(仅对自己可见)
func (s *chatServiceImpl) DeleteMessage(ctx context.Context, messageID string, userID string) error {
// 获取消息
var message model.Message
err := s.db.First(&message, "id = ?", messageID).Error
message, err := s.repo.GetMessageByID(messageID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("message not found")
}
return fmt.Errorf("failed to get message: %w", err)
return errors.New("message not found")
}
// 验证用户是否是会话参与者
_, err = s.getParticipant(ctx, message.ConversationID, userID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("no permission to delete this message")
}
return fmt.Errorf("failed to get participant: %w", err)
return errors.New("no permission to delete this message")
}
// 对于删除消息,我们使用软删除,但需要确保只对当前用户隐藏
@@ -629,7 +612,7 @@ func (s *chatServiceImpl) DeleteMessage(ctx context.Context, messageID string, u
}
// 更新消息状态为已删除
err = s.db.Model(&message).Update("status", model.MessageStatusDeleted).Error
err = s.repo.UpdateMessageStatus(message.ID, model.MessageStatusDeleted)
if err != nil {
return fmt.Errorf("failed to delete message: %w", err)
}

View File

@@ -15,8 +15,8 @@ import (
)
type CommentService struct {
commentRepo *repository.CommentRepository
postRepo *repository.PostRepository
commentRepo repository.CommentRepository
postRepo repository.PostRepository
systemMessageService SystemMessageService
cache cache.Cache
postAIService *PostAIService
@@ -24,7 +24,7 @@ type CommentService struct {
hookManager *hook.Manager
}
func NewCommentService(commentRepo *repository.CommentRepository, postRepo *repository.PostRepository, systemMessageService SystemMessageService, postAIService *PostAIService, cacheBackend cache.Cache, hookManager *hook.Manager) *CommentService {
func NewCommentService(commentRepo repository.CommentRepository, postRepo repository.PostRepository, systemMessageService SystemMessageService, postAIService *PostAIService, cacheBackend cache.Cache, hookManager *hook.Manager) *CommentService {
return &CommentService{
commentRepo: commentRepo,
postRepo: postRepo,

View File

@@ -106,25 +106,23 @@ type GroupMembersResult struct {
// groupService 群组服务实现
type groupService struct {
db *gorm.DB
groupRepo repository.GroupRepository
userRepo *repository.UserRepository
messageRepo *repository.MessageRepository
userRepo repository.UserRepository
messageRepo repository.MessageRepository
requestRepo repository.GroupJoinRequestRepository
notifyRepo *repository.SystemNotificationRepository
notifyRepo repository.SystemNotificationRepository
sseHub *sse.Hub
cache cache.Cache
}
// NewGroupService 创建群组服务
func NewGroupService(db *gorm.DB, groupRepo repository.GroupRepository, userRepo *repository.UserRepository, messageRepo *repository.MessageRepository, sseHub *sse.Hub, cacheBackend cache.Cache) GroupService {
func NewGroupService(groupRepo repository.GroupRepository, userRepo repository.UserRepository, messageRepo repository.MessageRepository, requestRepo repository.GroupJoinRequestRepository, notifyRepo repository.SystemNotificationRepository, sseHub *sse.Hub, cacheBackend cache.Cache) GroupService {
return &groupService{
db: db,
groupRepo: groupRepo,
userRepo: userRepo,
messageRepo: messageRepo,
requestRepo: repository.NewGroupJoinRequestRepository(db),
notifyRepo: repository.NewSystemNotificationRepository(db),
requestRepo: requestRepo,
notifyRepo: notifyRepo,
sseHub: sseHub,
cache: cacheBackend,
}
@@ -263,43 +261,17 @@ func (s *groupService) CreateGroup(ownerID string, name string, description stri
GroupID: &group.ID,
}
// 在事务中创建会话和参与者
err = s.db.Transaction(func(tx *gorm.DB) error {
// 创建会话
if err := tx.Create(conversation).Error; err != nil {
return err
// 收集所有参与者
participants := make([]string, 0, len(memberIDs)+1)
participants = append(participants, ownerID)
for _, memberID := range memberIDs {
if memberID != ownerID {
participants = append(participants, memberID)
}
}
// 添加群主为会话参与者
ownerParticipant := model.ConversationParticipant{
ConversationID: conversation.ID,
UserID: ownerID,
LastReadSeq: 0,
}
if err := tx.Create(&ownerParticipant).Error; err != nil {
return err
}
// 添加被邀请的成员为会话参与者
for _, memberID := range memberIDs {
if memberID == ownerID {
continue
}
participant := model.ConversationParticipant{
ConversationID: conversation.ID,
UserID: memberID,
LastReadSeq: 0,
}
if err := tx.Create(&participant).Error; err != nil {
// 单个参与者添加失败继续处理其他成员
continue
}
}
return nil
})
if err != nil {
// 使用仓储创建会话参与者
if err := s.messageRepo.CreateConversationWithParticipants(conversation, participants); err != nil {
// 记录错误但不影响群组创建成功
}
@@ -418,30 +390,8 @@ func (s *groupService) TransferOwner(userID string, groupID string, newOwnerID s
return ErrNotGroupMember
}
// 在事务中更新
return s.db.Transaction(func(tx *gorm.DB) error {
// 更新群组的群主
group.OwnerID = newOwnerID
if err := tx.Save(group).Error; err != nil {
return err
}
// 更新原群主为管理员
if err := tx.Model(&model.GroupMember{}).
Where("group_id = ? AND user_id = ?", groupID, userID).
Update("role", model.GroupRoleAdmin).Error; err != nil {
return err
}
// 更新新群主为群主
if err := tx.Model(&model.GroupMember{}).
Where("group_id = ? AND user_id = ?", groupID, newOwnerID).
Update("role", model.GroupRoleOwner).Error; err != nil {
return err
}
return nil
})
// 使用仓储的 TransferOwner 方法(在事务中更新
return s.groupRepo.TransferOwner(groupID, userID, newOwnerID)
}
// GetUserGroups 获取用户加入的群组列表
@@ -593,9 +543,7 @@ func (s *groupService) collectGroupReviewerIDs(groupID string, ownerID string, s
if ownerID != "" && ownerID != skipUserID {
reviewerSet[ownerID] = struct{}{}
}
var reviewers []model.GroupMember
if err := s.db.Where("group_id = ? AND role IN ?", groupID, []string{model.GroupRoleOwner, model.GroupRoleAdmin}).Find(&reviewers).Error; err == nil {
if reviewers, err := s.groupRepo.GetAdmins(groupID); err == nil {
for _, reviewer := range reviewers {
if reviewer.UserID == "" || reviewer.UserID == skipUserID {
continue

View File

@@ -19,7 +19,7 @@ import (
// HotRankWorker 定时在候选池上重算热门分,写入 Redis ZSET仅 TopN及 top_idsRedis+本地缓存)
type HotRankWorker struct {
cfg *config.Config
postRepo *repository.PostRepository
postRepo repository.PostRepository
c cache.Cache
mu sync.Mutex
stopOnce sync.Once
@@ -28,7 +28,7 @@ type HotRankWorker struct {
}
// NewHotRankWorker 创建热门榜重算 workercache 需为 Redis 实现才有意义)
func NewHotRankWorker(cfg *config.Config, postRepo *repository.PostRepository, c cache.Cache) *HotRankWorker {
func NewHotRankWorker(cfg *config.Config, postRepo repository.PostRepository, c cache.Cache) *HotRankWorker {
return &HotRankWorker{
cfg: cfg,
postRepo: postRepo,

View File

@@ -30,9 +30,9 @@ type LogCleanupService interface {
// logCleanupServiceImpl 日志清理服务实现
type logCleanupServiceImpl struct {
operationRepo *repository.OperationLogRepository
loginRepo *repository.LoginLogRepository
dataChangeRepo *repository.DataChangeLogRepository
operationRepo repository.OperationLogRepository
loginRepo repository.LoginLogRepository
dataChangeRepo repository.DataChangeLogRepository
cfg *LogCleanupConfig
logger *zap.Logger
ctx context.Context
@@ -41,9 +41,9 @@ type logCleanupServiceImpl struct {
// NewLogCleanupService 创建日志清理服务
func NewLogCleanupService(
operationRepo *repository.OperationLogRepository,
loginRepo *repository.LoginLogRepository,
dataChangeRepo *repository.DataChangeLogRepository,
operationRepo repository.OperationLogRepository,
loginRepo repository.LoginLogRepository,
dataChangeRepo repository.DataChangeLogRepository,
cfg *LogCleanupConfig,
logger *zap.Logger,
) LogCleanupService {

View File

@@ -4,6 +4,7 @@ import (
"context"
"time"
"carrot_bbs/internal/dto"
"carrot_bbs/internal/model"
"carrot_bbs/internal/repository"
)
@@ -11,7 +12,7 @@ import (
// OperationLogService 操作日志服务接口
type OperationLogService interface {
RecordOperation(log *model.OperationLog)
GetOperationLogs(ctx context.Context, filters repository.LogFilter, page, pageSize int) ([]*model.OperationLog, int64, error)
GetOperationLogs(ctx context.Context, filters dto.LogFilter, page, pageSize int) ([]*model.OperationLog, int64, error)
GetOperationLogsByUser(ctx context.Context, userID string, page, pageSize int) ([]*model.OperationLog, int64, error)
GetOperationLogsByTimeRange(ctx context.Context, startTime, endTime string, page, pageSize int) ([]*model.OperationLog, int64, error)
GetStatistics(ctx context.Context, startTime, endTime string) (*repository.OperationLogStatistics, error)
@@ -20,13 +21,13 @@ type OperationLogService interface {
// operationLogServiceImpl 操作日志服务实现
type operationLogServiceImpl struct {
asyncManager *AsyncLogManager
repo *repository.OperationLogRepository
repo repository.OperationLogRepository
}
// NewOperationLogService 创建操作日志服务
func NewOperationLogService(
asyncManager *AsyncLogManager,
repo *repository.OperationLogRepository,
repo repository.OperationLogRepository,
) OperationLogService {
return &operationLogServiceImpl{
asyncManager: asyncManager,
@@ -40,7 +41,7 @@ func (s *operationLogServiceImpl) RecordOperation(log *model.OperationLog) {
}
// GetOperationLogs 获取操作日志列表
func (s *operationLogServiceImpl) GetOperationLogs(ctx context.Context, filters repository.LogFilter, page, pageSize int) ([]*model.OperationLog, int64, error) {
func (s *operationLogServiceImpl) GetOperationLogs(ctx context.Context, filters dto.LogFilter, page, pageSize int) ([]*model.OperationLog, int64, error) {
return s.repo.GetOperationLogs(ctx, filters, page, pageSize)
}
@@ -62,7 +63,7 @@ func (s *operationLogServiceImpl) GetStatistics(ctx context.Context, startTime,
// LoginLogService 登录日志服务接口
type LoginLogService interface {
RecordLogin(log *model.LoginLog)
GetLoginLogs(ctx context.Context, filters repository.LoginFilter, page, pageSize int) ([]*model.LoginLog, int64, error)
GetLoginLogs(ctx context.Context, filters dto.LoginFilter, page, pageSize int) ([]*model.LoginLog, int64, error)
GetLoginLogsByUser(ctx context.Context, userID string, page, pageSize int) ([]*model.LoginLog, int64, error)
GetFailedLoginsByIP(ctx context.Context, ip string, timeWindow string) (int64, error)
GetRecentSuccessLogins(ctx context.Context, userID string, limit int) ([]*model.LoginLog, error)
@@ -72,13 +73,13 @@ type LoginLogService interface {
// loginLogServiceImpl 登录日志服务实现
type loginLogServiceImpl struct {
asyncManager *AsyncLogManager
repo *repository.LoginLogRepository
repo repository.LoginLogRepository
}
// NewLoginLogService 创建登录日志服务
func NewLoginLogService(
asyncManager *AsyncLogManager,
repo *repository.LoginLogRepository,
repo repository.LoginLogRepository,
) LoginLogService {
return &loginLogServiceImpl{
asyncManager: asyncManager,
@@ -92,7 +93,7 @@ func (s *loginLogServiceImpl) RecordLogin(log *model.LoginLog) {
}
// GetLoginLogs 获取登录日志列表
func (s *loginLogServiceImpl) GetLoginLogs(ctx context.Context, filters repository.LoginFilter, page, pageSize int) ([]*model.LoginLog, int64, error) {
func (s *loginLogServiceImpl) GetLoginLogs(ctx context.Context, filters dto.LoginFilter, page, pageSize int) ([]*model.LoginLog, int64, error) {
return s.repo.GetLoginLogs(ctx, filters, page, pageSize)
}
@@ -123,7 +124,7 @@ func (s *loginLogServiceImpl) GetStatistics(ctx context.Context, startTime, endT
// DataChangeLogService 数据变更日志服务接口
type DataChangeLogService interface {
RecordDataChange(log *model.DataChangeLog)
GetDataChangeLogs(ctx context.Context, filters repository.DataChangeFilter, page, pageSize int) ([]*model.DataChangeLog, int64, error)
GetDataChangeLogs(ctx context.Context, filters dto.DataChangeFilter, page, pageSize int) ([]*model.DataChangeLog, int64, error)
GetDataChangeLogsByUser(ctx context.Context, userID string, page, pageSize int) ([]*model.DataChangeLog, int64, error)
GetDataChangeLogsByOperator(ctx context.Context, operatorID string, page, pageSize int) ([]*model.DataChangeLog, int64, error)
GetStatistics(ctx context.Context, startTime, endTime string) (*repository.DataChangeLogStatistics, error)
@@ -132,13 +133,13 @@ type DataChangeLogService interface {
// dataChangeLogServiceImpl 数据变更日志服务实现
type dataChangeLogServiceImpl struct {
asyncManager *AsyncLogManager
repo *repository.DataChangeLogRepository
repo repository.DataChangeLogRepository
}
// NewDataChangeLogService 创建数据变更日志服务
func NewDataChangeLogService(
asyncManager *AsyncLogManager,
repo *repository.DataChangeLogRepository,
repo repository.DataChangeLogRepository,
) DataChangeLogService {
return &dataChangeLogServiceImpl{
asyncManager: asyncManager,
@@ -152,7 +153,7 @@ func (s *dataChangeLogServiceImpl) RecordDataChange(log *model.DataChangeLog) {
}
// GetDataChangeLogs 获取数据变更日志列表
func (s *dataChangeLogServiceImpl) GetDataChangeLogs(ctx context.Context, filters repository.DataChangeFilter, page, pageSize int) ([]*model.DataChangeLog, int64, error) {
func (s *dataChangeLogServiceImpl) GetDataChangeLogs(ctx context.Context, filters dto.DataChangeFilter, page, pageSize int) ([]*model.DataChangeLog, int64, error) {
return s.repo.GetDataChangeLogs(ctx, filters, page, pageSize)
}

View File

@@ -2,6 +2,8 @@ package service
import (
"errors"
"carrot_bbs/internal/dto"
"carrot_bbs/internal/model"
"carrot_bbs/internal/repository"
)
@@ -21,7 +23,7 @@ type MaterialService interface {
DeleteSubject(id string) error
// 资料相关
ListMaterials(params repository.MaterialFileQueryParams) ([]*model.MaterialFile, int64, error)
ListMaterials(params dto.MaterialFileQueryParams) ([]*model.MaterialFile, int64, error)
GetMaterialByID(id string) (*model.MaterialFile, error)
GetMaterialByIDWithSubject(id string) (*model.MaterialFile, error)
GetMaterialsBySubject(subjectID string, page, pageSize int) ([]*model.MaterialFile, int64, error)
@@ -36,14 +38,14 @@ type MaterialService interface {
// materialServiceImpl 学习资料服务实现
type materialServiceImpl struct {
subjectRepo *repository.MaterialSubjectRepository
fileRepo *repository.MaterialFileRepository
subjectRepo repository.MaterialSubjectRepository
fileRepo repository.MaterialFileRepository
}
// NewMaterialService 创建学习资料服务
func NewMaterialService(
subjectRepo *repository.MaterialSubjectRepository,
fileRepo *repository.MaterialFileRepository,
subjectRepo repository.MaterialSubjectRepository,
fileRepo repository.MaterialFileRepository,
) MaterialService {
return &materialServiceImpl{
subjectRepo: subjectRepo,
@@ -127,7 +129,7 @@ func (s *materialServiceImpl) DeleteSubject(id string) error {
// 资料相关方法
// =====================================================
func (s *materialServiceImpl) ListMaterials(params repository.MaterialFileQueryParams) ([]*model.MaterialFile, int64, error) {
func (s *materialServiceImpl) ListMaterials(params dto.MaterialFileQueryParams) ([]*model.MaterialFile, int64, error) {
return s.fileRepo.List(params)
}

View File

@@ -10,7 +10,6 @@ import (
"carrot_bbs/internal/repository"
"go.uber.org/zap"
"gorm.io/gorm"
)
// 缓存TTL常量
@@ -25,10 +24,8 @@ const (
// MessageService 消息服务
type MessageService struct {
db *gorm.DB
// 基础仓储
messageRepo *repository.MessageRepository
messageRepo repository.MessageRepository
// 缓存相关字段
conversationCache *cache.ConversationCache
@@ -40,7 +37,7 @@ type MessageService struct {
}
// NewMessageService 创建消息服务
func NewMessageService(db *gorm.DB, messageRepo *repository.MessageRepository, cacheBackend cache.Cache, uploadService *UploadService) *MessageService {
func NewMessageService(messageRepo repository.MessageRepository, cacheBackend cache.Cache, uploadService *UploadService) *MessageService {
// 创建适配器
convRepoAdapter := cache.NewConversationRepositoryAdapter(messageRepo)
msgRepoAdapter := cache.NewMessageRepositoryAdapter(messageRepo)
@@ -54,7 +51,6 @@ func NewMessageService(db *gorm.DB, messageRepo *repository.MessageRepository, c
)
return &MessageService{
db: db,
messageRepo: messageRepo,
conversationCache: conversationCache,
baseCache: cacheBackend,
@@ -161,7 +157,7 @@ func (s *MessageService) GetConversations(ctx context.Context, userID string, pa
// 生成缓存键
cacheKey := cache.ConversationListKey(userID, page, pageSize)
result, err := cache.GetOrLoadTyped[*ConversationListResult](
result, err := cache.GetOrLoadTyped(
s.baseCache,
cacheKey,
conversationTTL,
@@ -252,7 +248,7 @@ func (s *MessageService) GetUnreadCount(ctx context.Context, conversationID stri
// 生成缓存键
cacheKey := cache.UnreadDetailKey(userID, conversationID)
return cache.GetOrLoadTyped[int64](
return cache.GetOrLoadTyped(
s.baseCache,
cacheKey,
unreadTTL,

View File

@@ -20,12 +20,12 @@ const (
// NotificationService 通知服务
type NotificationService struct {
notificationRepo *repository.NotificationRepository
notificationRepo repository.NotificationRepository
cache cache.Cache
}
// NewNotificationService 创建通知服务
func NewNotificationService(notificationRepo *repository.NotificationRepository, cacheBackend cache.Cache) *NotificationService {
func NewNotificationService(notificationRepo repository.NotificationRepository, cacheBackend cache.Cache) *NotificationService {
return &NotificationService{
notificationRepo: notificationRepo,
cache: cacheBackend,

View File

@@ -73,7 +73,7 @@ type PostService interface {
// postServiceImpl 帖子服务实现
type postServiceImpl struct {
postRepo *repository.PostRepository
postRepo repository.PostRepository
systemMessageService SystemMessageService
cache cache.Cache
postAIService *PostAIService
@@ -82,7 +82,7 @@ type postServiceImpl struct {
hookManager *hook.Manager
}
func NewPostService(postRepo *repository.PostRepository, systemMessageService SystemMessageService, postAIService *PostAIService, cacheBackend cache.Cache, txManager repository.TransactionManager, hookManager *hook.Manager) PostService {
func NewPostService(postRepo repository.PostRepository, systemMessageService SystemMessageService, postAIService *PostAIService, cacheBackend cache.Cache, txManager repository.TransactionManager, hookManager *hook.Manager) PostService {
return &postServiceImpl{
postRepo: postRepo,
systemMessageService: systemMessageService,

View File

@@ -62,9 +62,9 @@ type PushService interface {
// pushServiceImpl 推送服务实现
type pushServiceImpl struct {
pushRepo *repository.PushRecordRepository
deviceRepo *repository.DeviceTokenRepository
messageRepo *repository.MessageRepository
pushRepo repository.PushRecordRepository
deviceRepo repository.DeviceTokenRepository
messageRepo repository.MessageRepository
sseHub *sse.Hub
// 推送队列
@@ -81,9 +81,9 @@ type pushTask struct {
// NewPushService 创建推送服务
func NewPushService(
pushRepo *repository.PushRecordRepository,
deviceRepo *repository.DeviceTokenRepository,
messageRepo *repository.MessageRepository,
pushRepo repository.PushRecordRepository,
deviceRepo repository.DeviceTokenRepository,
messageRepo repository.MessageRepository,
sseHub *sse.Hub,
) PushService {
return &pushServiceImpl{

View File

@@ -26,22 +26,30 @@ type SystemMessageService interface {
// 发送系统公告
SendSystemAnnouncement(ctx context.Context, userIDs []string, title string, content string) error
SendBroadcastAnnouncement(ctx context.Context, title string, content string) error
// 查询通知(供 Handler 层的 REST API 使用)
GetNotifications(receiverID string, page, pageSize int) ([]*model.SystemNotification, int64, error)
GetNotificationsByCursor(receiverID string, cursorStr string, pageSize int) ([]*model.SystemNotification, string, bool, error)
GetUnreadCount(receiverID string) (int64, error)
MarkAsRead(notificationID int64, receiverID string) error
MarkAllAsRead(receiverID string) error
DeleteNotification(notificationID int64, receiverID string) error
}
type systemMessageServiceImpl struct {
notifyRepo *repository.SystemNotificationRepository
notifyRepo repository.SystemNotificationRepository
pushService PushService
userRepo *repository.UserRepository
postRepo *repository.PostRepository
userRepo repository.UserRepository
postRepo repository.PostRepository
cache cache.Cache
}
// NewSystemMessageService 创建系统消息服务
func NewSystemMessageService(
notifyRepo *repository.SystemNotificationRepository,
notifyRepo repository.SystemNotificationRepository,
pushService PushService,
userRepo *repository.UserRepository,
postRepo *repository.PostRepository,
userRepo repository.UserRepository,
postRepo repository.PostRepository,
cacheBackend cache.Cache,
) SystemMessageService {
return &systemMessageServiceImpl{
@@ -402,6 +410,51 @@ func (s *systemMessageServiceImpl) createNotification(ctx context.Context, userI
return notification, nil
}
// GetNotifications 获取通知列表(供 Handler 调用)
func (s *systemMessageServiceImpl) GetNotifications(receiverID string, page, pageSize int) ([]*model.SystemNotification, int64, error) {
return s.notifyRepo.GetByReceiverID(receiverID, page, pageSize)
}
// GetNotificationsByCursor 游标分页获取通知列表(供 Handler 调用)
func (s *systemMessageServiceImpl) GetNotificationsByCursor(receiverID string, cursorStr string, pageSize int) ([]*model.SystemNotification, string, bool, error) {
return s.notifyRepo.GetByReceiverIDCursorLegacy(receiverID, cursorStr, pageSize)
}
// GetUnreadCount 获取未读数量(供 Handler 调用)
func (s *systemMessageServiceImpl) GetUnreadCount(receiverID string) (int64, error) {
return s.notifyRepo.GetUnreadCount(receiverID)
}
// MarkAsRead 标记单条为已读(供 Handler 调用)
func (s *systemMessageServiceImpl) MarkAsRead(notificationID int64, receiverID string) error {
err := s.notifyRepo.MarkAsRead(notificationID, receiverID)
if err != nil {
return err
}
cache.InvalidateUnreadSystem(s.cache, receiverID)
return nil
}
// MarkAllAsRead 标记全部为已读(供 Handler 调用)
func (s *systemMessageServiceImpl) MarkAllAsRead(receiverID string) error {
err := s.notifyRepo.MarkAllAsRead(receiverID)
if err != nil {
return err
}
cache.InvalidateUnreadSystem(s.cache, receiverID)
return nil
}
// DeleteNotification 删除通知(供 Handler 调用)
func (s *systemMessageServiceImpl) DeleteNotification(notificationID int64, receiverID string) error {
err := s.notifyRepo.Delete(notificationID, receiverID)
if err != nil {
return err
}
cache.InvalidateUnreadSystem(s.cache, receiverID)
return nil
}
// getActorInfo 获取操作者信息
func (s *systemMessageServiceImpl) getActorInfo(ctx context.Context, operatorID string) (string, string, error) {
// 从用户仓储获取用户信息

View File

@@ -35,11 +35,11 @@ type UserActivityService interface {
// userActivityService 实现
type userActivityService struct {
repo *repository.UserActivityRepository
repo repository.UserActivityRepository
}
// NewUserActivityService 创建用户活跃统计服务
func NewUserActivityService(repo *repository.UserActivityRepository) UserActivityService {
func NewUserActivityService(repo repository.UserActivityRepository) UserActivityService {
return &userActivityService{repo: repo}
}

View File

@@ -59,7 +59,7 @@ type UserService interface {
// userServiceImpl 用户服务实现
type userServiceImpl struct {
userRepo *repository.UserRepository
userRepo repository.UserRepository
systemMessageService SystemMessageService
emailCodeService EmailCodeService
logService *LogService
@@ -67,7 +67,7 @@ type userServiceImpl struct {
// NewUserService 创建用户服务
func NewUserService(
userRepo *repository.UserRepository,
userRepo repository.UserRepository,
systemMessageService SystemMessageService,
emailService EmailService,
cacheBackend cache.Cache,

View File

@@ -16,8 +16,8 @@ import (
// VoteService 投票服务
type VoteService struct {
voteRepo *repository.VoteRepository
postRepo *repository.PostRepository
voteRepo repository.VoteRepository
postRepo repository.PostRepository
cache cache.Cache
postAIService *PostAIService
systemMessageService SystemMessageService
@@ -25,8 +25,8 @@ type VoteService struct {
// NewVoteService 创建投票服务
func NewVoteService(
voteRepo *repository.VoteRepository,
postRepo *repository.PostRepository,
voteRepo repository.VoteRepository,
postRepo repository.PostRepository,
cache cache.Cache,
postAIService *PostAIService,
systemMessageService SystemMessageService,