Browse Source

更新

master
huangjiajun 2 weeks ago
parent
commit
8839c1dacb
15 changed files with 1181 additions and 24 deletions
  1. +24
    -0
      app/hdl/hdl_data_center.go
  2. +77
    -0
      app/hdl/hdl_index.go
  3. +5
    -5
      app/hdl/hdl_login.go
  4. +9
    -0
      app/md/md_data_center.go
  5. +24
    -0
      app/md/md_index.go
  6. +13
    -7
      app/router/router.go
  7. +71
    -8
      app/svc/svc_data_center.go
  8. +122
    -0
      app/svc/svc_index.go
  9. +52
    -0
      app/utils/convert.go
  10. +8
    -3
      app/utils/time.go
  11. +36
    -0
      app/utils/xls.go
  12. +276
    -0
      docs/docs.go
  13. +276
    -0
      docs/swagger.json
  14. +184
    -0
      docs/swagger.yaml
  15. +4
    -1
      go.mod

+ 24
- 0
app/hdl/hdl_data_center.go View File

@@ -83,6 +83,30 @@ func DataCenterRecordList(c *gin.Context) {
return return
} }


// DataCenterRecordOutPut
// @Summary 数据明细-导出
// @Tags 数据中心------嘉俊
// @Description 数据中心-数据明细-导出
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Accept json
// @Produce json
// @Param args body md.DataCenterRecordOutPutReq true "请求参数"
// @Success 200 {string} "具体看返回内容 这是data里面的数据"
// @Failure 400 {object} md.Response "具体错误"
// @Router /api/dataCenter/record/output [POST]
func DataCenterRecordOutPut(c *gin.Context) {
var req md.DataCenterRecordOutPutReq
err := c.ShouldBindJSON(&req)
if err != nil {
err = validate.HandleValidateErr(err)
err1 := err.(e.E)
e.OutErr(c, err1.Code, err1.Error())
return
}
svc.DataCenterRecordOutPut(c, req)
return
}

// DataCenterSelectData // DataCenterSelectData
// @Summary 筛选条件 // @Summary 筛选条件
// @Tags 数据中心------嘉俊 // @Tags 数据中心------嘉俊


+ 77
- 0
app/hdl/hdl_index.go View File

@@ -0,0 +1,77 @@
package hdl

import (
"applet/app/e"
"applet/app/lib/validate"
"applet/app/md"
"applet/app/svc"
"applet/app/utils"
db "code.fnuoos.com/zhimeng/model.git/src"
"code.fnuoos.com/zhimeng/model.git/src/super/implement"
"github.com/gin-gonic/gin"
)

// Base
// @Summary 右上角基本数据
// @Tags 首页------嘉俊
// @Description 首页-右上角基本数据
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Accept json
// @Produce json
// @Success 200 {string} "具体看返回内容 这是data里面的数据"
// @Failure 400 {object} md.Response "具体错误"
// @Router /api/index/base [GET]
func Base(c *gin.Context) {
user := svc.GetUser(c)
NewMediumListDb := implement.NewMediumListDb(db.Db)
data, _ := NewMediumListDb.GetMediumList(user.MediumId)
settleType := []string{"", "日结", "周结", "月结", "预付"}
res := map[string]string{
"account_id": utils.IntToStr(user.MediumId),
"name": user.Username,
"account": user.Username,
"settle_type": utils.IntToStr(data.SettlementType),
"settle_type_str": settleType[data.SettlementType],
}
e.OutSuc(c, res, nil)
return
}

// IndexTotal
// @Summary 统计数据
// @Tags 首页------嘉俊
// @Description 首页-统计数据
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Accept json
// @Produce json
// @Success 200 {string} "具体看返回内容 这是data里面的数据"
// @Failure 400 {object} md.Response "具体错误"
// @Router /api/index/total [GET]
func IndexTotal(c *gin.Context) {
svc.IndexTotal(c)
}

// IndexAppList
// @Summary 数据明细
// @Tags 数据中心------嘉俊
// @Description 数据中心-数据明细
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Accept json
// @Produce json
// @Param args body md.IndexAppListReq true "请求参数"
// @Success 200 {object} md.IndexAppListRes "具体看返回内容 这是data里面的数据"
// @Failure 400 {object} md.Response "具体错误"
// @Router /api/index/app/list [POST]
func IndexAppList(c *gin.Context) {
var req md.IndexAppListReq
err := c.ShouldBindJSON(&req)
if err != nil {
err = validate.HandleValidateErr(err)
err1 := err.(e.E)
e.OutErr(c, err1.Code, err1.Error())
return
}
res := svc.IndexAppList(c, req)
e.OutSuc(c, res, nil)
return
}

+ 5
- 5
app/hdl/hdl_login.go View File

@@ -131,11 +131,11 @@ func Register(c *gin.Context) {
return return
} }
engine := db.DBs[svc.GetMasterId(c)] engine := db.DBs[svc.GetMasterId(c)]
check, err := svc.SmsCheck(c, req.UserName, req.Captcha)
if check == false {
e.OutErr(c, 400, e.NewErr(400, err.Error()))
return
}
//check, err := svc.SmsCheck(c, req.UserName, req.Captcha)
//if check == false {
// e.OutErr(c, 400, e.NewErr(400, err.Error()))
// return
//}
now := time.Now() now := time.Now()
//1、判断当前账号是否已存在 //1、判断当前账号是否已存在
mediumDb := implement.NewMediumDb(engine) mediumDb := implement.NewMediumDb(engine)


+ 9
- 0
app/md/md_data_center.go View File

@@ -17,6 +17,15 @@ type DataCenterRecordReq struct {
Limit string `json:"limit"` Limit string `json:"limit"`
Page string `json:"page" ` Page string `json:"page" `
} }
type DataCenterRecordOutPutReq struct {
StartDate string `json:"start_date" example:"2024-08-30"`
EndDate string `json:"end_date" example:"2024-08-30"`
Platform string `json:"platform" example:"平台"`
AppId string `json:"app_id" example:"应用"`
AdType string `json:"ad_type" example:"广告位类型"`
Limit string `json:"limit" example:"10000 个一页"`
Page string `json:"page" `
}
type DataCenterTableRes struct { type DataCenterTableRes struct {
List []DataCenterTableData `json:"list" ` List []DataCenterTableData `json:"list" `
} }


+ 24
- 0
app/md/md_index.go View File

@@ -0,0 +1,24 @@
package md

type IndexAppListReq struct {
StartDate string `json:"start_date" example:"2024-08-30"`
EndDate string `json:"end_date" example:"2024-08-30"`
Sort string `json:"sort" example:"排序"`
}
type IndexAppListRes struct {
List []IndexAppListData `json:"list" `
Sort []SelectData `json:"sort"`
}

type IndexAppListData struct {
Name string `json:"name"`
Logo string `json:"logo"`
List []IndexAppListDataList `json:"list"`
TableList []string `json:"table_list"`
}
type IndexAppListDataList struct {
Name string `json:"name"`
Value string `json:"value"`
Type string `json:"type"`
Bili string `json:"bili"`
}

+ 13
- 7
app/router/router.go View File

@@ -64,9 +64,9 @@ func route(r *gin.RouterGroup) {
r.POST("/qiniuyun/upload", hdl.ImgReqUpload) //七牛云上传 r.POST("/qiniuyun/upload", hdl.ImgReqUpload) //七牛云上传
r.POST("/sms", hdl.Sms) //短信发送 r.POST("/sms", hdl.Sms) //短信发送
} }
r.Use(mw.Auth) // 以下接口需要JWT验证
rRole(r.Group("/role")) //权限管理
r.Use(mw.Auth) // 以下接口需要JWT验证
rRole(r.Group("/role")) //权限管理
rIndex(r.Group("/index")) //首页
rApplication(r.Group("/application")) //应用管理 rApplication(r.Group("/application")) //应用管理
rAccount(r.Group("/account")) //账号中心 rAccount(r.Group("/account")) //账号中心
rSettleCenter(r.Group("/settleCenter")) //结算中心 rSettleCenter(r.Group("/settleCenter")) //结算中心
@@ -117,8 +117,14 @@ func rInvoiceCenter(r *gin.RouterGroup) {
} }


func rDataCenter(r *gin.RouterGroup) { func rDataCenter(r *gin.RouterGroup) {
r.GET("/select/data", hdl.DataCenterSelectData) //数据中心-筛选条件
r.POST("/table", hdl.DataCenterTable) //数据中心-数据图表
r.POST("/record/total", hdl.DataCenterRecordTotal) //数据中心-数据明细合计
r.POST("/record/list", hdl.DataCenterRecordList) //数据中心-数据明细
r.GET("/select/data", hdl.DataCenterSelectData) //数据中心-筛选条件
r.POST("/table", hdl.DataCenterTable) //数据中心-数据图表
r.POST("/record/total", hdl.DataCenterRecordTotal) //数据中心-数据明细合计
r.POST("/record/list", hdl.DataCenterRecordList) //数据中心-数据明细
r.POST("/record/output", hdl.DataCenterRecordOutPut) //数据中心-数据明细-导出
}
func rIndex(r *gin.RouterGroup) {
r.GET("/base", hdl.Base) //首页-基本信息
r.GET("/total", hdl.IndexTotal) //首页-统计数据
r.POST("/app/list", hdl.IndexAppList) //首页-应用数据
} }

+ 71
- 8
app/svc/svc_data_center.go View File

@@ -23,7 +23,7 @@ func DataCenterTable(c *gin.Context, req md.DataCenterTableReq) md.DataCenterTab
tmp := md.DataCenterTableData{ tmp := md.DataCenterTableData{
Date: v["date"], Date: v["date"],
ExposureCount: v["exposure_count"], ExposureCount: v["exposure_count"],
MediaRevenue: v["media_revenue"],
MediaRevenue: utils.Float64ToStr(utils.StrToFloat64(v["media_revenue"]) / 100),
Ecpm: v["ecpm"], Ecpm: v["ecpm"],
} }
list = append(list, tmp) list = append(list, tmp)
@@ -39,7 +39,7 @@ func DataCenterRecordTotal(c *gin.Context, req md.DataCenterTableReq) md.DataCen
SELECT SELECT
SUM(exposure_count) as exposure_count, SUM(exposure_count) as exposure_count,
SUM(click_count) as click_count, SUM(click_count) as click_count,
SUM(click_rate) as click_rate,
SUM(click_count)/SUM(exposure_count)*100 as click_rate,
SUM(ecpm) as ecpm, SUM(ecpm) as ecpm,
SUM(media_revenue) as media_revenue SUM(media_revenue) as media_revenue
FROM generate_wx_ad_data FROM generate_wx_ad_data
@@ -68,9 +68,9 @@ func DataCenterRecordTotal(c *gin.Context, req md.DataCenterTableReq) md.DataCen
PlatformName: "-", PlatformName: "-",
AdvName: "-", AdvName: "-",
ExposureCount: v["exposure_count"], ExposureCount: v["exposure_count"],
MediaRevenue: v["media_revenue"],
Ecpm: v["ecpm"],
ClickRate: v["click_rate"],
MediaRevenue: utils.Float64ToStr(utils.StrToFloat64(v["media_revenue"]) / 100),
Ecpm: utils.Float64ToStr(utils.StrToFloat64(v["ecpm"]) / 100),
ClickRate: utils.GetPrec(v["click_rate"], "2"),
ClickCount: v["click_count"], ClickCount: v["click_count"],
} }
} }
@@ -94,8 +94,8 @@ func DataCenterRecordList(c *gin.Context, req md.DataCenterRecordReq) md.DataCen
PlatformName: md.AppletPlatformMap[platform], PlatformName: md.AppletPlatformMap[platform],
AdvName: enum.AdunitType(v["ad_slot"]).String(), AdvName: enum.AdunitType(v["ad_slot"]).String(),
ExposureCount: v["exposure_count"], ExposureCount: v["exposure_count"],
MediaRevenue: v["media_revenue"],
Ecpm: v["ecpm"],
MediaRevenue: utils.Float64ToStr(utils.StrToFloat64(v["media_revenue"]) / 100),
Ecpm: utils.Float64ToStr(utils.StrToFloat64(v["ecpm"]) / 100),
ClickRate: v["click_rate"], ClickRate: v["click_rate"],
ClickCount: v["click_count"], ClickCount: v["click_count"],
} }
@@ -107,6 +107,54 @@ func DataCenterRecordList(c *gin.Context, req md.DataCenterRecordReq) md.DataCen
} }
return res return res
} }
func DataCenterRecordOutPut(c *gin.Context, req md.DataCenterRecordOutPutReq) {
var req1 md.DataCenterRecordReq
copier.Copy(&req1, &req)
req.Limit = "10000"
nativeString, _ := comm(c, 0, req1)
appId := make([]string, 0)
for _, v := range nativeString {
appId = append(appId, v["app_id"])
}
var app []model2.AppletApplication
appMap := make(map[string]model2.AppletApplication)
MasterDb(c).In("app_id=?", appId).Find(&app)
for _, v := range app {
appMap[v.AppId] = v
}
name := req.StartDate + "~" + req.EndDate + "-第" + req.Page + "页"
//写入数据
data := map[string]string{
"A1": "日期",
"B1": "应用名称",
"C1": "平台类型",
"D1": "广告位",
"E1": "曝光量",
"F1": "点击量",
"G1": "ECPM",
"H1": "预估收益",
}
for k, v := range nativeString {
i := utils.IntToStr(k + 2)
data["A"+i] = v["date"]
data["B"+i] = appMap[v["app_id"]].Name
data["C"+i] = md.AppletPlatformMap[appMap[v["app_id"]].Platform]
data["D"+i] = enum.AdunitType(v["ad_slot"]).String()
data["E"+i] = v["exposure_count"]
data["F"+i] = v["click_count"]
data["G"+i] = utils.Float64ToStr(utils.StrToFloat64(v["ecpm"]) / 100)
data["H"+i] = utils.Float64ToStr(utils.StrToFloat64(v["media_revenue"]) / 100)
}

file := utils.Output(c, name, data)
filename := name + ".xlsx"
r := map[string]string{
"file": file,
"filename": filename,
}
e.OutSuc(c, r, nil)
return
}
func comm(c *gin.Context, isTotal int, req md.DataCenterRecordReq) ([]map[string]string, int64) { func comm(c *gin.Context, isTotal int, req md.DataCenterRecordReq) ([]map[string]string, int64) {
appId := GetAppletId(c, req.AppId, req.Platform) appId := GetAppletId(c, req.AppId, req.Platform)
sql := ` sql := `
@@ -142,7 +190,7 @@ func comm(c *gin.Context, isTotal int, req md.DataCenterRecordReq) ([]map[string


var total int64 = 0 var total int64 = 0
if isTotal == 1 { if isTotal == 1 {
sqlTotal := fmt.Sprintf(sql, "COUNT(*) as count ", where)
sqlTotal := fmt.Sprintf(sql, "COUNT(*) as count ", where, "")
nativeStringTotal, _ := db.QueryNativeString(db.Db, sqlTotal) nativeStringTotal, _ := db.QueryNativeString(db.Db, sqlTotal)
for _, v := range nativeStringTotal { for _, v := range nativeStringTotal {
total = utils.StrToInt64(v["count"]) total = utils.StrToInt64(v["count"])
@@ -203,3 +251,18 @@ func GetAppletId(c *gin.Context, appId, platform string) string {
} }
return mediumId return mediumId
} }
func GetAppletInfo(c *gin.Context, id string) map[string]string {
var res = map[string]string{
"platform": "",
"name": "",
"logo": "",
}
NewAppletApplicationDb := implement.NewAppletApplicationDb(MasterDb(c))
data, _ := NewAppletApplicationDb.GetAppletApplicationListByAppid(id)
if data != nil {
res["platform"] = data.Platform
res["name"] = data.Name
res["logo"] = data.Logo
}
return res
}

+ 122
- 0
app/svc/svc_index.go View File

@@ -0,0 +1,122 @@
package svc

import (
"applet/app/e"
"applet/app/md"
"applet/app/utils"
db "code.fnuoos.com/zhimeng/model.git/src"
"fmt"
"github.com/gin-gonic/gin"
"time"
)

func IndexTotal(c *gin.Context) {
yesterday := utils.GetTimeRange("yesterday")
yesterdayTotal := commTotal(c, time.Unix(yesterday["start"], 0).Format("2006-01-02"), time.Unix(yesterday["end"]-3600, 0).Format("2006-01-02"))
withinSevenDays := utils.GetTimeRange("new_within_seven_days")
withinSevenDaysTotal := commTotal(c, time.Unix(withinSevenDays["start"], 0).Format("2006-01-02"), time.Unix(withinSevenDays["end"]-3600, 0).Format("2006-01-02"))
currentMonth := utils.GetTimeRange("current_month")
currentMonthTotal := commTotal(c, time.Unix(currentMonth["start"], 0).Format("2006-01-02"), time.Unix(currentMonth["end"]-3600, 0).Format("2006-01-02"))
lastMonth := utils.GetTimeRange("last_month")
lastMonthTotal := commTotal(c, time.Unix(lastMonth["start"], 0).Format("2006-01-02"), time.Unix(lastMonth["end"]-3600, 0).Format("2006-01-02"))
res := []md.IndexAppListDataList{
{Name: "昨日收益", Type: "yesterday", Bili: "-%", Value: utils.Float64ToStr(utils.StrToFloat64(yesterdayTotal[0]["media_revenue"]) / 100)},
{Name: "七日收益", Type: "within_seven_days", Bili: "-%", Value: utils.Float64ToStr(utils.StrToFloat64(withinSevenDaysTotal[0]["media_revenue"]) / 100)},
{Name: "本月收益", Type: "current_month", Bili: "-%", Value: utils.Float64ToStr(utils.StrToFloat64(currentMonthTotal[0]["media_revenue"]) / 100)},
{Name: "上月收益", Type: "last_month", Bili: "-%", Value: utils.Float64ToStr(utils.StrToFloat64(lastMonthTotal[0]["media_revenue"]) / 100)},
}
e.OutSuc(c, res, nil)
return
}
func IndexAppList(c *gin.Context, req md.IndexAppListReq) md.IndexAppListRes {
data := commTotalByApp(c, req)
list := make([]md.IndexAppListData, 0)
for _, v := range data {
dataList := []md.IndexAppListDataList{
{Name: "广告预估收益", Type: "media_revenue", Bili: "-%", Value: utils.Float64ToStr(utils.StrToFloat64(v["media_revenue"]) / 100)},
{Name: "ECPM", Type: "ecpm", Bili: "-%", Value: v["ecpm"]},
{Name: "曝光量", Type: "exposure_count", Bili: "-%", Value: v["exposure_count"]},
{Name: "点击量", Type: "click_count", Bili: "-%", Value: v["click_count"]},
{Name: "点击率", Type: "click_rate", Bili: "-%", Value: utils.GetPrec(v["click_rate"], "2")},
}
applet := GetAppletInfo(c, v["app_id"])
tmp := md.IndexAppListData{
Name: applet["name"],
Logo: applet["logo"],
List: dataList,
TableList: []string{},
}
list = append(list, tmp)
}
res := md.IndexAppListRes{
List: list,
Sort: []md.SelectData{
{Name: "按收益最高", Value: "media_revenue desc"},
{Name: "按ECPM最高", Value: "ecpm desc"},
{Name: "按曝光量最高", Value: "exposure_count desc"},
},
}
return res
}
func commTotal(c *gin.Context, startDate, endDate string) []map[string]string {
sql := `
SELECT
SUM(exposure_count) as exposure_count,
SUM(click_count) as click_count,
SUM(click_rate) as click_rate,
SUM(ecpm) as ecpm,
SUM(media_revenue) as media_revenue
FROM generate_wx_ad_data
where %s
`
where := "uuid=" + c.GetString("mid")
if startDate != "" {
where += " and date>='" + startDate + "'"
}
if endDate != "" {
where += " and date<='" + endDate + "'"
}
sql = fmt.Sprintf(sql, where)
nativeString, _ := db.QueryNativeString(db.Db, sql)
if len(nativeString) == 0 {
nativeString = []map[string]string{
{
"media_revenue": "0",
},
}
}
return nativeString
}
func commTotalByApp(c *gin.Context, req md.IndexAppListReq) []map[string]string {
sql := `
SELECT
app_id as app_id,
SUM(exposure_count) as exposure_count,
SUM(click_count) as click_count,
SUM(click_count)/SUM(exposure_count)*100 as click_rate,
SUM(ecpm) as ecpm,
SUM(media_revenue) as media_revenue
FROM generate_wx_ad_data
where %s group by app_id order by %s,id asc limit 10
`
where := "uuid=" + c.GetString("mid")
if req.StartDate != "" {
where += " and date>='" + req.StartDate + "'"
}
if req.EndDate != "" {
where += " and date<='" + req.EndDate + "'"
}
if req.Sort == "" {
req.Sort = "media_revenue desc"
}
sql = fmt.Sprintf(sql, where, req.Sort)
nativeString, _ := db.QueryNativeString(db.Db, sql)
if len(nativeString) == 0 {
nativeString = []map[string]string{
{
"media_revenue": "0",
},
}
}
return nativeString
}

+ 52
- 0
app/utils/convert.go View File

@@ -320,3 +320,55 @@ func IntToStr(i int) string {
func Int64ToStr(i int64) string { func Int64ToStr(i int64) string {
return strconv.FormatInt(i, 10) return strconv.FormatInt(i, 10)
} }
func StrToFormat(s string, prec int) string {
ex := strings.Split(s, ".")
if len(ex) == 2 {
if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了
return ex[0]
}
//看取多少位
str := ex[1]
str1 := str
if prec < len(str) {
str1 = str[0:prec]
} else {
for i := 0; i < prec-len(str); i++ {
str1 += "0"
}
}
if prec > 0 {
return ex[0] + "." + str1
} else {
return ex[0]
}
}
return s
}
func Float64ToStrByPrec(f float64, prec int) string {
return strconv.FormatFloat(f, 'f', prec, 64)
}
func GetPrec(sum, commPrec string) string {
if sum == "" {
sum = "0"
}
sum = StrToFormat(sum, StrToInt(commPrec))
ex := strings.Split(sum, ".")
if len(ex) == 2 {
if StrToFloat64(ex[1]) == 0 {
sum = ex[0]
} else {
val := Float64ToStrByPrec(StrToFloat64(ex[1]), 0)
keyMax := 0
for i := 0; i < len(val); i++ {
ch := string(val[i])
fmt.Println(StrToInt(ch))
if StrToInt(ch) > 0 {
keyMax = i
}
}
valNew := val[0 : keyMax+1]
sum = ex[0] + "." + strings.ReplaceAll(ex[1], val, valNew)
}
}
return sum
}

+ 8
- 3
app/utils/time.go View File

@@ -167,6 +167,11 @@ func GetTimeRange(s string) map[string]int64 {
stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location()) stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location())
// 明天 0点 // 明天 0点
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location())
case "new_within_seven_days":
// 前7天0点
stime = time.Date(t.Year(), t.Month(), t.Day()-7, 0, 0, 0, 0, t.Location())
// 今日 0点
etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
case "current_month": case "current_month":
stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location())
etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location())
@@ -209,18 +214,18 @@ func GetDateTimeRangeStr(s string) (string, string) {
return stime.Format("2006-01-02 15:04:05"), etime.Format("2006-01-02 15:04:05") return stime.Format("2006-01-02 15:04:05"), etime.Format("2006-01-02 15:04:05")
} }


//获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。
// 获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。
func GetFirstDateOfMonth(d time.Time) time.Time { func GetFirstDateOfMonth(d time.Time) time.Time {
d = d.AddDate(0, 0, -d.Day()+1) d = d.AddDate(0, 0, -d.Day()+1)
return GetZeroTime(d) return GetZeroTime(d)
} }


//获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。
// 获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。
func GetLastDateOfMonth(d time.Time) time.Time { func GetLastDateOfMonth(d time.Time) time.Time {
return GetFirstDateOfMonth(d).AddDate(0, 1, -1) return GetFirstDateOfMonth(d).AddDate(0, 1, -1)
} }


//获取某一天的0点时间
// 获取某一天的0点时间
func GetZeroTime(d time.Time) time.Time { func GetZeroTime(d time.Time) time.Time {
return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location()) return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
} }

+ 36
- 0
app/utils/xls.go View File

@@ -0,0 +1,36 @@
package utils

import (
"bytes"
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
"github.com/gin-gonic/gin"
"io/ioutil"
)

func Output(c *gin.Context, name string, data map[string]string) string {
//创建excel文件
xlsx := excelize.NewFile()
//创建新表单
index := xlsx.NewSheet(name)
for k, v := range data {
//设置单元格的值
xlsx.SetCellValue(name, k, v)
}
//设置默认打开的表单
xlsx.SetActiveSheet(index)
////保存文件到指定路径
//err := xlsx.SaveAs("./" + name + ".xlsx")
//if err != nil {
// log.Fatal(err)
//}
//_ = file.Save(fileName)
c.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name+".xlsx"))
c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
var buffer bytes.Buffer
_ = xlsx.Write(&buffer)
r := bytes.NewReader(buffer.Bytes())
fSrc, _ := ioutil.ReadAll(r)
str := "data:application/vnd.ms-excel;base64," + Base64RawStdEncode(string(fSrc))
return str
}

+ 276
- 0
docs/docs.go View File

@@ -562,6 +562,53 @@ const docTemplate = `{
} }
} }
}, },
"/api/dataCenter/record/output": {
"post": {
"description": "数据中心-数据明细-导出",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"数据中心------嘉俊"
],
"summary": "数据明细-导出",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "请求参数",
"name": "args",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/md.DataCenterRecordOutPutReq"
}
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/dataCenter/record/total": { "/api/dataCenter/record/total": {
"post": { "post": {
"description": "数据中心-数据明细合计", "description": "数据中心-数据明细合计",
@@ -694,6 +741,129 @@ const docTemplate = `{
} }
} }
}, },
"/api/index/app/list": {
"post": {
"description": "数据中心-数据明细",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"数据中心------嘉俊"
],
"summary": "数据明细",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "请求参数",
"name": "args",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/md.IndexAppListReq"
}
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"$ref": "#/definitions/md.IndexAppListRes"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/index/base": {
"get": {
"description": "首页-右上角基本数据",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"首页------嘉俊"
],
"summary": "右上角基本数据",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/index/total": {
"get": {
"description": "首页-统计数据",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"首页------嘉俊"
],
"summary": "统计数据",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/invoiceCenter/detail": { "/api/invoiceCenter/detail": {
"post": { "post": {
"description": "发票中心-发票详情", "description": "发票中心-发票详情",
@@ -2224,6 +2394,38 @@ const docTemplate = `{
} }
} }
}, },
"md.DataCenterRecordOutPutReq": {
"type": "object",
"properties": {
"ad_type": {
"type": "string",
"example": "广告位类型"
},
"app_id": {
"type": "string",
"example": "应用"
},
"end_date": {
"type": "string",
"example": "2024-08-30"
},
"limit": {
"type": "string",
"example": "10000 个一页"
},
"page": {
"type": "string"
},
"platform": {
"type": "string",
"example": "平台"
},
"start_date": {
"type": "string",
"example": "2024-08-30"
}
}
},
"md.DataCenterRecordReq": { "md.DataCenterRecordReq": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2379,6 +2581,80 @@ const docTemplate = `{
} }
} }
}, },
"md.IndexAppListData": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/md.IndexAppListDataList"
}
},
"logo": {
"type": "string"
},
"name": {
"type": "string"
},
"table_list": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"md.IndexAppListDataList": {
"type": "object",
"properties": {
"bili": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"md.IndexAppListReq": {
"type": "object",
"properties": {
"end_date": {
"type": "string",
"example": "2024-08-30"
},
"sort": {
"type": "string",
"example": "排序"
},
"start_date": {
"type": "string",
"example": "2024-08-30"
}
}
},
"md.IndexAppListRes": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/md.IndexAppListData"
}
},
"sort": {
"type": "array",
"items": {
"$ref": "#/definitions/md.SelectData"
}
}
}
},
"md.Invoice": { "md.Invoice": {
"type": "object", "type": "object",
"properties": { "properties": {


+ 276
- 0
docs/swagger.json View File

@@ -554,6 +554,53 @@
} }
} }
}, },
"/api/dataCenter/record/output": {
"post": {
"description": "数据中心-数据明细-导出",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"数据中心------嘉俊"
],
"summary": "数据明细-导出",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "请求参数",
"name": "args",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/md.DataCenterRecordOutPutReq"
}
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/dataCenter/record/total": { "/api/dataCenter/record/total": {
"post": { "post": {
"description": "数据中心-数据明细合计", "description": "数据中心-数据明细合计",
@@ -686,6 +733,129 @@
} }
} }
}, },
"/api/index/app/list": {
"post": {
"description": "数据中心-数据明细",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"数据中心------嘉俊"
],
"summary": "数据明细",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
},
{
"description": "请求参数",
"name": "args",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/md.IndexAppListReq"
}
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"$ref": "#/definitions/md.IndexAppListRes"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/index/base": {
"get": {
"description": "首页-右上角基本数据",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"首页------嘉俊"
],
"summary": "右上角基本数据",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/index/total": {
"get": {
"description": "首页-统计数据",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"首页------嘉俊"
],
"summary": "统计数据",
"parameters": [
{
"type": "string",
"description": "验证参数Bearer和token空格拼接",
"name": "Authorization",
"in": "header",
"required": true
}
],
"responses": {
"200": {
"description": "具体看返回内容 这是data里面的数据",
"schema": {
"type": "string"
}
},
"400": {
"description": "具体错误",
"schema": {
"$ref": "#/definitions/md.Response"
}
}
}
}
},
"/api/invoiceCenter/detail": { "/api/invoiceCenter/detail": {
"post": { "post": {
"description": "发票中心-发票详情", "description": "发票中心-发票详情",
@@ -2216,6 +2386,38 @@
} }
} }
}, },
"md.DataCenterRecordOutPutReq": {
"type": "object",
"properties": {
"ad_type": {
"type": "string",
"example": "广告位类型"
},
"app_id": {
"type": "string",
"example": "应用"
},
"end_date": {
"type": "string",
"example": "2024-08-30"
},
"limit": {
"type": "string",
"example": "10000 个一页"
},
"page": {
"type": "string"
},
"platform": {
"type": "string",
"example": "平台"
},
"start_date": {
"type": "string",
"example": "2024-08-30"
}
}
},
"md.DataCenterRecordReq": { "md.DataCenterRecordReq": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2371,6 +2573,80 @@
} }
} }
}, },
"md.IndexAppListData": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/md.IndexAppListDataList"
}
},
"logo": {
"type": "string"
},
"name": {
"type": "string"
},
"table_list": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"md.IndexAppListDataList": {
"type": "object",
"properties": {
"bili": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"md.IndexAppListReq": {
"type": "object",
"properties": {
"end_date": {
"type": "string",
"example": "2024-08-30"
},
"sort": {
"type": "string",
"example": "排序"
},
"start_date": {
"type": "string",
"example": "2024-08-30"
}
}
},
"md.IndexAppListRes": {
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"$ref": "#/definitions/md.IndexAppListData"
}
},
"sort": {
"type": "array",
"items": {
"$ref": "#/definitions/md.SelectData"
}
}
}
},
"md.Invoice": { "md.Invoice": {
"type": "object", "type": "object",
"properties": { "properties": {


+ 184
- 0
docs/swagger.yaml View File

@@ -275,6 +275,29 @@ definitions:
example: 列表id example: 列表id
type: string type: string
type: object type: object
md.DataCenterRecordOutPutReq:
properties:
ad_type:
example: 广告位类型
type: string
app_id:
example: 应用
type: string
end_date:
example: "2024-08-30"
type: string
limit:
example: 10000 个一页
type: string
page:
type: string
platform:
example: 平台
type: string
start_date:
example: "2024-08-30"
type: string
type: object
md.DataCenterRecordReq: md.DataCenterRecordReq:
properties: properties:
ad_type: ad_type:
@@ -383,6 +406,55 @@ definitions:
description: 文件大小, 单位byte description: 文件大小, 单位byte
type: integer type: integer
type: object type: object
md.IndexAppListData:
properties:
list:
items:
$ref: '#/definitions/md.IndexAppListDataList'
type: array
logo:
type: string
name:
type: string
table_list:
items:
type: string
type: array
type: object
md.IndexAppListDataList:
properties:
bili:
type: string
name:
type: string
type:
type: string
value:
type: string
type: object
md.IndexAppListReq:
properties:
end_date:
example: "2024-08-30"
type: string
sort:
example: 排序
type: string
start_date:
example: "2024-08-30"
type: string
type: object
md.IndexAppListRes:
properties:
list:
items:
$ref: '#/definitions/md.IndexAppListData'
type: array
sort:
items:
$ref: '#/definitions/md.SelectData'
type: array
type: object
md.Invoice: md.Invoice:
properties: properties:
count: count:
@@ -1201,6 +1273,37 @@ paths:
summary: 数据明细 summary: 数据明细
tags: tags:
- 数据中心------嘉俊 - 数据中心------嘉俊
/api/dataCenter/record/output:
post:
consumes:
- application/json
description: 数据中心-数据明细-导出
parameters:
- description: 验证参数Bearer和token空格拼接
in: header
name: Authorization
required: true
type: string
- description: 请求参数
in: body
name: args
required: true
schema:
$ref: '#/definitions/md.DataCenterRecordOutPutReq'
produces:
- application/json
responses:
"200":
description: 具体看返回内容 这是data里面的数据
schema:
type: string
"400":
description: 具体错误
schema:
$ref: '#/definitions/md.Response'
summary: 数据明细-导出
tags:
- 数据中心------嘉俊
/api/dataCenter/record/total: /api/dataCenter/record/total:
post: post:
consumes: consumes:
@@ -1288,6 +1391,87 @@ paths:
summary: 数据图表 summary: 数据图表
tags: tags:
- 数据中心------嘉俊 - 数据中心------嘉俊
/api/index/app/list:
post:
consumes:
- application/json
description: 数据中心-数据明细
parameters:
- description: 验证参数Bearer和token空格拼接
in: header
name: Authorization
required: true
type: string
- description: 请求参数
in: body
name: args
required: true
schema:
$ref: '#/definitions/md.IndexAppListReq'
produces:
- application/json
responses:
"200":
description: 具体看返回内容 这是data里面的数据
schema:
$ref: '#/definitions/md.IndexAppListRes'
"400":
description: 具体错误
schema:
$ref: '#/definitions/md.Response'
summary: 数据明细
tags:
- 数据中心------嘉俊
/api/index/base:
get:
consumes:
- application/json
description: 首页-右上角基本数据
parameters:
- description: 验证参数Bearer和token空格拼接
in: header
name: Authorization
required: true
type: string
produces:
- application/json
responses:
"200":
description: 具体看返回内容 这是data里面的数据
schema:
type: string
"400":
description: 具体错误
schema:
$ref: '#/definitions/md.Response'
summary: 右上角基本数据
tags:
- 首页------嘉俊
/api/index/total:
get:
consumes:
- application/json
description: 首页-统计数据
parameters:
- description: 验证参数Bearer和token空格拼接
in: header
name: Authorization
required: true
type: string
produces:
- application/json
responses:
"200":
description: 具体看返回内容 这是data里面的数据
schema:
type: string
"400":
description: 具体错误
schema:
$ref: '#/definitions/md.Response'
summary: 统计数据
tags:
- 首页------嘉俊
/api/invoiceCenter/detail: /api/invoiceCenter/detail:
post: post:
consumes: consumes:


+ 4
- 1
go.mod View File

@@ -3,9 +3,10 @@ module applet
go 1.18 go 1.18


//replace code.fnuoos.com/zhimeng/model.git => E:/company/ad/models //replace code.fnuoos.com/zhimeng/model.git => E:/company/ad/models

// //
require ( require (
code.fnuoos.com/zhimeng/model.git v0.0.3-0.20240830085315-046c30582759
code.fnuoos.com/zhimeng/model.git v0.0.3-0.20240831024508-c37ec92bfc03
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
github.com/boombuler/barcode v1.0.1 github.com/boombuler/barcode v1.0.1
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5 github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5
@@ -37,6 +38,7 @@ require (


require ( require (
code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git v1.1.21-0.20240821062104-50d608c7fd6a code.fnuoos.com/go_rely_warehouse/zyos_go_third_party_api.git v1.1.21-0.20240821062104-50d608c7fd6a
github.com/360EntSecGroup-Skylar/excelize v1.4.1
github.com/jinzhu/copier v0.4.0 github.com/jinzhu/copier v0.4.0
) )


@@ -76,6 +78,7 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect


Loading…
Cancel
Save