github.com/SupenBysz/gf-admin-community@v0.7.4/internal/logic/sys_message/sys_message.go (about)

     1  package sys_message
     2  
     3  import (
     4  	"context"
     5  	"github.com/SupenBysz/gf-admin-community/sys_model"
     6  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_dao"
     7  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_do"
     8  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_entity"
     9  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_enum"
    10  	"github.com/SupenBysz/gf-admin-community/sys_model/sys_hook"
    11  	"github.com/SupenBysz/gf-admin-community/sys_service"
    12  	"github.com/gogf/gf/v2/container/garray"
    13  	"github.com/gogf/gf/v2/database/gdb"
    14  	"github.com/gogf/gf/v2/frame/g"
    15  	"github.com/gogf/gf/v2/os/gtime"
    16  	"github.com/gogf/gf/v2/util/gconv"
    17  	"github.com/kysion/base-library/base_hook"
    18  	"github.com/kysion/base-library/base_model"
    19  	"github.com/kysion/base-library/utility/daoctl"
    20  	"github.com/kysion/base-library/utility/kconv"
    21  	"github.com/yitter/idgenerator-go/idgen"
    22  )
    23  
    24  type sMessage struct {
    25  	MessageHook base_hook.BaseHook[sys_enum.MessageType, sys_hook.MessageTypeHookFunc]
    26  }
    27  
    28  func NewMessage() sys_service.IMessage {
    29  	return &sMessage{}
    30  }
    31  
    32  func init() {
    33  	sys_service.RegisterMessage(NewMessage())
    34  }
    35  
    36  // GetMessageById 根据id查询消息
    37  func (s *sMessage) GetMessageById(ctx context.Context, id int64) (*sys_model.SysMessageRes, error) {
    38  	result, err := daoctl.GetByIdWithError[sys_entity.SysMessage](sys_dao.SysMessage.Ctx(ctx), id)
    39  	if err != nil {
    40  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "根据id查询消息失败"+err.Error(), sys_dao.SysMessage.Table())
    41  	}
    42  
    43  	// 业务层  Hook处理渲染,如果没有Hook的话,那就直接格式化成默认的个人资质
    44  	s.MessageHook.Iterator(func(key sys_enum.MessageType, value sys_hook.MessageTypeHookFunc) {
    45  		// 判断注入的Hook业务类型是否一致
    46  		if key.Code()&result.Type == result.Type {
    47  			// 业务类型一致则调用注入的Hook函数
    48  			g.Try(ctx, func(ctx context.Context) {
    49  				err = value(ctx, sys_enum.Message.State.New(result.Type), (*sys_model.SysMessageRes)(result))
    50  			})
    51  		}
    52  	})
    53  
    54  	return (*sys_model.SysMessageRes)(result), err
    55  }
    56  
    57  // GetMessageDetailById 根据id查询消息详情
    58  func (s *sMessage) GetMessageDetailById(ctx context.Context, messageId, userId int64) (*sys_model.SysMessageRes, error) {
    59  	result, err := daoctl.GetByIdWithError[sys_entity.SysMessage](sys_dao.SysMessage.Ctx(ctx), messageId)
    60  	if err != nil {
    61  		return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "根据id查询消息失败"+err.Error(), sys_dao.SysMessage.Table())
    62  	}
    63  
    64  	// TODO 修改消息状态,改变为已读
    65  	//_, err = s.SetMessageState(ctx, id, unionMainId, sys_enum.Message.State.Readed)
    66  	//if err != nil {
    67  	//	return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "根据id查询消息详情失败"+err.Error(), sys_dao.SysMessage.Table())
    68  	//}
    69  
    70  	// TODO 直接追加消息的已读用户
    71  	_, err = s.SetMessageReadUserIds(ctx, messageId, userId)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	return (*sys_model.SysMessageRes)(result), nil
    77  }
    78  
    79  // CreateMessage 添加消息
    80  func (s *sMessage) CreateMessage(ctx context.Context, info *sys_model.SysMessage) (*sys_model.SysMessageRes, error) {
    81  	// 订阅附加数据
    82  
    83  	//ctx = base_funs.AttrBuilder[co_model.IEmployeeRes, co_model.IEmployeeRes](ctx, co_dao.CompanyEmployee.Columns().Id) //toUserId不但是学生、可以是老师
    84  
    85  	//ctx = base_funs.AttrBuilder[sys_model.SysUser, *sys_entity.SysUserDetail](ctx, sys_dao.SysUser.Columns().Id)
    86  
    87  	idStrArr, err := s.checkUser(ctx, info.ToUserIds)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	data := kconv.Struct(info, &sys_do.SysMessage{})
    93  	data.Id = idgen.NextId()
    94  
    95  	if len(idStrArr) > 0 {
    96  		slice := garray.NewStrArrayFrom(idStrArr).Unique().Slice()
    97  		data.ToUserIds = slice
    98  	}
    99  
   100  	// 赋值接收者类型
   101  	//data.ToUserType = employee.Data().User.Type
   102  	// 未读状态
   103  	//data.State = sys_enum.Message.State.UnRead.Code()
   104  
   105  	if info.ExtJson == "" {
   106  		data.ExtJson = nil
   107  	}
   108  
   109  	err = sys_dao.SysMessage.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   110  		data.CreatedAt = gtime.Now()
   111  		affected, err := daoctl.InsertWithError(sys_dao.SysMessage.Ctx(ctx).Data(data))
   112  
   113  		if affected == 0 || err != nil {
   114  			return sys_service.SysLogs().ErrorSimple(ctx, err, "添加消息失败"+err.Error(), sys_dao.SysMessage.Table())
   115  		}
   116  
   117  		return nil
   118  	})
   119  
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	return s.GetMessageById(ctx, gconv.Int64(data.Id))
   125  }
   126  
   127  // UpdateMessage 编辑消息 (限制是还未发送的)
   128  func (s *sMessage) UpdateMessage(ctx context.Context, id int64, info *sys_model.UpdateSysMessage) (*sys_model.SysMessageRes, error) {
   129  	//var employee co_model.IEmployeeRes
   130  	var err error
   131  
   132  	// 判断消息是否存在
   133  	message, err := s.GetMessageById(ctx, id)
   134  	if err != nil || message == nil {
   135  		return nil, err
   136  	}
   137  
   138  	// 判断消息状态,只有未发送的消息支持编辑
   139  	if message.SendAt != nil {
   140  		return nil, sys_service.SysLogs().ErrorSimple(ctx, nil, "只有未发送的消息支持编辑", sys_dao.SysMessage.Table())
   141  	}
   142  
   143  	// 消息接受者是否全部存在
   144  	idStrArr, err := s.checkUser(ctx, info.ToUserIds)
   145  
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	data := kconv.Struct(info, &sys_do.SysMessage{})
   150  	if len(idStrArr) > 0 {
   151  		slice := garray.NewStrArrayFrom(idStrArr).Unique().Slice()
   152  		data.ToUserIds = slice
   153  	} else {
   154  		data.ToUserIds = nil
   155  	}
   156  
   157  	if info.ExtJson == "" {
   158  		data.ExtJson = nil
   159  	}
   160  
   161  	err = sys_dao.SysMessage.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
   162  		affected, err := daoctl.UpdateWithError(sys_dao.SysMessage.Ctx(ctx).Where(
   163  			sys_do.SysMessage{
   164  				Id: id,
   165  			},
   166  		).OmitNilData().Data(data))
   167  
   168  		if affected == 0 || err != nil {
   169  			return sys_service.SysLogs().ErrorSimple(ctx, err, "信息修改失败"+err.Error(), sys_dao.SysMessage.Table())
   170  		}
   171  
   172  		return nil
   173  	})
   174  
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  
   179  	return s.GetMessageById(ctx, gconv.Int64(id))
   180  }
   181  
   182  // QueryMessage 查询消息列表
   183  func (s *sMessage) QueryMessage(ctx context.Context, params *base_model.SearchParams, isExport bool) (*sys_model.SysMessageListRes, error) {
   184  	if &params.Pagination == nil {
   185  		params.Pagination = base_model.Pagination{
   186  			PageNum:  1,
   187  			PageSize: 20,
   188  		}
   189  	}
   190  
   191  	params.Filter = append(params.Filter, base_model.FilterInfo{
   192  		Field:       sys_dao.SysMessage.Columns().Id,
   193  		Where:       ">",
   194  		IsOrWhere:   false,
   195  		Value:       0,
   196  		IsNullValue: false,
   197  	})
   198  
   199  	res, err := daoctl.Query[sys_model.SysMessageRes](sys_dao.SysMessage.Ctx(ctx), params, isExport)
   200  
   201  	if err != nil {
   202  		return &sys_model.SysMessageListRes{}, sys_service.SysLogs().ErrorSimple(ctx, err, "消息列表查询失败"+err.Error(), sys_dao.SysMessage.Table())
   203  	}
   204  
   205  	return (*sys_model.SysMessageListRes)(res), nil
   206  }
   207  
   208  // QueryUserMessage 查询指定用户的消息|列表
   209  func (s *sMessage) QueryUserMessage(ctx context.Context, userId int64, params *base_model.SearchParams, isExport bool) (*sys_model.SysMessageListRes, error) {
   210  
   211  	res, err := daoctl.Query[sys_model.SysMessageRes](sys_dao.SysMessage.Ctx(ctx).
   212  		WhereLike(sys_dao.SysMessage.Columns().ToUserIds, "%"+gconv.String(userId)+"%"),
   213  
   214  		params, isExport)
   215  
   216  	if err != nil {
   217  		return &sys_model.SysMessageListRes{}, sys_service.SysLogs().ErrorSimple(ctx, err, "消息列表查询失败"+err.Error(), sys_dao.SysMessage.Table())
   218  	}
   219  
   220  	return (*sys_model.SysMessageListRes)(res), nil
   221  }
   222  
   223  // QueryUnionMainMessage 查询指定主体发送的消息列表 (支持未发送消息列表,添加params参数)
   224  func (s *sMessage) QueryUnionMainMessage(ctx context.Context, unionMainId int64, params *base_model.SearchParams, isExport bool) (*sys_model.SysMessageListRes, error) {
   225  	res, err := daoctl.Query[sys_model.SysMessageRes](sys_dao.SysMessage.Ctx(ctx).Where(sys_do.SysMessage{
   226  		FromUserId: unionMainId,
   227  		//SendAt:     nil,
   228  	}), params, isExport)
   229  
   230  	if err != nil {
   231  		return &sys_model.SysMessageListRes{}, sys_service.SysLogs().ErrorSimple(ctx, err, "消息列表查询失败"+err.Error(), sys_dao.SysMessage.Table())
   232  	}
   233  
   234  	return (*sys_model.SysMessageListRes)(res), nil
   235  }
   236  
   237  // HasUnReadMessage 是否存在未读消息
   238  func (s *sMessage) HasUnReadMessage(ctx context.Context, userId int64) (int, error) {
   239  
   240  	count, err := sys_dao.SysMessage.Ctx(ctx).
   241  		WhereLike(sys_dao.SysMessage.Columns().ToUserIds, "%"+gconv.String(userId)+"%").
   242  		WhereNotLike(sys_dao.SysMessage.Columns().ReadUserIds, "%"+gconv.String(userId)+"%").
   243  		Count()
   244  
   245  	if err != nil {
   246  		return 0, sys_service.SysLogs().ErrorSimple(ctx, err, "查询未读的消息失败"+err.Error(), sys_dao.SysMessage.Table())
   247  
   248  	}
   249  	return count, nil
   250  }
   251  
   252  //// SetMessageState 设置消息状态  有已读UserIds,就不需要消息状态了
   253  //func (s *sMessage) setMessageState(ctx context.Context, id, unionMainId int64, state sys_enum.MessageState) (bool, error) {
   254  //	affected, err := daoctl.UpdateWithError(sys_dao.SysMessage.Ctx(ctx).Where(sys_do.SysMessage{
   255  //		Id:         id,
   256  //		FromUserId: unionMainId,
   257  //	}).Data(sys_do.SysMessage{
   258  //		State:  state.Code(),
   259  //		ReadAt: gtime.Now(),
   260  //	}))
   261  //
   262  //	if affected == 0 || err != nil {
   263  //		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "消息状态修改失败"+err.Error(), sys_dao.SysMessage.Table())
   264  //	}
   265  //
   266  //	return affected > 0, nil
   267  //}
   268  
   269  // SetMessageReadUserIds 追加公告已读用户
   270  func (s *sMessage) SetMessageReadUserIds(ctx context.Context, messageId int64, userId int64) (bool, error) {
   271  	message, err := s.GetMessageById(ctx, messageId)
   272  	if err != nil {
   273  		return false, err
   274  	}
   275  	var ids []string
   276  	gconv.Struct(message.ReadUserIds, &ids)
   277  
   278  	//oldArr  := garray.NewSortedStrArrayFrom(ids).Unique().Slice()
   279  
   280  	arr := garray.NewSortedStrArrayFrom(
   281  		append([]string{gconv.String(userId)}, ids...)).Unique().Slice()
   282  
   283  	affected, err := daoctl.UpdateWithError(sys_dao.SysMessage.Ctx(ctx).Where(sys_do.SysMessage{Id: messageId}).Data(sys_do.SysMessage{ReadUserIds: arr}))
   284  
   285  	if err != nil || affected <= 0 {
   286  		return false, sys_service.SysLogs().ErrorSimple(ctx, err, "追加公告已读用户失败"+err.Error(), sys_dao.SysMessage.Table())
   287  	}
   288  
   289  	return affected > 0, nil
   290  }
   291  
   292  // checkUser 校验消息接受者toUserIds是否全部存在
   293  func (s *sMessage) checkUser(ctx context.Context, toUserIds []int64) (idStrArr []string, err error) {
   294  	for _, userId := range toUserIds {
   295  		idStrArr = append(idStrArr, gconv.String(userId))
   296  		sysUser, err := sys_service.SysUser().GetSysUserById(ctx, userId)
   297  		if err != nil || sysUser == nil {
   298  			return nil, sys_service.SysLogs().ErrorSimple(ctx, err, "消息接收者中有用户不存在", sys_dao.SysMessage.Table())
   299  		}
   300  	}
   301  
   302  	return idStrArr, err
   303  }