www vor 1 Jahr
Ursprung
Commit
84e85448c8

+ 9 - 14
api/v1/task/game_task.go

@@ -5,7 +5,6 @@ import (
 	"go.uber.org/zap"
 	"log-server/global"
 	"log-server/model/common/response"
-	log2 "log-server/model/log"
 	"log-server/model/task/request"
 	taskResponse "log-server/model/task/response"
 	"log-server/utils"
@@ -608,24 +607,20 @@ func (e *GameTaskApi) PushCompleteTaskData(c *gin.Context) {
 	response.OkWithMessage("推送成功", c)
 }
 
-func (e *GameTaskApi) GetWindowTask(c *gin.Context) {
-	var confit log2.IpLogResponse
-	_ = c.ShouldBindJSON(&confit)
-	if confit.GameId == 0 {
-		response.FailWithMessage("游戏id不能为空", c)
-		return
-	}
-	if confit.PcCode == "" {
-		response.FailWithMessage("租机编号不能为空", c)
-		return
-	}
-	list, _, err := taskService.GetWindowTask(confit.PcCode, confit.GameId)
+func (e *GameTaskApi) GetGameTaskRatioList(c *gin.Context) {
+	var params request.GetGameTaskRatioListPageRequest
+	_ = c.ShouldBindJSON(&params)
+
+	list, total, err := taskService.GetGameTaskRatioList(params.GetGameTaskRatioListRequest, params.PageInfo, params.OrderKey, params.Desc)
 	if err != nil {
 		global.GVA_LOG.Error("获取失败!", zap.Error(err))
 		response.FailWithMessage("获取失败", c)
 	} else {
 		response.OkWithDetailed(response.PageResult{
-			List: list,
+			List:     list,
+			Total:    total,
+			Page:     params.Page,
+			PageSize: params.PageSize,
 		}, "获取成功", c)
 	}
 }

+ 3 - 0
initialize/gorm.go

@@ -2,6 +2,7 @@ package initialize
 
 import (
 	"log-server/model/log"
+	"log-server/model/task"
 	"os"
 
 	"go.uber.org/zap"
@@ -27,6 +28,8 @@ func Gorm() *gorm.DB {
 func RegisterTables(db *gorm.DB) {
 	err := db.AutoMigrate(
 		log.GameCharacter{},
+		task.GameRetainedData{},
+		task.GameRatioData{},
 	)
 	if err != nil {
 		global.GVA_LOG.Error("register table failed", zap.Error(err))

+ 17 - 1
initialize/timer.go

@@ -62,7 +62,7 @@ func Timer() {
 	if err != nil {
 		fmt.Println("add TodayCreateStatisticsGameInfoLog timer error:", err)
 	}
-	// 同步任务统计数据
+	// 同步群控任务数据
 	_, err = global.GVA_Timer.AddTaskByFunc("TaskStatisticsDataCache", "20 0/3 6-23 * * * ", serviceStatisticsLog.TaskStatisticsDataCache)
 	if err != nil {
 		fmt.Println("add TaskStatisticsDataCache timer error:", err)
@@ -262,4 +262,20 @@ func Timer() {
 		fmt.Println("add GameTaskTargetInfoPush timer error:", err)
 	}
 
+	// 检查群控完成数据为0的游戏
+	_, err = global.GVA_Timer.AddTaskByFunc("SyncTaskData", "2 1 10-23 * * *", syncData.CheckControlCompleteData)
+	if err != nil {
+		fmt.Println("add SyncTaskData timer error:", err)
+	}
+
+	_, err = global.GVA_Timer.AddTaskByFunc("SyncControlRetainedRatioData", "30 50 23 * * *", syncData.SyncControlRetainedRatioData)
+	if err != nil {
+		fmt.Println("add SyncControlRetainedRatioData timer error:", err)
+	}
+
+	_, err = global.GVA_Timer.AddTaskByFunc("SyncControlRatio", "30 53 23 * * *", syncData.SyncControlRatio)
+	if err != nil {
+		fmt.Println("add SyncControlRatio timer error:", err)
+	}
+
 }

+ 3 - 0
model/log/request/log_statistics.go

@@ -53,6 +53,9 @@ type TaskStatistics struct {
 	FeeAccountNum         int    `json:"fee_account_num"`      // 付费账号
 	Remark                string `json:"remark"`               //负责人
 	GameRate              string `json:"game_rate"`            // 游戏效率
+
+	CompleteNum      string `json:"complete_num"`       //"complete_num": "12/21/3", 小绵羊数据
+	CompleteLocalNum string `json:"complete_local_num"` //"complete_local_num": "3/18/0",群控数据
 }
 
 type TaskData struct {

+ 24 - 0
model/task/game_ratio_data.go

@@ -0,0 +1,24 @@
+package task
+
+import "time"
+
+type GameRatioData struct {
+	Id        uint `json:"id" gorm:"primarykey"`
+	CreatedAt time.Time
+	UpdatedAt time.Time
+	GameId    int `json:"game_id"`
+	Second    int `json:"second"`    // 次留
+	Third     int `json:"third"`     // 3留
+	Forth     int `json:"forth"`     // 4留
+	Fifth     int `json:"fifth"`     // 5留
+	Sixth     int `json:"sixth"`     // 6留
+	Seventh   int `json:"seventh"`   // 7留
+	Tenth     int `json:"tenth"`     // 10留
+	Fifteenth int `json:"fifteenth"` // 15留
+	Twentieth int `json:"twentieth"` // 20留
+	Thirtieth int `json:"thirtieth"` // 30留
+}
+
+func (GameRatioData) TableName() string {
+	return "game_ratio_data"
+}

+ 18 - 0
model/task/game_retained_data.go

@@ -0,0 +1,18 @@
+package task
+
+import "time"
+
+type GameRetainedData struct {
+	Id           uint `json:"id" gorm:"primarykey"`
+	CreatedAt    time.Time
+	UpdatedAt    time.Time
+	NewDate      string    `json:"new_date" gorm:"comment:留存日期"`
+	Duration     int       `json:"duration" gorm:"comment:几留"`
+	Total        int       `json:"total" gorm:"comment:账号个数"`
+	GameId       int       `json:"game_id"` //游戏id
+	RetainedDate time.Time `json:"retained_date" gorm:"type:date;comment:账号个数"`
+}
+
+func (GameRetainedData) TableName() string {
+	return "game_retained_data"
+}

+ 1 - 0
model/task/game_target_complete.go

@@ -14,6 +14,7 @@ type GameTargetComplete struct {
 	NewTarget            int       `json:"new_target"`
 	PayTarget            int       `json:"pay_target"`
 	RetainedTarget       int       `json:"retained_target"`
+	JfRetainedTarget     int       `json:"jf_retained_target"`
 	Amount               int       `json:"amount"`
 	CreateDate           time.Time `json:"create_date"`
 	UpdateTime           time.Time `json:"update_time"` // 更新时间

+ 14 - 0
model/task/request/game_task.go

@@ -86,6 +86,20 @@ type GameTargetCompleteRequest struct {
 	TotalAmount      float64  `json:"total_amount"`
 }
 
+type GetGameTaskRatioListPageRequest struct {
+	GetGameTaskRatioListRequest
+	PageInfo
+	OrderKey string `json:"orderKey"` // 排序
+	Desc     bool   `json:"desc"`     // 排序方式:升序false(默认)|降序true
+}
+
+type GetGameTaskRatioListRequest struct {
+	TaskId   int    `json:"task_id"`
+	Date     string `json:"date"`
+	TaskName string `json:"task_name"`
+	User     string `json:"user"`
+}
+
 type GetGameTargetCompleteInfo struct {
 	GameId           int    `json:"game_id"`
 	GameName         string `json:"game_name"`

+ 18 - 0
model/task/response/game_task.go

@@ -1,6 +1,7 @@
 package response
 
 import (
+	"log-server/model/task"
 	"time"
 )
 
@@ -74,6 +75,23 @@ type GetGameTargetComplete struct {
 	GameIdXmy            string  `json:"game_id_xmy"`
 	Aupr                 int     `json:"aupr"`
 	TotalAmount          float64 `json:"total_amount"`
+	JfRetainedTarget     int     `json:"jf_retained_target"`
+}
+
+type GetGameRatioData struct {
+	TaskId     int    `json:"task_id"`
+	TaskName   string `json:"task_name"`
+	User       string `json:"user"`
+	NewTarget  int    `json:"new_target"`
+	CreateDate string `json:"create_date"`
+	task.GameRatioData
+	RetainedData []RetainedData `json:"retained_data" gorm:"-"`
+}
+
+type RetainedData struct {
+	task.GameRetainedData
+	NewTarget   int `json:"new_target"`
+	NewComplete int `json:"new_complete"`
 }
 
 type GameTargetStatistics struct {

+ 1 - 0
router/task/game_task.go

@@ -33,6 +33,7 @@ func (e *GameTaskRouter) InitGameTaskRouter(Router *gin.RouterGroup) {
 		gameTaskRouter.POST("updateRatio", GameTaskApi.UpdateRetentionRatio)
 		gameTaskRouter.POST("uploadGameCharacter", GameTaskApi.UploadGameCharacter)
 		gameTaskRouter.GET("pushTaskData", GameTaskApi.PushCompleteTaskData)
+		gameTaskRouter.POST("getGameTaskRatioList", GameTaskApi.GetGameTaskRatioList)
 	}
 	GameTaskRouter1 := Router.Group("gameTask").Use(middleware.OperationRecord())
 	{

+ 10 - 10
service/log/log_statistics.go

@@ -1048,24 +1048,24 @@ func (s *ServiceStatisticsLog) TaskStatisticsDataCache() {
 		return
 	}
 	var taskData []request.TaskData
-	var taskStatistics []request.TaskStatistics
-	_ = json.Unmarshal(data, &taskStatistics)
+	var taskStatistics1 []request.TaskStatistics
+	_ = json.Unmarshal(data, &taskStatistics1)
 	_ = json.Unmarshal(dataTask, &taskData)
 	mps := map[int]request.TaskData{}
 	for _, td := range taskData {
 		mps[td.GameId] = td
 	}
-	for _, data := range taskStatistics {
+	for _, data1 := range taskStatistics1 {
 		var id int
-		id = data.GameId
+		id = data1.GameId
 		if _, ok := mps[id]; ok {
-			data.NewScanningCode = mps[id].NewScanningCode
-			data.RetainedPullAccount = mps[id].RetainedPullAccount
-			data.NewPullAccount = mps[id].NewPullAccount
-			data.FeeAccountNum = mps[id].FeeAccountNum
-			data.RetainedAccountNum = mps[id].RetainedAccountNum
+			data1.NewScanningCode = mps[id].NewScanningCode
+			data1.RetainedPullAccount = mps[id].RetainedPullAccount
+			data1.NewPullAccount = mps[id].NewPullAccount
+			data1.FeeAccountNum = mps[id].FeeAccountNum
+			data1.RetainedAccountNum = mps[id].RetainedAccountNum
 		}
-		bd, _ := json.Marshal(data)
+		bd, _ := json.Marshal(data1)
 		err = global.GVA_REDIS.HSet(ctx, key, id, bd).Err()
 		if err != nil {
 			global.GVA_LOG.Error("添加缓存数据失败TaskStatisticsDataCache", zap.Error(err))

+ 10 - 4
service/task/central_control_conf.go

@@ -63,12 +63,18 @@ func (s *CentralControlService) GetCentralControlConfList(conf task.CentralContr
 	limit := info.PageSize
 	offset := (info.Page - 1) * info.PageSize
 	db := global.GVA_DB.Model(&task.CentralControlConf{})
-	var confList []task.CentralControlConf
+	var confList []task.CentralControlConfList
 
+	db = db.Select("central_control_conf.*, game_task.user")
+	db = db.Joins("left join game_task on central_control_conf.task_id = game_task.task_id")
 	//先条件过滤
 	if conf.TaskId != 0 {
 		//条件过滤记录数
-		db = db.Where("task_id", conf.TaskId)
+		db = db.Where("central_control_conf.task_id", conf.TaskId)
+	}
+
+	if conf.User != "" {
+		db = db.Where("game_task.user LIKE ?", "%"+conf.User+"%")
 	}
 
 	err = db.Count(&total).Error
@@ -89,7 +95,7 @@ func (s *CentralControlService) GetCentralControlConfList(conf task.CentralContr
 			orderMap["update_time"] = true
 			if orderMap[order] {
 				if desc {
-					orderStr = order + " desc"
+					orderStr = "central_control_conf." + order + " desc"
 				} else {
 					orderStr = order
 				}
@@ -102,7 +108,7 @@ func (s *CentralControlService) GetCentralControlConfList(conf task.CentralContr
 			err = db.Order(orderStr).Find(&confList).Error
 		} else {
 			//没有传入排序字段,默认按照类型名称降序排序
-			err = db.Order("id desc").Find(&confList).Error
+			err = db.Order("central_control_conf.id desc").Find(&confList).Error
 		}
 	}
 	//是因为只有切片能排序,model没办法排序;还是说为了将数组返回至前端才find扫描至切片呢?

+ 75 - 1
service/task/game_task.go

@@ -648,7 +648,7 @@ func (apiService *GameTask) GetGameTaskTargetInfoList(api request.GameTargetComp
 		endDate = api.Date[1]
 	}
 	db := global.GVA_DB.Table("game_target_complete gtc")
-	db = db.Select("gtc.id,gtc.task_id,gt.task_name,gt.game_id_xmy,gtc.new_target,gt.login_method,gt.user,gtc.pay_target,gtc.retained_target," +
+	db = db.Select("gtc.id,gtc.task_id,gt.task_name,gt.game_id_xmy,gtc.new_target,gt.login_method,gt.user,gtc.pay_target,gtc.retained_target,gtc.jf_retained_target," +
 		"gtc.new_complete,gtc.pay_complete,gtc.retained_complete,gtc.create_date,gtc.amount,gtc.game_rate,gtc.is_complete,gtc.hand_new_complete," +
 		"gtc.hand_retained_complete,gtc.hand_pay_complete,gtc.hand_amount_total,gtc.aupr, gtc.total_amount")
 	db = db.Joins("left join game_task gt on gt.task_id = gtc.task_id")
@@ -1454,3 +1454,77 @@ func (s *GameTask) GetWindowTask(pcCode string, id int) (list interface{}, d str
 	//global.GVA_LOG.Warn(msg)
 	return
 }
+
+func (apiService *GameTask) GetGameTaskRatioList(api request.GetGameTaskRatioListRequest, info request.PageInfo, order string, desc bool) (apiList []response.GetGameRatioData, total int64, err error) {
+	limit := info.PageSize
+	offset := info.PageSize * (info.Page - 1)
+	if api.Date == "" {
+		api.Date = time.Now().Add(-time.Hour * 24).Format("2006-01-02")
+	}
+	db := global.GVA_DB.Table("game_target_complete gtc")
+	db = db.Select("gtc.task_id,gtc.create_date,gt.task_name,gt.user,gtc.new_target,grd.*")
+	db = db.Joins("left join game_task gt on gt.task_id = gtc.task_id")
+	db = db.Joins("left join game_ratio_data grd on grd.game_id = gtc.task_id")
+	db = db.Where("gtc.create_date = ?", api.Date)
+	db = db.Where("gtc.task_id not in(?)", []int{1000770})
+	db = db.Where("gtc.new_target <> ?", 0)
+	if api.TaskName != "" {
+		db = db.Where("gt.task_name LIKE ?", "%"+api.TaskName+"%")
+	}
+	if api.User != "" {
+		db = db.Where("gt.user LIKE ?", "%"+api.User+"%")
+	}
+
+	if api.TaskId != 0 {
+		db = db.Where("gtc.task_id = ?", api.TaskId)
+	}
+
+	err = db.Count(&total).Error
+
+	if err != nil {
+		return apiList, total, err
+	} else {
+		db = db.Limit(limit).Offset(offset)
+		if order != "" {
+			var OrderStr string
+			// 设置有效排序key 防止sql注入
+			// 感谢 Tom4t0 提交漏洞信息
+			orderMap := make(map[string]bool, 4)
+			orderMap["task_name"] = true
+			orderMap["user"] = true
+			if orderMap[order] {
+				if desc {
+					OrderStr = "gt." + order + " desc"
+				} else {
+					OrderStr = order
+				}
+			} else { // didn't matched any order key in `orderMap`
+				err = fmt.Errorf("非法的排序字段: %v", order)
+				return apiList, total, err
+			}
+
+			err = db.Order(OrderStr).Find(&apiList).Error
+		} else {
+			err = db.Order("gtc.id desc").Find(&apiList).Error
+		}
+	}
+	if len(apiList) != 0 {
+		for i, apiData := range apiList {
+			date := strings.Split(apiData.CreateDate, "T")
+			apiList[i].CreateDate = date[0]
+			var retainedData []response.RetainedData
+			db1 := global.GVA_DB.Table("game_retained_data grd")
+			db1 = db1.Select("gtc.new_target,gtc.new_complete,grd.*")
+			db1 = db1.Joins("left join game_target_complete gtc on gtc.task_id = grd.game_id and gtc.create_date = grd.new_date")
+			db1 = db1.Where("grd.game_id = ?", apiData.TaskId)
+			db1 = db1.Where("grd.retained_date = ?", api.Date)
+			db1 = db1.Order("grd.duration")
+			err = db1.Find(&retainedData).Error
+			if err != nil {
+				continue
+			}
+			apiList[i].RetainedData = retainedData
+		}
+	}
+	return apiList, total, err
+}

+ 210 - 8
service/task/sync_data.go

@@ -209,7 +209,7 @@ func (s *SyncData) SyncTaskData() {
 		//global.GVA_DB.Where("task_id = ?", gameTask.TaskId).Where("create_date = ?", date).First(&gameTargetComplete)
 		var gameTarget task.GameTargetComplete
 		roomData, _ := s.SyncRoomData(date, gameTask.TaskId)
-
+		gameTarget.JfRetainedTarget = roomData.RetainedTarget
 		if gameTask.GameIdXmy != "" {
 			gameIdXmy, _ := strconv.Atoi(gameTask.GameIdXmy)
 			xmyGameInfo := xmyGameData[gameIdXmy]
@@ -296,12 +296,10 @@ func (s *SyncData) SyncTaskData() {
 			}
 		}
 		gameTarget.IsComplete = -1
-		if gameTarget.RetainedComplete+completeTaskData[gameTask.TaskId].HandRetainedComplete >= completeTaskData[gameTask.TaskId].RetainedTarget && gameTarget.PayComplete >= completeTaskData[gameTask.TaskId].PayTarget && gameTarget.NewComplete+completeTaskData[gameTask.TaskId].HandNewComplete >= completeTaskData[gameTask.TaskId].NewTarget {
+		if gameTarget.RetainedComplete+completeTaskData[gameTask.TaskId].HandRetainedComplete >= completeTaskData[gameTask.TaskId].JfRetainedTarget && gameTarget.PayComplete >= completeTaskData[gameTask.TaskId].PayTarget && gameTarget.NewComplete+completeTaskData[gameTask.TaskId].HandNewComplete >= completeTaskData[gameTask.TaskId].NewTarget {
 			gameTarget.IsComplete = 1
 		}
-		//if completeTaskData[gameTask.TaskId].RetainedTarget == 0 || completeTaskData[gameTask.TaskId].RetainedTarget == 1 {
-		//	gameTarget.RetainedTarget = roomData.RetainedTarget
-		//}
+
 		global.GVA_DB.Model(&task.GameTargetComplete{}).Where("task_id = ?", gameTask.TaskId).Where("create_date = ?", date).Omit("create_date", "update_time", "task_id").Updates(gameTarget)
 	}
 	go s.common.PaymentRatioErrSendMsg(paymentRatio)
@@ -373,7 +371,7 @@ func (s *SyncData) YesterdaySyncTaskData() {
 	for _, gameTask := range apiList {
 		var gameTarget task.GameTargetComplete
 		roomData, _ := s.SyncRoomData(date, gameTask.TaskId)
-
+		gameTarget.JfRetainedTarget = roomData.RetainedTarget
 		if gameTask.GameIdXmy != "" {
 			gameIdXmy, _ := strconv.Atoi(gameTask.GameIdXmy)
 			xmyGameInfo := xmyGameData[gameIdXmy]
@@ -1109,9 +1107,9 @@ func (s *SyncData) TaskMsgSendRetainedDataUpdate(ctx context.Context, completesI
 			_ = s.cache.SetCacheStr(ctx, lastNewCompletedUpdateTimeKey, ctime) //上次新增完成更新时间
 		}
 		// 处理留存
-		if complete.RetainedTarget > currentRetainedCompleted {
+		if complete.JfRetainedTarget > currentRetainedCompleted {
 			lastRetainedCompleted, _ := s.cache.GetCacheNum(ctx, lastRetainedCompletedKey)
-			alsoRetainedTarget := complete.RetainedTarget - currentRetainedCompleted
+			alsoRetainedTarget := complete.JfRetainedTarget - currentRetainedCompleted
 			retainedRate := 0
 			lastRetainedCompletedUpdateTime, _ := s.cache.GetCacheNum(ctx, lastRetainedCompletedUpdateTimeKey)
 			timeRate := int(ctime) - lastRetainedCompletedUpdateTime
@@ -1667,3 +1665,207 @@ func (s *SyncData) RequestControlBackend(requestData []request2.GetGameTargetCom
 	global.GVA_LOG.Warn(msg)
 	return
 }
+
+func (s SyncData) CheckControlCompleteData() {
+	db := global.GVA_DB.Model(&task.GameTask{})
+	var apiList []task.GameTask
+	db = db.Where("is_del = ?", -1)
+	db = db.Where("status = ?", 1)
+	err := db.Order("id desc").Find(&apiList).Error
+	if err != nil {
+		global.GVA_LOG.Error("查询任务数据失败", zap.Error(err))
+		return
+	}
+	if len(apiList) == 0 {
+		global.GVA_LOG.Info("没有任务数据")
+		return
+	}
+	date := time.Now().Format("2006-01-02")
+	for _, gameTask := range apiList {
+		roomData, _ := s.SyncRoomData(date, gameTask.TaskId)
+		xmyComplete := strings.Split(roomData.CompleteNum, "/")
+		if len(xmyComplete) < 3 {
+			continue
+		}
+		xmyNewComplete, _ := strconv.Atoi(xmyComplete[0])
+		xmyRetainedComplete, _ := strconv.Atoi(xmyComplete[1])
+		controlComplete := strings.Split(roomData.CompleteLocalNum, "/")
+		if len(controlComplete) < 3 {
+			continue
+		}
+		controlNewComplete, _ := strconv.Atoi(controlComplete[0])
+		controlRetainedComplete, _ := strconv.Atoi(controlComplete[1])
+		if xmyNewComplete > 1 && controlNewComplete == 0 {
+			// 新增异常,推送消息
+			content := s.CheckControlCompleteDataMsg(gameTask.TaskId, gameTask.TaskName, "新增")
+			s.SendMsg(content, gameTask.User)
+		}
+		if xmyRetainedComplete > 1 && controlRetainedComplete == 0 {
+			// 留存异常,推送消息
+			content := s.CheckControlCompleteDataMsg(gameTask.TaskId, gameTask.TaskName, "留存")
+			s.SendMsg(content, gameTask.User)
+		}
+	}
+}
+
+func (s SyncData) CheckControlCompleteDataMsg(gameId int, gameName, typeStr string) string {
+	c := "# 群控数据异常"
+	c += fmt.Sprintf("<font color=\"warning\">%s</font>", time.Now().Format("2006-01-02 15:04:05"))
+	c += "\n"
+	c += typeStr
+	c += "\n"
+	ct := fmt.Sprintf("<font color=\"warning\"> %d, %s</font>", gameId, gameName)
+	ct = c + ct
+	return ct
+}
+
+func (s *SyncData) SendContent(content, url string) {
+	var sendMsg SendMsg
+	sendMsg.MsgType = "markdown"
+	sendMsg.Markdown.Content = content
+	s.SendMsgData(url, sendMsg)
+}
+
+func (s *SyncData) SendMsg(content string, operator string) {
+	mpsPerson, _ := s.Person.GetUserInfoData()
+	if operator != "" {
+		s.SendContent(content, mpsPerson[operator].Url)
+		url := global.GVA_CONFIG.SendUrl.ComputerSendUrl
+		s.SendContent(content, url)
+		var sendTextData SendTextMsg
+		sendTextData.MsgType = "text"
+		sendTextData.Text.MentionedMobileList = []string{mpsPerson[operator].MobilePhoneNumber}
+		s.SendMsgData(url, sendTextData)
+	}
+}
+
+type RetainedRatioData struct {
+	Data   map[int][]RatioData `json:"data"`
+	Status string              `json:"status"`
+}
+
+type RatioData struct {
+	NewDate  string `json:"NewDate"`
+	Duration int    `json:"Duration"`
+	Total    int    `json:"Total"`
+}
+
+func (s *SyncData) SyncControlRetainedRatioData() {
+	requestData := s.getRatioData()
+	if requestData.Status != "OK" {
+		return
+	}
+	db := global.GVA_DB.Model(&task.GameTask{})
+	var apiList []task.GameTask
+	db = db.Where("is_del = ?", -1)
+	db = db.Where("status = ?", 1)
+	err := db.Order("id desc").Find(&apiList).Error
+	if err != nil {
+		global.GVA_LOG.Error("查询任务数据失败", zap.Error(err))
+		return
+	}
+	if len(apiList) == 0 {
+		global.GVA_LOG.Info("没有任务数据")
+		return
+	}
+	var gameRDs []task.GameRetainedData
+	for _, gameTask := range apiList {
+		if _, ok := requestData.Data[gameTask.TaskId]; !ok {
+			continue
+		}
+		for _, data := range requestData.Data[gameTask.TaskId] {
+			var gameRD task.GameRetainedData
+			gameRD.GameId = gameTask.TaskId
+			gameRD.Total = data.Total
+			gameRD.Duration = data.Duration
+			gameRD.NewDate = data.NewDate
+			gameRD.RetainedDate = time.Now()
+			gameRDs = append(gameRDs, gameRD)
+		}
+	}
+	global.GVA_DB.Create(&gameRDs)
+	return
+}
+
+func (s SyncData) getRatioData() (requestData RetainedRatioData) {
+	xmyUrl := "http://xjf.lianyou.fun:8099/v1/account/retained_rate"
+	params := map[string]string{}
+	xmyByteData, err := utils.HttpGet(xmyUrl, params)
+	if err != nil {
+		return
+	}
+	_ = json.Unmarshal(xmyByteData, &requestData)
+	return
+}
+
+type GameRatio struct {
+	Id        int `json:"id"`
+	GameId    int `json:"game_id"`
+	Second    int `json:"second"`    // 次留
+	Third     int `json:"third"`     // 3留
+	Forth     int `json:"forth"`     // 4留
+	Fifth     int `json:"fifth"`     // 5留
+	Sixth     int `json:"sixth"`     // 6留
+	Seventh   int `json:"seventh"`   // 7留
+	Tenth     int `json:"tenth"`     // 10留
+	Fifteenth int `json:"fifteenth"` // 15留
+	Twentieth int `json:"twentieth"` // 20留
+	Thirtieth int `json:"thirtieth"` // 30留
+}
+
+func (s SyncData) getRatio(gameId int) (requestData GameRatio) {
+	xmyUrl := fmt.Sprintf("http://xjf.lianyou.fun:8099/v1/task_statistics/retained/%d", gameId)
+	params := map[string]string{}
+	xmyByteData, err := utils.HttpGet(xmyUrl, params)
+	if err != nil {
+		return
+	}
+	_ = json.Unmarshal(xmyByteData, &requestData)
+	return
+}
+
+func (s *SyncData) SyncControlRatio() {
+	db := global.GVA_DB.Model(&task.GameTask{})
+	var apiList []task.GameTask
+	db = db.Where("is_del = ?", -1)
+	db = db.Where("status = ?", 1)
+	err := db.Order("id desc").Find(&apiList).Error
+	if err != nil {
+		global.GVA_LOG.Error("查询任务数据失败", zap.Error(err))
+		return
+	}
+	if len(apiList) == 0 {
+		global.GVA_LOG.Info("没有任务数据")
+		return
+	}
+	var gameRDs []task.GameRatioData
+	for _, gameTask := range apiList {
+		requestData := s.getRatio(gameTask.TaskId)
+		if requestData.Id == 0 {
+			continue
+		}
+		var gameRD task.GameRatioData
+		global.GVA_DB.Where("game_id = ?", gameTask.TaskId).First(&gameRD)
+		gameRD.Second = requestData.Second
+		gameRD.Third = requestData.Third
+		gameRD.Forth = requestData.Forth
+		gameRD.Fifth = requestData.Fifth
+		gameRD.Sixth = requestData.Sixth
+		gameRD.Seventh = requestData.Seventh
+		gameRD.Tenth = requestData.Tenth
+		gameRD.Fifteenth = requestData.Fifteenth
+		gameRD.Twentieth = requestData.Twentieth
+		gameRD.Thirtieth = requestData.Thirtieth
+		if gameRD.GameId == 0 {
+			gameRD.GameId = gameTask.TaskId
+			gameRDs = append(gameRDs, gameRD)
+		} else {
+			global.GVA_DB.Where("game_id = ?", gameTask.TaskId).Updates(&gameRD)
+		}
+
+	}
+	if len(gameRDs) > 0 {
+		global.GVA_DB.Create(&gameRDs)
+	}
+	return
+}