123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- package service
- import (
- "context"
- "encoding/json"
- "entrance-grpc/iam"
- "fmt"
- "gadmin/config"
- "gadmin/internal/admin/consts"
- "gadmin/internal/admin/forms"
- "gadmin/internal/admin/gm_rpc/rpc_share"
- "gadmin/internal/gorm/model"
- "gadmin/internal/gorm/query"
- "gadmin/package/gmdata"
- "gadmin/utility"
- "gadmin/utility/character"
- "gadmin/utility/player"
- "gadmin/utility/serializer"
- "gadmin/utility/token"
- "github.com/gin-gonic/gin"
- "github.com/sirupsen/logrus"
- "github.com/spf13/cast"
- "github.com/xuri/excelize/v2"
- model2 "leafstalk/covenant/model"
- msg2 "leafstalk/covenant/msg"
- "strconv"
- "strings"
- "time"
- )
- // AdminEmail 邮件
- var AdminEmail = new(sAdminEmail)
- type sAdminEmail struct{}
- type Ret struct {
- model.AdminEmail
- Sender string `json:"sender"`
- }
- type Ext struct {
- Id string `json:"id"`
- Count string `json:"count"`
- }
- func (s *sAdminEmail) List(ctx *gin.Context, req forms.AdminEmailListReq) serializer.Response {
- var (
- q = query.Use(config.DB).AdminEmail
- m = q.WithContext(ctx)
- //u = query.Use(config.DB).AdminUser
- offset int64 = 0
- models forms.UserAccountListRes
- lists []*Ret
- )
- req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
- models.Page = req.Page
- models.PerPage = req.PerPage
- if req.Sender != "" {
- first, err := config.GetIamClient().GetAdminUserByNickName(ctx, &iam.GetAdminUserByNickNameReq{
- NickName: req.Sender,
- })
- if err == nil && first.Code == 0 {
- m = m.Where(q.OperatorID.Eq(first.Data.ID))
- }
- }
- if req.OperatorId > 0 {
- m = m.Where(q.OperatorID.Eq(req.OperatorId))
- }
- if len(req.CreatedAt) == 2 {
- m = m.Where(q.CreatedAt.Between(req.CreatedAt[0], req.CreatedAt[1]))
- }
- m = m.Order(q.ID.Desc())
- count, err := m.Count()
- if err != nil {
- return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
- }
- if count == 0 {
- return serializer.Suc(models)
- }
- if req.IsExport == 1 {
- if err = m.Scan(&lists); err != nil {
- return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
- }
- err = s.Export(ctx, lists)
- if err != nil {
- return serializer.Err(consts.CodeParamErr, "导出错误", err)
- }
- return serializer.Response{}
- }
- if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
- return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
- }
- uIdMap := make(map[int64]struct{})
- for i, v := range lists {
- if v.OperatorID > 0 {
- uIdMap[v.OperatorID] = struct{}{}
- }
- lists[i].PlayerIds = strings.Replace(v.PlayerIds, "[", "", -1)
- lists[i].PlayerIds = strings.Replace(v.PlayerIds, "]", "", -1)
- lists[i].PlayerIds = strings.Replace(v.PlayerIds, "\"", "", -1)
- }
- uIds := make([]int64, 0, len(lists))
- for uid := range uIdMap {
- uIds = append(uIds, uid)
- }
- res, err := config.GetIamClient().BatchGetAdminUser(context.Background(), &iam.BatchGetAdminUserReq{UIds: uIds})
- if err != nil || res.Code != 0 {
- return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
- }
- uMap := make(map[int64]*iam.AdminUserInfo)
- for _, usr := range res.Data {
- uMap[usr.ID] = usr
- }
- for _, it := range lists {
- if _, ok := uMap[it.OperatorID]; !ok {
- continue
- }
- it.Sender = uMap[it.OperatorID].NickName
- }
- models.List = lists
- models.PageCount = (count + req.PerPage - 1) / req.PerPage
- return serializer.Suc(models)
- }
- func (s *sAdminEmail) Verify(ctx *gin.Context, req forms.AdminEmailVerifyReq) serializer.Response {
- var q = query.Use(config.DB).AdminEmail
- first, err := q.WithContext(ctx).Where(q.ID.Eq(req.Id)).First()
- if err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- if first == nil {
- return serializer.ParamErr("邮件不存在", nil)
- }
- if first.Status != consts.EmailStatusVerify {
- return serializer.ParamErr("当前邮件状态非审核状态,操作失败!", nil)
- }
- // 拒绝发送
- if req.VerifyStatus == 2 {
- _, err2 := q.WithContext(ctx).Where(q.ID.Eq(first.ID)).Updates(model.AdminEmail{
- Status: consts.EmailStatusCanceled,
- })
- if err2 != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- return serializer.Suc(nil)
- }
- // 同意发送,进入发送环节
- var status int32
- // 立即发送,进入发送中状态
- if first.SendType == 1 {
- status = consts.EmailStatusIn
- }
- // 延迟发送
- if first.SendType == 2 {
- status = consts.EmailStatusWait
- }
- // 先更新数据
- if _, err = q.WithContext(ctx).Where(q.ID.Eq(first.ID)).Updates(model.AdminEmail{Status: status}); err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- // 立即发送
- if status == consts.EmailStatusIn {
- q := query.Use(config.DB).AdminEmail
- if err = s.SendEmailToWorld(first); err != nil {
- logrus.Warnf("邮件发送失败-3:%+v", err)
- _, err2 := q.WithContext(ctx).Where(q.ID.Eq(first.ID)).Updates(model.AdminEmail{Status: consts.EmailStatusErr})
- if err2 != nil {
- logrus.Warnf("邮件更新失败:%+v", err2)
- }
- return serializer.ParamErr(err.Error(), err)
- }
- // 发送成功
- _, err2 := q.WithContext(ctx).Where(q.ID.Eq(first.ID)).Updates(model.AdminEmail{
- Status: consts.EmailStatusSent,
- SendAt: time.Now().Unix(),
- })
- if err2 != nil {
- logrus.Warnf("邮件更新失败-2:%+v", err2)
- }
- }
- return serializer.Suc(nil)
- }
- func (s *sAdminEmail) Add(ctx *gin.Context, req forms.AdminEmailAddReq) serializer.Response {
- ext, err := json.Marshal(req.Ext)
- if err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- serverIds, err := json.Marshal(req.ServerIds)
- if err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- playerIds, err := json.Marshal(req.PlayerIds)
- if err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- var status int32
- // 立即发送,进入发送中状态
- if req.SendType == 1 {
- status = consts.EmailStatusIn
- }
- // 延迟发送
- if req.SendType == 2 {
- status = consts.EmailStatusWait
- }
- // 非超管发送全服或指定服邮件直接进入待审核状态
- if ctx.GetInt64("admin_role_id") != 1 {
- status = consts.EmailStatusVerify
- }
- logrus.Warnf("AdminEmailAdd req:%+v", utility.DumpToJSON(req))
- data := &model.AdminEmail{
- ID: 0,
- Title: req.Title,
- Content: req.Content,
- Ext: string(ext),
- SendType: req.SendType,
- SendAt: req.SendAt,
- Expired: req.Expired,
- ReceiptType: req.ReceiptType,
- ServerIds: string(serverIds),
- PlayerIds: string(playerIds),
- OperatorID: token.GetUID(ctx),
- Status: status,
- UpdatedAt: time.Now().Unix(),
- CreatedAt: time.Now().Unix(),
- Remark: req.Remark,
- }
- logrus.Warnf("AdminEmailAdd data:%+v", utility.DumpToJSON(data))
- if err = query.Use(config.DB).AdminEmail.WithContext(ctx).Create(data); err != nil {
- return serializer.ParamErr(err.Error(), err)
- }
- logrus.Infof("新增邮件内容:%+v", utility.DumpToJSON(data))
- // 立即发送
- if status == consts.EmailStatusIn {
- q := query.Use(config.DB).AdminEmail
- if err = s.SendEmailToWorld(data); err != nil {
- logrus.Warnf("邮件发送失败:%+v", err)
- _, err2 := q.WithContext(ctx).Where(q.ID.Eq(data.ID)).Updates(model.AdminEmail{Status: consts.EmailStatusErr})
- if err2 != nil {
- logrus.Warnf("邮件更新失败:%+v", err2)
- }
- return serializer.ParamErr(err.Error(), err)
- }
- // 发送成功
- _, err2 := q.WithContext(ctx).Where(q.ID.Eq(data.ID)).Updates(model.AdminEmail{
- Status: consts.EmailStatusSent,
- SendAt: time.Now().Unix(),
- })
- if err2 != nil {
- logrus.Warnf("邮件更新失败-2:%+v", err2)
- }
- }
- return serializer.Suc(nil)
- }
- // DecodeExtData 解析奖励道具
- func (s *sAdminEmail) DecodeExtData(es string) (data []*model2.DropedItem, err error) {
- type Extra struct {
- Id string `json:"id"`
- Num string `json:"num"`
- Type int64 `json:"type"`
- }
- var (
- extra []*Extra
- )
- if err = json.Unmarshal([]byte(es), &extra); err != nil {
- return []*model2.DropedItem{}, err
- }
- for _, it := range extra {
- data = append(data, &model2.DropedItem{
- Id: cast.ToInt64(it.Id),
- Num: cast.ToInt64(it.Num),
- Type: it.Type,
- })
- }
- return
- }
- // SendEmailToWorld 发送邮件到游戏服务器
- func (s *sAdminEmail) SendEmailToWorld(params *model.AdminEmail) (err error) {
- letter := &model2.MailGlobal{
- MailType: 1,
- MaxPlayerId: 0,
- Title: params.Title,
- Content: params.Content,
- ExtraInfo: nil,
- CreateTime: time.Now(),
- ExpireTime: time.Now().AddDate(0, 0, int(params.Expired)),
- }
- letter.Extra, err = s.DecodeExtData(params.Ext)
- if err != nil {
- return err
- }
- switch params.ReceiptType {
- case 1: // 全服
- msg := msg2.GMLetter{
- MsgId: character.GenerateMsgId(),
- Letter: letter,
- Players: []int64{},
- OperatorId: params.OperatorID,
- }
- rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,全服投递",
- utility.FormatSecond(time.Now()),
- params.ID)
- for _, serverId := range ServerOption.GetServerIds() {
- DB, err := player.GetDBByServerID(serverId)
- if err != nil {
- logrus.Warnf("sendLetterToWorld GetDBByServerID err:%+v", err)
- continue
- }
- var resp *msg2.ResponseGMLetter
- res, err := config.GmNats.GmRequest(DB, "GMLetter", msg)
- if err != nil {
- logrus.Warnf("sendLetterToWorld GmRequest err:%+v", err)
- continue
- }
- if err = json.Unmarshal(res, &resp); err != nil {
- logrus.Warnf("sendLetterToWorld nats Unmarshal err:%+v", err)
- continue
- }
- rpc_share.LogChan <- rpc_share.LogMsg{
- MsgID: msg.MsgId,
- Data: resp,
- }
- }
- case 2: // 指定服
- var serverIds []int32
- if err = json.Unmarshal([]byte(params.ServerIds), &serverIds); err != nil {
- return err
- }
- for _, serverId := range serverIds {
- sId := cast.ToInt(serverId)
- if sId > 0 {
- DB, err := player.GetDBByServerID(sId)
- if err != nil {
- logrus.Warnf("sendLetterToWorld2 GetDBByServerID2 err:%+v", err)
- continue
- }
- msg := msg2.GMLetter{
- MsgId: character.GenerateMsgId(),
- Letter: letter,
- Players: []int64{},
- OperatorId: params.OperatorID,
- }
- rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,投递服务器ID:%v",
- utility.FormatSecond(time.Now()), params.ID, sId)
- var resp *msg2.ResponseGMLetter
- res, err := config.GmNats.GmRequest(DB, "GMLetter", msg)
- if err != nil {
- logrus.Warnf("sendLetterToWorld2 GmRequest err:%+v", err)
- continue
- }
- if err = json.Unmarshal(res, &resp); err != nil {
- logrus.Warnf("sendLetterToWorld2 nats Unmarshal err:%+v", err)
- continue
- }
- rpc_share.LogChan <- rpc_share.LogMsg{
- MsgID: msg.MsgId,
- Data: resp,
- }
- }
- }
- case 3: // 指定玩家
- var playerIds []string
- if err = json.Unmarshal([]byte(params.PlayerIds), &playerIds); err != nil {
- return err
- }
- lineMap := make(map[int][]int64)
- errPlayerIds := make([]int64, 0)
- for _, v := range playerIds {
- playerID := cast.ToInt64(v)
- if playerID <= 0 {
- errPlayerIds = append(errPlayerIds, playerID)
- continue
- }
- db, err := player.GetDBByUserId(playerID)
- if err != nil {
- errPlayerIds = append(errPlayerIds, playerID)
- logrus.Warnf("sendLetterToWorld3 GetDBByUserId err:%+v", err)
- continue
- }
- if _, ok := lineMap[db]; ok {
- lineMap[db] = append(lineMap[db], playerID)
- } else {
- lineMap[db] = []int64{playerID}
- }
- }
- if len(errPlayerIds) > 0 {
- logrus.Warnf("sendLetterToWorld3 errPlayerIds:%v", errPlayerIds)
- }
- for line, ids := range lineMap {
- msg := msg2.GMLetter{
- MsgId: character.GenerateMsgId(),
- Letter: letter,
- Players: ids,
- OperatorId: params.OperatorID,
- }
- rpc_share.MsgMap[msg.MsgId] = fmt.Sprintf("%s,GM邮件(编号 %d) 投递成功,投递玩家ID:%v",
- utility.FormatSecond(time.Now()), params.ID, ids)
- var resp *msg2.ResponseGMLetter
- res, err := config.GmNats.GmRequest(line, "GMLetter", msg)
- if err != nil {
- logrus.Warnf("sendLetterToWorld3 GmRequest err:%+v", err)
- continue
- }
- if err = json.Unmarshal(res, &resp); err != nil {
- logrus.Warnf("sendLetterToWorld3 nats Unmarshal err:%+v", err)
- continue
- }
- rpc_share.LogChan <- rpc_share.LogMsg{
- MsgID: msg.MsgId,
- Data: resp,
- }
- }
- }
- return
- }
- func (s *sAdminEmail) Export(ctx *gin.Context, list []*Ret) error {
- 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", 20)
- 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", "I", "I", 15)
- f.SetColWidth("Sheet1", "J", "J", 15)
- f.SetColWidth("Sheet1", "K", "K", 15)
- // 创建一个工作表
- f.SetCellValue("Sheet1", "A1", "序号")
- f.SetCellValue("Sheet1", "B1", "标题")
- f.SetCellValue("Sheet1", "C1", "收件人")
- f.SetCellValue("Sheet1", "D1", "有效期")
- f.SetCellValue("Sheet1", "E1", "邮件内容")
- f.SetCellValue("Sheet1", "F1", "邮件备注")
- f.SetCellValue("Sheet1", "G1", "发送道具")
- f.SetCellValue("Sheet1", "H1", "预计发送时间")
- f.SetCellValue("Sheet1", "I1", "发送状态")
- f.SetCellValue("Sheet1", "J1", "创建人")
- f.SetCellValue("Sheet1", "K1", "创建时间")
- //获取道具和装备信息
- materials := gmdata.MaterialsDict //道具
- equipments := gmdata.EquipmentDict //装备
- materialMap := make(map[int64]gmdata.Material)
- equipmentMap := make(map[int64]gmdata.Equipment)
- for _, item := range materials {
- materialMap[int64(item.ID)] = item
- }
- for _, item := range equipments {
- equipmentMap[item.LevelId] = item
- }
- data := make([]Ext, 0)
- sendStatus := map[int32]string{1: "已发送", 2: "等待发送", 3: "待审核", 4: "已取消", 5: "发送中", 6: "发送出错"}
- uIds := make([]int64, len(list))
- uMap := make(map[int64]*model.AdminUser)
- for i, v := range list {
- if v.OperatorID > 0 {
- uIds[i] = v.OperatorID
- }
- }
- u := query.Use(config.DB).AdminUser
- usrs, err := u.WithContext(ctx).Where(u.ID.In(uIds...)).Find()
- if err != nil {
- return err
- }
- for _, usr := range usrs {
- uMap[usr.ID] = usr
- }
- type props struct {
- Name string `json:"name"`
- Count string `json:"count"`
- }
- for i, v := range list {
- f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.ID)
- f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), v.Title)
- if v.ReceiptType == 1 {
- f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), "全服")
- } else if v.ReceiptType == 2 {
- f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), fmt.Sprintf("指定服%s", v.ServerIds))
- } else if v.ReceiptType == 3 {
- f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), fmt.Sprintf("指定玩家%s", v.PlayerIds))
- }
- f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), fmt.Sprintf("%d天", v.Expired))
- f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), v.Content)
- f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.Remark)
- //装备或者道具
- err := json.Unmarshal([]byte(v.Ext), &data)
- if err != nil {
- return err
- }
- propsArr := make([]props, 0)
- propsStr := ""
- for _, item := range data {
- //装备id大于10000000
- id, _ := strconv.ParseInt(item.Id, 10, 64)
- if id > 1000000 {
- if equipment, ok := equipmentMap[id]; ok {
- propsArr = append(propsArr, props{Name: equipment.Name, Count: item.Count})
- }
- } else if id > 0 && id < 1000000 {
- if material, ok := materialMap[id]; ok {
- propsArr = append(propsArr, props{
- Name: material.Name,
- Count: item.Count,
- })
- }
- }
- marshal, err := json.Marshal(propsArr)
- if err != nil {
- return err
- }
- propsStr = string(marshal)
- }
- f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), propsStr)
- if v.SendAt < 1 {
- f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), "-")
- } else {
- f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), utility.FormatSecond(time.Unix(v.SendAt, 0)))
- }
- f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i+2), sendStatus[v.Status])
- f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i+2), uMap[v.OperatorID].Nickname)
- f.SetCellValue("Sheet1", fmt.Sprintf("K%d", i+2), utility.FormatSecond(time.Unix(v.CreatedAt, 0)))
- }
- // 设置工作簿的默认工作表
- 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
- }
|