From 401eaaaaba0451f52f2a4edfd96be63e8b15b982 Mon Sep 17 00:00:00 2001 From: chenlin Date: Fri, 7 Feb 2025 11:55:45 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E8=90=A5=E6=94=B6=E5=88=86=E6=9E=90?= =?UTF-8?q?=E3=80=81=E7=94=A8=E6=88=B7=E7=95=99=E5=AD=98=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E3=80=81=E4=BA=A4=E6=98=93=E6=B5=81=E6=B0=B4=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=AD=89=E6=8E=A5=E5=8F=A3=E5=A2=9E=E5=8A=A0excel=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=8A=9F=E8=83=BD=EF=BC=9B=202=E3=80=81=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E5=88=97=E8=A1=A8=E3=80=81=E4=BA=A4=E6=98=93=E6=B5=81?= =?UTF-8?q?=E6=B0=B4=E8=AE=B0=E5=BD=95=E5=AF=BC=E5=87=BAexcel=E6=97=B6?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=B6=E9=97=B4=E9=99=90=E5=88=B6=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/apis/migumanage/migu_admin.go | 90 +++++++- app/admin/models/migu.go | 280 +++++++++++++++++++++++- app/admin/router/migu.go | 2 +- docs/admin/admin_docs.go | 18 +- docs/admin/admin_swagger.json | 18 +- docs/admin/admin_swagger.yaml | 14 +- 6 files changed, 403 insertions(+), 19 deletions(-) diff --git a/app/admin/apis/migumanage/migu_admin.go b/app/admin/apis/migumanage/migu_admin.go index 11993a9..192873a 100644 --- a/app/admin/apis/migumanage/migu_admin.go +++ b/app/admin/apis/migumanage/migu_admin.go @@ -46,6 +46,15 @@ func (e MiGuDeployService) TransactionList(c *gin.Context) { PageNum: req.PageNum, } + // 导出excel时检查时间范围 + if req.IsExport == 1 { + err = models.CheckDateRange(req.StartTime, req.EndTime, 7) + if err != nil { + response.Error(c, http.StatusBadRequest, err, err.Error()) + return + } + } + pageNum := req.PageNum - 1 if pageNum < 0 { pageNum = 0 @@ -93,7 +102,11 @@ func (e MiGuDeployService) TransactionList(c *gin.Context) { } var transactionLogs []models.MgTransactionLog - err = qs.Order("created_at desc").Offset(pageNum * req.PageSize).Limit(req.PageSize).Find(&transactionLogs).Error + if req.IsExport == 1 { + err = qs.Order("created_at desc").Find(&transactionLogs).Error + } else { + err = qs.Order("created_at desc").Offset(pageNum * req.PageSize).Limit(req.PageSize).Find(&transactionLogs).Error + } if err != nil { logger.Errorf("TransactionList err:%#v", err) response.Error(c, http.StatusInternalServerError, err, "查询失败") @@ -103,6 +116,16 @@ func (e MiGuDeployService) TransactionList(c *gin.Context) { resp.List = transactionLogs resp.Count = int(count) + if req.IsExport == 1 { + url, err := models.ExportTransactionToExcel(transactionLogs, e.Orm) + if err != nil { + response.Error(c, http.StatusInternalServerError, err, "导出失败") + return + } + response.OK(c, map[string]string{"export_url": url}, "导出成功") + return + } + e.OK(resp, "") } @@ -268,6 +291,15 @@ func (e MiGuDeployService) OrderList(c *gin.Context) { fmt.Println("Orm is nil") } + // 导出excel时检查时间范围 + if req.IsExport == 1 { + err = models.CheckDateRange(req.StartTime, req.EndTime, 31) + if err != nil { + response.Error(c, http.StatusBadRequest, err, err.Error()) + return + } + } + qs := e.Orm.Model(&models.MgOrder{}) // 产品编号 if req.SkuCode != 0 { @@ -1419,6 +1451,16 @@ func (e MiGuDeployService) UserRetentionList(c *gin.Context) { resp.List = retentionList resp.Count = len(retentionList) // Count should reflect the actual number of entries + if req.IsExport == 1 { + url, err := models.ExportUserRetentionToExcel(retentionList, e.Orm) + if err != nil { + response.Error(c, http.StatusInternalServerError, err, "导出失败") + return + } + response.OK(c, map[string]string{"export_url": url}, "导出成功") + return + } + // 返回结果 response.OK(c, resp, "成功") } @@ -2039,21 +2081,32 @@ func (e MiGuDeployService) CalculateRevenueAnalysis(c *gin.Context) { query = query.Where("channel_code = ?", req.Channel) } - // 获取每个月的新用户数和有效用户数 + // 获取每个月的新用户数和有效用户数,以下代码是按退订时间超过1天来统计数据 var result []models.MonthlyRetention err = query. Select(`DATE_FORMAT(subscribe_time, '%Y-%m') AS month, - COUNT(DISTINCT phone_number) AS new_user_count, - COUNT(DISTINCT CASE - WHEN unsubscribe_time IS NULL OR TIMESTAMPDIFF(HOUR, subscribe_time, unsubscribe_time) > 24 - THEN phone_number END) AS valid_users_count`). + COUNT(DISTINCT phone_number) AS new_user_count, + COUNT(DISTINCT CASE + WHEN unsubscribe_time IS NULL OR TIMESTAMPDIFF(HOUR, subscribe_time, unsubscribe_time) > 24 + THEN phone_number END) AS valid_users_count`). Group("month"). Order("month"). Find(&result).Error - if err != nil { - response.Error(c, http.StatusInternalServerError, err, "查询失败") - return - } + + // 以下代码是按非1小时退订来统计数据 + //err = query. + // Select(`DATE_FORMAT(subscribe_time, '%Y-%m') AS month, + // COUNT(DISTINCT phone_number) AS new_user_count, + // COUNT(DISTINCT CASE + // WHEN is_one_hour_cancel != 1 + // THEN phone_number END) AS valid_users_count`). + // Group("month"). + // Order("month"). + // Find(&result).Error + //if err != nil { + // response.Error(c, http.StatusInternalServerError, err, "查询失败") + // return + //} // 查询每个月的上个月未退订用户数 for i := 0; i < len(result); i++ { @@ -2073,7 +2126,9 @@ func (e MiGuDeployService) CalculateRevenueAnalysis(c *gin.Context) { return } - result[i].ValidUsersCount += totalValidUsers + totalUnsubscribedUsers + result[i].RetainedUsersCount += totalValidUsers + totalUnsubscribedUsers + + result[i].TotalValidUsersCount = result[i].RetainedUsersCount + result[i].ValidUsersCount //// 获取当前记录的月份 //currentMonth := result[i].Month @@ -2102,7 +2157,7 @@ func (e MiGuDeployService) CalculateRevenueAnalysis(c *gin.Context) { totalValidUsers := 0 for _, data := range result { totalNewUserCount += data.NewUserCount - totalValidUsers += data.ValidUsersCount + totalValidUsers += data.TotalValidUsersCount } // 返回结果 @@ -2111,6 +2166,17 @@ func (e MiGuDeployService) CalculateRevenueAnalysis(c *gin.Context) { TotalValidUsers: totalValidUsers, // 添加有效用户数 MonthlyRetentionData: result, } + + if req.IsExport == 1 { + url, err := models.ExportRevenueAnalysisToExcel(resp, e.Orm) + if err != nil { + response.Error(c, http.StatusInternalServerError, err, "导出失败") + return + } + response.OK(c, map[string]string{"export_url": url}, "导出成功") + return + } + response.OK(c, resp, "查询成功") } diff --git a/app/admin/models/migu.go b/app/admin/models/migu.go index 912ee9c..d40729f 100644 --- a/app/admin/models/migu.go +++ b/app/admin/models/migu.go @@ -3,6 +3,7 @@ package models import ( "bytes" "encoding/json" + "errors" "fmt" "github.com/go-admin-team/go-admin-core/logger" "github.com/xuri/excelize/v2" @@ -344,6 +345,7 @@ type TransactionListReq struct { EndTime string `json:"end_time"` // 结束时间 PageNum int `json:"page_num"` // 页码 PageSize int `json:"page_size"` // 每页条数 + IsExport uint32 `json:"is_export"` // 1-导出 } // TransactionListResp 查询交易流水记录-出参 @@ -628,13 +630,16 @@ type RetentionMonthsReq struct { EndTime string `json:"end_time"` // 查询结束时间 ProductID int `json:"product_id"` // 产品ID Channel string `json:"channel"` // 渠道名称 + IsExport uint32 `json:"is_export"` // 1-导出 } // MonthlyRetention 表示每月留存数据 type MonthlyRetention struct { - Month string `json:"month"` // 年月 - NewUserCount int `json:"new_user_count"` // 新用户数 - ValidUsersCount int `json:"valid_users_count"` // 当月有效用户数 + Month string `json:"month"` // 年月 + NewUserCount int `json:"new_user_count"` // 新用户数 + ValidUsersCount int `json:"valid_users_count"` // 当月新增有效用户数 + RetainedUsersCount int `json:"retained_users_count"` // 历史推广用户本月留存数 + TotalValidUsersCount int `json:"total_valid_users_count"` // 总有效用户数 } // RetentionMonthsResp 表示响应参数结构体 @@ -1781,3 +1786,272 @@ func ExportHourSummaryToExcel(data []MgHourSummary, sumData TotalHourSummary, db return url, nil } + +// ExportRevenueAnalysisToExcel 营收分析数据导出excel +func ExportRevenueAnalysisToExcel(data RetentionMonthsResp, db *gorm.DB) (string, error) { + // 创建一个新的Excel文件 + file := excelize.NewFile() + sheet := "Sheet1" + + // 设置标题栏 + titles := []string{"年月", "新用户数", "当月新增有效用户数", "历史推广用户本月留存数", "总有效用户数"} + for i, title := range titles { + cell, _ := excelize.CoordinatesToCellName(i+1, 1) + file.SetCellValue(sheet, cell, title) + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + // 设置单元格高度 + file.SetRowHeight(sheet, 1, 20) + + // 设置列宽 + file.SetColWidth(sheet, "A", "A", 15) + file.SetColWidth(sheet, "B", "B", 15) + file.SetColWidth(sheet, "C", "C", 20) + file.SetColWidth(sheet, "D", "D", 20) + file.SetColWidth(sheet, "E", "E", 18) + + // 填充数据 + for i, record := range data.MonthlyRetentionData { + row := i + 2 + file.SetCellValue(sheet, "A"+strconv.Itoa(row), record.Month) + file.SetCellValue(sheet, "B"+strconv.Itoa(row), record.NewUserCount) + file.SetCellValue(sheet, "C"+strconv.Itoa(row), record.ValidUsersCount) + file.SetCellValue(sheet, "D"+strconv.Itoa(row), record.RetainedUsersCount) + file.SetCellValue(sheet, "E"+strconv.Itoa(row), record.TotalValidUsersCount) + } + + // 填充合计行数据 + file.SetCellValue(sheet, "A"+strconv.Itoa(len(data.MonthlyRetentionData)+2), "合计:") + file.SetCellValue(sheet, "B"+strconv.Itoa(len(data.MonthlyRetentionData)+2), data.TotalNewUsers) + file.SetCellValue(sheet, "C"+strconv.Itoa(len(data.MonthlyRetentionData)+2), "--") + file.SetCellValue(sheet, "D"+strconv.Itoa(len(data.MonthlyRetentionData)+2), "--") + file.SetCellValue(sheet, "E"+strconv.Itoa(len(data.MonthlyRetentionData)+2), data.TotalValidUsers) + + endRow := fmt.Sprintf("E%d", len(data.MonthlyRetentionData)+2) + // 应用样式到整个表格 + _ = file.SetCellStyle(sheet, "A1", endRow, style) + + // 从配置文件读取保存路径和URL前缀 + fileName := time.Now().Format("20060102150405") + "_营收分析.xlsx" + url := MiGuExportUrl + fileName + + // 保存Excel文件 + if err := file.SaveAs(ExportFile + fileName); err != nil { + logger.Errorf("Failed to save Excel file: %v", err) + return "", err + } + + return url, nil +} + +// CheckDateRange 检查时间间隔是否超过 n 天 +func CheckDateRange(start, end string, nDay int) error { + if start == "" || end == "" { + return errors.New("导出失败,时间不能为空") + } + + // 解析时间,假设时间格式为 "2006-01-02" + startTime, err := time.Parse(MiGuTimeFormat, start) + if err != nil { + return errors.New("开始时间格式错误") + } + endTime, err := time.Parse(MiGuTimeFormat, end) + if err != nil { + return errors.New("结束时间格式错误") + } + + // 计算时间间隔 + if endTime.Sub(startTime).Hours() > float64(nDay*24) { + return errors.New(fmt.Sprintf("导出时间间隔不能超过 %d 天", nDay)) + } + + return nil +} + +// ExportUserRetentionToExcel 用户留存记录导出excel +func ExportUserRetentionToExcel(data []MgUserRetention, db *gorm.DB) (string, error) { + // 创建一个新的Excel文件 + file := excelize.NewFile() + sheet := "Sheet1" + + lastMonthFirstDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Local) // 当前月1号 + lastTwoMonthFirstDay := lastMonthFirstDay.AddDate(0, -1, 0) // 上个月1号 + + lastMonthCountTitle := lastMonthFirstDay.Format("2006-01-02") + "留存数" + lastMonthRateTitle := lastMonthFirstDay.Format("2006-01-02") + "留存率" + + lastTwoMonthCountTitle := lastTwoMonthFirstDay.Format("2006-01-02") + "留存数" + lastTwoMonthRateTitle := lastTwoMonthFirstDay.Format("2006-01-02") + "留存率" + + // 设置标题栏 + titles := []string{"留存月份", "渠道", "产品", "新增数", "留存数", "留存率", lastTwoMonthCountTitle, lastTwoMonthRateTitle, + lastMonthCountTitle, lastMonthRateTitle} + for i, title := range titles { + cell, _ := excelize.CoordinatesToCellName(i+1, 1) + file.SetCellValue(sheet, cell, title) + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + // 设置单元格高度 + file.SetRowHeight(sheet, 1, 20) + + // 设置列宽 + file.SetColWidth(sheet, "A", "A", 15) + file.SetColWidth(sheet, "B", "B", 15) + file.SetColWidth(sheet, "C", "C", 18) + file.SetColWidth(sheet, "D", "D", 15) + file.SetColWidth(sheet, "E", "E", 15) + file.SetColWidth(sheet, "F", "F", 15) + file.SetColWidth(sheet, "G", "G", 18) + file.SetColWidth(sheet, "H", "H", 18) + file.SetColWidth(sheet, "I", "I", 18) + file.SetColWidth(sheet, "J", "J", 18) + + // 创建一个产品ID到名称的映射 + productMap := make(map[int64]string) + for _, order := range data { + if _, exists := productMap[order.ProductID]; !exists { + var product MgProduct + // 查询产品信息 + if err := db.First(&product, order.ProductID).Error; err == nil { + productMap[order.ProductID] = product.Name + } else { + productMap[order.ProductID] = "未知产品" + } + } + } + + // 填充数据 + for i, record := range data { + row := i + 2 + productName := productMap[record.ProductID] // 获取产品名称 + file.SetCellValue(sheet, "A"+strconv.Itoa(row), record.RetentionMonth) + file.SetCellValue(sheet, "B"+strconv.Itoa(row), record.ChannelCode) + file.SetCellValue(sheet, "C"+strconv.Itoa(row), productName) + file.SetCellValue(sheet, "D"+strconv.Itoa(row), record.NewUserCount) + file.SetCellValue(sheet, "E"+strconv.Itoa(row), record.RetainedUserCount) + file.SetCellValue(sheet, "F"+strconv.Itoa(row), record.RetentionRate) + file.SetCellValue(sheet, "G"+strconv.Itoa(row), record.LastTwoMonthRetentionCount) + file.SetCellValue(sheet, "H"+strconv.Itoa(row), record.LastTwoMonthRetentionRate) + file.SetCellValue(sheet, "I"+strconv.Itoa(row), record.LastMonthRetentionCount) + file.SetCellValue(sheet, "J"+strconv.Itoa(row), record.LastMonthRetentionRate) + } + + endRow := fmt.Sprintf("J%d", len(data)+1) + // 应用样式到整个表格 + _ = file.SetCellStyle(sheet, "A1", endRow, style) + + // 从配置文件读取保存路径和URL前缀 + fileName := time.Now().Format("20060102150405") + "_用户留存记录.xlsx" + url := MiGuExportUrl + fileName + + // 保存Excel文件 + if err := file.SaveAs(ExportFile + fileName); err != nil { + logger.Errorf("Failed to save Excel file: %v", err) + return "", err + } + + return url, nil +} + +// ExportTransactionToExcel 交易流水记录导出excel +func ExportTransactionToExcel(data []MgTransactionLog, db *gorm.DB) (string, error) { + // 创建一个新的Excel文件 + file := excelize.NewFile() + sheet := "Sheet1" + + // 设置标题栏 + titles := []string{"调用时间", "产品", "渠道", "手机号", "平台订单号", "外部平台订单号", "渠道订单号", "结果", "原因", + "验证码", "订单时间"} + for i, title := range titles { + cell, _ := excelize.CoordinatesToCellName(i+1, 1) + file.SetCellValue(sheet, cell, title) + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + // 设置单元格高度 + file.SetRowHeight(sheet, 1, 20) + + // 设置列宽 + file.SetColWidth(sheet, "A", "A", 18) + file.SetColWidth(sheet, "B", "B", 18) + file.SetColWidth(sheet, "C", "C", 15) + file.SetColWidth(sheet, "D", "D", 15) + file.SetColWidth(sheet, "E", "E", 20) + file.SetColWidth(sheet, "F", "F", 20) + file.SetColWidth(sheet, "G", "G", 28) + file.SetColWidth(sheet, "I", "I", 28) + file.SetColWidth(sheet, "K", "K", 18) + + // 创建一个产品ID到名称的映射 + productMap := make(map[int64]string) + for _, order := range data { + if _, exists := productMap[order.ProductID]; !exists { + var product MgProduct + // 查询产品信息 + if err := db.First(&product, order.ProductID).Error; err == nil { + productMap[order.ProductID] = product.Name + } else { + productMap[order.ProductID] = "未知产品" + } + } + } + + // 填充数据 + for i, record := range data { + row := i + 2 + var orderTime string + if record.OrderTime == nil { + orderTime = "" + } else { + orderTime = record.OrderTime.Format(MiGuTimeFormat) + } + productName := productMap[record.ProductID] // 获取产品名称 + file.SetCellValue(sheet, "A"+strconv.Itoa(row), record.CreatedAt.Format(MiGuTimeFormat)) + file.SetCellValue(sheet, "B"+strconv.Itoa(row), productName) + file.SetCellValue(sheet, "C"+strconv.Itoa(row), record.ChannelCode) + file.SetCellValue(sheet, "D"+strconv.Itoa(row), record.PhoneNumber) + file.SetCellValue(sheet, "E"+strconv.Itoa(row), record.OutTradeNo) + file.SetCellValue(sheet, "F"+strconv.Itoa(row), record.LinkId) + file.SetCellValue(sheet, "G"+strconv.Itoa(row), record.ChannelTradeNo) + file.SetCellValue(sheet, "H"+strconv.Itoa(row), record.Result) + file.SetCellValue(sheet, "I"+strconv.Itoa(row), record.Reason) + file.SetCellValue(sheet, "J"+strconv.Itoa(row), record.VerificationCode) + file.SetCellValue(sheet, "K"+strconv.Itoa(row), orderTime) + } + + endRow := fmt.Sprintf("K%d", len(data)+2) + // 应用样式到整个表格 + _ = file.SetCellStyle(sheet, "A1", endRow, style) + + // 从配置文件读取保存路径和URL前缀 + fileName := time.Now().Format("20060102150405") + "_交易流水记录.xlsx" + url := MiGuExportUrl + fileName + + // 保存Excel文件 + if err := file.SaveAs(ExportFile + fileName); err != nil { + logger.Errorf("Failed to save Excel file: %v", err) + return "", err + } + + return url, nil +} diff --git a/app/admin/router/migu.go b/app/admin/router/migu.go index c864b6a..236b48e 100644 --- a/app/admin/router/migu.go +++ b/app/admin/router/migu.go @@ -30,7 +30,7 @@ func registerMiGuControlManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gi api.POST("user_day_retention/list", apiMiGu.UserDayRetentionList) // 用户留存记录(按天) api.POST("sys_channel/list", apiMiGu.SysChannelList) // 查询系统所有渠道编码 api.POST("home/data", apiMiGu.HomepageDataSummary) // 查询首页汇总数据 - api.POST("home/revenue_analysis", apiMiGu.CalculateRevenueAnalysis) // 查询不同日期的留存月份 + api.POST("home/revenue_analysis", apiMiGu.CalculateRevenueAnalysis) // 营收分析 api.POST("historical_summary/list", apiMiGu.HistoricalSummaryListOld) // 历史汇总查询 //api.POST("order/import", apiMiGu.ImportExcelToMgOrderHandler) // 通过excel导入订单数据 diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index 8368f53..f33e6d7 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -5408,8 +5408,16 @@ const docTemplateadmin = `{ "description": "新用户数", "type": "integer" }, + "retained_users_count": { + "description": "历史推广用户本月留存数", + "type": "integer" + }, + "total_valid_users_count": { + "description": "总有效用户数", + "type": "integer" + }, "valid_users_count": { - "description": "当月有效用户数", + "description": "当月新增有效用户数", "type": "integer" } } @@ -5969,6 +5977,10 @@ const docTemplateadmin = `{ "description": "渠道号", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "only_first_day": { "description": "是否只查询每个月1号的数据", "type": "boolean" @@ -6018,6 +6030,10 @@ const docTemplateadmin = `{ "description": "渠道号", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "page_num": { "description": "页码", "type": "integer" diff --git a/docs/admin/admin_swagger.json b/docs/admin/admin_swagger.json index dde54bf..329f581 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -5400,8 +5400,16 @@ "description": "新用户数", "type": "integer" }, + "retained_users_count": { + "description": "历史推广用户本月留存数", + "type": "integer" + }, + "total_valid_users_count": { + "description": "总有效用户数", + "type": "integer" + }, "valid_users_count": { - "description": "当月有效用户数", + "description": "当月新增有效用户数", "type": "integer" } } @@ -5961,6 +5969,10 @@ "description": "渠道号", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "only_first_day": { "description": "是否只查询每个月1号的数据", "type": "boolean" @@ -6010,6 +6022,10 @@ "description": "渠道号", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "page_num": { "description": "页码", "type": "integer" diff --git a/docs/admin/admin_swagger.yaml b/docs/admin/admin_swagger.yaml index 60df94c..f72ea89 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -1402,8 +1402,14 @@ definitions: new_user_count: description: 新用户数 type: integer + retained_users_count: + description: 历史推广用户本月留存数 + type: integer + total_valid_users_count: + description: 总有效用户数 + type: integer valid_users_count: - description: 当月有效用户数 + description: 当月新增有效用户数 type: integer type: object models.OrderListReq: @@ -1789,6 +1795,9 @@ definitions: channel: description: 渠道号 type: string + is_export: + description: 1-导出 + type: integer only_first_day: description: 是否只查询每个月1号的数据 type: boolean @@ -1827,6 +1836,9 @@ definitions: channel: description: 渠道号 type: string + is_export: + description: 1-导出 + type: integer page_num: description: 页码 type: integer