From 2eb326eb0a6b990f33aab7a91823077a2b31ee4b Mon Sep 17 00:00:00 2001 From: chenlin Date: Mon, 14 Apr 2025 17:06:07 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=8E=86=E5=8F=B2=E6=B1=87=E6=80=BB?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=96=B0=E5=A2=9E24=E5=B0=8F=E6=97=B6?= =?UTF-8?q?=E9=80=80=E8=AE=A2=E6=95=B0=E5=92=8C=E9=80=80=E8=AE=A2=E7=8E=87?= =?UTF-8?q?=EF=BC=8C=E5=AF=B9=E5=BA=94excel=E8=B0=83=E6=95=B4=EF=BC=9B=202?= =?UTF-8?q?=E3=80=81=E8=AE=A2=E5=8D=95=E8=A1=A8=E6=96=B0=E5=A2=9E=E7=8A=B6?= =?UTF-8?q?=E6=80=814-24=E5=B0=8F=E6=97=B6=E9=80=80=E8=AE=A2=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=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 | 449 +++++++++++++----------- app/admin/models/migu.go | 40 ++- app/admin/router/migu.go | 2 +- docs/admin/admin_docs.go | 16 + docs/admin/admin_swagger.json | 16 + docs/admin/admin_swagger.yaml | 12 + 6 files changed, 303 insertions(+), 232 deletions(-) diff --git a/app/admin/apis/migumanage/migu_admin.go b/app/admin/apis/migumanage/migu_admin.go index c3a3524..4866bcd 100644 --- a/app/admin/apis/migumanage/migu_admin.go +++ b/app/admin/apis/migumanage/migu_admin.go @@ -1,16 +1,13 @@ package migumanage import ( - "encoding/csv" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk/pkg/response" "go-admin/app/admin/models" - "go-admin/tools" "gorm.io/gorm" - "io" "net/http" "sort" "strconv" @@ -336,6 +333,10 @@ func (e MiGuDeployService) OrderList(c *gin.Context) { if req.State != 0 { if req.State == 3 { // 1小时内退订 qs = qs.Where("is_one_hour_cancel = ?", 1) + } else if req.State == 4 { + // 查询退订状态为2,且退订时间与订购时间在24小时内 + qs = qs.Where("state = ?", 2) + qs = qs.Where("TIMESTAMPDIFF(HOUR, subscribe_time, unsubscribe_time) <= 24") } else { state := 1 // 订阅 if req.State == 1 { @@ -508,10 +509,12 @@ func (e MiGuDeployService) HistoricalSummaryListOld(c *gin.Context) { IFNULL(submission_count.submission_count, 0) AS submission_count, COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) AS new_user_unsub_within_hour, COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) AS new_user_unsub_on_day, + COUNT(CASE WHEN mg_order.state = 2 AND TIMESTAMPDIFF(HOUR, mg_order.subscribe_time, mg_order.unsubscribe_time) <= 24 THEN 1 END) AS new_user_unsub_within_24h, COUNT(*) AS new_user_count, SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) AS total_new_user_unsub, CONCAT(ROUND(COUNT(CASE WHEN mg_order.is_one_hour_cancel = 1 THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_within_hour_rate, CONCAT(ROUND(COUNT(CASE WHEN mg_order.state = 2 AND DATE(mg_order.unsubscribe_time) = DATE(mg_order.subscribe_time) THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_on_day_rate, + CONCAT(ROUND(COUNT(CASE WHEN mg_order.state = 2 AND TIMESTAMPDIFF(HOUR, mg_order.subscribe_time, mg_order.unsubscribe_time) <= 24 THEN 1 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS new_user_unsub_within_24h_rate, CONCAT(ROUND(SUM(CASE WHEN mg_order.state = 2 THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(*), 0), 2), '%') AS total_new_user_unsub_rate, IFNULL( CONCAT( @@ -2667,215 +2670,215 @@ func (e MiGuDeployService) AddProduct(c *gin.Context) { // e.OK("", "删除成功") //} -// ImportExcelToMgOrderHandler 处理Excel文件导入请求 -// @Summary 导入订单Excel文件 -// @Tags 2024-咪咕-管理后台 -// @Accept multipart/form-data -// @Produce json -// @Param file formData file true "Excel文件" -// @Success 200 {object} map[string]string{"message": "导入成功"} -// @Router /api/v1/admin/order/import [post] -func (e MiGuDeployService) ImportExcelToMgOrderHandler(c *gin.Context) { - err := e.MakeContext(c).MakeOrm().Errors - if err != nil { - e.Logger.Error(err) - response.Error(c, http.StatusInternalServerError, err, "创建上下文失败") - return - } - - // 从请求中获取文件 - file, err := c.FormFile("file") - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"}) - return - } - - // 打开上传的文件 - fileStream, err := file.Open() - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"}) - return - } - defer fileStream.Close() - - // 创建 CSV 阅读器 - reader := csv.NewReader(fileStream) - reader.LazyQuotes = true - - // 跳过 CSV 文件的标题行 - if _, err := reader.Read(); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"}) - return - } - - //nRow := 0 - // 逐行读取 CSV 并插入数据库 - for { - //nRow++ - row, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"}) - return - } - - // 检查数据是否齐全 - if len(row) < 3 { - continue // 跳过数据不全的行 - } - - // 解析订阅时间 - subscribeTime, err := time.Parse("2006-01-02 15:04:05", row[1]) - if err != nil { - fmt.Printf("解析时间错误: %v\n", err) - continue - } - - //const cutoffTimeStr = "2024-10-18 18:58:00" - //cutoffTime, _ := time.Parse("2006-01-02 15:04:05", cutoffTimeStr) - //// 判断是否超过截止时间 - //if subscribeTime.After(cutoffTime) { - // fmt.Printf("跳过超过截止时间的记录: %v\n", subscribeTime) - // continue - //} - - // 将时间转换为 UTC+08:00 - // 将时间往前推8小时 - localTime := subscribeTime.Add(-8 * time.Hour) - - tempOrderNo := models.GetExcelOrderSerial(e.Orm, subscribeTime) - - // 创建MgOrder对象 - order := models.MgOrderCopy{ - ProductID: 2, - ChannelCode: "00211NV", - OrderSerial: tempOrderNo, - SubscribeTime: &localTime, - PhoneNumber: row[0], - ChannelTradeNo: tempOrderNo, - ExternalOrderID: tempOrderNo, - State: 1, - } - - if row[2] == "未包月" { // 1小时内退订 - order.IsOneHourCancel = 1 - order.State = 2 - unsubscribeTime := localTime.Add(30 * time.Minute) - order.UnsubscribeTime = &unsubscribeTime - } - - order.CreatedAt = localTime - order.UpdatedAt = localTime - order.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, order.PhoneNumber) - - // 插入到数据库 - if err := e.Orm.Create(&order).Error; err != nil { - fmt.Printf("插入订单数据失败: %v\n", err) - continue - } - - fmt.Println("order is:", order) - //if nRow > 4 { - // break - //} - } - - // 返回成功消息 - c.JSON(http.StatusOK, gin.H{"message": "导入成功"}) -} - -// ImportExcelToMgOrderHandlerUpdate 处理Excel文件导入请求 -// @Summary 导入订单Excel退订文件 -// @Tags 2024-咪咕-管理后台 -// @Accept multipart/form-data -// @Produce json -// @Param file formData file true "Excel文件" -// @Success 200 {object} map[string]string{"message": "导入成功"} -// @Router /api/v1/admin/order/import_update [post] -func (e MiGuDeployService) ImportExcelToMgOrderHandlerUpdate(c *gin.Context) { - err := e.MakeContext(c).MakeOrm().Errors - if err != nil { - e.Logger.Error(err) - response.Error(c, http.StatusInternalServerError, err, "创建上下文失败") - return - } - - // 从请求中获取文件 - file, err := c.FormFile("file") - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"}) - return - } - - // 打开上传的文件 - fileStream, err := file.Open() - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"}) - return - } - defer fileStream.Close() - - // 创建 CSV 阅读器 - reader := csv.NewReader(fileStream) - reader.LazyQuotes = true - - // 跳过 CSV 文件的标题行 - if _, err := reader.Read(); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"}) - return - } - - //nRow := 0 - // 逐行读取 CSV 并插入数据库 - for { - //nRow++ - row, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"}) - return - } - - // 检查数据是否齐全 - if len(row) < 3 { - continue // 跳过数据不全的行 - } - - // 将时间往前推8小时 - //localTime := subscribeTime.Add(-8 * time.Hour) - - if !(row[0] != "" && len(row[0]) == 11) { - continue - } - - if row[0] == "15812800163" { - fmt.Println("found phone number: 15812800163") - break - } - - unsubscribeTime, _ := models.ConvertStringToTime(row[2]) - - err = e.Orm.Table("mg_order_copy").Where("phone_number = ?", row[0]).Updates(map[string]interface{}{ - "state": models.UnsubscribeOK, - "unsubscribe_time": unsubscribeTime, - "updated_at": unsubscribeTime, - }).Error - if err != nil { - fmt.Println("CheckOrderState update mg_order err:", err.Error()) - continue - } - //if nRow > 4 { - // break - //} - } - - // 返回成功消息 - c.JSON(http.StatusOK, gin.H{"message": "导入成功"}) -} +//// ImportExcelToMgOrderHandler 处理Excel文件导入请求 +//// @Summary 导入订单Excel文件 +//// @Tags 2024-咪咕-管理后台 +//// @Accept multipart/form-data +//// @Produce json +//// @Param file formData file true "Excel文件" +//// @Success 200 {object} map[string]string{"message": "导入成功"} +//// @Router /api/v1/admin/order/import [post] +//func (e MiGuDeployService) ImportExcelToMgOrderHandler(c *gin.Context) { +// err := e.MakeContext(c).MakeOrm().Errors +// if err != nil { +// e.Logger.Error(err) +// response.Error(c, http.StatusInternalServerError, err, "创建上下文失败") +// return +// } +// +// // 从请求中获取文件 +// file, err := c.FormFile("file") +// if err != nil { +// c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"}) +// return +// } +// +// // 打开上传的文件 +// fileStream, err := file.Open() +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"}) +// return +// } +// defer fileStream.Close() +// +// // 创建 CSV 阅读器 +// reader := csv.NewReader(fileStream) +// reader.LazyQuotes = true +// +// // 跳过 CSV 文件的标题行 +// if _, err := reader.Read(); err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"}) +// return +// } +// +// //nRow := 0 +// // 逐行读取 CSV 并插入数据库 +// for { +// //nRow++ +// row, err := reader.Read() +// if err == io.EOF { +// break +// } +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"}) +// return +// } +// +// // 检查数据是否齐全 +// if len(row) < 3 { +// continue // 跳过数据不全的行 +// } +// +// // 解析订阅时间 +// subscribeTime, err := time.Parse("2006-01-02 15:04:05", row[1]) +// if err != nil { +// fmt.Printf("解析时间错误: %v\n", err) +// continue +// } +// +// //const cutoffTimeStr = "2024-10-18 18:58:00" +// //cutoffTime, _ := time.Parse("2006-01-02 15:04:05", cutoffTimeStr) +// //// 判断是否超过截止时间 +// //if subscribeTime.After(cutoffTime) { +// // fmt.Printf("跳过超过截止时间的记录: %v\n", subscribeTime) +// // continue +// //} +// +// // 将时间转换为 UTC+08:00 +// // 将时间往前推8小时 +// localTime := subscribeTime.Add(-8 * time.Hour) +// +// tempOrderNo := models.GetExcelOrderSerial(e.Orm, subscribeTime) +// +// // 创建MgOrder对象 +// order := models.MgOrderCopy{ +// ProductID: 2, +// ChannelCode: "00211NV", +// OrderSerial: tempOrderNo, +// SubscribeTime: &localTime, +// PhoneNumber: row[0], +// ChannelTradeNo: tempOrderNo, +// ExternalOrderID: tempOrderNo, +// State: 1, +// } +// +// if row[2] == "未包月" { // 1小时内退订 +// order.IsOneHourCancel = 1 +// order.State = 2 +// unsubscribeTime := localTime.Add(30 * time.Minute) +// order.UnsubscribeTime = &unsubscribeTime +// } +// +// order.CreatedAt = localTime +// order.UpdatedAt = localTime +// order.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, order.PhoneNumber) +// +// // 插入到数据库 +// if err := e.Orm.Create(&order).Error; err != nil { +// fmt.Printf("插入订单数据失败: %v\n", err) +// continue +// } +// +// fmt.Println("order is:", order) +// //if nRow > 4 { +// // break +// //} +// } +// +// // 返回成功消息 +// c.JSON(http.StatusOK, gin.H{"message": "导入成功"}) +//} +// +//// ImportExcelToMgOrderHandlerUpdate 处理Excel文件导入请求 +//// @Summary 导入订单Excel退订文件 +//// @Tags 2024-咪咕-管理后台 +//// @Accept multipart/form-data +//// @Produce json +//// @Param file formData file true "Excel文件" +//// @Success 200 {object} map[string]string{"message": "导入成功"} +//// @Router /api/v1/admin/order/import_update [post] +//func (e MiGuDeployService) ImportExcelToMgOrderHandlerUpdate(c *gin.Context) { +// err := e.MakeContext(c).MakeOrm().Errors +// if err != nil { +// e.Logger.Error(err) +// response.Error(c, http.StatusInternalServerError, err, "创建上下文失败") +// return +// } +// +// // 从请求中获取文件 +// file, err := c.FormFile("file") +// if err != nil { +// c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取文件"}) +// return +// } +// +// // 打开上传的文件 +// fileStream, err := file.Open() +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开文件"}) +// return +// } +// defer fileStream.Close() +// +// // 创建 CSV 阅读器 +// reader := csv.NewReader(fileStream) +// reader.LazyQuotes = true +// +// // 跳过 CSV 文件的标题行 +// if _, err := reader.Read(); err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "无法读取CSV标题行"}) +// return +// } +// +// //nRow := 0 +// // 逐行读取 CSV 并插入数据库 +// for { +// //nRow++ +// row, err := reader.Read() +// if err == io.EOF { +// break +// } +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "读取CSV文件失败"}) +// return +// } +// +// // 检查数据是否齐全 +// if len(row) < 3 { +// continue // 跳过数据不全的行 +// } +// +// // 将时间往前推8小时 +// //localTime := subscribeTime.Add(-8 * time.Hour) +// +// if !(row[0] != "" && len(row[0]) == 11) { +// continue +// } +// +// if row[0] == "15812800163" { +// fmt.Println("found phone number: 15812800163") +// break +// } +// +// unsubscribeTime, _ := models.ConvertStringToTime(row[2]) +// +// err = e.Orm.Table("mg_order_copy").Where("phone_number = ?", row[0]).Updates(map[string]interface{}{ +// "state": models.UnsubscribeOK, +// "unsubscribe_time": unsubscribeTime, +// "updated_at": unsubscribeTime, +// }).Error +// if err != nil { +// fmt.Println("CheckOrderState update mg_order err:", err.Error()) +// continue +// } +// //if nRow > 4 { +// // break +// //} +// } +// +// // 返回成功消息 +// c.JSON(http.StatusOK, gin.H{"message": "导入成功"}) +//} // HourSummaryList 历史汇总(按小时) // @Summary 历史汇总(按小时) @@ -3086,15 +3089,33 @@ func (e MiGuDeployService) queryHistoricalDataByHour(startTime, endTime string, // 拆分小时数据与汇总数据 var filteredData []models.MgHourSummary - var summaryData *models.MgHourSummary + summaryData := &models.MgHourSummary{} for _, item := range data { if item.Hour == "Total" { - summaryData = &item + // 累积汇总数据 + summaryData.SubmissionCount += item.SubmissionCount + summaryData.NewUserCount += item.NewUserCount + summaryData.NewUserUnsubWithinHour += item.NewUserUnsubWithinHour + summaryData.NewUserUnsubOnDay += item.NewUserUnsubOnDay + summaryData.TotalNewUserUnsub += item.TotalNewUserUnsub } else { filteredData = append(filteredData, item) } } + // 汇总数据比率重新计算 + if summaryData.NewUserCount > 0 { + summaryData.SubmissionSuccessRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserCount)*100/float64(summaryData.SubmissionCount)) + summaryData.NewUserUnsubWithinHourRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserUnsubWithinHour)*100/float64(summaryData.NewUserCount)) + summaryData.NewUserUnsubOnDayRate = fmt.Sprintf("%.2f%%", float64(summaryData.NewUserUnsubOnDay)*100/float64(summaryData.NewUserCount)) + summaryData.TotalNewUserUnsubRate = fmt.Sprintf("%.2f%%", float64(summaryData.TotalNewUserUnsub)*100/float64(summaryData.NewUserCount)) + } else { + summaryData.SubmissionSuccessRate = "0.00%" + summaryData.NewUserUnsubWithinHourRate = "0.00%" + summaryData.NewUserUnsubOnDayRate = "0.00%" + summaryData.TotalNewUserUnsubRate = "0.00%" + } + // 按小时降序排序 sort.Slice(filteredData, func(i, j int) bool { hourI, errI := strconv.Atoi(filteredData[i].Hour) diff --git a/app/admin/models/migu.go b/app/admin/models/migu.go index 388431a..efa32b1 100644 --- a/app/admin/models/migu.go +++ b/app/admin/models/migu.go @@ -139,18 +139,20 @@ type MgHourSummary struct { // MgHistoricalSummary 历史汇总查询表对应的结构体 type MgHistoricalSummary struct { - Date string `json:"date"` // 日期 - ProductID int64 `json:"product_id"` // 产品ID - ChannelCode string `gorm:"size:255" json:"channel_code"` // 渠道编码 - SubmissionCount int `json:"submission_count"` // 提交数 - NewUserCount int `json:"new_user_count"` // 新用户数 - SubmissionSuccessRate string `json:"submission_success_rate"` // 提交成功率 - NewUserUnsubWithinHour int `json:"new_user_unsub_within_hour"` // 当日新用户退订数(1小时以内) - NewUserUnsubWithinHourRate string `json:"new_user_unsub_within_hour_rate"` // 当日新用户退订率(1小时以内) - NewUserUnsubOnDay int `json:"new_user_unsub_on_day"` // 当日新用户退订数 - NewUserUnsubOnDayRate string `json:"new_user_unsub_on_day_rate"` // 当日新用户退订率 - TotalNewUserUnsub int `json:"total_new_user_unsub"` // 累计新用户退订数 - TotalNewUserUnsubRate string `json:"total_new_user_unsub_rate"` // 累计新用户退订率 + Date string `json:"date"` // 日期 + ProductID int64 `json:"product_id"` // 产品ID + ChannelCode string `gorm:"size:255" json:"channel_code"` // 渠道编码 + SubmissionCount int `json:"submission_count"` // 提交数 + NewUserCount int `json:"new_user_count"` // 新用户数 + SubmissionSuccessRate string `json:"submission_success_rate"` // 提交成功率 + NewUserUnsubWithinHour int `json:"new_user_unsub_within_hour"` // 当日新用户退订数(1小时以内) + NewUserUnsubWithinHourRate string `json:"new_user_unsub_within_hour_rate"` // 当日新用户退订率(1小时以内) + NewUserUnsubOnDay int `json:"new_user_unsub_on_day"` // 当日新用户退订数 + NewUserUnsubOnDayRate string `json:"new_user_unsub_on_day_rate"` // 当日新用户退订率 + NewUserUnsubWithin24H int `gorm:"column:new_user_unsub_within_24h" json:"new_user_unsub_within_24h"` // 当日新用户24小时退订数 + NewUserUnsubWithin24HRate string `gorm:"column:new_user_unsub_within_24h_rate" json:"new_user_unsub_within_24h_rate"` // 当日新用户24小时退订率 + TotalNewUserUnsub int `json:"total_new_user_unsub"` // 累计新用户退订数 + TotalNewUserUnsubRate string `json:"total_new_user_unsub_rate"` // 累计新用户退订率 //Province string `gorm:"size:255" json:"province"` // 省份 } @@ -398,7 +400,7 @@ type OrderListReq struct { ChannelTradeNo string `json:"channelTradeNo"` // 渠道订单号 Phone string `json:"phone"` // 手机号码 SM4PhoneNumber string `json:"sm4_phone_number"` // SM4加密手机号 - State int `json:"state"` // 退订状态 0-查所有 1-未退订 2-已退订 3-1小时内退订 + State int `json:"state"` // 退订状态 0-查所有 1-已退订 2-未退订 3-1小时内退订 4-24小时退订 PageNum int `json:"page_num"` // 页码 PageSize int `json:"page_size"` // 每页条数 IsExport uint32 `json:"is_export"` // 1-导出 @@ -1397,7 +1399,7 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st // 设置标题栏 titles := []string{"日期", "产品ID", "渠道编码", "提交数", "新用户数", "提交成功率", "1小时退订数", "1小时退订率", - "当日退订数", "当日退订率", "累计退订数", "累计退订率"} + "当日退订数", "当日退订率", "24小时退订数", "24小时退订率", "累计退订数", "累计退订率"} for i, title := range titles { cell, _ := excelize.CoordinatesToCellName(i+1, 1) file.SetCellValue(sheet, cell, title) @@ -1424,6 +1426,8 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st file.SetColWidth(sheet, "J", "J", 15) file.SetColWidth(sheet, "K", "K", 15) file.SetColWidth(sheet, "L", "L", 15) + file.SetColWidth(sheet, "M", "M", 15) + file.SetColWidth(sheet, "N", "N", 15) // 创建一个产品ID到名称的映射 productMap := make(map[int64]string) @@ -1453,11 +1457,13 @@ func ExportHistoricalSummaryToExcel(data []MgHistoricalSummary, db *gorm.DB) (st file.SetCellValue(sheet, "H"+strconv.Itoa(row), record.NewUserUnsubWithinHourRate) file.SetCellValue(sheet, "I"+strconv.Itoa(row), record.NewUserUnsubOnDay) file.SetCellValue(sheet, "J"+strconv.Itoa(row), record.NewUserUnsubOnDayRate) - file.SetCellValue(sheet, "K"+strconv.Itoa(row), record.TotalNewUserUnsub) - file.SetCellValue(sheet, "L"+strconv.Itoa(row), record.TotalNewUserUnsubRate) + file.SetCellValue(sheet, "K"+strconv.Itoa(row), record.NewUserUnsubWithin24H) + file.SetCellValue(sheet, "L"+strconv.Itoa(row), record.NewUserUnsubWithin24HRate) + file.SetCellValue(sheet, "M"+strconv.Itoa(row), record.TotalNewUserUnsub) + file.SetCellValue(sheet, "N"+strconv.Itoa(row), record.TotalNewUserUnsubRate) } - endRow := fmt.Sprintf("L%d", len(data)+1) + endRow := fmt.Sprintf("N%d", len(data)+1) // 应用样式到整个表格 _ = file.SetCellStyle(sheet, "A1", endRow, style) diff --git a/app/admin/router/migu.go b/app/admin/router/migu.go index 02e5f6f..53a9afa 100644 --- a/app/admin/router/migu.go +++ b/app/admin/router/migu.go @@ -33,7 +33,7 @@ func registerMiGuControlManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gi api.POST("home/revenue_analysis", apiMiGu.CalculateRevenueAnalysis) // 营收分析 api.POST("historical_summary/list", apiMiGu.HistoricalSummaryListOld) // 历史汇总查询 - api.POST("order/import", apiMiGu.ImportExcelToMgOrderHandler) // 通过excel导入订单数据 + //api.POST("order/import", apiMiGu.ImportExcelToMgOrderHandler) // 通过excel导入订单数据 //api.POST("order/import_update", apiMiGu.ImportExcelToMgOrderHandlerUpdate) // 通过excel导入订单退订数据 } } diff --git a/docs/admin/admin_docs.go b/docs/admin/admin_docs.go index f33e6d7..6800279 100644 --- a/docs/admin/admin_docs.go +++ b/docs/admin/admin_docs.go @@ -5046,6 +5046,14 @@ const docTemplateadmin = `{ "description": "当日新用户退订率", "type": "string" }, + "new_user_unsub_within_24h": { + "description": "当日新用户24小时退订数", + "type": "integer" + }, + "new_user_unsub_within_24h_rate": { + "description": "当日新用户24小时退订率", + "type": "string" + }, "new_user_unsub_within_hour": { "description": "当日新用户退订数(1小时以内)", "type": "integer" @@ -5677,6 +5685,10 @@ const docTemplateadmin = `{ "description": "查询结束时间", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "product_id": { "description": "产品ID", "type": "integer" @@ -5919,6 +5931,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 329f581..26c36e8 100644 --- a/docs/admin/admin_swagger.json +++ b/docs/admin/admin_swagger.json @@ -5038,6 +5038,14 @@ "description": "当日新用户退订率", "type": "string" }, + "new_user_unsub_within_24h": { + "description": "当日新用户24小时退订数", + "type": "integer" + }, + "new_user_unsub_within_24h_rate": { + "description": "当日新用户24小时退订率", + "type": "string" + }, "new_user_unsub_within_hour": { "description": "当日新用户退订数(1小时以内)", "type": "integer" @@ -5669,6 +5677,10 @@ "description": "查询结束时间", "type": "string" }, + "is_export": { + "description": "1-导出", + "type": "integer" + }, "product_id": { "description": "产品ID", "type": "integer" @@ -5911,6 +5923,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 f72ea89..a535aa4 100644 --- a/docs/admin/admin_swagger.yaml +++ b/docs/admin/admin_swagger.yaml @@ -1138,6 +1138,12 @@ definitions: new_user_unsub_on_day_rate: description: 当日新用户退订率 type: string + new_user_unsub_within_24h: + description: 当日新用户24小时退订数 + type: integer + new_user_unsub_within_24h_rate: + description: 当日新用户24小时退订率 + type: string new_user_unsub_within_hour: description: 当日新用户退订数(1小时以内) type: integer @@ -1589,6 +1595,9 @@ definitions: end_time: description: 查询结束时间 type: string + is_export: + description: 1-导出 + type: integer product_id: description: 产品ID type: integer @@ -1758,6 +1767,9 @@ definitions: end_time: description: 结束时间 type: string + is_export: + description: 1-导出 + type: integer page_num: description: 页码 type: integer