package service import ( "errors" "fmt" "gadmin/config" "gadmin/internal/admin/consts" "gadmin/internal/admin/forms" "gadmin/internal/gorm/model" "gadmin/internal/gorm/query" "gadmin/utility/player" "gadmin/utility/serializer" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" "io" "net/http" "strings" "time" ) var ChatReport = new(chatReportService) type chatReportService struct{} func (s *chatReportService) List(ctx *gin.Context, req *forms.ChatReportListReq) serializer.Response { var ( q = query.Use(config.DB).ChatReportLog m = q.WithContext(ctx) offset int64 = 0 list []model.ChatReportLog ) if req.PlayerID > 0 { m = m.Where(q.PlayerID.Eq(req.PlayerID)) } if req.ClanPlayerID > 0 { m = m.Where(q.ClanPlayerID.Eq(req.ClanPlayerID)) } if req.ServerID != 0 { m = m.Where(q.ServerID.Eq(req.ServerID)) } if req.ClanServerID != 0 { m = m.Where(q.ClanServerID.Eq(req.ClanServerID)) } if req.ClanChatChannel != 0 { m = m.Where(q.ClanChatChannel.Eq(req.ClanChatChannel)) } if len(req.CreateTime) == 2 { m = m.Where(q.CreateTime.Between(req.CreateTime[0], req.CreateTime[1])) } if len(req.ClanTime) == 2 { m = m.Where(q.ClanTime.Between(req.ClanTime[0], req.ClanTime[1])) } if len(req.Sorter) > 0 { for i := 0; i < len(req.Sorter); i++ { if req.Sorter[i].Field == "id" { if req.Sorter[i].By == "DESC" { m = m.Order(q.ID.Desc()) } else { m = m.Order(q.ID) } } if req.Sorter[i].Field == "clan_time" { if req.Sorter[i].By == "DESC" { m = m.Order(q.ClanTime.Desc()) } else { m = m.Order(q.ClanTime) } } if req.Sorter[i].Field == "create_time" { if req.Sorter[i].By == "DESC" { m = m.Order(q.CreateTime.Desc()) } else { m = m.Order(q.CreateTime) } } } } else { m = m.Order(q.ID.Desc()) } req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage) count, err := m.Count() if err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 count", err) } if req.IsExport == 1 { if count > 0 { if err = m.Scan(&list); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 lists", err) } if err := export(ctx, list); err != nil { return serializer.Err(consts.CodeParamErr, "生成Excel表错误", err) } } else { return serializer.Err(consts.CodeParamErr, "暂没有要导出的数据", errors.New("暂没有要导出的数据")) } return serializer.Response{} } if count > 0 { if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&list); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 list", err) } } retList, err := handlerRet(list) if err != nil { return serializer.Err(consts.CodeParamErr, "处理数据错误", err) } listRes := forms.ListRes{ Page: req.Page, PerPage: req.PerPage, PageCount: (count + req.PerPage - 1) / req.PerPage, List: retList, } type ret struct { forms.ListRes Count int64 `json:"count"` } return serializer.Suc(ret{ ListRes: listRes, Count: count, }) } func handlerRet(list []model.ChatReportLog) ([]*item, error) { layout := "2006010215" nowHour := time.Now().Truncate(time.Hour) retList := make([]*item, 0, len(list)) serverMap := make(map[int32]string) servers := ServerOption.Option(&gin.Context{}) for _, server := range servers { serverMap[server.Value.(int32)] = server.Name } delete(serverMap, 0) playerServerIDMap := make(map[int64]int32) for _, v := range list { // 兼容老数据 if v.ServerID == 0 { serverID := playerServerIDMap[v.PlayerID] if serverID == 0 { if id, err := player.GetDBByUserId(v.PlayerID); err != nil { return nil, err } else { v.ServerID = int32(id) playerServerIDMap[v.PlayerID] = serverID } } } if v.ClanServerID == 0 { serverID := playerServerIDMap[v.ClanPlayerID] if serverID == 0 { if id, err := player.GetDBByUserId(v.ClanPlayerID); err != nil { return nil, err } else { v.ClanServerID = int32(id) playerServerIDMap[v.ClanPlayerID] = serverID } } } chatLogs := make([]string, 0) day := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Format("20060102") beforeHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour).Add(-1 * time.Hour).Format(layout) chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, beforeHour)) clanHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour) afterClanHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour).Add(1 * time.Hour) if clanHour.Before(nowHour) { hour := clanHour.Format(layout) chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, hour)) } if afterClanHour.Before(nowHour) { afterHour := afterClanHour.Format(layout) chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, afterHour)) } serverName := serverMap[v.ServerID] clanServerName := serverMap[v.ClanServerID] retList = append(retList, &item{ ChatReportLog: v, ChatLogs: chatLogs, ServerName: serverName, ClanServerName: clanServerName, ClanChannelName: consts.ChannelMap[v.ClanChatChannel], }) } return retList, nil } type item struct { model.ChatReportLog ServerName string `json:"server_name"` ClanServerName string `json:"clan_server_name"` ClanChannelName string `json:"clan_channel_name"` ChatLogs []string `json:"chat_logs"` } func export(ctx *gin.Context, list []model.ChatReportLog) error { lists, err := handlerRet(list) if err != nil { return err } // 导出 f := excelize.NewFile() f.SetColWidth("Sheet1", "A", "A", 15) f.SetColWidth("Sheet1", "B", "B", 15) f.SetColWidth("Sheet1", "C", "C", 15) f.SetColWidth("Sheet1", "D", "D", 25) f.SetColWidth("Sheet1", "E", "E", 25) f.SetColWidth("Sheet1", "F", "F", 30) f.SetColWidth("Sheet1", "G", "G", 30) f.SetColWidth("Sheet1", "H", "H", 15) f.SetColWidth("Sheet1", "J", "J", 15) f.SetColWidth("Sheet1", "K", "K", 25) f.SetColWidth("Sheet1", "L", "L", 45) f.SetColWidth("Sheet1", "M", "M", 25) f.SetColWidth("Sheet1", "N", "N", 25) // 创建一个工作表 f.SetCellValue("Sheet1", "A1", "ID") f.SetCellValue("Sheet1", "B1", "举报者ID") f.SetCellValue("Sheet1", "C1", "举报者昵称") f.SetCellValue("Sheet1", "D1", "举报者服务器") f.SetCellValue("Sheet1", "E1", "被举报者ID") f.SetCellValue("Sheet1", "F1", "被举报者昵称") f.SetCellValue("Sheet1", "G1", "被举报者服务器") f.SetCellValue("Sheet1", "H1", "举报消息ID") f.SetCellValue("Sheet1", "J1", "消息频道") f.SetCellValue("Sheet1", "K1", "联盟code") f.SetCellValue("Sheet1", "L1", "消息内容") f.SetCellValue("Sheet1", "M1", "消息发送时间") f.SetCellValue("Sheet1", "N1", "举报时间") for i, v := range lists { f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.ID) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), v.PlayerID) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), v.PlayerName) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), v.ServerName) f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), v.ClanPlayerID) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.ClanPlayerName) f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), v.ClanServerName) f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), v.ClanChatID) f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i+2), v.ClanChannelName) f.SetCellValue("Sheet1", fmt.Sprintf("K%d", i+2), v.LeagueCode) f.SetCellValue("Sheet1", fmt.Sprintf("L%d", i+2), v.ClanContent) clanTime := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Format("2006-01-02 15:04:05") createTime := time.Unix(0, v.CreateTime*int64(time.Millisecond)).Format("2006-01-02 15:04:05") f.SetCellValue("Sheet1", fmt.Sprintf("M%d", i+2), clanTime) f.SetCellValue("Sheet1", fmt.Sprintf("N%d", i+2), createTime) } // 设置工作簿的默认工作表 f.SetActiveSheet(1) ctx.Header("Content-Type", "application/vnd.ms-excel") ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=聊天举报记录导出%s.xlsx", time.Now().Format("20060102150405"))) f.WriteTo(ctx.Writer) return nil } func (s *chatReportService) LogList(ctx *gin.Context, req *forms.ChatLogListReq) serializer.Response { var ( q = query.Use(config.DB).ChatMsgLog m = q.WithContext(ctx) list []model.ChatMsgLog ) m = m.Where(q.ChatChannel.Eq(req.ChatChannel)) if req.ChatChannel != consts.ChatChannel_CrossServer { m = m.Where(q.SeverID.Eq(req.ServerID)) } if req.CurrentID != 0 { m = m.Where(q.ChatID.Lte(fmt.Sprintf("%d", req.CurrentID))).Order(q.ChatID.Desc()) } if req.BeforeID != 0 { m = m.Where(q.ChatID.Lt(fmt.Sprintf("%d", req.BeforeID))).Order(q.ChatID.Desc()) } if req.LaterID != 0 { m = m.Where(q.ChatID.Gt(fmt.Sprintf("%d", req.LaterID))).Order(q.ChatID) } if err := m.Limit(50).Offset(0).Scan(&list); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 list", err) } if req.CurrentID != 0 || req.BeforeID != 0 { // 反转结果 for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 { list[i], list[j] = list[j], list[i] } } return serializer.Suc(list) } func (s *chatReportService) DownloadLog(c *gin.Context, req *forms.DownloadChatLogReq) { if req.Path == "" { c.JSON(http.StatusInternalServerError, gin.H{ "msg": "参数错误", }) return } split := strings.Split(req.Path, "/") filename := split[len(split)-1] response, err := config.GetChatLogCOSClient().Object.Get(c, req.Path, nil) defer response.Body.Close() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "msg": "从cos中获取日志文件发生错误:" + err.Error(), }) return } c.Header("Content-Disposition", "attachment; filename="+filename) c.Header("Content-Length", fmt.Sprintf("%d", response.ContentLength)) c.Header("Content-Type", "application/octet-stream") if _, err := io.Copy(c.Writer, response.Body); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "msg": "从cos中获取日志文件发生错误:" + err.Error(), }) return } c.Status(http.StatusOK) } func (s *chatReportService) ChatMsgList(c *gin.Context, req *forms.ChatMsgListReq) serializer.Response { var ( q = query.Use(config.DB).ChatMsgLog m = q.WithContext(c) list []model.ChatMsgLog offset int64 = 0 ) if req.ServerID != 0 { m = m.Where(q.SeverID.Eq(req.ServerID)) } chatChannelList := make([]int32, 0) for _, channel := range req.ChatChannel { chatChannelList = append(chatChannelList, channel) if channel == 0 { chatChannelList = make([]int32, 0) break } } if len(chatChannelList) > 0 { m = m.Where(q.ChatChannel.In(req.ChatChannel...)) } if req.PlayerID != 0 { m = m.Where(q.PlayerID.Eq(req.PlayerID)) } if len(req.CreateTime) == 2 { m = m.Where(q.CreateTime.Between(req.CreateTime[0], req.CreateTime[1])) } req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage) count, err := m.Count() if err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 count", err) } if count > 0 { if err = m.Order(q.ChatID.Desc()).Limit(int(req.PerPage)).Offset(int(offset)).Scan(&list); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 list", err) } } serverMap := make(map[int32]string) servers := ServerOption.Option(&gin.Context{}) for _, server := range servers { serverMap[server.Value.(int32)] = server.Name } delete(serverMap, 0) ret := make([]forms.ChatMsgListRet, 0, len(list)) for _, item := range list { ret = append(ret, forms.ChatMsgListRet{ ID: item.ID, PlayerID: item.PlayerID, NickName: item.NickName, HeadID: item.HeadID, FrameID: item.FrameID, HeadImg: item.HeadImg, CreateTime: item.CreateTime, ChatChannel: item.ChatChannel, ChannelName: consts.ChannelMap[item.ChatChannel], ChatID: item.ChatID, Content: item.Content, SeverID: item.SeverID, ServerName: serverMap[item.SeverID], }) } listRes := forms.ListRes{ Page: req.Page, PerPage: req.PerPage, PageCount: (count + req.PerPage - 1) / req.PerPage, List: ret, } return serializer.Suc(struct { forms.ListRes Count int64 `json:"count"` }{ ListRes: listRes, Count: count, }) }