package msg import ( "database/sql" "encoding/base64" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" "math/rand" "net/http" "rocommon" "rocommon/service" "rocommon/socket/mysql" "rocommon/util" "roserver/baseserver/model" dbmodel "roserver/db/model" selfmodel "roserver/game/model" gmweb "roserver/gmweb/model" "roserver/serverproto" "strconv" "strings" "time" ) type WebBriefInfo struct { Uid uint64 NickName string BaseLevel int32 CreateDate string LastLoginDate string BanDate string MapLevel int32 FightPower uint32 ActiveCode string OpenId string Serverid int //所属区服 } type WebUserDetailInfo struct { WebBriefInfo Rmb uint32 Zeny uint64 ArenaScore uint32 TowerLevel uint32 HeroData []*serverproto.HeroData } type WebUserChatMsgInfo struct { Uid uint64 TargetUid uint64 MsgType int32 Content string MsgData string } func verifyProcess(ctx *gin.Context) bool { return true tokenRaw := ctx.Request.FormValue("token") if tokenRaw == "" { tokenRaw = ctx.Request.Header.Get("Authorization") if tokenRaw == "" { ctx.JSON(http.StatusOK, "请重新登陆") return false } } _, err := gmweb.VerifyAction(tokenRaw) if err != nil { ctx.JSON(http.StatusOK, "请重新登陆") return false } return true } // 检索玩家数据 // select * from role where nick_name like '%11%' and base_level>=1 and base_level<=3 and create_date>=str_to_date('2020-05-07', '%Y-%m-%d') and ban_date is NULL and map_level >=2 and fight_power >=1 and fight_power <=3 // http://127.0.0.1:8086/gm/user_get?nickname=11&lmin=1&lmax=3&createdate=2020-05-07&banstatus=0&maplevel=2&fmin=1&fmax=3&pnum=1 func WebGmProcessUserGet(c *gin.Context) { if !verifyProcess(c) { return } nickName := c.DefaultQuery("nickname", "") ///default "" activeCode := c.DefaultQuery("activecode", "") lminStr := c.DefaultQuery("lmin", "") lmaxStr := c.DefaultQuery("lmax", "") createdate := c.DefaultQuery("createdate", "") lastlogindate := c.DefaultQuery("lastlogindate", "") banstatusStr := c.DefaultQuery("banstatus", "") maplevelStr := c.DefaultQuery("maplevel", "") fminStr := c.DefaultQuery("fmin", "") fmaxStr := c.DefaultQuery("fmax", "") pagNumStr := c.DefaultQuery("pnum", "") //var paramList []interface{} procSqlStrPrefix := "select * from role where " procSqlStr := "" if nickName != "" { //procSqlStr += "nick_name like ? " //paramList = append(paramList, "'%"+nickName+"%'") procSqlStr += "nick_name like '%" + nickName + "%'" } if activeCode != "" { procSqlStr += " and active_code=" + activeCode } if lminStr != "" { baseLevel, _ := model.Str2Num(lminStr) if baseLevel > 0 { procSqlStr += " and base_level>=" + lminStr } } if lmaxStr != "" { baseLevel, _ := model.Str2Num(lmaxStr) if baseLevel > 0 { procSqlStr += " and base_level<=" + lmaxStr } } if createdate != "" { //2020-05-07T10:13:02+08:00 //2018-01-12 procSqlStr += " and create_date>=str_to_date('" + createdate + "', '%Y-%m-%d')" } if lastlogindate != "" { //2018-01-12 procSqlStr += " and last_login_date>=str_to_date('" + lastlogindate + "', '%Y-%m-%d')" } if banstatusStr != "" { banstatus, _ := model.Str2Num(banstatusStr) if banstatus > 0 { procSqlStr += " and ban_date is not NULL" } else { procSqlStr += " and ban_date is NULL" } } if maplevelStr != "" { maplevel, _ := model.Str2Num(maplevelStr) if maplevel > 0 { procSqlStr += " and map_level >=" + maplevelStr } } if fminStr != "" { fmin, _ := model.Str2Num(fminStr) if fmin > 0 { procSqlStr += " and fight_power >=" + fminStr } } if fmaxStr != "" { fmax, _ := model.Str2Num(fmaxStr) if fmax > 0 { procSqlStr += " and fight_power <=" + fmaxStr } } if procSqlStr == "" { c.JSON(http.StatusOK, gin.H{ "err": "param is empty", }) return } procSqlStr = procSqlStrPrefix + procSqlStr pageNum, _ := model.Str2Num(pagNumStr) if pageNum <= 0 { pageNum = 1 } pageNum -= 1 procSqlStr += " limit " + strconv.Itoa(int(pageNum*20)) + ",20" var uidList []*WebBriefInfo service.GetMysql().Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) wrapper.Query(procSqlStr).Each(func(wrapper2 *mysql.Wrapper) bool { bfInfo := parseUserInfo(wrapper2) if bfInfo != nil { uidList = append(uidList, bfInfo) } return true }) if wrapper.Err != nil { util.ErrorF("nickname=%v WebGmProcessUserGet err=%v", nickName, wrapper.Err) } return nil }) c.JSON(http.StatusOK, uidList) } // 获取玩家详细信息 // http://127.0.0.1:8086/gm/info_get?uid=1111 func WebGmProcessUserInfoGet(c *gin.Context) { if !verifyProcess(c) { return } var errStr = "" uidStr := c.DefaultQuery("uid", "") ///default "" uid, _ := model.Str2NumU64(uidStr) if uidStr == "" || uid == 0 { errStr = "uid invalid!!!" util.InfoF(errStr) c.JSON(http.StatusOK, gin.H{ "err": errStr, }) return } //获取简介信息 var bfInfo *WebBriefInfo = nil if service.GetMysql() != nil { service.GetMysql().Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) wrapper.Query("select * from role where uid=?", uid).Each(func(wrapper2 *mysql.Wrapper) bool { bfInfo = parseUserInfo(wrapper2) return true }) if wrapper.Err != nil { util.ErrorF("uid=%v WebGmProcessUserGet err=%v", uid, wrapper.Err) } return nil }) if bfInfo == nil { c.JSON(http.StatusOK, gin.H{ "err": "玩家不存在!!!", }) return } } //从redis中获取其他详细信息 userInfo := webGMGetRoleInfo(uid) if userInfo == nil { c.JSON(http.StatusOK, bfInfo) } else { c.JSON(http.StatusOK, userInfo) //if bfInfo != nil { // detailInfo := &WebUserDetailInfo{WebBriefInfo: *bfInfo} // detailInfo.Rmb = userInfo.Base.Rmb // detailInfo.Zeny = userInfo.Base.Coin // // c.JSON(http.StatusOK, detailInfo) //} else { // c.JSON(http.StatusOK, userInfo) //} } } // 东南亚支付服务使用 func WebGmProcessUserListGet(c *gin.Context) { if !verifyProcess(c) { return } var errStr = "" uidStr := c.DefaultQuery("userId", "") ///default "" //uid, _ := model.Str2NumU64(uidStr) if uidStr == "" { errStr = "uid invalid!!!" util.InfoF(errStr) c.JSON(http.StatusOK, gin.H{ "err": errStr, }) return } //获取简介信息 bfInfoList := make([]*Uid, 0) if len(service.GetMysqlPay()) > 0 { for _, v := range service.GetMysqlPay() { var bfInfo *WebBriefInfo = nil v.Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) wrapper.Query("select * from role where open_id=?", uidStr).Each(func(wrapper2 *mysql.Wrapper) bool { bfInfo = parseUserInfo(wrapper2) return true }) if wrapper.Err != nil { util.ErrorF("uid=%v WebGmProcessUserGet err=%v", uidStr, wrapper.Err) } return nil }) serverId := strconv.Itoa(bfInfo.Serverid / 2) bfInfoList = append(bfInfoList, &Uid{Uid: strconv.FormatUint(bfInfo.Uid, 10), Server: serverId, CharacterName: bfInfo.NickName, ServerName: serverId + "区"}) } if len(bfInfoList) == 0 { c.JSON(http.StatusOK, gin.H{ "err": "玩家不存在!!!", }) return } } c.JSON(http.StatusOK, UserList{UserId: uidStr, Uids: bfInfoList}) } // 东南亚支付服务使用 func WebGmProcessUserListCheck(c *gin.Context) { if !verifyProcess(c) { return } var errStr = "" uidStr := c.DefaultQuery("uid", "") ///default "" uid, _ := model.Str2NumU64(uidStr) if uidStr == "" || uid == 0 { errStr = "uid invalid!!!" util.InfoF(errStr) c.JSON(http.StatusOK, gin.H{ "err": errStr, }) return } //获取简介信息 var bfInfo *WebBriefInfo = nil if len(service.GetMysqlPay()) > 0 { for _, v := range service.GetMysqlPay() { v.Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) wrapper.Query("select * from role where uid=?", uid).Each(func(wrapper2 *mysql.Wrapper) bool { bfInfo = parseUserInfo(wrapper2) return true }) if wrapper.Err != nil { util.ErrorF("uid=%v WebGmProcessUserGet err=%v", uid, wrapper.Err) } return nil }) } if bfInfo == nil { c.JSON(http.StatusOK, gin.H{ "err": "玩家不存在!!!", }) return } } if bfInfo == nil { c.JSON(404, gin.H{ "code": "UID_NOT_FOUND", "message": "UID does not exist", }) return } serverId := strconv.Itoa(bfInfo.Serverid / 2) c.JSON(http.StatusOK, CheckUser{CharacterName: bfInfo.NickName, Server: serverId, ServerName: serverId + "区"}) } func WebGmProcessCreateOrder(c *gin.Context) { if !verifyProcess(c) { return } var errStr = "" serverId := service.GetServiceConfig().Node.Zone / 2 uidStr := c.DefaultQuery("uid", "") ///default "" orderIdStr := c.DefaultQuery("order_id", "") ///default "" productIdStr := c.DefaultQuery("productId", "") ///default "" countStr := c.DefaultQuery("count", "") ///default "" typeStr := c.DefaultQuery("productType", "") ///default "" //uid, _ := model.Str2NumU64(uidStr) cpOrderId := model.GenerateUidByZone(service.GetServiceConfig().Node.Zone) productId, _ := strconv.Atoi(productIdStr) type1, _ := strconv.Atoi(typeStr) count, _ := strconv.Atoi(countStr) if uidStr == "" || orderIdStr == "" || productIdStr == "" { errStr = "uid invalid!!!" util.ErrorF("param error:%v ,%v,%v", uidStr, orderIdStr, productIdStr) c.JSON(http.StatusOK, gin.H{ "err": errStr, }) return } ss := &serverproto.SSPayOrderCreateReq{ OrderId: orderIdStr, GoodsId: int32(productId), GoodsType: int32(type1), Count: int32(count), Uid: uidStr, OrderCode: cpOrderId, } selfmodel.SendSocial(ss) c.JSON(http.StatusOK, gin.H{ "status": "success", "serverId": serverId, "order_code": strconv.FormatUint(uint64(cpOrderId), 10), }) } type UserList struct { UserId string `json:"userId"` Uids []*Uid `json:"uids"` } type Uid struct { Uid string `json:"uid"` Server string `json:"server"` ServerName string `json:"serverName"` CharacterName string `json:"characterName"` } type CheckUser struct { Server string `json:"server"` ServerName string `json:"serverName"` CharacterName string `json:"characterName"` //CallBackKey string `json:"callBackKey"` } // 封号 // http://127.0.0.1:8086/gm/ban?uid=1111&ban=1 func WebGmProcessBanUser(c *gin.Context) { if !verifyProcess(c) { return } var errStr = "" uidStr := c.DefaultQuery("uid", "") ///default "" banStr := c.DefaultQuery("ban", "") banTypeStr := c.DefaultQuery("bantype", "1") banDurationTimeStr := c.DefaultQuery("bantime", "25920") //25920小时 uid, _ := model.Str2NumU64(uidStr) if uidStr == "" || uid == 0 { errStr = "uid invalid!!!" util.InfoF(errStr) c.JSON(http.StatusOK, gin.H{ "err": errStr, }) return } ban, _ := model.Str2Num(banStr) banType, _ := model.Str2Num(banTypeStr) banDurationTime, _ := model.Str2Num(banDurationTimeStr) if service.GetMysql() != nil { var getUid uint64 = 0 var banData interface{} = nil service.GetMysql().Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) if banType == 1 { wrapper.Query("select uid,ban_date from role where uid=?", uid).Each(func(wrapper2 *mysql.Wrapper) bool { //bfInfo = parseUserInfo(wrapper2) err := wrapper.Scan(&getUid, &banData) if err != nil { util.ErrorF("uid=%v WebGmProcessBanUser err=%v", uid, err) } return true }) } else if banType == 2 { wrapper.Query("select uid,ban_chat_date from role where uid=?", uid).Each(func(wrapper2 *mysql.Wrapper) bool { //bfInfo = parseUserInfo(wrapper2) err := wrapper.Scan(&getUid, &banData) if err != nil { util.ErrorF("uid=%v WebGmProcessBanUser err=%v", uid, err) } return true }) } if wrapper.Err != nil { util.ErrorF("uid=%v WebGmProcessBanUser err=%v", uid, wrapper.Err) } return nil }) if getUid <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "user not find!!!", }) return } else if banData == nil && ban <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "玩家没有处于封号状态,无法做解封操作", }) return } } //} else if banData != nil && ban > 0 { // banTimeStamp := banData.(time.Time).Unix() // nowTime := util.GetTimeSeconds() // if banTimeStamp > nowTime { // c.JSON(http.StatusOK, gin.H{ // "err": "玩家处于封号状态,无法封号操作", // "endtime": banData, // }) // return // } //} //ban if ok, banEndTime := webGMRoleBan(uid, ban > 0, banType, banDurationTime); ok { c.JSON(http.StatusOK, gin.H{ "err": "操作成功", "endtime": util.GetTimeByUint32(uint32(banEndTime)), }) } else { c.JSON(http.StatusOK, gin.H{ "err": "玩家不存在", }) } } // 1私聊,2公聊 // http://127.0.0.1:8086/gm/chat_msg?type=2&uid=111&msgdate=2020-05-05%2021:42:59 func WebGmProcessChatMsg(c *gin.Context) { if !verifyProcess(c) { return } msgDataStr := c.DefaultQuery("msgdate", "") typeStr := c.DefaultQuery("type", "") uidStr := c.DefaultQuery("uid", "") ///default "" if msgDataStr == "" && uidStr == "" { c.JSON(http.StatusOK, gin.H{ "err": "输入时间和玩家uid不能都为空", }) return } procSqlStr := "select * from role_msg where " if typeStr != "" { msgType, _ := model.Str2Num(typeStr) if msgType > 0 { procSqlStr += " msg_type=" + typeStr } else { procSqlStr += " msg_type=1" } } if uidStr != "" { uid, _ := model.Str2NumU64(uidStr) if uid > 0 { procSqlStr += " and uid=" + uidStr } } procSqlStr += " and msg_date>=str_to_date('" + msgDataStr + "', '%Y-%m-%d %H:%i:%S')" var msgInfoList []*WebUserChatMsgInfo service.GetMysql().Operate(func(rawClient interface{}) interface{} { wrapper := mysql.NewWrapper(rawClient.(*sql.DB)) wrapper.Query(procSqlStr).Each(func(wrapper2 *mysql.Wrapper) bool { msgInfo := parseChatMsgInfo(wrapper2) if msgInfo != nil { msgInfoList = append(msgInfoList, msgInfo) } return true }) if wrapper.Err != nil { util.ErrorF("WebGmProcessChatMsg err=%v", wrapper.Err) } return nil }) if len(msgInfoList) <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "消息为空", }) } else { c.JSON(http.StatusOK, msgInfoList) } } // 邮件 // http://127.0.0.1:8086/gm/mail?type=list 获取当前的定时邮件列表 // http://127.0.0.1:8086/gm/mail?type=add&title=title&content=content&reward=101:1,102:3//添加邮件 // http://127.0.0.1:8086/gm/mail?type=add&title=title&content=content&reward=101:1,102:3&senddate=2020-05-09%2000:00:00 // http://127.0.0.1:8086/gm/mail?type=del&id=邮件id func WebGmProcessMail(c *gin.Context) { if !verifyProcess(c) { return } idStr := c.DefaultQuery("id", "") uidStr := c.DefaultQuery("uid", "") senddateStr := c.DefaultQuery("senddate", "") titleStr := c.DefaultQuery("title", "") contentStr := c.DefaultQuery("content", "") rewardStr := c.DefaultQuery("reward", "") // list表示获取邮件列表 // attach添加替换邮件 // del删除延迟发送邮件 mailType := c.DefaultQuery("type", "") if mailType == "add" && titleStr == "" && contentStr == "" { c.JSON(http.StatusOK, gin.H{ "err": "输入的标题和正文为空!!!", }) return } id, _ := model.Str2Num(idStr) //uid var uidList []uint64 uidStrList := strings.Split(uidStr, ",") for idx := 0; idx < len(uidStrList); idx++ { tmpUid, _ := model.Str2NumU64(uidStrList[idx]) if tmpUid > 0 { uidList = append(uidList, tmpUid) } } if len(uidList) <= 0 && uidStr != "" { c.JSON(http.StatusOK, gin.H{ "err": "输入的玩家id不正确!!!", }) return } //reward var rewardList []*serverproto.KeyValueType rewardStrList := strings.Split(rewardStr, ",") for idx := 0; idx < len(rewardStrList); idx++ { key, val := model.Str2Res(rewardStrList[idx]) if key > 0 && val > 0 { rewardList = append(rewardList, &serverproto.KeyValueType{Key: key, Value: val}) } } //sendtime var sendTime uint64 = 0 if senddateStr != "" { loc := util.GetLoc() sendDate, err := time.ParseInLocation(util.DATE_FORMAT, senddateStr, loc) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": "发送时间填写不对!!! 正确格式:2021-01-11 14:17:12", }) return } util.InfoF("WebGmProcessMail sendtime=%v", sendDate.Local().String()) sendTime = uint64(sendDate.Local().UnixNano() / 1e6) } else { //以发送时的时间为准 sendTime = util.GetTimeMilliseconds() } if mailType == "del" { gmweb.GetMailUpdateMag().DelMailItem(id) c.JSON(http.StatusOK, "删除延迟发送邮件成功") } else if mailType == "list" { mailList := gmweb.GetMailUpdateMag().GetMailList() c.JSON(http.StatusOK, mailList) } else if mailType == "add" { gmweb.GetMailUpdateMag().AttachMail2Update(id, uidList, titleStr, contentStr, sendTime, rewardList) c.JSON(http.StatusOK, "发送邮件成功") } } func WebGmProcessMailPost(c *gin.Context) { if !verifyProcess(c) { return } idStr := c.PostForm("id") uidStrList := c.PostFormArray("uid") senddateStr := c.PostForm("senddate") titleStr := c.PostForm("title") contentStr := c.PostForm("content") rewardStr := c.PostForm("reward") // list表示获取邮件列表 // attach添加替换邮件 // del删除延迟发送邮件 mailType := c.PostForm("type") if mailType == "add" && titleStr == "" && contentStr == "" { c.JSON(http.StatusOK, gin.H{ "err": "输入的标题和正文为空!!!", }) return } id, _ := model.Str2Num(idStr) //uid var uidList []uint64 for idx := 0; idx < len(uidStrList); idx++ { tmpUid, _ := model.Str2NumU64(uidStrList[idx]) if tmpUid > 0 { uidList = append(uidList, tmpUid) } } //reward var rewardList []*serverproto.KeyValueType rewardStrList := strings.Split(rewardStr, ",") for idx := 0; idx < len(rewardStrList); idx++ { key, val := model.Str2Res(rewardStrList[idx]) if key > 0 && val > 0 { rewardList = append(rewardList, &serverproto.KeyValueType{Key: key, Value: val}) } } //sendtime var sendTime uint64 = 0 if senddateStr != "" { loc := util.GetLoc() sendDate, err := time.ParseInLocation(util.DATE_FORMAT, senddateStr, loc) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": "发送时间填写不对!!!", }) return } util.InfoF("WebGmProcessMail sendtime=%v", sendDate.Local().String()) sendTime = uint64(sendDate.Local().UnixNano() / 1e6) } if mailType == "del" { gmweb.GetMailUpdateMag().DelMailItem(id) c.JSON(http.StatusOK, "删除延迟发送邮件成功") } else if mailType == "list" { mailList := gmweb.GetMailUpdateMag().GetMailList() c.JSON(http.StatusOK, mailList) } else if mailType == "add" { gmweb.GetMailUpdateMag().AttachMail2Update(id, uidList, titleStr, contentStr, sendTime, rewardList) c.JSON(http.StatusOK, "发送邮件成功") } } // http://127.0.0.1:8086/gm/notice?&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTAyMjQ2NzAsImlhdCI6MTU5MDIyMTA3MH0.WihVh5AsvHm6MKHwoCELJgNzz9aA-ETPtchotLj_9Z0&col=商城购买!!!!!!!!!!!!<%23color>&count=5&interval=5 func WebGmProcessNotice(c *gin.Context) { if !verifyProcess(c) { return } colorStr := c.DefaultQuery("col", "") //speedStr := c.DefaultQuery("speed", "") countStr := c.DefaultQuery("count", "") intervalStr := c.DefaultQuery("interval", "") if colorStr == "" || countStr == "" { c.JSON(http.StatusOK, "color,count,interval不能为空") return } count, _ := model.Str2Num(countStr) interval, _ := model.Str2Num(intervalStr) if count <= 0 || interval <= 0 { c.JSON(http.StatusOK, "color,count,interval不能为空") return } noticeNtf := &serverproto.SSWebGMNoticeNtf{ NoticeInfo: &serverproto.GMNoticeInfo{ NoticeColor: colorStr, NoticeCount: uint32(count), NoticeInterval: uint32(interval), }, } gmweb.SendSocial(noticeNtf) c.JSON(http.StatusOK, "公告发送成功") } func WebGMProcessServerMaintain(c *gin.Context) { stateStr := c.DefaultQuery("state", "1") //把在线玩家踢下线 if stateStr == "1" { state, _ := model.Str2Num(stateStr) ntfMsg := &serverproto.SSWEBGMServerMaintainNtf{ State: int32(state), } gmweb.SendSocial(ntfMsg) c.JSON(http.StatusOK, "维护成功(强制所有玩家下线)") } else { c.JSON(http.StatusOK, "state不为1") } } // http://127.0.0.1:8086/gm/guildbattle_state func WebGmGetGuildBattleState(c *gin.Context) { state, banType, ok := webGMGetGuildBattleState() if ok { c.JSON(http.StatusOK, gin.H{ "err": "操作成功", "battle_state": state, //0:不在公会战内,1:公会战内 "ban_type": banType, //0:公会战未禁止,1:公会战禁止 }) } else { c.JSON(http.StatusOK, gin.H{ "err": "操作失败", "battle_state": -1, //-1:数据库查询异常,0:不在公会战内,1:公会战内 "ban_type": -1, //-1:数据库查询异常,0:公会战未禁止,1:公会战禁止 }) } } func WebGMProcessServerRegister(c *gin.Context) { stateStr := c.DefaultQuery("state", "1") //关闭注册 if stateStr == "1" { webGMServerRegister(stateStr) c.JSON(http.StatusOK, "关闭注册操作成功") } else { //开启注册 webGMServerRegister(stateStr) c.JSON(http.StatusOK, "开启注册操作成功") } } func WebGMProcessServerConfigReload(c *gin.Context) { cfgStr := c.DefaultQuery("config", "") //例如AdvertisingScreen,ActivitiesCfg,ActiveCodeCfg cfgStrList := strings.Split(cfgStr, ",") if len(cfgStrList) <= 0 { c.JSON(http.StatusOK, "热加载配置文件不能为空!") return } for idx := 0; idx < len(cfgStrList); idx++ { if _, ok := serverproto.CFGNameList[cfgStrList[idx]]; !ok { errStr := "配置文件有误" + cfgStrList[idx] c.JSON(http.StatusOK, errStr) return } } webGMServerConfigReload(cfgStrList) c.JSON(http.StatusOK, "热加载配置文件成功!") } // 公会战GM//1:取消封停 2:封停 // http://127.0.0.1:8086/gm/guildbattle func WebGmProcessGuildBattle(c *gin.Context) { /* if !verifyProcess(c) { return } */ //ban if ok := webGMGuildBattleState(); ok { c.JSON(http.StatusOK, gin.H{ "err": "操作成功", }) } } func webGMGuildBattleState() bool { banNtf := &serverproto.SSWebGMGuildBattle{} gmweb.SendSocial(banNtf) return true } func webGMGetGuildBattleState() (int32, int32, bool) { keyStr := "guildbattle:base:" ret, err := service.GetRedis().Get(keyStr).Result() if err != nil { util.InfoF("loadGuildBattleBase get guildId key=%v err=%v\n", keyStr, err) return 0, 0, false } if ret == "" { util.InfoF("loadGuildBattleBase key(%v)->val empty", keyStr) return 0, 0, false } str, err := base64.StdEncoding.DecodeString(ret) if err != nil { util.InfoF("loadGuildBattleBase key(%v)->val DecodeString error", keyStr) return 0, 0, false } guildBase := &serverproto.GuildBattleBase{} err = rocommon.GetCodec().Unmarshal(str, guildBase) if err == nil { battleState := int32(0) //1:开始阶段, 10:展示阶段 if 1 <= guildBase.GuildBattleState && guildBase.GuildBattleState <= 10 { battleState = 1 } util.InfoF("loadGuildBattleBase success:%v", guildBase) return battleState, guildBase.BanType, true } return 0, 0, false } // /////////// func parseUserInfo(wrapper *mysql.Wrapper) *WebBriefInfo { var Uid uint64 var NickName sql.NullString var BaseLevel sql.NullInt64 var CreateDate sql.NullString var LastLoginDate sql.NullString var BanDate sql.NullString var MapLevel sql.NullInt64 var FightPower sql.NullInt64 var ActiveCode sql.NullString var OpenId sql.NullString err := wrapper.Scan(&Uid, &NickName, &BaseLevel, &CreateDate, &LastLoginDate, &BanDate, &MapLevel, &FightPower, &ActiveCode, &OpenId) if err == nil { bfInfo := &WebBriefInfo{ Uid: Uid, } if NickName.Valid { bfInfo.NickName = NickName.String } if BaseLevel.Valid { bfInfo.BaseLevel = int32(BaseLevel.Int64) } if CreateDate.Valid { bfInfo.CreateDate = CreateDate.String } if LastLoginDate.Valid { bfInfo.LastLoginDate = LastLoginDate.String } if BanDate.Valid { bfInfo.BanDate = BanDate.String } if MapLevel.Valid { bfInfo.MapLevel = int32(MapLevel.Int64) } if FightPower.Valid { bfInfo.FightPower = uint32(FightPower.Int64) } if ActiveCode.Valid { bfInfo.ActiveCode = ActiveCode.String } if OpenId.Valid { bfInfo.OpenId = OpenId.String } return bfInfo } else { util.ErrorF("WebGmProcessUserGet err=%v", wrapper.Err) } return nil } func parseChatMsgInfo(wrapper *mysql.Wrapper) *WebUserChatMsgInfo { var Uid uint64 var TargetUid sql.NullInt64 var MsgType sql.NullInt64 var Content sql.NullString var MsgData sql.NullString err := wrapper.Scan(&Uid, &TargetUid, &MsgType, &Content, &MsgData) if err == nil { msgInfo := &WebUserChatMsgInfo{ Uid: Uid, } if TargetUid.Valid { msgInfo.TargetUid = uint64(TargetUid.Int64) } if MsgType.Valid { msgInfo.MsgType = int32(MsgType.Int64) } if Content.Valid { msgInfo.Content = Content.String } if MsgData.Valid { msgInfo.MsgData = MsgData.String } return msgInfo } else { util.ErrorF("WebGmProcessUserGet err=%v", wrapper.Err) } return nil } func webGMGetRoleInfo(uid uint64) *serverproto.WebRoleInfo { if uid <= 0 { return nil } value := strconv.FormatUint(uid, 10) uidInfo := &serverproto.WebRoleInfo{} uidInfo.Base = &serverproto.RoleBase{} err := model.GetMessageFromRedis(dbmodel.RoleBasePrefix, value, uidInfo.Base) if err != nil { return nil } uidInfo.RoleHero = &serverproto.RoleHero{} err = dbmodel.GetRoleHeroDataFromRedis(uid, uidInfo.RoleHero) if err != nil && err != service.NIL { util.InfoF("WebGMGetRoleInfo RoleHero err=%v uid=%v", err, uid) return nil } return uidInfo } func webGMRoleBan(uid uint64, ban bool, banType, banDurationTime int) (bool, uint64) { value := strconv.FormatUint(uid, 10) tmpRoleBase := &serverproto.RoleBase{} err := model.GetMessageFromRedis(dbmodel.RoleBasePrefix, value, tmpRoleBase) if err != nil { util.InfoF("webGMRoleBan can't find uid=%v player", uid) return false, 0 } //默认2小时 //var banTime uint64 = 2 * 60 * 60 //s var banTime = uint64(banDurationTime) * 60 * 60 //s if ban { //1封号,2禁言 if banType == 1 { tmpRoleBase.BanTime = uint64(util.GetTimeSeconds()) + banTime } else if banType == 2 { tmpRoleBase.ChatBanTime = uint64(util.GetTimeSeconds()) + banTime } } else { if banType == 1 { tmpRoleBase.BanTime = 0 } else if banType == 2 { tmpRoleBase.ChatBanTime = 0 } //清除作弊次数 tmpRoleRoleStatistic := &serverproto.RoleStatistic{} err = model.GetMessageFromRedis(dbmodel.RoleStatisticDataPrefix, value, tmpRoleRoleStatistic) if err == nil { tmpRoleRoleStatistic.CheatData = nil err = dbmodel.SetSystemDataToRedis(dbmodel.RoleStatisticDataPrefix, uid, tmpRoleRoleStatistic) if err != nil { util.InfoF("webGMRoleBan clear cheat data err=%v uid=%v", err, uid) } } } err = dbmodel.SetRoleToRedis(uid, tmpRoleBase) if err != nil { util.InfoF("webGMRoleBan save banTime err=%v uid=%v", err, uid) } //banType 1封号,2禁言 if banType == 1 { dbmodel.DoUpdatePlayerBanInfo2MysqlORM(nil, uid, tmpRoleBase.BanTime, int32(banType)) } else if banType == 2 { dbmodel.DoUpdatePlayerBanInfo2MysqlORM(nil, uid, tmpRoleBase.ChatBanTime, int32(banType)) } //发送给social,在线的玩家直接踢下线 banNtf := &serverproto.SSWebGMBanNtf{ BanUid: uid, IsBan: ban, BanTime: banTime, BanType: int32(banType), } gmweb.SendSocial(banNtf) return true, tmpRoleBase.BanTime } // 服务器创建功能开启/关闭 func webGMServerRegister(stateStr string) { service.GetRedis().HSet(model.ServerPrefix, "registerclose", stateStr) } func webGMServerConfigReload(cfgStrList []string) { ntfMsg := &serverproto.SSServerConfigReloadNtf{ CfgList: cfgStrList, } gmweb.SendSocial(ntfMsg) } func WebGMLookMail(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") tmpBeginTime := c.DefaultQuery("begin_time", "0") tmpEndTime := c.DefaultQuery("end_time", "0") beginT, _ := model.Str2NumU64(tmpBeginTime) endT, _ := model.Str2NumU64(tmpEndTime) if len(uidStr) <= 0 { c.JSON(http.StatusOK, "uid 错误") return } var ret []*serverproto.MailContent keyStr := dbmodel.RoleMailDataPrefix + uidStr valueStrList, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil && err != service.NIL { util.InfoF("uid=%v GetRoleMailDataFromRedis err=%v", uidStr, err) return } for key, value := range valueStrList { if key == "maxId" || key == "gMaxId" { continue } //if key == "DelMail"{ // tmp := &serverproto.DelMail{} // err := model.GetDecodeMessage(tmp, value) // if err != nil{continue} // for _, mail := range tmp.DelMail { // if mail.BeginTime < beginT{continue} // if endT > 0 && mail.BeginTime > endT{continue} // ret = append(ret, mail) // } //} mailData := &serverproto.MailContent{} if err := model.GetDecodeMessage(mailData, value); err != nil { util.InfoF("uid=%v GetRoleMailDataFromRedis key=%v err=%v", uidStr, key, err) continue } else { if mailData.BeginTime < beginT { continue } if endT > 0 && mailData.BeginTime > endT { continue } ret = append(ret, mailData) } } c.JSON(http.StatusOK, ret) } func WebGMSetHead(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") headStr := c.DefaultQuery("headId", "0") stateStr := c.DefaultQuery("state", "0") headId, _ := model.Str2Num(headStr) state, _ := model.Str2Num(stateStr) uid, _ := model.Str2NumU64(uidStr) if headId <= 0 || state < 0 || uid <= 0 { c.JSON(http.StatusOK, "parameter error") return } msg := &serverproto.SSWebGMHeadChange{ HeadId: int32(headId), Uid: uid, State: int32(state), } gmweb.SendSocial(msg) c.JSON(http.StatusOK, msg) } func WebGMGetHead(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") if uidStr == "" { c.JSON(http.StatusOK, "uid error:"+uidStr) return } headData := &serverproto.RoleHead{} err := model.GetMessageFromRedis(dbmodel.RoleHeadDataPrefix, uidStr, headData) if err != nil && err != service.NIL { c.JSON(http.StatusOK, "uid read redis head error"+uidStr) return } retMsg := &serverproto.RoleHead{} for _, data := range headData.Heads { if data.State < int32(1) { // 未完成的称号不显示 continue } retMsg.Heads = append(retMsg.Heads, data) } c.JSON(http.StatusOK, retMsg) } // 删除背包内道具 func WebGMDelItem(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") delItemStr := c.DefaultQuery("del", "") if uidStr == "" { c.JSON(http.StatusOK, "uid error:"+uidStr) return } //uid uid, _ := model.Str2NumU64(uidStr) if uid <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid invalid", }) util.InfoF("uid=%v uid invalid", uid) return } //del item list var delKV []*serverproto.KeyValueType delItemStrList := strings.Split(delItemStr, ",") for idx := 0; idx < len(delItemStrList); idx++ { k, v := model.Str2Res(delItemStrList[idx]) if k <= 0 || v <= 0 { continue } delKV = append(delKV, &serverproto.KeyValueType{Key: k, Value: v}) } if len(delKV) <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid del item invalid", }) util.InfoF("uid=%v item invalid", uid) return } roleBag := &serverproto.RoleBag{} err := dbmodel.GetSystemDataFromRedis(dbmodel.RoleBagDataPrefix, uid, roleBag) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": "uid get bag error", }) util.InfoF("uid=%v uid get bag error=%v", uid, err) return } var tmpItemDataList []*serverproto.ItemData for idx := 0; idx < len(delKV); idx++ { delkv := delKV[idx] for i := 0; i < len(roleBag.ItemList); i++ { if roleBag.ItemList[i].ConfigId != delkv.Key { tmpItemDataList = append(tmpItemDataList, roleBag.ItemList[i]) } else { if roleBag.ItemList[i].Num >= uint32(delkv.Value) { roleBag.ItemList[i].Num -= uint32(delkv.Value) tmpItemDataList = append(tmpItemDataList, roleBag.ItemList[i]) } } } } roleBag.ItemList = tmpItemDataList //1.直接数据库操作 dbmodel.SetSystemDataToRedis(dbmodel.RoleBagDataPrefix, uid, roleBag) //2.在线发送给对应的game玩家 //发送给social,在线的玩家直接踢下线 banNtf := &serverproto.SSWebGMDelItemNtf{ Uid: uid, DelItemList: delKV, } gmweb.SendSocial(banNtf) c.JSON(http.StatusOK, gin.H{ "err": "del item ok", }) } var RedisCdk2 service.RedisConnector func GetCdk(c *gin.Context) { countStr := c.DefaultQuery("count", "") awardStr := c.DefaultQuery("award", "") if awardStr == "" { c.JSON(http.StatusOK, "award error:"+awardStr) return } count, e := strconv.Atoi(countStr) if e != nil { c.JSON(http.StatusOK, e) return } var awardKV []*serverproto.KeyValueType itemStrList := strings.Split(awardStr, ",") for idx := 0; idx < len(itemStrList); idx++ { k, v := model.Str2Res(itemStrList[idx]) if k <= 0 || v <= 0 { continue } awardKV = append(awardKV, &serverproto.KeyValueType{Key: k, Value: v}) } awardData := &serverproto.SCUseHeadFrameItemAck{} awardData.ItemList = awardKV err, a2 := model.GetEncodeMessage(awardData) if err != nil { c.JSON(http.StatusOK, err) return } rand.Seed(time.Now().UnixNano()) f := excelize.NewFile() sheetName := "Sheet1" cdk := make(map[string]interface{}, 0) for i := 0; i < count; i++ { // 生成随机字符串 randomString := generateRandomString(length) cdk[randomString] = a2 cellName, err := excelize.CoordinatesToCellName(1, i+1) if err != nil { c.JSON(http.StatusOK, err) return } // 设置单元格的值 f.SetCellValue(sheetName, cellName, randomString) } util.InfoF("aaaa:%v", cdk) _, err2 := RedisCdk2.RedisCli().HMSet(dbmodel.CdkNormal, cdk).Result() if err2 != nil { util.InfoF("aaaa3:%v", err2) c.JSON(http.StatusOK, err2) return } util.InfoF("aaaa2:%v", cdk) // 保存文件 filePath := "cdkNormal.xlsx" if err := f.SaveAs(filePath); err != nil { c.JSON(http.StatusOK, err) return } c.JSON(http.StatusOK, "cdk successful") } // 定义生成随机字符串的长度 const length = 15 func generateRandomString(length int) string { // 定义可用的字符集(大写字母) const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 初始化一个字节切片来存储结果 result := make([]byte, length) // 生成随机字符 for i := range result { result[i] = charset[rand.Intn(len(charset))] } // 将字节切片转换为字符串并返回 return string(result) } // 删除背包内道具 func WebGMDelPoint(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") delItemStr := c.DefaultQuery("del", "") if uidStr == "" { c.JSON(http.StatusOK, "uid error:"+uidStr) return } //uid uid, _ := model.Str2NumU64(uidStr) if uid <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid invalid", }) util.InfoF("uid=%v uid invalid", uid) return } //del item list var delKV []*serverproto.KeyValueType delItemStrList := strings.Split(delItemStr, ",") for idx := 0; idx < len(delItemStrList); idx++ { k, v := model.Str2Res(delItemStrList[idx]) if k <= 0 || v <= 0 { continue } delKV = append(delKV, &serverproto.KeyValueType{Key: k, Value: v}) } if len(delKV) <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid del item invalid", }) util.InfoF("uid=%v item invalid", uid) return } //2.在线发送给对应的game玩家 //发送给social,在线的玩家直接踢下线 banNtf := &serverproto.SSWebGMDelItemNtf{ Uid: uid, DelItemList: delKV, IsPoint: true, } gmweb.SendSocial(banNtf) c.JSON(http.StatusOK, gin.H{ "err": "del item ok", }) } // 删除背包内道具 func WebGMDelItemAll(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") delItemStr := c.DefaultQuery("del", "") if uidStr == "" { c.JSON(http.StatusOK, "uid error:"+uidStr) return } //uid uid, _ := model.Str2NumU64(uidStr) if uid <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid invalid", }) util.InfoF("uid=%v uid invalid", uid) return } //del item list var delKV []*serverproto.KeyValueType delItemStrList := strings.Split(delItemStr, ",") for idx := 0; idx < len(delItemStrList); idx++ { k, v := model.Str2Res(delItemStrList[idx]) if k <= 0 || v <= 0 { continue } delKV = append(delKV, &serverproto.KeyValueType{Key: k, Value: v}) } if len(delKV) <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid del item invalid", }) util.InfoF("uid=%v item invalid", uid) return } roleBag := &serverproto.RoleBag{} err := dbmodel.GetSystemDataFromRedis(dbmodel.RoleBagDataPrefix, uid, roleBag) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": "uid get bag error", }) util.InfoF("uid=%v uid get bag error=%v", uid, err) return } var count uint32 //var tmpItemDataList []*serverproto.ItemData for idx := 0; idx < len(delKV); idx++ { delkv := delKV[idx] for i := 0; i < len(roleBag.ItemList); i++ { if roleBag.ItemList[i].ConfigId != delkv.Key { //tmpItemDataList = append(tmpItemDataList, roleBag.ItemList[i]) continue } else { count = count + roleBag.ItemList[i].Num roleBag.ItemList[i].Num = 0 } } } //roleBag.ItemList = tmpItemDataList //1.直接数据库操作 dbmodel.SetSystemDataToRedis(dbmodel.RoleBagDataPrefix, uid, roleBag) if count > 0 { util.ErrorF("del 707 uid:%v count:%v", uid, count) } //2.在线发送给对应的game玩家 //发送给social,在线的玩家直接踢下线 //banNtf := &serverproto.SSWebGMDelItemNtf{ // Uid: uid, // DelItemList: delKV, //} //gmweb.SendSocial(banNtf) c.JSON(http.StatusOK, gin.H{ "err": "del item ok", }) } // 删除背包内道具 func WebGMDelEquip(c *gin.Context) { uidStr := c.DefaultQuery("uid", "") delItemStr := c.DefaultQuery("del", "") if uidStr == "" { c.JSON(http.StatusOK, "uid error:"+uidStr) return } //uid uid, _ := model.Str2NumU64(uidStr) if uid <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid invalid", }) util.InfoF("uid=%v uid invalid", uid) return } //del item list var delKV []*serverproto.KeyValueType delItemStrList := strings.Split(delItemStr, ",") for idx := 0; idx < len(delItemStrList); idx++ { k, v := model.Str2Res(delItemStrList[idx]) if k <= 0 || v <= 0 { continue } delKV = append(delKV, &serverproto.KeyValueType{Key: k, Value: v}) } if len(delKV) <= 0 { c.JSON(http.StatusOK, gin.H{ "err": "uid del item invalid", }) util.InfoF("uid=%v item invalid", uid) return } roleBag := &serverproto.RoleEquip{} err := dbmodel.GetSystemDataFromRedis(dbmodel.RoleEquipDataPrefix, uid, roleBag) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": err, }) util.ErrorF("uid=%v uid get equip error=%v", uid, err) return } roleBase := &serverproto.RoleBase{} _ = dbmodel.GetRoleBaseFromRedis(uid, roleBase) roleHero := &serverproto.RoleHero{} err = dbmodel.GetRoleHeroDataFromRedis(uid, roleHero) if err != nil { c.JSON(http.StatusOK, gin.H{ "err": "uid get bag error", }) util.InfoF("uid=%v uid get hero error=%v", uid, err) return } //roleCard := &serverproto.RoleCard{} //err = dbmodel.GetSystemDataFromRedis(dbmodel.RoleCardDataPrefix, uid, roleCard) //if err != nil { // c.JSON(http.StatusOK, gin.H{ // "err": "uid get bag error", // }) // util.InfoF("uid=%v uid get hero error=%v", uid, err) // return //} var count int32 //var tmpItemDataList []*serverproto.EquipData for i := 0; i < len(roleBag.EquipList); i++ { for idx := 0; idx < len(delKV); idx++ { delkv := delKV[idx] if roleBag.EquipList[i].ConfigId != delkv.Key { continue } else { count = count + roleBag.EquipList[i].Num roleBag.EquipList[i].Num = 0 } } } var count2 int32 for idx := 0; idx < len(delKV); idx++ { delkv := delKV[idx] for i := 0; i < len(roleBase.RoleData.HeroData.Slot.SlotList); i++ { if roleBase.RoleData.HeroData.Slot.SlotList[i].EquipId != delkv.Key { continue } else { roleBase.RoleData.HeroData.Slot.SlotList[i].EquipId = 0 count2++ } } } var count3 int32 ////cardlist := make([]int32, 0) for idx := 0; idx < len(delKV); idx++ { delkv := delKV[idx] for i := 0; i < len(roleHero.HeroData); i++ { for j := 0; j < len(roleHero.HeroData[i].Slot.SlotList); j++ { if roleHero.HeroData[i].Slot.SlotList[j].EquipId != delkv.Key { continue } else { roleHero.HeroData[i].Slot.SlotList[j].EquipId = 0 count3++ //util.ErrorF("get equip2 uid:%v count:%v", uid, count) } } } } if count+count2+count3 > 0 { util.ErrorF("del equip uid:%v count:%v ,%v,%v", uid, count, count2, count3) } //1.直接数据库操作 dbmodel.SetRoleHeroDataToRedis(uid, roleHero) dbmodel.SetSystemDataToRedis(dbmodel.RoleEquipDataPrefix, uid, roleBag) //dbmodel.SetRoleToRedis(uid, roleBase) //2.在线发送给对应的game玩家 //发送给social,在线的玩家直接踢下线 //banNtf := &serverproto.SSWebGMDelItemNtf{ // Uid: uid, // DelItemList: delKV, //} //gmweb.SendSocial(banNtf) c.JSON(http.StatusOK, gin.H{ "err": "del item ok", }) } /* //检索玩家数据 http://127.0.0.1:8086/gm/user_get?nickname=11&lmin=1&lmax=3&createdate=2020-05-07&banstatus=0&maplevel=2&fmin=1&fmax=3&pnum=1 nickname 昵称,不需要则不填写去掉nickname=11 lmin=1&lmax=3 等级,[min,max]区间内 createdate=2020-05-07 创建角色日期 lastlogindate=2020-05-07 最后登录日期 banstatus=0 当前玩家状态:0表示正常1表示封号 maplevel=10001 关卡进度,格式为mapid * 10000 + maplevel fmin=1&fmax=2 队伍战力 [min,max]区间 pnum=1 表示当前是第几页 //获取玩家详细信息 //http://127.0.0.1:8086/gm/info_get?uid=6824453512924037889 根据检索玩家数据,得到对应的玩家uid,再使用该url获取玩家的相信信息 uid=6824453512924037889 玩家uid //封号 //http://127.0.0.1:8086/gm/ban?uid=6824453512924037889&ban=1 ban=1 1表示封号,0表示解封 //聊天管理 //1私聊,2公聊 //http://127.0.0.1:8086/gm/chat_msg?type=2&uid=6824453512924037889&msgdate=2020-05-05%2021:42:59 type=2 1私聊,2公聊 uid=6824453512924037889 玩家uid msgdate=2020-05-05%2021:42:59 >=该时间后的所有聊天信息 //邮件管理 //http://127.0.0.1:8086/gm/mail?type=list 获取当前的定时邮件列表 //http://127.0.0.1:8086/gm/mail?type=add&title=title&content=content&reward=101:1,102:3 添加邮件 //http://127.0.0.1:8086/gm/mail?type=add&title=title&content=content&reward=101:1,102:3&senddate=2020-05-09%2000:00:00 添加邮件 //http://127.0.0.1:8086/gm/mail?type=del&id=1 删除延迟发送邮件(该邮件还未发送时才会删除成功) type=list list获取邮件列表操作,add添加操作,del删除操作 title=标题 邮件标题 content=正文 邮件正文 reward=奖励 邮件奖励,格式: 101:1,102:3,106:222 */ //登录的账号和密码 //[wtgame,wtgame123] //需要在请求时带上token //发送公告 //http://127.0.0.1:8086/gm/notice?&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTAyMzEyNTAsImlhdCI6MTU5MDIyNzY1MH0.PIGt_fXQFai4NJz3sg2LICbQFRFWWwxuak8KkUGtsig&col=商城购买12312321!!123123!!!!!!!!!!<%2Fcolor>&count=5&interval=5 //商城购买12312321!!123123!!!!!!!!!!<%2Fcolor> //记得修改和<%2Fcolor>之间的内容