浏览代码

电脑统计

wangbin 3 年之前
父节点
当前提交
ddce932021

+ 196 - 0
api/v1/log/computer.go

@@ -0,0 +1,196 @@
+package log
+
+import (
+	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+	"log-server/global"
+	"log-server/model/common/response"
+	"log-server/model/log"
+	"log-server/model/log/request"
+	"log-server/utils"
+	"os"
+	"strconv"
+	"time"
+)
+
+type ApiComputer struct {
+}
+
+// @Tags computer
+// @Summary 分页获租机号列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.GetCardListRequest true "分页获取租机列表"
+// @Success 200 {object} response.Response{data=response.GetPcListReply,msg=string} "分页获取租机列表,返回包括列表,总数,页码,每页数量"
+// @Router /computer/getPcList [post]
+func (s *ApiComputer) GetPcList(c *gin.Context) {
+	var paramsInfo request.GetPcListRequest
+	_ = c.ShouldBindJSON(&paramsInfo)
+	if err := utils.Verify(paramsInfo.PageInfo, utils.PageInfoVerify); err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	if list, total, err := ServiceComputer.GetPcInfoList(paramsInfo.Computer, paramsInfo.PageInfo, paramsInfo.OrderKey, paramsInfo.Desc); err != nil {
+		global.GVA_LOG.Error("获取失败!", zap.Error(err))
+		response.FailWithMessage("获取失败", c)
+	} else {
+		response.OkWithDetailed(response.PageResult{
+			List:     list,
+			Total:    total,
+			Page:     paramsInfo.Page,
+			PageSize: paramsInfo.PageSize,
+		}, "获取成功", c)
+	}
+}
+
+// @Tags computer
+// @Summary 根据id获取api
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.GetById true "根据id获取api"
+// @Success 200 {object} response.Response{data=systemRes.SysAPIResponse} "根据id获取api,返回包括api详情"
+// @Router /computer/getPcById [post]
+func (s *ApiComputer) GetPcById(c *gin.Context) {
+	var idInfo request.GetById
+	_ = c.ShouldBindJSON(&idInfo)
+	if err := utils.Verify(idInfo, utils.IdVerify); err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	api, err := ServiceComputer.GetPcById(idInfo.ID)
+	if err != nil {
+		global.GVA_LOG.Error("获取失败!", zap.Error(err))
+		response.FailWithMessage("获取失败", c)
+	} else {
+		response.OkWithDetailed(api, "获取成功", c)
+	}
+}
+
+// @Tags computer
+// @Summary 创建租机记录
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.CreateUpdatePcRequest true "租机编号, 使用者, 租机供应商"
+// @Success 200 {object} response.Response{msg=string} "创建租机信息"
+// @Router /computer/createPc [post]
+func (s *ApiComputer) CreatePc(c *gin.Context) {
+	var paramsInfo request.CreateUpdatePcRequest
+	_ = c.ShouldBindJSON(&paramsInfo)
+	if err := utils.Verify(paramsInfo, utils.PcVerify); err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	var computer log.Computer
+	computer.Supplier = paramsInfo.Supplier
+	computer.User = paramsInfo.User
+	computer.PcCode = paramsInfo.PcCode
+	computer.Status = paramsInfo.Status
+	if err := ServiceComputer.CreatePc(computer); err != nil {
+		global.GVA_LOG.Error("创建失败!", zap.Error(err))
+		response.FailWithMessage(err.Error(), c)
+	} else {
+		response.OkWithMessage("创建成功", c)
+	}
+}
+
+// @Tags computer
+// @Summary 修改租机信息
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.CreateUpdatePcRequest true "id, 租机编号, 使用者, 租机供应商"
+// @Success 200 {object} response.Response{msg=string} "修改租机信息"
+// @Router /computer/updatePc [post]
+func (s *ApiComputer) UpdatePc(c *gin.Context) {
+	var paramsInfo request.CreateUpdatePcRequest
+	_ = c.ShouldBindJSON(&paramsInfo)
+	if err := utils.Verify(paramsInfo, utils.PcVerify); err != nil {
+		response.FailWithMessage(err.Error(), c)
+		return
+	}
+	if paramsInfo.Id == 0 {
+		response.FailWithMessage("Id不能为空", c)
+		return
+	}
+	var computer log.Computer
+	computer.Id = paramsInfo.Id
+	computer.Supplier = paramsInfo.Supplier
+	computer.User = paramsInfo.User
+	computer.PcCode = paramsInfo.PcCode
+	computer.Status = paramsInfo.Status
+	if err := ServiceComputer.UpdatePc(computer); err != nil {
+		global.GVA_LOG.Error("修改失败!", zap.Error(err))
+		response.FailWithMessage(err.Error(), c)
+	} else {
+		response.OkWithMessage("修改成功", c)
+	}
+}
+
+// @Tags computer
+// @Summary 修改租机状态
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.PcStatusOperationRequest true "id, 状态"
+// @Success 200 {object} response.Response{msg=string} "修改卡状态"
+// @Router /computer/statusOperation [post]
+func (s *ApiComputer) PcStatusOperation(c *gin.Context) {
+	var paramsInfo request.PcStatusOperationRequest
+	_ = c.ShouldBindJSON(&paramsInfo)
+	if paramsInfo.Id == 0 {
+		response.FailWithMessage("Id不能为空", c)
+		return
+	}
+	if paramsInfo.Status == 0 {
+		response.FailWithMessage("状态值不能为空", c)
+		return
+	}
+	var computer log.Computer
+	computer.Id = paramsInfo.Id
+	computer.Status = paramsInfo.Status
+	if err := ServiceComputer.UpdatePcStatus(computer); err != nil {
+		global.GVA_LOG.Error("修改失败!", zap.Error(err))
+		response.FailWithMessage(err.Error(), c)
+	} else {
+		response.OkWithMessage("修改成功", c)
+	}
+}
+
+// @Tags computer
+// @Summary 导入Excel文件
+// @Security ApiKeyAuth
+// @accept multipart/form-data
+// @Produce  application/json
+// @Param file formData file true "导入Excel文件"
+// @Success 200 {object} response.Response{msg=string} "导入Excel文件"
+// @Router /computer/importExcel [post]
+func (e *ApiComputer) ImportExcel(c *gin.Context) {
+	_, header, err := c.Request.FormFile("file")
+	if err != nil {
+		global.GVA_LOG.Error("接收文件失败!", zap.Error(err))
+		response.FailWithMessage("接收文件失败", c)
+		return
+	}
+	//创建目录
+	uploadDir := global.GVA_CONFIG.Excel.Dir + strconv.Itoa(int(time.Now().Unix())) + "/"
+	err = os.MkdirAll(uploadDir, os.ModePerm)
+	if err != nil {
+		response.FailWithMessage("接收文件失败"+err.Error(), c)
+		return
+	}
+	filePath := uploadDir + "PcCodeExcelImport.xlsx"
+	err = c.SaveUploadedFile(header, filePath)
+	if err != nil {
+		response.FailWithMessage("接收文件失败"+err.Error(), c)
+		return
+	}
+	err = ServiceComputer.ParseExcel2InfoList(filePath)
+	if err != nil {
+		response.FailWithMessage("接收文件失败"+err.Error(), c)
+		return
+	}
+	response.OkWithMessage("导入成功", c)
+}

+ 2 - 0
api/v1/log/enter.go

@@ -8,6 +8,7 @@ type GroupLog struct {
 	ApiLogCoding
 	ApiEnvLog
 	ApiLoging
+	ApiComputer
 }
 
 var (
@@ -16,4 +17,5 @@ var (
 	ServiceLogList         = service.ServiceGroupApp.LogServiceGroup.ServiceLogList
 	ServiceReportPointsLog = service.ServiceGroupApp.LogServiceGroup.ServiceReportPointsLog
 	ServiceStatisticsLog   = service.ServiceGroupApp.LogServiceGroup.ServiceStatisticsLog
+	ServiceComputer        = service.ServiceGroupApp.LogServiceGroup.ServiceComputer
 )

+ 29 - 1
api/v1/log/loging.go

@@ -6,6 +6,7 @@ import (
 	"go.uber.org/zap"
 	"log-server/global"
 	"log-server/model/common/response"
+	"log-server/model/example"
 	"log-server/model/log/request"
 	"log-server/service/log"
 	loging2 "log-server/service/log/loging"
@@ -340,6 +341,33 @@ func (s *ApiLoging) ComputerHeartbeat(c *gin.Context) {
 func (s *ApiLoging) ComputerTest(c *gin.Context) {
 	var paramsInfo request.OnlineComputerRequest
 	_ = c.ShouldBindJSON(&paramsInfo)
-	ServiceStatisticsLog.CreateComputerStatisticsData()
+	ServiceStatisticsLog.RegularCheckPc()
 	response.OkWithDetailed(0, "上报成功", c)
 }
+
+// @Tags excel
+// @Summary 导出Excel
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce  application/octet-stream
+// @Param data body example.ExcelInfo true "导出Excel文件信息"
+// @Success 200
+// @Router /excel/exportExcel [post]
+func (e *ApiLoging) ExportExcel(c *gin.Context) {
+	var createDate request.CreateDateReply
+	_ = c.ShouldBindJSON(&createDate)
+	if createDate.CreateDate == "" {
+		global.GVA_LOG.Error("参数错误!")
+		response.FailWithMessage("参数错误", c)
+	}
+	fileName := createDate.CreateDate + "-pc.xlsx"
+	filePath := global.GVA_CONFIG.Excel.Dir + fileName
+	err := excelService.ParseInfoList2Excel(excelInfo.InfoList, filePath)
+	if err != nil {
+		global.GVA_LOG.Error("转换Excel失败!", zap.Error(err))
+		response.FailWithMessage("转换Excel失败", c)
+		return
+	}
+	c.Writer.Header().Add("success", "true")
+	c.File(filePath)
+}

+ 2 - 0
initialize/router.go

@@ -19,6 +19,7 @@ func Routers() *gin.Engine {
 	systemRouter := router.RouterGroupApp.System
 	exampleRouter := router.RouterGroupApp.Example
 	logingRouter := router.RouterGroupApp.Loging
+	computerRouter := router.RouterGroupApp.Computer
 
 	// 如果想要不使用nginx代理前端网页,可以修改 web/.env.production 下的
 	// VUE_APP_BASE_API = /
@@ -52,6 +53,7 @@ func Routers() *gin.Engine {
 		systemRouter.InitInitRouter(PublicGroup) // 自动初始化相关
 		logingRouter.InitLogingRouter(PublicGroup)
 		logingRouter.InitCodingLogRouter(PublicGroup)
+		computerRouter.InitComputerRouter(PublicGroup)
 	}
 	PrivateGroup := Router.Group("")
 	PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())

+ 70 - 0
model/log/computer.go

@@ -0,0 +1,70 @@
+package log
+
+import (
+	"context"
+	"log-server/global"
+)
+
+type Computer struct {
+	Id         uint   `json:"id"`
+	PcCode     string `json:"pc_code"`
+	User       string `json:"user"`
+	Status     int    `json:"status"`
+	CreateTime string `json:"create_time"` // 创建时间
+	UpdateTime string `json:"update_time"` // 更新时间
+	Supplier   string `json:"supplier"`    //电脑供应商
+}
+
+func (Computer) TableName() string {
+	return "computer"
+}
+
+const OnlinePcCode = "Online:PcCode"
+
+func (c *Computer) OnlinePcCodeCache() (mps map[string]string, err error) {
+	ctx := context.Background()
+	isNull, _ := global.GVA_REDIS.Exists(ctx, OnlinePcCode).Result()
+	if isNull != 0 {
+		mps, err = global.GVA_REDIS.HGetAll(ctx, OnlinePcCode).Result()
+		return
+	}
+	var computers []*Computer
+	err = global.GVA_DB.Where("status = ?", 1).Find(&computers).Error
+	if err != nil {
+		return
+	}
+	if len(computers) == 0 {
+		return
+	}
+	var mp = map[string]string{}
+	for _, pc := range computers {
+		mp[pc.PcCode] = pc.User
+	}
+	err = global.GVA_REDIS.HSet(ctx, OnlinePcCode, mp).Err()
+	if err != nil {
+		return
+	}
+	return mp, err
+}
+
+// 更新单条缓存数据
+func (c *Computer) UpdateOnlinePcCodeCache(pcCode, user string) (err error) {
+	ctx := context.Background()
+	err = global.GVA_REDIS.HSet(ctx, OnlinePcCode, pcCode, user).Err()
+	return
+}
+
+// 删除单条缓存数据
+func (c *Computer) DelOnlinePcCodeCache(pcCode string) (err error) {
+	ctx := context.Background()
+	err = global.GVA_REDIS.HDel(ctx, OnlinePcCode, pcCode).Err()
+	return
+}
+
+// 清空缓存数据
+func (c *Computer) DelAllOnlinePcCodeCache() (err error) {
+	ctx := context.Background()
+	keys, _ := global.GVA_REDIS.HKeys(ctx, OnlinePcCode).Result()
+	err = global.GVA_REDIS.HDel(ctx, OnlinePcCode, keys...).Err()
+	return
+}

+ 1 - 0
model/log/log_computer.go

@@ -15,6 +15,7 @@ type LogComputer struct {
 	GameFeeRate             int    `json:"game_fee_rate"`
 	ComputerHourAverageRate int    `json:"computer_hour_average_rate"`
 	EnterMain               int    `json:"enter_main"`
+	Status                  int    `json:"status"`
 }
 
 func (LogComputer) TableName() string {

+ 49 - 0
model/log/loging.go

@@ -1,5 +1,11 @@
 package log
 
+import (
+	"fmt"
+	"log-server/global"
+	"time"
+)
+
 type Loging struct {
 	Id           uint   `json:"id"`
 	SimulatorIp  string `json:"simulator_ip"`
@@ -29,3 +35,46 @@ type Loging struct {
 func (Loging) TableName() string {
 	return "loging"
 }
+
+func (Loging) CreateLogingTable() (err error) {
+	tableName := fmt.Sprintf("loging_%s", time.Now().Add(+time.Hour*24*31).Format("2006-01"))
+	sql := "DROP TABLE IF EXISTS `" + tableName + "`"
+	err = global.GVA_DB.Exec(sql).Error
+	if err != nil {
+		return err
+	}
+	sql = fmt.Sprintf("CREATE TABLE `%s` (", tableName)
+	sql += "  `id` int(11) NOT NULL AUTO_INCREMENT,"
+	sql += " `simulator_ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模拟器ip',"
+	sql += " `simulator_mac` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模拟器mac地址',"
+	sql += " `pc_code` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '租机编号',"
+	sql += " `pc_mac` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '租机mac地址',"
+	sql += " `pc_ip` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '租机ip',"
+	sql += " `device_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '绑定设备id',"
+	sql += " `account` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '账号',"
+	sql += " `game_id` int NOT NULL COMMENT '游戏id',"
+	sql += " `coding` int NOT NULL COMMENT '日志编号',"
+	sql += " `node_coding` int NOT NULL COMMENT '日志节点编号',"
+	sql += " `type_coding` int NOT NULL COMMENT '日志类型编号',"
+	sql += " `computer_type` int DEFAULT '1' COMMENT '电脑类型1电脑2板子',"
+	sql += " `env_code` int NOT NULL COMMENT '环境编号',"
+	sql += " `account_type` int DEFAULT '1' COMMENT '账号类型',"
+	sql += " `status` tinyint(1) DEFAULT '1' COMMENT '状态1成功2失败',"
+	sql += " `remarks` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',"
+	sql += " `log_uuid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '日志唯一id',"
+	sql += " `operator` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '脚本开发员',"
+	sql += " `create_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',"
+	sql += " `create_date` date DEFAULT NULL COMMENT '创建日期',"
+	sql += " `task_type` tinyint(1) DEFAULT '0' COMMENT '新增1 活跃2',"
+	sql += " `script_type` tinyint(1) DEFAULT '0',"
+	sql += " PRIMARY KEY (`id`) USING BTREE,"
+	sql += " KEY `log_uuid` (`log_uuid`) USING BTREE,"
+	sql += " KEY `date_game_id` (`create_date`,`game_id`),"
+	sql += " KEY `coding` (`coding`)"
+	sql += ") ENGINE=InnoDB DEFAULT CHARSET=utf8;"
+	err = global.GVA_DB.Exec(sql).Error
+	if err != nil {
+		return err
+	}
+	return
+}

+ 5 - 0
model/log/request/common.go

@@ -12,6 +12,11 @@ type GetById struct {
 	ID int `json:"id" form:"id"` // 主键ID
 }
 
+// Create Date Find by id structure
+type CreateDateReply struct {
+	CreateDate string `json:"create_date"` // 日期
+}
+
 func (r *GetById) Uint() uint {
 	return uint(r.ID)
 }

+ 25 - 0
model/log/request/computer.go

@@ -0,0 +1,25 @@
+package request
+
+import (
+	"log-server/model/log"
+)
+
+type GetPcListRequest struct {
+	log.Computer
+	PageInfo
+	OrderKey string `json:"orderKey"` // 排序
+	Desc     bool   `json:"desc"`     // 排序方式:升序false(默认)|降序true
+}
+
+type CreateUpdatePcRequest struct {
+	Id       uint   `json:"id"`
+	PcCode   string `json:"pc_code"`
+	User     string `json:"user"`
+	Status   int    `json:"status"`
+	Supplier string `json:"supplier"`
+}
+
+type PcStatusOperationRequest struct {
+	Id     uint `json:"id"`
+	Status int  `json:"status"`
+}

+ 11 - 0
model/log/response/computer.go

@@ -0,0 +1,11 @@
+package response
+
+type GetPcListReply struct {
+	Id         uint   `json:"id"`
+	PcCode     string `json:"pc_code"`
+	User       string `json:"user"`
+	Status     int    `json:"status"`
+	CreateTime string `json:"create_time"` // 创建时间
+	UpdateTime string `json:"update_time"` // 更新时间
+	Supplier   string `json:"supplier"`    //电脑供应商
+}

+ 10 - 0
model/log/response/loging.go

@@ -53,6 +53,7 @@ type ComputerStatisticsReply1 struct {
 	ComputerFeeRate         int         `json:"computer_fee_rate"`
 	ComputerHourAverageRate int         `json:"computer_hour_average_rate"`
 	EnterMain               int         `json:"enter_main"`
+	Status                  int         `json:"status"`
 	DataNumInfo
 }
 
@@ -68,3 +69,12 @@ type GameIdStatisticsReply struct {
 	OneComputerAverageNum    int    `json:"one_computer_average_num"`
 	EnterMainTotal           int    `json:"enter_main_total"`
 }
+
+type ComputerUseLogReply struct {
+	CreateDate       string `json:"create_date"`
+	PcCode           string `json:"pc_code"`
+	Operator         string `json:"operator"`
+	Status           int    `json:"status"`
+	TaskSuccessTotal int    `json:"task_success_total"`
+	EnterMainTotal   int    `json:"enter_main_total"`
+}

+ 4 - 3
router/enter.go

@@ -7,9 +7,10 @@ import (
 )
 
 type RouterGroup struct {
-	System  system.RouterGroup
-	Example example.RouterGroup
-	Loging  log.RouterGroup
+	System   system.RouterGroup
+	Example  example.RouterGroup
+	Loging   log.RouterGroup
+	Computer log.ComputerRouter
 }
 
 var RouterGroupApp = new(RouterGroup)

+ 22 - 0
router/log/computer.go

@@ -0,0 +1,22 @@
+package log
+
+import (
+	"github.com/gin-gonic/gin"
+	v1 "log-server/api/v1"
+)
+
+type ComputerRouter struct {
+}
+
+func (e *ComputerRouter) InitComputerRouter(Router *gin.RouterGroup) {
+	computerRouter := Router.Group("computer")
+	computerApi := v1.ApiGroupApp.LogApiGroup.ApiComputer
+	{
+		computerRouter.POST("getPcList", computerApi.GetPcList)
+		computerRouter.POST("getPcById", computerApi.GetPcById)
+		computerRouter.POST("createPc", computerApi.CreatePc)
+		computerRouter.POST("updatePc", computerApi.UpdatePc)
+		computerRouter.POST("statusOperation", computerApi.PcStatusOperation)
+		computerRouter.POST("importExcel", computerApi.ImportExcel)
+	}
+}

+ 9 - 8
service/cache/cache.go

@@ -2,7 +2,6 @@ package cache
 
 import (
 	"context"
-	"fmt"
 	"github.com/go-redis/redis/v8"
 	"log-server/global"
 	"time"
@@ -19,9 +18,10 @@ func (s *Cache) DelBatheHsCache(ctx context.Context, key string) (err error) {
 		}
 		return
 	}
-	for _, v := range keys {
-		global.GVA_REDIS.HDel(ctx, key, v)
-	}
+	global.GVA_REDIS.HDel(ctx, key, keys...)
+	//for _, v := range keys {
+	//	global.GVA_REDIS.HDel(ctx, key, v)
+	//}
 	return
 }
 
@@ -33,10 +33,11 @@ func (s *Cache) DelBatheCache(ctx context.Context, key string) (err error) {
 		}
 		return
 	}
-	for _, v := range keys {
-		fmt.Println(v)
-		global.GVA_REDIS.Del(ctx, v)
-	}
+	global.GVA_REDIS.Del(ctx, keys...)
+	//for _, v := range keys {
+	//	fmt.Println(v)
+	//	global.GVA_REDIS.Del(ctx, v)
+	//}
 	return
 }
 

+ 281 - 0
service/log/computer.go

@@ -0,0 +1,281 @@
+package log
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"github.com/xuri/excelize/v2"
+	"go.uber.org/zap"
+	"gorm.io/gorm"
+	"log-server/global"
+	"log-server/model/log"
+	"log-server/model/log/request"
+	"log-server/model/log/response"
+	loging2 "log-server/service/log/loging"
+	"os"
+	"time"
+)
+
+type ServiceComputer struct {
+	Logical loging2.LogicalLog
+}
+
+func (exa *ServiceComputer) ParseExcel2InfoList(filePath string) (err error) {
+	skipHeader := true
+	fixedHeader := []string{"pc_code", "user", "supplier"}
+	file, err := excelize.OpenFile(filePath)
+	if err != nil {
+		return err
+	}
+	var Computers []*log.Computer
+	rows, err := file.Rows("Sheet1")
+	if err != nil {
+		return err
+	}
+	for rows.Next() {
+		row, err := rows.Columns()
+		if err != nil {
+			return err
+		}
+		if skipHeader {
+			if exa.compareStrSlice(row, fixedHeader) {
+				skipHeader = false
+				continue
+			} else {
+				return errors.New("Excel格式错误")
+			}
+		}
+		if len(row) != len(fixedHeader) {
+			continue
+		}
+		c := new(log.Computer)
+		c.PcCode = row[0]
+		c.User = row[1]
+		c.Supplier = row[2]
+		c.CreateTime = time.Now().Format("2006-01-02 15:04:05")
+		c.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
+		c.Status = 1
+		Computers = append(Computers, c)
+	}
+	err = os.RemoveAll(filePath)
+	if err != nil {
+		return
+	}
+	err = global.GVA_DB.Create(Computers).Error
+	if err != nil {
+		return
+	}
+	var cp log.Computer
+	err = cp.DelAllOnlinePcCodeCache()
+	return
+}
+
+func (exa *ServiceComputer) compareStrSlice(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	if (b == nil) != (a == nil) {
+		return false
+	}
+	for key, value := range a {
+		if value != b[key] {
+			return false
+		}
+	}
+	return true
+}
+
+//@author: [piexlmax](https://github.com/piexlmax)
+//@function: GetPcInfoList
+//@description: 分页获取数据,
+//@param: card card.Card, info request.PageInfo, order string, desc bool
+//@return: list interface{}, total int64, err error
+func (apiService *ServiceComputer) GetPcInfoList(api log.Computer, info request.PageInfo, order string, desc bool) (list interface{}, total int64, err error) {
+	limit := info.PageSize
+	offset := info.PageSize * (info.Page - 1)
+	db := global.GVA_DB.Model(&log.Computer{})
+	var apiList []log.Computer
+
+	if api.PcCode != "" {
+		db = db.Where("pc_code LIKE ?", "%"+api.PcCode+"%")
+	}
+
+	if api.User != "" {
+		db = db.Where("user LIKE ?", "%"+api.User+"%")
+	}
+
+	if api.Status != 0 {
+		if api.Status == -1 {
+			db = db.Where("status = ?", 0)
+		}
+	}
+
+	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["id"] = true
+			orderMap["pc_code"] = true
+			orderMap["user"] = true
+			if orderMap[order] {
+				if desc {
+					OrderStr = 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("id").Find(&apiList).Error
+		}
+	}
+	var apisReply []*response.GetPcListReply
+	if len(apiList) != 0 {
+		for _, apiInfo := range apiList {
+			apiReply := new(response.GetPcListReply)
+			apiReply.Id = apiInfo.Id
+			apiReply.Status = apiInfo.Status
+			apiReply.PcCode = apiInfo.PcCode
+			apiReply.Supplier = apiInfo.Supplier
+			apiReply.UpdateTime = apiInfo.UpdateTime
+			apiReply.CreateTime = apiInfo.CreateTime
+			apiReply.User = apiInfo.User
+			apisReply = append(apisReply, apiReply)
+		}
+
+	}
+	return apisReply, total, err
+}
+
+//@author: [piexlmax](https://github.com/piexlmax)
+//@function: GetPcById
+//@description: 根据id获取pc
+//@param: id uint
+//@return: apiReply response.GetPcListReply, err error
+func (c *ServiceComputer) GetPcById(id int) (cardReply response.GetPcListReply, err error) {
+	var api log.Computer
+	err = global.GVA_DB.Where("id = ?", id).First(&api).Error
+	if err != nil {
+		return
+	}
+	cardReply.Id = api.Id
+	cardReply.Status = api.Status
+	cardReply.Supplier = api.Supplier
+	cardReply.User = api.User
+	cardReply.PcCode = api.PcCode
+	cardReply.CreateTime = api.CreateTime
+	cardReply.UpdateTime = api.UpdateTime
+	return
+}
+
+func (a *ServiceComputer) CreatePc(c log.Computer) (err error) {
+	if !errors.Is(global.GVA_DB.Where("pc_code = ?", c.PcCode).First(&log.Computer{}).Error, gorm.ErrRecordNotFound) {
+		return errors.New("存在相同编号")
+	}
+	c.CreateTime = time.Now().Format("2006-01-02 15:04:05")
+	c.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
+	err = global.GVA_DB.Create(&c).Error
+	if err != nil {
+		return err
+	}
+	if c.Status == 1 {
+		err = c.UpdateOnlinePcCodeCache(c.PcCode, c.User)
+	}
+	return
+}
+
+//@author: [piexlmax](https://github.com/piexlmax)
+//@function: UpdatePc
+//@description: 根据id更新pc
+//@param: Computer log.Computer
+//@return: err error
+func (a *ServiceComputer) UpdatePc(c log.Computer) (err error) {
+	var oldA log.Computer
+	err = global.GVA_DB.Where("id = ?", c.Id).First(&oldA).Error
+	if err != nil {
+		return err
+	}
+	if oldA.PcCode != c.PcCode {
+		if !errors.Is(global.GVA_DB.Where("pc_code = ?", c.PcCode).First(&log.Computer{}).Error, gorm.ErrRecordNotFound) {
+			return errors.New("存在相同编号")
+		}
+	}
+	var updateInfo = make(map[string]interface{})
+	updateInfo["pc_code"] = c.PcCode
+	updateInfo["user"] = c.User
+	updateInfo["supplier"] = c.Supplier
+	updateInfo["status"] = c.Status
+	err = global.GVA_DB.Table("computer").Where("id", c.Id).Updates(updateInfo).Error
+	if err != nil {
+		return err
+	}
+	if c.Status == -1 {
+		err = oldA.DelOnlinePcCodeCache(c.PcCode)
+	} else if c.Status == 1 {
+		err = oldA.UpdateOnlinePcCodeCache(c.PcCode, c.User)
+	}
+	return err
+}
+
+//@author: [piexlmax](https://github.com/piexlmax)
+//@function: UpdatePcStatus
+//@description: 根据id更新 status
+//@param: Computer log.Computer
+//@return: err error
+func (a *ServiceComputer) UpdatePcStatus(c log.Computer) (err error) {
+	var oldA log.Computer
+	err = global.GVA_DB.Where("id = ?", c.Id).First(&oldA).Error
+	if err != nil {
+		return err
+	}
+	err = global.GVA_DB.Table("computer").Where("id", c.Id).Update("status", c.Status).Error
+	return err
+}
+
+// 定时检查电脑情况
+func (s *ServiceComputer) RegularCheckPc() {
+	ctx := context.Background()
+	date := s.Logical.CurrentDate()
+	// 获取当天已上报的电脑数据
+	onlineComputerMpa, _ := s.Logical.GetOnlineComputerNumCache(ctx, date)
+	// 获取数据库的数据
+	var computer log.Computer
+	computers, err := computer.OnlinePcCodeCache()
+	if err != nil {
+		global.GVA_LOG.Error("获取租机表数据失败", zap.Error(err))
+	}
+	// 查询两小时内上报的数据
+	var noReportingPc []string
+	for pc, _ := range onlineComputerMpa {
+		num := s.Logical.GetPcReportingLog(ctx, pc)
+		delete(computers, pc)
+		if num == 0 {
+			noReportingPc = append(noReportingPc, pc)
+		}
+	}
+	// 未上报逻辑
+	var errReportingPc []string
+	for pc, _ := range computers {
+		errReportingPc = append(errReportingPc, pc)
+	}
+	if len(errReportingPc) != 0 {
+		// 发信息数据群里
+		fmt.Println("异常上报数据: ", errReportingPc, len(errReportingPc))
+	}
+
+	if len(noReportingPc) != 0 {
+		// 发信息数据群里
+		fmt.Println("两小时内未检测到上报数据: ", noReportingPc, len(noReportingPc))
+	}
+}

+ 1 - 0
service/log/enter.go

@@ -7,4 +7,5 @@ type ServiceGroup struct {
 	ServiceReportPointsLog
 	ServiceLogList
 	ServiceStatisticsLog
+	ServiceComputer
 }

+ 3 - 14
service/log/log_list.go

@@ -126,19 +126,6 @@ func (s *ServiceLogList) GetCodeLogList(ctx context.Context, api log.Loging, inf
 	return apisReply, total, err
 }
 
-/*var loging1 = map[string]ServiceLoging{
-	"410":new(loging2.PullAccountLog),
-	"430":new(loging2.SimulatorStartLog),
-	//"450":new(loging2.ScriptStartLog),
-	"450":new(loging2.GameStartLog),
-	"460":new(loging2.LoginLog),
-	//"470":new(loging2.EnterGameLog),
-	"470":new(loging2.EnterMainLog),
-	"480":new(loging2.FeeLog),
-	"490":new(loging2.TaskEndLog),
-	"other":new(loging2.OtherLog),
-}*/
-
 var failCacheKey = "%s:fail:list"
 
 func (s *ServiceLogList) CreateLog(c context.Context, request request.AddLogRequest, logical ServiceLoging, status, noLogStatus string) {
@@ -150,6 +137,9 @@ func (s *ServiceLogList) CreateLog(c context.Context, request request.AddLogRequ
 	} else {
 		err = logical.FailLog(c, request)
 	}
+	if request.Coding == 4301001 {
+		return
+	}
 	if err != nil {
 		body, _ := json.Marshal(request)
 		current := time.Now().Format("2006-01-02")
@@ -230,5 +220,4 @@ func (s *ServiceLogList) CreateFailLog() {
 		s.CreateLog(c, data, logical, status, noLogStatus)
 		global.GVA_LOG.Info("重试!: " + data.LogUuid + " code: " + strconv.Itoa(data.Coding))
 	}
-
 }

+ 96 - 11
service/log/log_statistics.go

@@ -6,12 +6,14 @@ import (
 	"errors"
 	"fmt"
 	"github.com/go-redis/redis/v8"
+	"github.com/xuri/excelize/v2"
 	"go.uber.org/zap"
 	"gorm.io/gorm"
 	"log-server/global"
 	"log-server/model/log"
 	"log-server/model/log/request"
 	"log-server/model/log/response"
+	"log-server/model/system"
 	loging2 "log-server/service/log/loging"
 	"math"
 	"strconv"
@@ -488,6 +490,7 @@ func (s *ServiceStatisticsLog) EveryDayResetStatisticsCache() {
 	global.GVA_LOG.Info("游戏重置缓存完成!")
 }
 
+// 添加和更新电脑指标数据
 func (s *ServiceStatisticsLog) CreateComputerStatisticsData() {
 	ctx := context.Background()
 	codeMps, err := s.LogicalLog.GetComputerCache(ctx, s.LogicalLog.CurrentDate())
@@ -499,7 +502,8 @@ func (s *ServiceStatisticsLog) CreateComputerStatisticsData() {
 	}
 	key := fmt.Sprintf(taskStatistics, s.LogicalLog.CurrentDate())
 	onlineComputerMpa, _ := s.LogicalLog.GetOnlineComputerNumCache(ctx, s.LogicalLog.CurrentDate())
-	fmt.Println(onlineComputerMpa)
+	var computer log.Computer
+	computerData, _ := computer.OnlinePcCodeCache()
 	var csReplys []*log.LogComputer
 	for code, r := range codeMps {
 		accountMps, err := s.LogicalLog.GetComputerPullAccountNumCache(ctx, s.LogicalLog.CurrentDate(), code)
@@ -514,13 +518,13 @@ func (s *ServiceStatisticsLog) CreateComputerStatisticsData() {
 		if err != nil {
 			continue
 		}
-
+		delete(computerData, code)
 		for gameId, num := range accountMps {
 			csReply := new(log.LogComputer)
+			csReply.PcCode = code
 			if _, ok := onlineComputerMpa[csReply.PcCode]; ok {
 				delete(onlineComputerMpa, csReply.PcCode)
 			}
-			csReply.PcCode = code
 			csReply.Operator = r
 			data, err := global.GVA_REDIS.HGet(ctx, key, gameId).Result()
 			if err != nil {
@@ -545,6 +549,7 @@ func (s *ServiceStatisticsLog) CreateComputerStatisticsData() {
 			csReply.GameFeeRate = s.GetStatisticsFeeRate(ctx, csReply.GameId)
 			runTime := time.Now().Hour() + 1 - csReply.ComputerFreeTime
 			csReply.ComputerHourAverageRate = csReply.TaskSuccessNum / runTime
+			csReply.Status = 2
 			global.GVA_DB.Where("create_date = ?", csReply.CreateDate).Where("pc_code = ?", csReply.PcCode).Where("game_id = ?", 0).Delete(&log.LogComputer{})
 			if !errors.Is(global.GVA_DB.Where("create_date = ?", csReply.CreateDate).Where("pc_code = ?", csReply.PcCode).First(&log.LogComputer{}).Error, gorm.ErrRecordNotFound) {
 				// 已存在,更新
@@ -579,10 +584,34 @@ func (s *ServiceStatisticsLog) CreateComputerStatisticsData() {
 	if len(onlineComputerMpa) != 0 {
 		var onlineComputer []*log.LogComputer
 		for pcCode, op := range onlineComputerMpa {
+			delete(computerData, pcCode)
 			csReply := new(log.LogComputer)
 			csReply.PcCode = pcCode
 			csReply.Operator = op
 			csReply.CreateDate = time.Now().Format("2006-01-02")
+			csReply.Status = 1
+			if !errors.Is(global.GVA_DB.Where("create_date = ?", csReply.CreateDate).Where("pc_code = ?", csReply.PcCode).First(&log.LogComputer{}).Error, gorm.ErrRecordNotFound) {
+				continue
+			}
+			onlineComputer = append(onlineComputer, csReply)
+		}
+		if len(onlineComputer) != 0 {
+			err = global.GVA_DB.Table("log_computer").Create(onlineComputer).Error
+			if err != nil {
+				global.GVA_LOG.Error("更新数据失败", zap.Error(err))
+			}
+		}
+	}
+
+	// 没记录电脑数据
+	if len(computerData) != 0 {
+		var onlineComputer []*log.LogComputer
+		for pcCode, op := range computerData {
+			csReply := new(log.LogComputer)
+			csReply.PcCode = pcCode
+			csReply.Operator = op
+			csReply.CreateDate = time.Now().Format("2006-01-02")
+			csReply.Status = -1
 			if !errors.Is(global.GVA_DB.Where("create_date = ?", csReply.CreateDate).Where("pc_code = ?", csReply.PcCode).First(&log.LogComputer{}).Error, gorm.ErrRecordNotFound) {
 				continue
 			}
@@ -704,6 +733,9 @@ func (s *ServiceStatisticsLog) OnlineComputerStatistics(ctx context.Context, api
 	if api.PcCode != "" {
 		db = db.Where("pc_code = ?", api.PcCode)
 	}
+	if api.Status != 0 {
+		db = db.Where("status = ?", api.Status)
+	}
 	db = db.Group("pc_code")
 	err := db.Count(&total).Error
 	if err != nil {
@@ -744,14 +776,7 @@ func (s *ServiceStatisticsLog) OnlineComputerStatistics(ctx context.Context, api
 		statisticsLogComputer.PcCode = statisticsLog.PcCode
 		statisticsLogComputer.Operator = statisticsLog.Operator
 		statisticsLogComputer.CreateDate = statisticsLog.CreateDate[:10]
-		statisticsLogComputer.GameId = statisticsLog.GameId
-		statisticsLogComputer.PullAccountNum = statisticsLog.PullAccountNum
-		statisticsLogComputer.TaskSuccessNum = statisticsLog.TaskSuccessNum
-		statisticsLogComputer.TargetNum = statisticsLog.TargetNum
-		statisticsLogComputer.ComputerFreeTime = statisticsLog.ComputerFreeTime
-		statisticsLogComputer.ComputerFeeRate = statisticsLog.ComputerFeeRate
-		statisticsLogComputer.EnterMain = statisticsLog.EnterMain
-		statisticsLogComputer.ComputerHourAverageRate = statisticsLog.ComputerHourAverageRate
+		statisticsLogComputer.Status = statisticsLog.Status
 		statisticsLogsComputer = append(statisticsLogsComputer, statisticsLogComputer)
 	}
 	return statisticsLogsComputer, total, err
@@ -923,6 +948,10 @@ func (s *ServiceStatisticsLog) GetComputerNum(date string) int64 {
 // 在线电脑接口
 func (s *ServiceStatisticsLog) ComputerHeartbeat(c context.Context, onlineComputer request.OnlineComputerRequest) error {
 	err := s.LogicalLog.SetOnlineComputerNumCache(c, s.LogicalLog.CurrentDate(), onlineComputer.PcCode, onlineComputer.Operator)
+	if err != nil {
+		return err
+	}
+	s.LogicalLog.SetPcReportingLog(c, onlineComputer.PcCode, onlineComputer.Operator)
 	return err
 }
 
@@ -934,3 +963,59 @@ func (s *ServiceStatisticsLog) ComputerTest(c context.Context) (interface{}, err
 	}
 	return mps, err
 }
+
+// 定时检查电脑情况
+func (s *ServiceStatisticsLog) RegularCheckPc() {
+	ctx := context.Background()
+	date := s.LogicalLog.CurrentDate()
+	// 获取当天已上报的电脑数据
+	onlineComputerMpa, _ := s.LogicalLog.GetOnlineComputerNumCache(ctx, date)
+	// 获取数据库的数据
+	var computer log.Computer
+	computers, err := computer.OnlinePcCodeCache()
+	if err != nil {
+		global.GVA_LOG.Error("获取租机表数据失败", zap.Error(err))
+	}
+	// 查询两小时内上报的数据
+	var noReportingPc []string
+	for pc, _ := range onlineComputerMpa {
+		num := s.LogicalLog.GetPcReportingLog(ctx, pc)
+		delete(computers, pc)
+		if num == 0 {
+			noReportingPc = append(noReportingPc, pc)
+		}
+	}
+	// 未上报逻辑
+	var errReportingPc []string
+	for pc, _ := range computers {
+		errReportingPc = append(errReportingPc, pc)
+	}
+	if len(errReportingPc) != 0 {
+		// 发信息数据群里
+		fmt.Println("异常上报数据: ", errReportingPc, len(errReportingPc))
+	}
+
+	if len(noReportingPc) != 0 {
+		// 发信息数据群里
+		fmt.Println("两小时内未检测到上报数据: ", noReportingPc, len(noReportingPc))
+	}
+}
+
+func (exa *ServiceStatisticsLog) ParseInfoList2Excel(infoList []system.SysBaseMenu, filePath string) error {
+	excel := excelize.NewFile()
+	excel.SetSheetRow("Sheet1", "A1", &[]string{"ID", "路由Name", "路由Path", "是否隐藏", "父节点", "排序", "文件名称"})
+	for i, menu := range infoList {
+		axis := fmt.Sprintf("A%d", i+2)
+		excel.SetSheetRow("Sheet1", axis, &[]interface{}{
+			menu.ID,
+			menu.Name,
+			menu.Path,
+			menu.Hidden,
+			menu.ParentId,
+			menu.Sort,
+			menu.Component,
+		})
+	}
+	err := excel.SaveAs(filePath)
+	return err
+}

+ 35 - 1
service/log/loging/logical_log.go

@@ -31,8 +31,8 @@ var (
 	GameFeeRateCacheKey         = "%s:game:gameFeeRate:%d"
 	GameComputerRateCacheKey    = "%s:Computer:Rate:%s:"
 	GamePcFeeRateCacheKey       = "%s:gamePc:gameFeeRate:%d:%s"
-	PcGameFeeRateCacheKey       = "%s:PcGame:FeeRate:%s"
 	OnLineComputerNum           = "%s:OnLineComputerNum:"
+	PcReportingLog              = "%s:pc:Reporting:%s"
 )
 
 type LogicalLog struct {
@@ -714,3 +714,37 @@ func (s *LogicalLog) GetAllOnlineComputerNumCache(ctx context.Context, key strin
 	}
 	return
 }
+
+// 获取电脑2小时内上报的次数
+func (s *LogicalLog) GetPcReportingLog(ctx context.Context, pcCode string) (num int) {
+	key := fmt.Sprintf(PcReportingLog, s.CurrentDate(), pcCode)
+	z, err := global.GVA_REDIS.ZRangeWithScores(ctx, key, -1, -1).Result()
+	if err != nil {
+		return
+	}
+	if len(z) == 0 {
+		return
+	}
+	end := time.Now().UnixNano() / 1e6
+	start := end - (120*60*1000 + 60*1000)
+	op := redis.ZRangeBy{
+		Min: strconv.Itoa(int(start)),
+		Max: strconv.Itoa(int(end)),
+	}
+	i, err := global.GVA_REDIS.ZRangeByScore(ctx, key, &op).Result()
+	if err != nil {
+		return
+	}
+	num = len(i)
+	return
+}
+
+// 添加电脑定时上报记录
+func (s *LogicalLog) SetPcReportingLog(ctx context.Context, pcCode string, operator string) {
+	key := fmt.Sprintf(PcReportingLog, s.CurrentDate(), pcCode)
+	z := &redis.Z{
+		Member: operator,
+		Score:  float64(time.Now().UnixNano() / 1e6),
+	}
+	global.GVA_REDIS.ZAdd(ctx, key, z)
+}

+ 1 - 0
utils/verify.go

@@ -18,4 +18,5 @@ var (
 	SetUserAuthorityVerify = Rules{"AuthorityId": {NotEmpty()}}
 	LogCodingVerify        = Rules{"Coding": {NotEmpty()}, "Describe": {NotEmpty()}}
 	LogAddVerify           = Rules{"LogUuid": {NotEmpty()}, "Coding": {NotEmpty()}}
+	PcVerify               = Rules{"PcCode": {NotEmpty()}, "User": {NotEmpty()}, "Supplier": {NotEmpty()}}
 )