2025-07-17 17:09:09 +08:00
|
|
|
package domain
|
|
|
|
|
|
|
|
import (
|
|
|
|
"admin/apps/game/domain/projects"
|
|
|
|
"admin/apps/game/domain/repo"
|
|
|
|
"admin/internal/consts"
|
|
|
|
"admin/internal/errcode"
|
|
|
|
"admin/internal/model/dto"
|
|
|
|
"admin/lib/xlog"
|
|
|
|
"context"
|
|
|
|
"github.com/jmoiron/sqlx"
|
2025-08-12 14:42:34 +08:00
|
|
|
"github.com/xuri/excelize/v2"
|
2025-07-17 17:09:09 +08:00
|
|
|
"gorm.io/gorm"
|
2025-07-22 09:37:37 +08:00
|
|
|
"strconv"
|
2025-07-17 17:09:09 +08:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type GameLogService struct {
|
|
|
|
projectRepo repo.IProjectRepo
|
|
|
|
repo repo.IGameLogRepo
|
|
|
|
}
|
|
|
|
|
2025-07-22 09:37:37 +08:00
|
|
|
func NewGameLogSvc(db *gorm.DB, metaDb *gorm.DB, clickHouseSqlx *sqlx.DB) *GameLogService {
|
|
|
|
return &GameLogService{projectRepo: repo.NewProjectRepo(db), repo: repo.NewGameLogRepo(metaDb, clickHouseSqlx)}
|
2025-07-17 17:09:09 +08:00
|
|
|
}
|
|
|
|
|
2025-07-22 09:37:37 +08:00
|
|
|
func (svc *GameLogService) QueryEventList(projectId int, eventName []string, serverId int, account, roleId string,
|
2025-07-17 17:09:09 +08:00
|
|
|
pageNo, pageLen int, dateStart, dateEnd time.Time) (totalCount int, fieldsDescInfo []*dto.GameLogFieldInfo, rows [][]any, err error) {
|
|
|
|
|
|
|
|
_, projectEt, find, err := svc.projectRepo.GetById(projectId)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, err
|
|
|
|
}
|
|
|
|
if !find {
|
|
|
|
return 0, nil, nil, errcode.New(errcode.ServerError, "not found project %v db data", projectId)
|
|
|
|
}
|
2025-07-22 09:37:37 +08:00
|
|
|
appId := projectEt.Po.BiAdminAppId
|
|
|
|
|
|
|
|
if appId == 0 {
|
|
|
|
return 0, make([]*dto.GameLogFieldInfo, 0), make([][]any, 0), nil
|
|
|
|
}
|
2025-07-17 17:09:09 +08:00
|
|
|
|
|
|
|
var attrList []*repo.AttrInfo
|
|
|
|
attrList, err = svc.repo.QueryAttrListByEvent(appId, eventName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2025-07-22 09:37:37 +08:00
|
|
|
querier := svc.repo.NewEventListQuerier("xwl_event"+strconv.Itoa(appId), eventName, attrList)
|
2025-07-17 17:09:09 +08:00
|
|
|
totalCount, fieldsDescInfo, rows, err = querier.CondRoleId(serverId, roleId).CondAccount(serverId, account).
|
|
|
|
Go(context.Background(), pageNo, pageLen, dateStart, dateEnd)
|
|
|
|
if err != nil {
|
|
|
|
xlog.Warnf("event list error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
hook := projects.GetProjectResourceHook(projectEt, consts.ResourcesName_GameLog)
|
|
|
|
if h, ok := hook.(projects.IGameLogEventListHook); ok {
|
|
|
|
totalCount, fieldsDescInfo, rows = h.Trim(projectEt, eventName, totalCount, fieldsDescInfo, rows)
|
|
|
|
}
|
|
|
|
|
2025-07-23 18:06:16 +08:00
|
|
|
if rows == nil {
|
|
|
|
rows = make([][]any, 0)
|
|
|
|
}
|
|
|
|
|
2025-07-17 17:09:09 +08:00
|
|
|
return
|
|
|
|
}
|
2025-08-12 14:42:34 +08:00
|
|
|
|
|
|
|
func (svc *GameLogService) QueryEventListExport(projectId int, eventName []string, serverId int, account, roleId string,
|
|
|
|
dateStart, dateEnd time.Time) (filePath string, err error) {
|
|
|
|
|
|
|
|
_, projectEt, find, err := svc.projectRepo.GetById(projectId)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if !find {
|
|
|
|
return "", errcode.New(errcode.ServerError, "not found project %v db data", projectId)
|
|
|
|
}
|
|
|
|
appId := projectEt.Po.BiAdminAppId
|
|
|
|
|
|
|
|
if appId == 0 {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var attrList []*repo.AttrInfo
|
|
|
|
attrList, err = svc.repo.QueryAttrListByEvent(appId, eventName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
pageNo := 1
|
|
|
|
pageLen := 1000
|
|
|
|
|
|
|
|
querier := svc.repo.NewEventListQuerier("xwl_event"+strconv.Itoa(appId), eventName, attrList)
|
|
|
|
querier.CondRoleId(serverId, roleId).CondAccount(serverId, account)
|
|
|
|
|
|
|
|
queryEventLogFun := func(curPageNo, curPageLen int) (int, []*dto.GameLogFieldInfo, [][]any, error) {
|
|
|
|
a, b, c, err := querier.Go(context.Background(), curPageNo, curPageLen, dateStart, dateEnd)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, err
|
|
|
|
}
|
|
|
|
hook := projects.GetProjectResourceHook(projectEt, consts.ResourcesName_GameLog)
|
|
|
|
if h, ok := hook.(projects.IGameLogEventListHook); ok {
|
|
|
|
a, b, c = h.Trim(projectEt, eventName, a, b, c)
|
|
|
|
}
|
|
|
|
return a, b, c, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 先读第一页看看总数
|
|
|
|
totalCount, fieldsDescInfo, tmpRows, err := queryEventLogFun(pageNo, pageLen)
|
|
|
|
if err != nil {
|
|
|
|
xlog.Warnf("event list error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
filePath = "/tmp/" + "gamelog-" + time.Now().Format("20060102150405") + ".xlsx"
|
|
|
|
f := excelize.NewFile()
|
|
|
|
defer f.Close()
|
|
|
|
f.SetDefaultFont("Arial")
|
|
|
|
index, err := f.NewSheet("Sheet1")
|
|
|
|
if err != nil {
|
|
|
|
return "", errcode.New(errcode.ServerError, "new excel sheet error:%v", err)
|
|
|
|
}
|
|
|
|
f.SetActiveSheet(index)
|
|
|
|
sheetWriter, err := f.NewStreamWriter("Sheet1")
|
|
|
|
if err != nil {
|
|
|
|
return "", errcode.New(errcode.ServerError, "new excel sheet writer error:%v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写入excel文件头
|
|
|
|
writeHeaders := make([]any, 0, len(fieldsDescInfo))
|
|
|
|
for _, field := range fieldsDescInfo {
|
|
|
|
writeHeaders = append(writeHeaders, field.Alias)
|
|
|
|
}
|
|
|
|
headerCell, _ := excelize.CoordinatesToCellName(1, 1)
|
|
|
|
err = sheetWriter.SetRow(headerCell, writeHeaders)
|
|
|
|
if err != nil {
|
|
|
|
xlog.Warnf("set row error:%v", err)
|
|
|
|
return "", errcode.New(errcode.ServerError, "set row error:%v", err)
|
|
|
|
}
|
|
|
|
xlog.Tracef("set headers %+v ok", writeHeaders)
|
|
|
|
//err = sheetWriter.Flush()
|
|
|
|
//if err != nil {
|
|
|
|
// return "", errcode.New(errcode.ServerError, "flush error:%v", err)
|
|
|
|
//}
|
|
|
|
|
|
|
|
writeQueue := make(chan [][]any, 20)
|
|
|
|
resultQueue := make(chan error, 1)
|
|
|
|
// 启动另一个协程来写文件
|
|
|
|
go func() {
|
|
|
|
curRowNum := 2
|
|
|
|
timeout := time.NewTicker(time.Second * 120)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case recvRows, ok := <-writeQueue:
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, row := range recvRows {
|
|
|
|
rowCell, _ := excelize.CoordinatesToCellName(1, curRowNum)
|
|
|
|
err = sheetWriter.SetRow(rowCell, row)
|
|
|
|
if err != nil {
|
|
|
|
resultQueue <- errcode.New(errcode.ServerError, "set row error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
xlog.Tracef("set row %+v ok", row)
|
|
|
|
curRowNum++
|
|
|
|
}
|
|
|
|
|
|
|
|
if curRowNum >= totalCount {
|
|
|
|
err = sheetWriter.Flush()
|
|
|
|
if err != nil {
|
|
|
|
resultQueue <- errcode.New(errcode.ServerError, "flush error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
saveErr := f.SaveAs(filePath)
|
|
|
|
if saveErr != nil {
|
|
|
|
err = errcode.New(errcode.ServerError, "save as error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
xlog.Infof("finish write total count %v to file:%v", curRowNum, filePath)
|
|
|
|
// 搞完了
|
|
|
|
resultQueue <- nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
case <-timeout.C:
|
|
|
|
xlog.Warnf("timeout!!")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
writeFileHandler := func(fields []*dto.GameLogFieldInfo, rows [][]any) {
|
|
|
|
writeQueue <- rows
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写第一页数据
|
|
|
|
writeFileHandler(fieldsDescInfo, tmpRows)
|
|
|
|
|
|
|
|
if totalCount >= pageLen {
|
|
|
|
// 总数还有,分页读了
|
|
|
|
totalPageNum := totalCount/pageLen + 1
|
|
|
|
|
|
|
|
for i := 1; i <= totalPageNum; i++ {
|
|
|
|
if i == 1 {
|
|
|
|
// 第一页读过了,跳过
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
totalCount, fieldsDescInfo, tmpRows, err = queryEventLogFun(pageNo, i*pageLen)
|
|
|
|
if err != nil {
|
|
|
|
xlog.Warnf("event list error:%v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
writeFileHandler(fieldsDescInfo, tmpRows)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = <-resultQueue
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
xlog.Warnf("event list write excel file:%v", err)
|
|
|
|
} else {
|
|
|
|
xlog.Infof("export file %v successfully!", filePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|