chat_report.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package service
  2. import (
  3. "errors"
  4. "fmt"
  5. "gadmin/config"
  6. "gadmin/internal/admin/consts"
  7. "gadmin/internal/admin/forms"
  8. "gadmin/internal/gorm/model"
  9. "gadmin/internal/gorm/query"
  10. "gadmin/utility/player"
  11. "gadmin/utility/serializer"
  12. "github.com/gin-gonic/gin"
  13. "github.com/xuri/excelize/v2"
  14. "io"
  15. "net/http"
  16. "strings"
  17. "time"
  18. )
  19. var ChatReport = new(chatReportService)
  20. type chatReportService struct{}
  21. func (s *chatReportService) List(ctx *gin.Context, req *forms.ChatReportListReq) serializer.Response {
  22. var (
  23. q = query.Use(config.DB).ChatReportLog
  24. m = q.WithContext(ctx)
  25. offset int64 = 0
  26. list []model.ChatReportLog
  27. )
  28. if req.PlayerID > 0 {
  29. m = m.Where(q.PlayerID.Eq(req.PlayerID))
  30. }
  31. if req.ClanPlayerID > 0 {
  32. m = m.Where(q.ClanPlayerID.Eq(req.ClanPlayerID))
  33. }
  34. if req.ServerID != 0 {
  35. m = m.Where(q.ServerID.Eq(req.ServerID))
  36. }
  37. if req.ClanServerID != 0 {
  38. m = m.Where(q.ClanServerID.Eq(req.ClanServerID))
  39. }
  40. if req.ClanChatChannel != 0 {
  41. m = m.Where(q.ClanChatChannel.Eq(req.ClanChatChannel))
  42. }
  43. if len(req.CreateTime) == 2 {
  44. m = m.Where(q.CreateTime.Between(req.CreateTime[0], req.CreateTime[1]))
  45. }
  46. if len(req.ClanTime) == 2 {
  47. m = m.Where(q.ClanTime.Between(req.ClanTime[0], req.ClanTime[1]))
  48. }
  49. if len(req.Sorter) > 0 {
  50. for i := 0; i < len(req.Sorter); i++ {
  51. if req.Sorter[i].Field == "id" {
  52. if req.Sorter[i].By == "DESC" {
  53. m = m.Order(q.ID.Desc())
  54. } else {
  55. m = m.Order(q.ID)
  56. }
  57. }
  58. if req.Sorter[i].Field == "clan_time" {
  59. if req.Sorter[i].By == "DESC" {
  60. m = m.Order(q.ClanTime.Desc())
  61. } else {
  62. m = m.Order(q.ClanTime)
  63. }
  64. }
  65. if req.Sorter[i].Field == "create_time" {
  66. if req.Sorter[i].By == "DESC" {
  67. m = m.Order(q.CreateTime.Desc())
  68. } else {
  69. m = m.Order(q.CreateTime)
  70. }
  71. }
  72. }
  73. } else {
  74. m = m.Order(q.ID.Desc())
  75. }
  76. req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
  77. count, err := m.Count()
  78. if err != nil {
  79. return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
  80. }
  81. if req.IsExport == 1 {
  82. if count > 0 {
  83. if err = m.Scan(&list); err != nil {
  84. return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
  85. }
  86. if err := export(ctx, list); err != nil {
  87. return serializer.Err(consts.CodeParamErr, "生成Excel表错误", err)
  88. }
  89. } else {
  90. return serializer.Err(consts.CodeParamErr, "暂没有要导出的数据", errors.New("暂没有要导出的数据"))
  91. }
  92. return serializer.Response{}
  93. }
  94. if count > 0 {
  95. if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&list); err != nil {
  96. return serializer.Err(consts.CodeParamErr, "查询出错 list", err)
  97. }
  98. }
  99. retList, err := handlerRet(list)
  100. if err != nil {
  101. return serializer.Err(consts.CodeParamErr, "处理数据错误", err)
  102. }
  103. listRes := forms.ListRes{
  104. Page: req.Page,
  105. PerPage: req.PerPage,
  106. PageCount: (count + req.PerPage - 1) / req.PerPage,
  107. List: retList,
  108. }
  109. type ret struct {
  110. forms.ListRes
  111. Count int64 `json:"count"`
  112. }
  113. return serializer.Suc(ret{
  114. ListRes: listRes,
  115. Count: count,
  116. })
  117. }
  118. func handlerRet(list []model.ChatReportLog) ([]*item, error) {
  119. layout := "2006010215"
  120. nowHour := time.Now().Truncate(time.Hour)
  121. retList := make([]*item, 0, len(list))
  122. serverMap := make(map[int32]string)
  123. servers := ServerOption.Option(&gin.Context{})
  124. for _, server := range servers {
  125. serverMap[server.Value.(int32)] = server.Name
  126. }
  127. delete(serverMap, 0)
  128. playerServerIDMap := make(map[int64]int32)
  129. for _, v := range list {
  130. // 兼容老数据
  131. if v.ServerID == 0 {
  132. serverID := playerServerIDMap[v.PlayerID]
  133. if serverID == 0 {
  134. if id, err := player.GetDBByUserId(v.PlayerID); err != nil {
  135. return nil, err
  136. } else {
  137. v.ServerID = int32(id)
  138. playerServerIDMap[v.PlayerID] = serverID
  139. }
  140. }
  141. }
  142. if v.ClanServerID == 0 {
  143. serverID := playerServerIDMap[v.ClanPlayerID]
  144. if serverID == 0 {
  145. if id, err := player.GetDBByUserId(v.ClanPlayerID); err != nil {
  146. return nil, err
  147. } else {
  148. v.ClanServerID = int32(id)
  149. playerServerIDMap[v.ClanPlayerID] = serverID
  150. }
  151. }
  152. }
  153. chatLogs := make([]string, 0)
  154. day := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Format("20060102")
  155. beforeHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour).Add(-1 * time.Hour).Format(layout)
  156. chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, beforeHour))
  157. clanHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour)
  158. afterClanHour := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Truncate(time.Hour).Add(1 * time.Hour)
  159. if clanHour.Before(nowHour) {
  160. hour := clanHour.Format(layout)
  161. chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, hour))
  162. }
  163. if afterClanHour.Before(nowHour) {
  164. afterHour := afterClanHour.Format(layout)
  165. chatLogs = append(chatLogs, fmt.Sprintf("%s/%s/chat.%s.log", consts.ServerMap[v.ClanServerID], day, afterHour))
  166. }
  167. serverName := serverMap[v.ServerID]
  168. clanServerName := serverMap[v.ClanServerID]
  169. retList = append(retList, &item{
  170. ChatReportLog: v,
  171. ChatLogs: chatLogs,
  172. ServerName: serverName,
  173. ClanServerName: clanServerName,
  174. ClanChannelName: consts.ChannelMap[v.ClanChatChannel],
  175. })
  176. }
  177. return retList, nil
  178. }
  179. type item struct {
  180. model.ChatReportLog
  181. ServerName string `json:"server_name"`
  182. ClanServerName string `json:"clan_server_name"`
  183. ClanChannelName string `json:"clan_channel_name"`
  184. ChatLogs []string `json:"chat_logs"`
  185. }
  186. func export(ctx *gin.Context, list []model.ChatReportLog) error {
  187. lists, err := handlerRet(list)
  188. if err != nil {
  189. return err
  190. }
  191. // 导出
  192. f := excelize.NewFile()
  193. f.SetColWidth("Sheet1", "A", "A", 15)
  194. f.SetColWidth("Sheet1", "B", "B", 15)
  195. f.SetColWidth("Sheet1", "C", "C", 15)
  196. f.SetColWidth("Sheet1", "D", "D", 25)
  197. f.SetColWidth("Sheet1", "E", "E", 25)
  198. f.SetColWidth("Sheet1", "F", "F", 30)
  199. f.SetColWidth("Sheet1", "G", "G", 30)
  200. f.SetColWidth("Sheet1", "H", "H", 15)
  201. f.SetColWidth("Sheet1", "J", "J", 15)
  202. f.SetColWidth("Sheet1", "K", "K", 25)
  203. f.SetColWidth("Sheet1", "L", "L", 45)
  204. f.SetColWidth("Sheet1", "M", "M", 25)
  205. f.SetColWidth("Sheet1", "N", "N", 25)
  206. // 创建一个工作表
  207. f.SetCellValue("Sheet1", "A1", "ID")
  208. f.SetCellValue("Sheet1", "B1", "举报者ID")
  209. f.SetCellValue("Sheet1", "C1", "举报者昵称")
  210. f.SetCellValue("Sheet1", "D1", "举报者服务器")
  211. f.SetCellValue("Sheet1", "E1", "被举报者ID")
  212. f.SetCellValue("Sheet1", "F1", "被举报者昵称")
  213. f.SetCellValue("Sheet1", "G1", "被举报者服务器")
  214. f.SetCellValue("Sheet1", "H1", "举报消息ID")
  215. f.SetCellValue("Sheet1", "J1", "消息频道")
  216. f.SetCellValue("Sheet1", "K1", "联盟code")
  217. f.SetCellValue("Sheet1", "L1", "消息内容")
  218. f.SetCellValue("Sheet1", "M1", "消息发送时间")
  219. f.SetCellValue("Sheet1", "N1", "举报时间")
  220. for i, v := range lists {
  221. f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.ID)
  222. f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), v.PlayerID)
  223. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), v.PlayerName)
  224. f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), v.ServerName)
  225. f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), v.ClanPlayerID)
  226. f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.ClanPlayerName)
  227. f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), v.ClanServerName)
  228. f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), v.ClanChatID)
  229. f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i+2), v.ClanChannelName)
  230. f.SetCellValue("Sheet1", fmt.Sprintf("K%d", i+2), v.LeagueCode)
  231. f.SetCellValue("Sheet1", fmt.Sprintf("L%d", i+2), v.ClanContent)
  232. clanTime := time.Unix(0, v.ClanTime*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
  233. createTime := time.Unix(0, v.CreateTime*int64(time.Millisecond)).Format("2006-01-02 15:04:05")
  234. f.SetCellValue("Sheet1", fmt.Sprintf("M%d", i+2), clanTime)
  235. f.SetCellValue("Sheet1", fmt.Sprintf("N%d", i+2), createTime)
  236. }
  237. // 设置工作簿的默认工作表
  238. f.SetActiveSheet(1)
  239. ctx.Header("Content-Type", "application/vnd.ms-excel")
  240. ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=聊天举报记录导出%s.xlsx", time.Now().Format("20060102150405")))
  241. f.WriteTo(ctx.Writer)
  242. return nil
  243. }
  244. func (s *chatReportService) LogList(ctx *gin.Context, req *forms.ChatLogListReq) serializer.Response {
  245. var (
  246. q = query.Use(config.DB).ChatMsgLog
  247. m = q.WithContext(ctx)
  248. list []model.ChatMsgLog
  249. )
  250. m = m.Where(q.ChatChannel.Eq(req.ChatChannel))
  251. if req.ChatChannel != consts.ChatChannel_CrossServer {
  252. m = m.Where(q.SeverID.Eq(req.ServerID))
  253. }
  254. if req.CurrentID != 0 {
  255. m = m.Where(q.ChatID.Lte(fmt.Sprintf("%d", req.CurrentID))).Order(q.ChatID.Desc())
  256. }
  257. if req.BeforeID != 0 {
  258. m = m.Where(q.ChatID.Lt(fmt.Sprintf("%d", req.BeforeID))).Order(q.ChatID.Desc())
  259. }
  260. if req.LaterID != 0 {
  261. m = m.Where(q.ChatID.Gt(fmt.Sprintf("%d", req.LaterID))).Order(q.ChatID)
  262. }
  263. if err := m.Limit(50).Offset(0).Scan(&list); err != nil {
  264. return serializer.Err(consts.CodeParamErr, "查询出错 list", err)
  265. }
  266. if req.CurrentID != 0 || req.BeforeID != 0 {
  267. // 反转结果
  268. for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 {
  269. list[i], list[j] = list[j], list[i]
  270. }
  271. }
  272. return serializer.Suc(list)
  273. }
  274. func (s *chatReportService) DownloadLog(c *gin.Context, req *forms.DownloadChatLogReq) {
  275. if req.Path == "" {
  276. c.JSON(http.StatusInternalServerError, gin.H{
  277. "msg": "参数错误",
  278. })
  279. return
  280. }
  281. split := strings.Split(req.Path, "/")
  282. filename := split[len(split)-1]
  283. response, err := config.GetChatLogCOSClient().Object.Get(c, req.Path, nil)
  284. defer response.Body.Close()
  285. if err != nil {
  286. c.JSON(http.StatusInternalServerError, gin.H{
  287. "msg": "从cos中获取日志文件发生错误:" + err.Error(),
  288. })
  289. return
  290. }
  291. c.Header("Content-Disposition", "attachment; filename="+filename)
  292. c.Header("Content-Length", fmt.Sprintf("%d", response.ContentLength))
  293. c.Header("Content-Type", "application/octet-stream")
  294. if _, err := io.Copy(c.Writer, response.Body); err != nil {
  295. c.JSON(http.StatusInternalServerError, gin.H{
  296. "msg": "从cos中获取日志文件发生错误:" + err.Error(),
  297. })
  298. return
  299. }
  300. c.Status(http.StatusOK)
  301. }
  302. func (s *chatReportService) ChatMsgList(c *gin.Context, req *forms.ChatMsgListReq) serializer.Response {
  303. var (
  304. q = query.Use(config.DB).ChatMsgLog
  305. m = q.WithContext(c)
  306. list []model.ChatMsgLog
  307. offset int64 = 0
  308. )
  309. if req.ServerID != 0 {
  310. m = m.Where(q.SeverID.Eq(req.ServerID))
  311. }
  312. chatChannelList := make([]int32, 0)
  313. for _, channel := range req.ChatChannel {
  314. chatChannelList = append(chatChannelList, channel)
  315. if channel == 0 {
  316. chatChannelList = make([]int32, 0)
  317. break
  318. }
  319. }
  320. if len(chatChannelList) > 0 {
  321. m = m.Where(q.ChatChannel.In(req.ChatChannel...))
  322. }
  323. if req.PlayerID != 0 {
  324. m = m.Where(q.PlayerID.Eq(req.PlayerID))
  325. }
  326. if len(req.CreateTime) == 2 {
  327. m = m.Where(q.CreateTime.Between(req.CreateTime[0], req.CreateTime[1]))
  328. }
  329. req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
  330. count, err := m.Count()
  331. if err != nil {
  332. return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
  333. }
  334. if count > 0 {
  335. if err = m.Order(q.ChatID.Desc()).Limit(int(req.PerPage)).Offset(int(offset)).Scan(&list); err != nil {
  336. return serializer.Err(consts.CodeParamErr, "查询出错 list", err)
  337. }
  338. }
  339. serverMap := make(map[int32]string)
  340. servers := ServerOption.Option(&gin.Context{})
  341. for _, server := range servers {
  342. serverMap[server.Value.(int32)] = server.Name
  343. }
  344. delete(serverMap, 0)
  345. ret := make([]forms.ChatMsgListRet, 0, len(list))
  346. for _, item := range list {
  347. ret = append(ret, forms.ChatMsgListRet{
  348. ID: item.ID,
  349. PlayerID: item.PlayerID,
  350. NickName: item.NickName,
  351. HeadID: item.HeadID,
  352. FrameID: item.FrameID,
  353. HeadImg: item.HeadImg,
  354. CreateTime: item.CreateTime,
  355. ChatChannel: item.ChatChannel,
  356. ChannelName: consts.ChannelMap[item.ChatChannel],
  357. ChatID: item.ChatID,
  358. Content: item.Content,
  359. SeverID: item.SeverID,
  360. ServerName: serverMap[item.SeverID],
  361. })
  362. }
  363. listRes := forms.ListRes{
  364. Page: req.Page,
  365. PerPage: req.PerPage,
  366. PageCount: (count + req.PerPage - 1) / req.PerPage,
  367. List: ret,
  368. }
  369. return serializer.Suc(struct {
  370. forms.ListRes
  371. Count int64 `json:"count"`
  372. }{
  373. ListRes: listRes,
  374. Count: count,
  375. })
  376. }