forked from all_user/stat_center
Initial commit
This commit is contained in:
@@ -0,0 +1,568 @@
|
||||
package crossSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"stat/api/proto"
|
||||
"stat/common"
|
||||
"stat/common/statutils"
|
||||
"stat/common/tgbot"
|
||||
"stat/common/utils"
|
||||
"stat/models/botdailyhourstat"
|
||||
"stat/statg"
|
||||
"time"
|
||||
|
||||
"github.com/wcharczuk/go-chart/v2"
|
||||
|
||||
"github.com/wcharczuk/go-chart/v2/drawing"
|
||||
|
||||
"github.com/vicanso/go-charts/v2"
|
||||
)
|
||||
|
||||
var Colors = []drawing.Color{
|
||||
drawing.ColorFromHex("0780cf"),
|
||||
drawing.ColorFromHex("765005"),
|
||||
drawing.ColorFromHex("fa6d1d"),
|
||||
drawing.ColorFromHex("0e2c82"),
|
||||
drawing.ColorFromHex("b6b51f"),
|
||||
drawing.ColorFromHex("da1f18"),
|
||||
drawing.ColorFromHex("701866"),
|
||||
drawing.ColorFromHex("f47a75"),
|
||||
drawing.ColorFromHex("009db2"),
|
||||
drawing.ColorFromHex("024b51"),
|
||||
drawing.ColorFromHex("0780cf"),
|
||||
drawing.ColorFromHex("765005"),
|
||||
}
|
||||
|
||||
type CrossStatMethod = func(ctx context.Context, cmd *tgbot.Command) error
|
||||
|
||||
// 统计方法汇总
|
||||
var CrossStatMethodMap = map[string]CrossStatMethod{
|
||||
statutils.StatProjectRecharge: CrossStatRecharge,
|
||||
statutils.StatProjectRechargeNew: CrossStatRechargeNew,
|
||||
statutils.StatProjectRechargeOld: CrossStatRechargeOld,
|
||||
statutils.StatProjectRechargeGold: CrossStatRechargeGold,
|
||||
statutils.StatProjectRechargeVip: CrossStatRechargeVip,
|
||||
statutils.StatProjectRegister: CrossStatRegister,
|
||||
statutils.StatProjectVisit: CrossStatVisit,
|
||||
statutils.StatProjectOrder: CrossStatOrder,
|
||||
}
|
||||
|
||||
type CrossAppDownloadRes struct {
|
||||
Code int32 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Tip string `json:"tip"`
|
||||
Data *proto.PageButtonClickResp `json:"data"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
type CrossStatRes struct {
|
||||
Code int32 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Tip string `json:"tip"`
|
||||
Data *proto.BotDailyHourListResp `json:"data"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
type CrossMonthRes struct {
|
||||
Code int32 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Tip string `json:"tip"`
|
||||
Data *proto.BotMonthStatResp `json:"data"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
type StatItem struct {
|
||||
Value int64
|
||||
Stat *botdailyhourstat.BotHourStat
|
||||
}
|
||||
|
||||
type FuncGetStatValue func(item *botdailyhourstat.BotHourStat) int64
|
||||
|
||||
type StatItemList []*StatItem
|
||||
|
||||
func (a StatItemList) Len() int { return len(a) }
|
||||
func (a StatItemList) Less(i, j int) bool { return a[i].Value > a[j].Value }
|
||||
func (a StatItemList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
func CrossMonthStat(ctx context.Context, cmd *tgbot.Command) error {
|
||||
appId, _ := cmd.GetFlagInt32Value("-app")
|
||||
monthStr := cmd.GetFlagStringValue("-month")
|
||||
month, err := time.ParseInLocation("2006-01-02", monthStr, time.Local)
|
||||
if err != nil {
|
||||
return tgbot.NewUserError(cmd, "解析日期出错, 格式:\n"+cmd.Help+"\n"+cmd.Desc)
|
||||
}
|
||||
getValue := func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.Recharge.Value()
|
||||
}
|
||||
statList := make(StatItemList, 0)
|
||||
for _, addr := range statg.Conf.InnerServers {
|
||||
req := &proto.BotMonthStatReq{Month: month}
|
||||
if appId > 0 {
|
||||
req.AppId = &appId
|
||||
}
|
||||
res := CrossMonthRes{}
|
||||
err = InnerRequest(addr+"/api/stat/inner/botMonthStat", req, &res, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.Data == nil {
|
||||
continue
|
||||
}
|
||||
for _, stat := range res.Data.List {
|
||||
if statg.GlobalEndpoints.ExistsByAppId(stat.AppId) {
|
||||
value := getValue(stat)
|
||||
statList = append(statList, &StatItem{
|
||||
Value: value,
|
||||
Stat: stat,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort
|
||||
sort.Sort(statList)
|
||||
// 显示
|
||||
y, m, _ := month.Date()
|
||||
for _, item := range statList {
|
||||
appName := statg.GlobalEndpoints.ExistsByAppId(item.Stat.AppId)
|
||||
title := fmt.Sprintf("%d年%d月【%s】数据汇总", y, m, appName)
|
||||
text := item.Stat.DisplaySummaryText(title)
|
||||
if err = cmd.SendBack(text); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CrossStatRecharge(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "充值排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.Recharge.Value() / 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("充值排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatRechargeNew(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "新用户充值排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.RechargeNew.Value() / 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("新用户充值排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatRechargeOld(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "老用户充值排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.RechargeOld.Value() / 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("老用户充值排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatRechargeGold(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "金币充值排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.RechargeGold.Value() / 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("金币充值排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatRechargeVip(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "会员充值排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.RechargeVip.Value() / 100
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("会员充值排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatRegister(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "注册排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.Register.Value()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("注册排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatVisit(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "日活排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.Visit.Value()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("日活排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func CrossStatOrder(ctx context.Context, cmd *tgbot.Command) error {
|
||||
moveBackDays, _ := cmd.GetFlagInt64Value("-back")
|
||||
if moveBackDays > 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
// get stats
|
||||
now := time.Now()
|
||||
reportTime := utils.RecentMinute(now, 60)
|
||||
if moveBackDays != 0 {
|
||||
reportTime = utils.BeginWithTime(now.AddDate(0, 0, int(moveBackDays)+1))
|
||||
}
|
||||
title := GetDateDesc(0) + "订单排名:" + reportTime.Format("2006-01-02T15:04:05")
|
||||
photo, _, err := GetRankPhoto(reportTime, title, func(item *botdailyhourstat.BotHourStat) int64 {
|
||||
return item.TodayStat.Order.Count()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.PhotoPath = photo
|
||||
return cmd.SendBack(fmt.Sprintf("订单排名:%s\n", reportTime.Format("2006-01-02T15:04:05")))
|
||||
}
|
||||
|
||||
func GetRankPhoto(reportTime time.Time, title string, getValue FuncGetStatValue) (string, []byte, error) {
|
||||
charts.SetDefaultFont(statutils.Font)
|
||||
statList := make(StatItemList, 0)
|
||||
registerStatList := make(StatItemList, 0)
|
||||
var total, registerTotal, visitTotal int64
|
||||
for _, addr := range statg.Conf.InnerServers {
|
||||
req := &proto.BotDailyHourListReq{
|
||||
Page: common.Page{
|
||||
PageNum: 1,
|
||||
PageSize: 100,
|
||||
},
|
||||
SumDateStart: reportTime,
|
||||
SumDateStop: reportTime,
|
||||
}
|
||||
res := CrossStatRes{}
|
||||
err := InnerRequest(addr+"/api/stat/inner/botStatList", req, &res, true)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if res.Data == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, stat := range res.Data.List {
|
||||
if statg.GlobalEndpoints.GetBotRankEndpoints().ExistsByAppId(stat.AppId) {
|
||||
value := getValue(stat)
|
||||
total += value
|
||||
statList = append(statList, &StatItem{
|
||||
Value: value,
|
||||
Stat: stat,
|
||||
})
|
||||
|
||||
registerValue := stat.TodayStat.Register.Total.Value()
|
||||
registerTotal += registerValue
|
||||
visitTotal += stat.TodayStat.Visit.Total.Value()
|
||||
registerStatList = append(registerStatList, &StatItem{
|
||||
Value: registerValue,
|
||||
Stat: stat,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort
|
||||
sort.Sort(statList)
|
||||
// draw chart
|
||||
xNames := make([]string, 0)
|
||||
for _, stat := range statList {
|
||||
xNames = append(xNames, statg.GlobalEndpoints.GetAppShortNameById(stat.Stat.AppId))
|
||||
}
|
||||
sDatas := make([]charts.SeriesData, 0)
|
||||
rDatas := make([]charts.SeriesData, 0)
|
||||
for index, stat := range statList {
|
||||
sDatas = append(sDatas, charts.SeriesData{
|
||||
Value: float64(stat.Value),
|
||||
Style: charts.Style{
|
||||
FillColor: Colors[index%len(Colors)],
|
||||
TextWrap: chart.TextWrapRune,
|
||||
},
|
||||
})
|
||||
for _, registerStat := range registerStatList {
|
||||
if stat.Stat.AppId == registerStat.Stat.AppId {
|
||||
rDatas = append(rDatas, charts.SeriesData{
|
||||
Value: float64(registerStat.Value),
|
||||
Style: charts.Style{
|
||||
FillColor: Colors[index%len(Colors)],
|
||||
TextWrap: chart.TextWrapRune,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chartOpt := charts.ChartOption{
|
||||
Width: statg.Conf.ChartsConfig.Width,
|
||||
Height: statg.Conf.ChartsConfig.Height,
|
||||
Type: charts.ChartOutputPNG,
|
||||
Title: charts.TitleOption{
|
||||
Text: title,
|
||||
},
|
||||
XAxis: charts.NewXAxisOption(xNames),
|
||||
Legend: charts.LegendOption{
|
||||
Data: []string{
|
||||
fmt.Sprintf("应用:%d", len(xNames)),
|
||||
fmt.Sprintf("充值:%d", total),
|
||||
fmt.Sprintf("日活:%d", visitTotal),
|
||||
fmt.Sprintf("注册:%d", registerTotal),
|
||||
},
|
||||
Icon: charts.IconRect,
|
||||
Left: charts.PositionRight,
|
||||
},
|
||||
SeriesList: []charts.Series{
|
||||
{
|
||||
Type: charts.ChartTypeBar,
|
||||
Data: sDatas,
|
||||
Label: charts.SeriesLabel{
|
||||
Show: true,
|
||||
Position: charts.PositionBottom,
|
||||
},
|
||||
MarkLine: charts.NewMarkLine(
|
||||
charts.SeriesMarkDataTypeAverage,
|
||||
),
|
||||
},
|
||||
{
|
||||
Type: charts.ChartTypeBar,
|
||||
Data: rDatas,
|
||||
Label: charts.SeriesLabel{
|
||||
Show: true,
|
||||
Position: charts.PositionBottom,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
show := true
|
||||
chartOpt.XAxis.Show = &show
|
||||
d, err := charts.Render(chartOpt)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
buf, err := d.Bytes()
|
||||
if err != nil {
|
||||
return "", buf, err
|
||||
}
|
||||
photo := fmt.Sprintf("/tmp/%s.png", utils.UUID())
|
||||
if err = statutils.WriteBytesToFile(buf, photo); err != nil {
|
||||
return "", buf, err
|
||||
}
|
||||
return photo, buf, nil
|
||||
}
|
||||
|
||||
func GetRankDetail(reportTime time.Time, title string, getValue FuncGetStatValue) (string, error) {
|
||||
charts.SetDefaultFont(statutils.Font)
|
||||
statList := make(StatItemList, 0)
|
||||
registerStatList := make(StatItemList, 0)
|
||||
var total, registerTotal int64
|
||||
for _, addr := range statg.Conf.InnerServers {
|
||||
req := &proto.BotDailyHourListReq{
|
||||
Page: common.Page{
|
||||
PageNum: 1,
|
||||
PageSize: 100,
|
||||
},
|
||||
SumDateStart: reportTime,
|
||||
SumDateStop: reportTime,
|
||||
}
|
||||
res := CrossStatRes{}
|
||||
err := InnerRequest(addr+"/api/stat/inner/botStatList", req, &res, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if res.Data == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, stat := range res.Data.List {
|
||||
if statg.GlobalEndpoints.GetBotRankEndpoints().ExistsByAppId(stat.AppId) {
|
||||
value := getValue(stat)
|
||||
total += value
|
||||
statList = append(statList, &StatItem{
|
||||
Value: value,
|
||||
Stat: stat,
|
||||
})
|
||||
|
||||
registerValue := stat.TodayStat.Register.Total.Value()
|
||||
registerTotal += registerValue
|
||||
registerStatList = append(registerStatList, &StatItem{
|
||||
Value: registerValue,
|
||||
Stat: stat,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort
|
||||
sort.Sort(statList)
|
||||
// draw chart
|
||||
xNames := make([]string, 0)
|
||||
for _, stat := range statList {
|
||||
xNames = append(xNames, statg.GlobalEndpoints.GetAppShortNameById(stat.Stat.AppId))
|
||||
}
|
||||
sDatas := make([]charts.SeriesData, 0)
|
||||
rDatas := make([]charts.SeriesData, 0)
|
||||
for index, stat := range statList {
|
||||
sDatas = append(sDatas, charts.SeriesData{
|
||||
Value: float64(stat.Value),
|
||||
Style: charts.Style{
|
||||
FillColor: Colors[index%len(Colors)],
|
||||
TextWrap: chart.TextWrapRune,
|
||||
},
|
||||
})
|
||||
for _, registerStat := range registerStatList {
|
||||
if stat.Stat.AppId == registerStat.Stat.AppId {
|
||||
rDatas = append(rDatas, charts.SeriesData{
|
||||
Value: float64(registerStat.Value),
|
||||
Style: charts.Style{
|
||||
FillColor: Colors[index%len(Colors)],
|
||||
TextWrap: chart.TextWrapRune,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chartOpt := charts.ChartOption{
|
||||
Width: statg.Conf.ChartsConfig.Width,
|
||||
Height: statg.Conf.ChartsConfig.Height,
|
||||
Type: charts.ChartOutputPNG,
|
||||
Title: charts.TitleOption{
|
||||
Text: title,
|
||||
},
|
||||
XAxis: charts.NewXAxisOption(xNames),
|
||||
Legend: charts.LegendOption{
|
||||
Data: []string{
|
||||
fmt.Sprintf("应用:%d", len(xNames)),
|
||||
fmt.Sprintf("充值:%d", total),
|
||||
fmt.Sprintf("注册:%d", registerTotal),
|
||||
},
|
||||
Icon: charts.IconRect,
|
||||
Left: charts.PositionRight,
|
||||
},
|
||||
SeriesList: []charts.Series{
|
||||
{
|
||||
Type: charts.ChartTypeBar,
|
||||
Data: sDatas,
|
||||
Label: charts.SeriesLabel{
|
||||
Show: true,
|
||||
Position: charts.PositionBottom,
|
||||
},
|
||||
MarkLine: charts.NewMarkLine(
|
||||
charts.SeriesMarkDataTypeAverage,
|
||||
),
|
||||
},
|
||||
{
|
||||
Type: charts.ChartTypeBar,
|
||||
Data: rDatas,
|
||||
Label: charts.SeriesLabel{
|
||||
Show: true,
|
||||
Position: charts.PositionBottom,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
show := true
|
||||
chartOpt.XAxis.Show = &show
|
||||
d, err := charts.Render(chartOpt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf, err := d.Bytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
photo := fmt.Sprintf("/tmp/%s.png", utils.UUID())
|
||||
if err = statutils.WriteBytesToFile(buf, photo); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return photo, nil
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package crossSer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"stat/common/crypt"
|
||||
"stat/statg"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InnerCryptPost(requestURL string, postData []byte) (*http.Response, error) {
|
||||
key := statg.Conf.InnerKey
|
||||
enData, err := crypt.CoreAesEncryptEx(postData, 12, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bodyReader := bytes.NewReader(enData)
|
||||
req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timeout := 30 * time.Second
|
||||
if strings.Contains(requestURL, "botMonthStat") {
|
||||
timeout = 15 * time.Minute
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
client := http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enData, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deData, err := crypt.CoreAesDecryptEx(enData, 12, key)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
resp.Body = io.NopCloser(bytes.NewBuffer(deData))
|
||||
resp.ContentLength = int64(len(deData))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func InnerPlainPost(requestURL string, postData []byte) (*http.Response, error) {
|
||||
bodyReader := bytes.NewReader(postData)
|
||||
req, err := http.NewRequest(http.MethodPost, requestURL, bodyReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timeout := 8 * time.Second
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
client := http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
return client.Do(req)
|
||||
}
|
||||
|
||||
func InnerRequest(url string, req interface{}, bind interface{}, crypt bool) error {
|
||||
data, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var resp *http.Response
|
||||
if crypt {
|
||||
resp, err = InnerCryptPost(url, data)
|
||||
} else {
|
||||
resp, err = InnerPlainPost(url, data)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("error status %s, http code %d", resp.Status, resp.StatusCode)
|
||||
}
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, bind)
|
||||
}
|
||||
|
||||
func GetDateDesc(moveBackDays int) string {
|
||||
if moveBackDays < 0 {
|
||||
moveBackDays = moveBackDays * -1
|
||||
}
|
||||
switch moveBackDays {
|
||||
case 0:
|
||||
return "今天"
|
||||
case 1:
|
||||
return "昨天"
|
||||
case 2:
|
||||
return "前天"
|
||||
default:
|
||||
return fmt.Sprintf("前%d天", moveBackDays)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user