package sys import ( "context" "fmt" "hotgo/internal/consts" "hotgo/internal/library/contexts" "hotgo/internal/library/imkafka" "hotgo/internal/model/input/form" "hotgo/internal/model/input/sysin" "hotgo/internal/service" "hotgo/utility/convert" "hotgo/utility/excel" "net/url" "strconv" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" ) type sSysImPrivateMessage struct{} type sSysImGroupMessage struct{} func NewSysImPrivateMessage() *sSysImPrivateMessage { return &sSysImPrivateMessage{} } func NewSysImGroupMessage() *sSysImGroupMessage { return &sSysImGroupMessage{} } func init() { service.RegisterSysImPrivateMessage(NewSysImPrivateMessage()) service.RegisterSysImGroupMessage(NewSysImGroupMessage()) } func (s *sSysImPrivateMessage) List(ctx context.Context, in *sysin.ImPrivateMessageListInp) ([]*sysin.ImMessageListModel, int, error) { if err := in.Filter(ctx); err != nil { return nil, 0, err } values := addPageQuery(url.Values{}, in.Page, in.PerPage) setQuery(values, "topic", in.Topic) setQuery(values, "from_user_id", in.FromUserId) setQuery(values, "to_user_id", in.ToUserId) setQuery(values, "content_type", in.ContentType) setQuery(values, "status", in.Status) setQuery(values, "keyword", in.Keyword) addTimeRangeQuery(values, "created_at", in.CreatedAt) return queryImMessages(ctx, in.TenantId, "private-messages", values) } func (s *sSysImGroupMessage) List(ctx context.Context, in *sysin.ImGroupMessageListInp) ([]*sysin.ImMessageListModel, int, error) { if err := in.Filter(ctx); err != nil { return nil, 0, err } values := addPageQuery(url.Values{}, in.Page, in.PerPage) setQuery(values, "topic", in.Topic) if in.SeqId > 0 { values.Set("seq_id", strconv.FormatInt(in.SeqId, 10)) } setQuery(values, "sender_user_id", in.SenderUserId) setQuery(values, "sender_username", in.SenderUsername) setQuery(values, "sender_nickname", in.SenderNickname) setQuery(values, "group_name", in.GroupName) setQuery(values, "content_type", in.ContentType) setQuery(values, "status", in.Status) setQuery(values, "keyword", in.Keyword) addTimeRangeQuery(values, "created_at", in.CreatedAt) return queryImMessages(ctx, in.TenantId, "group-messages", values) } func queryImMessages(ctx context.Context, tenantId int64, resource string, values url.Values) ([]*sysin.ImMessageListModel, int, error) { tenant, err := resolveImAdminTenant(ctx, tenantId) if err != nil { return nil, 0, err } return imAdminQueryList[sysin.ImMessageListModel](ctx, tenant, "/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/"+resource, values, map[string]string{"sender_user_id": "fromUserId", "sent_at": "createdAt", "message_type": "contentType", "content_summary": "contentExcerpt"}) } func (s *sSysImPrivateMessage) View(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) { return viewImMessage(ctx, in) } func (s *sSysImGroupMessage) View(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) { return viewImMessage(ctx, in) } func viewImMessage(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) { if err := in.Filter(ctx); err != nil { return nil, err } tenant, err := resolveImAdminTenant(ctx, in.TenantId) if err != nil { return nil, err } path := "/internal/admin-query/tenants/" + url.PathEscape(tenant.Code) + "/messages/" + url.PathEscape(in.Topic) + "/" + strconv.FormatInt(in.SeqId, 10) return imAdminQueryOne[sysin.ImMessageViewModel](ctx, tenant, path, map[string]string{"sender_user_id": "fromUserId", "sent_at": "createdAt", "message_type": "contentType"}) } func (s *sSysImPrivateMessage) Hide(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) { return publishMessageCommand(ctx, in, "private", consts.ImAdminCommandMessageHide) } func (s *sSysImPrivateMessage) Delete(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) { return publishMessageCommand(ctx, in, "private", consts.ImAdminCommandMessageDelete) } func (s *sSysImGroupMessage) Hide(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) { return publishMessageCommand(ctx, in, "group", consts.ImAdminCommandMessageHide) } func (s *sSysImGroupMessage) Delete(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) { return publishMessageCommand(ctx, in, "group", consts.ImAdminCommandMessageDelete) } func publishMessageCommand(ctx context.Context, in *sysin.ImMessageActionInp, conversationType string, eventType string) (*sysin.ImMessageCommandModel, error) { if err := in.Filter(ctx); err != nil { return nil, err } tenant, err := resolveImAdminTenant(ctx, in.TenantId) if err != nil { return nil, err } user := contexts.GetUser(ctx) actorName := "" if user != nil { actorName = user.RealName } bizId := in.Topic + ":" + strconv.FormatInt(in.SeqId, 10) command, err := imkafka.PublishAdminCommand(ctx, imkafka.AdminCommandInput{ TenantID: tenant.Id, TenantCode: tenant.Code, EventType: eventType, BizType: "message", BizID: bizId, Actor: &imkafka.Actor{Type: "admin", ID: strconv.FormatInt(contexts.GetUserId(ctx), 10), DisplayName: actorName}, Payload: map[string]any{"conversation_type": conversationType, "topic": in.Topic, "seq_id": in.SeqId, "reason": in.Reason}, CreatedBy: contexts.GetUserId(ctx), }) result := "success" if err != nil { result = "failed" } _ = writeImAdminAudit(ctx, tenant.Id, eventType, "message", in.SeqId, result, map[string]any{"conversation_type": conversationType, "topic": in.Topic, "reason": in.Reason}) if err != nil { return nil, err } return &sysin.ImMessageCommandModel{CommandId: command.CommandID, EventId: command.EventID, Status: command.Status}, nil } func (s *sSysImPrivateMessage) Export(ctx context.Context, in *sysin.ImPrivateMessageListInp) error { list, total, err := s.List(ctx, in) if err != nil { return err } return exportImMessages(ctx, list, total, in.Page, in.PerPage, "单聊消息") } func (s *sSysImGroupMessage) Export(ctx context.Context, in *sysin.ImGroupMessageListInp) error { list, total, err := s.List(ctx, in) if err != nil { return err } return exportImMessages(ctx, list, total, in.Page, in.PerPage, "群聊消息") } func exportImMessages(ctx context.Context, list []*sysin.ImMessageListModel, total int, page int, perPage int, label string) error { tags, err := convert.GetEntityDescTags(sysin.ImMessageExportModel{}) if err != nil { return err } var exports []sysin.ImMessageExportModel if err = gconv.Scan(list, &exports); err != nil { return err } fileName := "导出" + label + "-" + gctx.CtxId(ctx) sheetName := fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", total, form.CalPageCount(total, perPage), page, len(list)) return excel.ExportByStructs(ctx, tags, exports, fileName, sheetName) } func setQuery(values url.Values, key string, value string) { if value != "" { values.Set(key, value) } }