This commit is contained in:
likun 2025-08-12 14:42:34 +08:00
parent 709920a152
commit 4237a3bf89
32 changed files with 894 additions and 16 deletions

View File

@ -9,6 +9,7 @@ import (
"admin/lib/xlog"
"context"
"github.com/jmoiron/sqlx"
"github.com/xuri/excelize/v2"
"gorm.io/gorm"
"strconv"
"time"
@ -64,3 +65,162 @@ func (svc *GameLogService) QueryEventList(projectId int, eventName []string, ser
return
}
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
}

View File

@ -65,6 +65,250 @@ func init() {
func (hook *GameLogHook) Trim(projectInfo *entity.Project, eventName []string, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
totalCount, fieldsDescInfo, rows = hook.getTrimHandlerByEventName(eventName)(projectInfo, totalCount, fieldsDescInfo, rows)
return totalCount, fieldsDescInfo, rows
}
func (hook *GameLogHook) getTrimHandlerByEventName(eventName []string) func(projectInfo *entity.Project, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
for _, v := range eventName {
if v == "chatlog" {
return hook.trimChat
}
if v == "addcoin" || v == "costcoin" {
return hook.trimCurrencyChange
}
if v == "gainitem" || v == "loseitem" {
return hook.trimItemChange
}
}
return nil
}
func (hook *GameLogHook) trimChat(projectInfo *entity.Project, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
newFields, newRows := hook.trimCommon(projectInfo, fieldsDescInfo, rows)
extractFields := [][2]string{{"chatlog_channel", "渠道"}, {"chatlog_msg", "聊天内容"}}
for _, eField := range extractFields {
for colI, field := range fieldsDescInfo {
if field.Name == eField[0] {
field.Alias = eField[1]
newFields = append(newFields, field)
for rowI, row := range rows {
if field.Name == "chatlog_msg" {
newValue, err := base64.StdEncoding.DecodeString(row[colI].(string))
if err != nil {
xlog.Warnf("base64 decode field:%v value:%v error:%v", field.Name, row[colI], err)
} else {
newRows[rowI] = append(newRows[rowI], string(newValue))
}
} else if field.Name == "chatlog_channel" {
channel := int(row[colI].(float64))
channelDesc, find := chatChannels[channel]
if find {
newRows[rowI] = append(newRows[rowI], channelDesc)
} else {
newRows[rowI] = append(newRows[rowI], fmt.Sprintf("%v", row[colI]))
}
}
}
break
}
}
}
return totalCount, newFields, newRows
}
func (hook *GameLogHook) trimCurrencyChange(projectInfo *entity.Project, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
newFields, newRows := hook.trimCommon(projectInfo, fieldsDescInfo, rows)
newFields = append(newFields, []*dto2.GameLogFieldInfo{
{Name: "coinType", Alias: "货币类型"},
{Name: "coinPath", Alias: "途径"},
{Name: "beforeNum", Alias: "改变前数量"},
{Name: "deltaNum", Alias: "改变数量"},
{Name: "afterNum", Alias: "改变后数量"},
}...)
extractFields := map[string][]string{
"addcoin": {"addcoin_cointype", "addcoin_coinpath", "addcoin_coin", "addcoin_coinleft"},
"costcoin": {"costcoin_cointype", "costcoin_coinpath", "costcoin_coin", "costcoin_coinleft"},
}
// 刷新一下缓存
new(Items).GetItems(projectInfo)
for rowI, row := range rows {
eventName := row[0].(string)
for _, eFieldName := range extractFields[eventName] {
for fieldI, field := range fieldsDescInfo {
if field.Name == eFieldName {
colValue := row[fieldI]
if field.Name == "addcoin_cointype" || field.Name == "costcoin_cointype" {
// 货币类型要获取对应中文描述
coinType := int(colValue.(float64))
coinDesc := currencyDescTypes[coinType]
colValue = coinDesc
} else if field.Name == "addcoin_coinpath" {
desc, find := reasonGainEnumDesc[int(colValue.(float64))]
if find {
colValue = desc
}
} else if field.Name == "costcoin_coinpath" {
desc, find := reasonCostEnumDesc[int(colValue.(float64))]
if find {
colValue = desc
}
}
newRows[rowI] = append(newRows[rowI], colValue)
break
}
}
}
}
// 计算一下改变前数量
for i, row := range newRows {
deltaNum := row[len(row)-2].(float64)
leftCount := row[len(row)-1].(float64)
if row[0].(string) == "costcoin" {
deltaNum = -deltaNum
}
beforeNum := leftCount - deltaNum
row = row[:len(row)-2]
row = append(row, beforeNum)
row = append(row, deltaNum)
row = append(row, leftCount)
newRows[i] = row
}
return totalCount, newFields, newRows
}
func (hook *GameLogHook) trimItemChange(projectInfo *entity.Project, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
newFields, newRows := hook.trimCommon(projectInfo, fieldsDescInfo, rows)
newFields = append(newFields, []*dto2.GameLogFieldInfo{
{Name: "itemid", Alias: "道具id"},
{Name: "itemName", Alias: "道具名称"},
{Name: "reason", Alias: "途径"},
{Name: "beforeNum", Alias: "改变前数量"},
{Name: "deltaNum", Alias: "改变数量"},
{Name: "afterNum", Alias: "改变后数量"},
}...)
extractFields := map[string][]string{
"gainitem": {"gainitem_itemid", "gainitem_itempath", "gainitem_itemcount", "gainitem_itemleft"},
"loseitem": {"loseitem_itemid", "loseitem_itempath", "loseitem_itemcount", "loseitem_itemleft"},
}
// 刷新一下缓存
new(Items).GetItems(projectInfo)
for rowI, row := range rows {
eventName := row[0].(string)
for _, eFieldName := range extractFields[eventName] {
for fieldI, field := range fieldsDescInfo {
if field.Name == eFieldName {
colValue := row[fieldI]
if field.Name == "gainitem_itemid" || field.Name == "loseitem_itemid" {
// 道具id要获取对应道具名
itemId := int(colValue.(float64))
if itemsCache != nil {
itemInfo, find := itemsCache.mapItems[itemId]
if find {
itemName := itemInfo.Desc
newRows[rowI] = append(newRows[rowI], itemId)
newRows[rowI] = append(newRows[rowI], itemName)
} else {
newRows[rowI] = append(newRows[rowI], itemId)
newRows[rowI] = append(newRows[rowI], strconv.Itoa(itemId))
}
} else {
newRows[rowI] = append(newRows[rowI], itemId)
newRows[rowI] = append(newRows[rowI], strconv.Itoa(itemId))
}
} else if field.Name == "gainitem_itempath" {
desc, find := reasonGainDesc[colValue.(string)]
if find {
newRows[rowI] = append(newRows[rowI], desc)
} else {
newRows[rowI] = append(newRows[rowI], colValue)
}
} else if field.Name == "loseitem_itempath" {
desc, find := reasonCostDesc[colValue.(string)]
if find {
newRows[rowI] = append(newRows[rowI], desc)
} else {
newRows[rowI] = append(newRows[rowI], colValue)
}
} else {
newRows[rowI] = append(newRows[rowI], colValue)
}
break
}
}
}
}
// 计算一下改变前数量
for i, row := range newRows {
deltaNum := row[len(row)-2].(float64)
leftCount := row[len(row)-1].(float64)
if row[0].(string) == "loseitem" {
deltaNum = -deltaNum
}
beforeNum := leftCount - deltaNum
row = row[:len(row)-2]
row = append(row, beforeNum)
row = append(row, deltaNum)
row = append(row, leftCount)
newRows[i] = row
}
return totalCount, newFields, newRows
}
var commonExtractFields = [][2]string{
{"xwl_part_event", "事件类型"},
{"xwl_part_date", "时间"},
{"pub_userid", "账号"},
{"pub_roleid", "角色id"},
{"pub_rolename", "角色名"},
}
func (hook *GameLogHook) trimCommon(projectInfo *entity.Project, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
[]*dto2.GameLogFieldInfo, [][]any) {
newFields := make([]*dto2.GameLogFieldInfo, 0, 10)
newRows := make([][]any, len(rows))
for _, eField := range commonExtractFields {
for i, field := range fieldsDescInfo {
if eField[0] == field.Name {
field.Alias = eField[1]
newFields = append(newFields, field)
for j, newRow := range newRows {
if field.Name == "pub_rolename" {
newValue, err := base64.StdEncoding.DecodeString(rows[j][i].(string))
if err != nil {
xlog.Warnf("base64 decode field:%v value:%v error:%v", field.Name, rows[j][i], err)
} else {
newRows[j] = append(newRows[j], string(newValue))
}
} else if field.Name == "xwl_part_date" {
v := rows[j][i].(time.Time)
newRows[j] = append(newRow, v.Format(time.DateTime))
} else {
newRows[j] = append(newRow, rows[j][i])
}
}
break
}
}
}
return newFields, newRows
}
func (hook *GameLogHook) TrimBak(projectInfo *entity.Project, eventName []string, totalCount int, fieldsDescInfo []*dto2.GameLogFieldInfo, rows [][]any) (
int, []*dto2.GameLogFieldInfo, [][]any) {
// 删除不需要的字段
i := 0

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,17 @@ import (
"admin/internal/errcode"
"admin/internal/model/dto"
"admin/lib/httpclient"
"time"
)
type itemsCacher struct {
list []*dto.CommonDtoFieldChoice
mapItems map[int]*dto.ItemInfo
getTime time.Time
}
var itemsCache *itemsCacher
type Items struct {
}
@ -17,6 +26,12 @@ func (items *Items) GetItems(projectInfo *entity.Project) ([]*dto.CommonDtoField
// {Desc: "黄金大刀", Value: 346, Type: 1},
// {Desc: "白银大刀", Value: 346, Type: 1},
//}, nil
if itemsCache != nil && time.Now().Sub(itemsCache.getTime) < time.Minute {
// 小于1分钟就不拉了
return itemsCache.list, nil
}
alisrvAddr := projectInfo.GetApiAddr()
if alisrvAddr == "" {
return nil, errcode.New(errcode.ServerError, "项目%v没有配置api服务器地址", projectInfo.Po.Name)
@ -34,5 +49,21 @@ func (items *Items) GetItems(projectInfo *entity.Project) ([]*dto.CommonDtoField
if err != nil {
return make([]*dto.CommonDtoFieldChoice, 0), nil
}
itemsCache = &itemsCacher{
list: rsp.Data.List,
mapItems: make(map[int]*dto.ItemInfo),
getTime: time.Now(),
}
for _, v := range rsp.Data.List {
itemInfo := &dto.ItemInfo{
ItemID: int(v.Value.(float64)),
ItemNum: 0,
Desc: v.Desc,
}
itemsCache.mapItems[itemInfo.ItemID] = itemInfo
}
return rsp.Data.List, nil
}

View File

@ -169,7 +169,8 @@ func (hook *ServerHook) IsServerDownStatus(projectInfo *entity.Project, serverIn
return s.IsServerDown
}
}
return true
// 可能被合服了
return false
}
// getAllRunningServers 获取本地配置的服务器列表和远程获取的运行中服务器列表求个交集

View File

@ -7,6 +7,8 @@ import (
"admin/internal/model/dto"
"admin/lib/httpclient"
"admin/lib/xlog"
"os"
"path/filepath"
"strconv"
"strings"
"time"
@ -96,6 +98,48 @@ func (ctl *controller) GameLogEventList(ctx *context.WebContext, params *dto.Gam
return err
}
func (ctl *controller) GameLogEventListExport(ctx *context.WebContext, params *dto.GameLogEventListReq, rsp *dto.GameLogEventListRsp) error {
projectId := getCtxURIProjectId(ctx)
ds, _ := time.ParseInLocation("2006-01-02 15:04:05", params.DateStart, time.Local)
de, _ := time.ParseInLocation("2006-01-02 15:04:05", params.DateEnd, time.Local)
if ds.IsZero() {
ds = time.Now().Add(-time.Hour * 24 * 7)
}
if de.IsZero() {
de = time.Now().Add(time.Hour)
}
var eventList []string
if params.EventName != "" {
eventList = strings.Split(params.EventName, ",")
for _, en := range eventList {
if en == "" {
return errcode.New(errcode.ParamsInvalid, "event name invalid:[%v]", params.EventName)
}
}
}
var filePath string
var err error
filePath, err =
ctl.svc.GameLogSvc.QueryEventListExport(projectId,
eventList, params.ServerId, params.Account, params.RoleId, ds, de)
if err != nil {
return err
}
//filePath = "/tmp/Achievement.xlsx"
fileContentDisposition := "attachment; filename=" + filepath.Base(filePath)
ctx.GinCtx().Header("Content-Type", "application/octet-stream")
ctx.GinCtx().Header("Content-Disposition", fileContentDisposition)
ctx.GinCtx().Header("Content-Transfer-Encoding", "binary")
ctx.GinCtx().File(filePath)
os.Remove(filePath)
ctx.AlreadyOk()
return err
}
func (ctl *controller) getProjectResourceCommandApiAddr(ctx *context.WebContext) ([]string, error) {
projectId := getCtxURIProjectId(ctx)
//resouce := getCtxURIResource(ctx)

View File

@ -45,9 +45,12 @@ func (srv *Server) Route(engine *web.Engine, sdkEngine *web.Engine) {
accountGroup := projectGroup.Group("/:projectId/account/special", "")
accountGroup.Get("/detail", "账号详情查看", consts.WebPathPermit_Write, srv.ctl.GetAccountDetail)
accountGroup.Get("/event_list", "查询事件详细列表", consts.WebPathPermit_Write, srv.ctl.GameLogEventList)
accountGroup.Get("/event_list_export", "导出", consts.WebPathPermit_Write, srv.ctl.GameLogEventListExport)
roleGroup := projectGroup.Group("/:projectId/role/special", "")
roleGroup.Get("/detail", "角色详情查看", consts.WebPathPermit_Write, srv.ctl.GetRoleDetail)
roleGroup.Get("/event_list", "查询事件详细列表", consts.WebPathPermit_Write, srv.ctl.GameLogEventList)
roleGroup.Get("/event_list_export", "导出", consts.WebPathPermit_Write, srv.ctl.GameLogEventListExport)
}
}

Binary file not shown.

View File

@ -102,6 +102,8 @@ require (
github.com/quic-go/quic-go v0.49.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/rpcxio/libkv v0.5.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/rubyist/circuitbreaker v2.2.1+incompatible // indirect
@ -113,6 +115,7 @@ require (
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1201 // indirect
github.com/tiendc/go-deepcopy v1.6.0 // indirect
github.com/tinylib/msgp v1.2.5 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@ -121,6 +124,9 @@ require (
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/xtaci/kcp-go v5.4.20+incompatible // indirect
github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/excelize/v2 v2.9.1 // indirect
github.com/xuri/nfp v0.0.1 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
go.uber.org/mock v0.5.0 // indirect

View File

@ -497,6 +497,11 @@ github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -611,6 +616,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:
github.com/tencentyun/cos-go-sdk-v5 v0.7.66 h1:O4O6EsozBoDjxWbltr3iULgkI7WPj/BFNlYTXDuE64E=
github.com/tencentyun/cos-go-sdk-v5 v0.7.66/go.mod h1:8+hG+mQMuRP/OIS9d83syAvXvrMj9HhkND6Q1fLghw0=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tiendc/go-deepcopy v1.6.0 h1:0UtfV/imoCwlLxVsyfUd4hNHnB3drXsfle+wzSCA5Wo=
github.com/tiendc/go-deepcopy v1.6.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
github.com/tjfoc/gmsm v1.4.0/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
@ -643,6 +650,12 @@ github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.9.1 h1:VdSGk+rraGmgLHGFaGG9/9IWu1nj4ufjJ7uwMDtj8Qw=
github.com/xuri/excelize/v2 v2.9.1/go.mod h1:x7L6pKz2dvo9ejrRuD8Lnl98z4JLt0TGAwjhW+EiP8s=
github.com/xuri/nfp v0.0.1 h1:MDamSGatIvp8uOmDP8FnmjuQpu90NzdJxo7242ANR9Q=
github.com/xuri/nfp v0.0.1/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=

View File

@ -81,6 +81,10 @@ func (ctx *WebContext) Fail(err error) {
ctx.alreadySetRsp = true
}
func (ctx *WebContext) AlreadyOk() {
ctx.alreadySetRsp = true
}
func (ctx *WebContext) OkFile(fileName string, content string) {
if ctx.alreadySetRsp {
return

View File

@ -5,7 +5,7 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<script type="module" crossorigin src="/static/js/index-u8jI_EeY.js"></script>
<script type="module" crossorigin src="/static/js/index-Ks0AOv4F.js"></script>
<link rel="modulepreload" crossorigin href="/static/js/vendor-BRRlSJxx.js">
<link rel="stylesheet" crossorigin href="/static/css/vendor-DnLjZ1mj.css">
<link rel="stylesheet" crossorigin href="/static/css/index-BqAGgcXq.css">

View File

@ -0,0 +1 @@
.roleDetailList[data-v-5a8d8958] .el-table__header-wrapper th{word-break:break-word;background-color:#f8f8f9!important;color:#515a6e;height:40px!important;font-size:13px}.roleDetailList[data-v-5a8d8958] .el-table__header .el-table-column--selection .cell{width:60px!important}.roleDetailList[data-v-5a8d8958] .el-table .fixed-width .el-button--small{padding-left:0;padding-right:0;width:20px!important}.roleDetailList[data-v-5a8d8958] .el-table__header{background:#f5f7fa!important}.roleDetailList[data-v-5a8d8958] .el-table__row td{border-color:#ebeef5}.app-content[data-v-a4ce6ca8]{height:calc(100vh - 100px);display:flex}.app-content .table-content[data-v-a4ce6ca8]{display:flex;flex-direction:column;justify-content:space-between;height:100%;overflow:auto}.app-content .table-content .table[data-v-a4ce6ca8]{flex:1;position:relative}.app-content .table-content .table[data-v-a4ce6ca8] .el-table{flex:1;position:absolute}.app-content .table-content .table[data-v-a4ce6ca8] .el-popper{max-width:640px;word-break:break-all}.pagination-container .el-pagination[data-v-a4ce6ca8]{right:0;position:absolute;height:25px;margin-bottom:50px;margin-top:0;padding:10px 30px!important;z-index:2}.pagination-container.hidden[data-v-a4ce6ca8]{display:none}@media (max-width: 768px){.pagination-container .el-pagination>.el-pagination__jump[data-v-a4ce6ca8]{display:none!important}.pagination-container .el-pagination>.el-pagination__sizes[data-v-a4ce6ca8]{display:none!important}}

View File

@ -0,0 +1 @@
import{r as e,ab as a,a as s,o,d as r,b as l,w as n,a0 as t,a3 as u,ac as d,W as i,v as p,$ as c,a9 as m,I as v}from"./vendor-BRRlSJxx.js";import{_ as f,u as _,r as g}from"./index-Ks0AOv4F.js";const y={class:"login-box"},h={class:m({container:!0,animate__animated:!0,animate__flipInX:!0})},w={class:"form-container sign-in-container"},b=f({__name:"Login",setup(m){e(void 0);const{proxy:f}=a(),b=e({user:"",password:""}),V={user:[{required:!0,trigger:"blur",message:"请输入您的账号"}],password:[{required:!0,trigger:"blur",message:"请输入您的密码"}]},x=e=>{e&&f.$refs.ruleFormRef.validate((e=>{if(!e)return console.log("error submit!"),!1;_().login(b.value.user,b.value.password).then((()=>{console.log("登录成功,推送首页。。"),g.push({path:"/welcome"})}),(e=>{})).catch((()=>{v.error("login response error")}))}))};return(e,a)=>{const m=u,v=t,f=i,_=c;return o(),s("div",y,[r("div",h,[r("div",w,[l(_,{ref:"ruleFormRef",model:b.value,"status-icon":"",rules:V,class:"form"},{default:n((()=>[l(v,{class:"form-item",prop:"username"},{default:n((()=>[l(m,{modelValue:b.value.user,"onUpdate:modelValue":a[0]||(a[0]=e=>b.value.user=e),placeholder:"用户名",autocomplete:"off",onKeyup:a[1]||(a[1]=d((e=>x(b.value)),["enter"]))},null,8,["modelValue"])])),_:1}),l(v,{class:"form-item",prop:"password"},{default:n((()=>[l(m,{modelValue:b.value.password,"onUpdate:modelValue":a[2]||(a[2]=e=>b.value.password=e),placeholder:"密码",type:"password",autocomplete:"off",onKeyup:a[3]||(a[3]=d((e=>x(b.value)),["enter"]))},null,8,["modelValue"])])),_:1}),l(f,{class:"theme-button",type:"primary",onClick:a[4]||(a[4]=e=>x(b.value)),onKeydown:a[5]||(a[5]=d((e=>{var a;13!==a.keyCode&&100!==a.keyCode||x(b.value)}),["enter"]))},{default:n((()=>a[6]||(a[6]=[p("登 陆 ")]))),_:1})])),_:1},8,["model"])]),a[7]||(a[7]=r("div",{class:"overlay_container"},[r("div",{class:"overlay"},[r("div",{class:"overlay_panel overlay_right_container"},[r("h2",{class:"container-title"},"hello friend!"),r("p",null,"输入您的个人信息,以便使用后台管理系统")])])],-1))])])}}},[["__scopeId","data-v-68d4afe9"]]);export{b as default};

View File

@ -0,0 +1 @@
import{t as e}from"./tableUser-tEl1GqlP.js";import{u as r,L as t}from"./index-Ks0AOv4F.js";import{a as s,o as a,c as o,B as c}from"./vendor-BRRlSJxx.js";import"./resource-D-H98mQ5.js";import"./empty-DW_11tNO.js";const m={__name:"character",setup(m){let u={meta:{desc:"character",resource:"character",resource_url:"/resource/character",methods:{get:!0,post:!0,put:!0,delete:!0}}};return"admin"!==r().userInfo.character&&(u.meta.methods={}),t.setCache("resource",u),(r,t)=>(a(),s("div",null,[(a(),o(c(e)))]))}};export{m as default};

View File

@ -0,0 +1 @@
import{c as o,o as r,ai as s}from"./vendor-BRRlSJxx.js";import{_ as n}from"./index-Ks0AOv4F.js";const e=n({},[["render",function(n,e){const t=s;return r(),o(t,{description:"没有权限!请联系管理员添加权限!"})}]]);export{e};

View File

@ -0,0 +1 @@
import{r as e,T as a,a as l,o as t,c as o,u,B as n,F as s,U as p,w as r,b as d,V as i,a7 as v,a3 as m,a8 as c,W as g,v as h,C as y,d as f,X as V,Y as b,Z as x,D as w,a9 as I}from"./vendor-BRRlSJxx.js";import{_ as k,u as _,a as C}from"./index-Ks0AOv4F.js";import{e as U}from"./empty-DW_11tNO.js";const z={class:"table-content"},j={class:"table"},D={class:"pagination-container"},R=k({__name:"history",props:{rowInfo:{},disableConditionInput:!0},setup(k){const R=k;let S=!0;!1===R.disableConditionInput&&(S=!1);const T="admin"===_().userInfo.character,A=e(T),B=e(1),F=e(20),G=e(R.userId);R.rowInfo&&void 0!==R.rowInfo.ID&&(G.value=R.rowInfo.ID);const K=e(""),N=e(""),P=e(""),W=e(""),X=e(!1),Y=[20,50,100],Z=e(0),q=e([]),E=()=>{C(B.value,F.value,G.value,K.value,N.value,P.value,W.value).then((e=>{q.value=e.data.list,Z.value=e.data.totalCount,X.value=!0}),(e=>{}))};a((()=>{E()}));const H=()=>{G.value="",K.value="",N.value="",P.value="",W.value=""},J=e=>{Z.value<=0||F.value*B.value>Z.value&&q.value.length>=Z.value||E()},L=e=>{E()};return(e,a)=>{const k=m,_=g,C=v,R=i,T=b,M=V,O=x,Q=y,$=w;return t(),l("div",{class:I(u(S)?"app-content1":"app-content")},[u(A)?(t(),l(s,{key:1},[u(X)?(t(),o($,{key:0},{default:r((()=>[d(R,{style:{"margin-bottom":"10px"}},{default:r((()=>[d(C,null,{default:r((()=>[!1===u(S)?(t(),o(k,{key:0,modelValue:u(G),"onUpdate:modelValue":a[0]||(a[0]=e=>c(G)?G.value=e:null),placeholder:"用户id",style:{width:"150px","margin-right":"10px"}},null,8,["modelValue"])):p("",!0),!1===u(S)?(t(),o(k,{key:1,modelValue:u(K),"onUpdate:modelValue":a[1]||(a[1]=e=>c(K)?K.value=e:null),placeholder:"操作资源类型",style:{width:"150px","margin-right":"10px"}},null,8,["modelValue"])):p("",!0),!1===u(S)?(t(),o(k,{key:2,modelValue:u(N),"onUpdate:modelValue":a[2]||(a[2]=e=>c(N)?N.value=e:null),placeholder:"操作资源组",style:{width:"150px","margin-right":"10px"}},null,8,["modelValue"])):p("",!0),!1===u(S)?(t(),o(k,{key:3,modelValue:u(P),"onUpdate:modelValue":a[3]||(a[3]=e=>c(P)?P.value=e:null),placeholder:"操作对象",style:{width:"150px","margin-right":"10px"}},null,8,["modelValue"])):p("",!0),!1===u(S)?(t(),o(k,{key:4,modelValue:u(W),"onUpdate:modelValue":a[4]||(a[4]=e=>c(W)?W.value=e:null),placeholder:"操作方法",style:{width:"150px","margin-right":"10px"}},null,8,["modelValue"])):p("",!0),!1===u(S)?(t(),o(_,{key:5,onClick:E,type:"primary",style:{"margin-right":"10px"}},{default:r((()=>a[7]||(a[7]=[h("条件搜索 ")]))),_:1})):p("",!0),!1===u(S)?(t(),o(_,{key:6,onClick:H},{default:r((()=>a[8]||(a[8]=[h("清空条件")]))),_:1})):p("",!0)])),_:1})])),_:1}),d(Q,null,{default:r((()=>[f("div",z,[f("div",j,[d(M,{data:u(q),style:{width:"100%"},"table-layout":"auto",stripe:"","tooltip-effect":"light"},{default:r((()=>[d(T,{prop:"userId",label:"用户id"}),d(T,{prop:"userName",label:"用户名"}),d(T,{prop:"opResourceType",label:"操作资源类型"}),d(T,{prop:"opResourceGroup",label:"操作资源组"}),d(T,{prop:"opResourceKey",label:"操作对象"}),d(T,{prop:"method",label:"操作方法"}),d(T,{prop:"createdAt",label:"创建时间"}),d(T,{prop:"detailInfo",label:"详情数据","show-overflow-tooltip":""})])),_:1},8,["data"])]),f("div",D,[d(O,{"current-page":u(B),"onUpdate:currentPage":a[5]||(a[5]=e=>c(B)?B.value=e:null),"page-size":u(F),"onUpdate:pageSize":a[6]||(a[6]=e=>c(F)?F.value=e:null),"page-sizes":Y,layout:"total, sizes, prev, pager, next, jumper",total:u(Z),onSizeChange:J,onCurrentChange:L},null,8,["current-page","page-size","total"])])])])),_:1})])),_:1})):p("",!0)],64)):(t(),o(n(U),{key:0}))],2)}}},[["__scopeId","data-v-926d7759"]]);export{R as t};

View File

@ -0,0 +1 @@
import{t as s}from"./history-Cm4C7MHj.js";import{c as o,o as t,B as e}from"./vendor-BRRlSJxx.js";import"./index-Ks0AOv4F.js";import"./empty-DW_11tNO.js";const i={__name:"history",setup:i=>(i,r)=>(t(),o(e(s),{disableConditionInput:false}))};export{i as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{t as e}from"./table-BxcMHrUV.js";import{L as s,u as a,c as r}from"./index-Ks0AOv4F.js";import{i as t,a as o,o as m,c,B as p}from"./vendor-BRRlSJxx.js";import"./resource-D-H98mQ5.js";import"./empty-DW_11tNO.js";const i={__name:"project",setup(i){s.setCache("project",{}),t();let n=r;return"admin"!==a().userInfo.character&&(n.meta.methods={}),s.setCache("resource",n),(s,a)=>(m(),o("div",null,[(m(),c(p(e)))]))}};export{i as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{s as t}from"./index-Ks0AOv4F.js";function r(r,e){return t({url:r,method:"get",params:e})}function e(r,e){return t({url:r,method:"post",data:{dto:e}})}function o(r,e){return t({url:r,method:"put",data:{dto:e}})}function n(r,e){return t({url:r,method:"delete",data:e})}function u(r,e){return t({url:r+"/selection",method:"post",data:e})}function a(r){return t({url:"/project/"+r.toString()+"/items",method:"get"})}export{n as a,e as b,o as c,a as d,u as e,r};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{t as e}from"./tableUser-tEl1GqlP.js";import{u as s,L as r}from"./index-Ks0AOv4F.js";import{t}from"./history-Cm4C7MHj.js";import{a as o,o as a,c,B as m}from"./vendor-BRRlSJxx.js";import"./resource-D-H98mQ5.js";import"./empty-DW_11tNO.js";const u={__name:"user",setup(u){let n={meta:{desc:"user",resource:"user",resource_url:"/resource/user",methods:{get:!0,post:!0,put:!0,delete:!0}}};"admin"!==s().userInfo.character&&(n.meta.methods={}),r.setCache("resource",n);const p=[];return p.push({key:"user:exec:history",name:"执行记录",btn_color_type:"info",btn_type:1,btn_callback_component:t}),(s,r)=>(a(),o("div",null,[(a(),c(m(e),{rowClickDialogBtns:p}))]))}};export{u as default};

View File

@ -0,0 +1 @@
import{a as s,o as a,d as e,b as n,v as t,t as o,u as r,aa as p,F as l}from"./vendor-BRRlSJxx.js";import{u}from"./index-Ks0AOv4F.js";const f={style:{"font-size":"40px"}},i={style:{color:"darkslategrey","font-size":"50px"}},m={__name:"welcome",setup(m){const c=u().userInfo;return(u,m)=>{const d=p;return a(),s(l,null,[e("span",f,[m[0]||(m[0]=t("亲爱的")),e("span",i,o(r(c).nick_name),1),m[1]||(m[1]=t("!欢迎使用本公司后台管理系统!"))]),n(d),m[2]||(m[2]=e("span",{style:{"font-size":"40px"}},"硬盘有价,数据无价,操作不规范,亲人两行泪。",-1))],64)}}};export{m as default};

View File

@ -1,5 +1,5 @@
import request from '@/utils/request'
import axios from 'axios'
export function accountGetDetail(baseUrl, params) {
return request({
@ -23,4 +23,13 @@ export function gameLogEventList(baseUrl, params) {
method: 'get',
params: params,
})
}
export function gameLogExportEventList(baseUrl, params) {
return request({
url: baseUrl + '/special/event_list_export',
method: 'get',
responseType: 'blob',
params: params,
})
}

View File

@ -1,6 +1,6 @@
<script setup>
import {gameLogEventList} from "@/api/account.js";
import {gameLogEventList, gameLogExportEventList} from "@/api/account.js";
import LocalCache from "@/stores/localCache.js";
import dayjs from 'dayjs';
@ -63,15 +63,15 @@ const getEventList = () => {
eventList.value.rows.forEach(row => {
let find = false
for (let i = 0; i < roleIdFilters.value.length; i++) {
if (row[4] === roleIdFilters.value[i].value) {
if (row[3] === roleIdFilters.value[i].value) {
find = true
break
}
}
if (!find) {
roleIdFilters.value.push({
text: row[4],
value: row[4],
text: row[3],
value: row[3],
})
}
})
@ -101,6 +101,51 @@ const onClickResetParams = () => {
dateTimeValue.value = [todayStart, todayEnd]
}
const onClickExport = () => {
let listParams = {
"EventName": props.eventName,
"ServerId": props.serverId,
"Account": props.account,
"RoleId": props.roleId,
"PageNo": getPageNo.value,
"PageLen": getPageLen.value,
}
console.log("select name:", selectedEventName.value)
if (selectedEventName.value !== undefined && selectedEventName.value !== '' && selectedEventName.value !== ' ') {
listParams.EventName = selectedEventName.value
}
if (dateTimeValue.value.length === 2) {
console.log("select date time:", dateTimeValue.value)
listParams.DateStart = dayjs(dateTimeValue.value[0]).format('YYYY-MM-DD HH:mm:ss')
listParams.DateEnd = dayjs(dateTimeValue.value[1]).format('YYYY-MM-DD HH:mm:ss')
}
gameLogExportEventList(resource_url, listParams).then(res => {
console.log("点击导出返回:", res)
//
// Blob
const blob = new Blob([res.data], {type: 'application/octet-stream'})
const url = window.URL.createObjectURL(blob)
//
const contentDisposition = res.headers['content-disposition']
const fileName = contentDisposition
?.split('filename=')[1]
?.replace(/"/g, '')
|| 'download-file'
//
const link = document.createElement('a')
link.href = url
link.download = fileName
document.body.appendChild(link)
link.click()
window.URL.revokeObjectURL(url)
document.body.removeChild(link)
return
}, err => {
})
}
const filterRoleIdHandler = (
value,
row,
@ -212,13 +257,20 @@ const dateTimeShortcuts = [
重置
</el-button>
<el-button type="warning" @click="onClickExport">
<el-icon>
<Download/>
</el-icon>
导出
</el-button>
<div style="width:100%;height:0px;border: 1px solid #ebeef5;margin:8px 0 8px 0"/>
</el-row>
<el-row>
<el-table :data="eventList.rows" max-height="500px" style="width: 100%" table-layout="auto" border
:show-header="true">
<template v-for="(field, i) in eventList.fieldsDescInfo">
<el-table-column :prop="field.name" :label="field.alias" width="100px" v-if="field.name === 'pub_roleid'"
<el-table-column :prop="field.name" :label="field.alias" v-if="field.name === 'pub_roleid'"
:filters="roleIdFilters" :filter-method="filterRoleIdHandler">
<template #default="scope">
<span>
@ -226,7 +278,7 @@ const dateTimeShortcuts = [
</span>
</template>
</el-table-column>
<el-table-column :prop="field.name" :label="field.alias" width="100px" v-else>
<el-table-column :prop="field.name" :label="field.alias" v-else>
<template #default="scope">
<span>
{{ scope.row[i] }}

View File

@ -3,6 +3,7 @@
import roleDetailItems from '@/components/game/roleDetailItems.vue';
import {roleGetDetail} from "@/api/account.js";
import LocalCache from "@/stores/localCache.js";
import gamelogList from '@/components/game/gamelogList.vue';
const props = defineProps({
rowInfo: {},
@ -30,6 +31,10 @@ roleGetDetail(resource_url, props.rowInfo).then((res) => {
})
const gamelogChatChildRef = ref(null);
const gamelogCurrencyChildRef = ref(null);
const gamelogItemChangeChildRef = ref(null);
const handleClick = (tab, event) => {
// console.log("tab info:", tab)
switch (tab.props.name) {
@ -39,8 +44,15 @@ const handleClick = (tab, event) => {
case 'order':
console.log("点击了充值订单记录")
break
case 'currency':
console.log("点击了货币记录")
case 'chat':
gamelogChatChildRef.value.getEventList()
break
case 'currencyChange':
gamelogCurrencyChildRef.value.getEventList()
break
case 'itemChange':
gamelogItemChangeChildRef.value.getEventList()
break
}
}
@ -53,7 +65,24 @@ const handleClick = (tab, event) => {
<roleDetailItems :items="roleInfo.items"/>
</el-tab-pane>
<!-- <el-tab-pane label="货币记录" name="currency" v-if="accountInfo !== null">货币记录子页面</el-tab-pane>-->
<el-tab-pane key="tab-chat" label="聊天记录" name="chat">
<gamelogList key="tab-chat" :ref="(el) => gamelogChatChildRef = el"
:serverId="serverId" :roleId="roleId"
eventName="chatlog"/>
</el-tab-pane>
<el-tab-pane key="tab-currency" label="货币变动" name="currencyChange">
<gamelogList key="tab-currency" :ref="(el) => gamelogCurrencyChildRef = el"
:serverId="serverId" :roleId="roleId"
eventName="addcoin,costcoin"/>
</el-tab-pane>
<el-tab-pane key="tab-item" label="道具变动" name="itemChange">
<gamelogList key="tab-item" :ref="(el) => gamelogItemChangeChildRef = el"
:serverId="serverId" :roleId="roleId"
eventName="gainitem,loseitem"/>
</el-tab-pane>
</el-tabs>
</div>
</template>

View File

@ -62,7 +62,7 @@ const handleClick = (tab, event) => {
</script>
<template>
<div style="width: 1000px">
<div style="width: 100%;max-height: 60%">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick" v-if="loadAccountOk">
<el-tab-pane label="账号详情" name="detail">
<component :is="userDetailAccount" :accountInfo="accountInfo"/>

View File

@ -311,7 +311,7 @@ const tableSelectRows2 = (btnInfo, index, row) => {
const tableSelectRow3 = (i, row) => {
rowClickBtnSelectRow.value = row
rowClickBtnVisibleList[i] = true
console.log("点击按钮:", rowClickBtnSelectRow)
console.log("点击按钮:", rowClickBtnSelectRow.value)
}
const tableSelectRow4 = (btnInfo, row) => {
btnInfo.click_handler(row)
@ -785,7 +785,7 @@ const handleGenRandAccount = () => {
<template v-for="(btn, index) in rowClickBtns">
<el-dialog v-model="rowClickBtnVisibleList[index]" :title="btn.name"
@close="rowClickBtnVisibleList[index]=false"
destroy-on-close style="width: 1020px">
destroy-on-close style="width: 80%">
<component :is="btn.btn_callback_component" :rowInfo="rowClickBtnSelectRow"
:fieldsDescInfo="fieldsDescInfo"/>
</el-dialog>

View File

@ -55,10 +55,11 @@ const reqInterceptor = (config) => {
}
const resInterceptor = (res) => {
console.log("res:", res.data)
console.log("res:", res)
const contentDisposition = res.headers['content-disposition'];
const filenameRegex = /filename\*?=(?:UTF-8'')?"?([^";]+)"?/i;
if (contentDisposition) {
console.log("提取到文件:", contentDisposition)
const matches = contentDisposition.match(filenameRegex);
if (matches) {
return res
@ -105,7 +106,7 @@ const resInterceptor = (res) => {
}
const resErrorInterceptor = (err) => {
console.log(err)
console.log("返回错误:", err)
const code = err.response && err.response.status || -1
const message = err.response && err.response.data.message || err
ElMessageBox.alert(message, "请求服务器返回http错误码-" + code, {