diff --git a/apis/public/user.api b/apis/public/user.api index 1686b32..963c4ad 100644 --- a/apis/public/user.api +++ b/apis/public/user.api @@ -106,6 +106,22 @@ type ( UnbindDeviceRequest { Id int64 `json:"id" validate:"required"` } + + GetDeviceOnlineStatsResponse { + WeeklyStats []WeeklyStat `json:"weekly_stats"` + ConnectionRecords ConnectionRecords `json:"connection_records"` + } + + WeeklyStat { + Day int `json:"day"` + DayName string `json:"day_name"` + Hours float64 `json:"hours"` + } + ConnectionRecords { + CurrentContinuousDays int64 `json:"current_continuous_days"` + HistoryContinuousDays int64 `json:"history_continuous_days"` + LongestSingleConnection int64 `json:"longest_single_connection"` + } ) @server ( @@ -209,5 +225,21 @@ service ppanel { @doc "Unbind Device" @handler UnbindDevice put /unbind_device (UnbindDeviceRequest) + + @doc "Device Online Statistics" + @handler DeviceOnlineStatistics + get /device_online_statistics returns (GetDeviceOnlineStatsResponse) } + +@server( + prefix: v1/public/user + group: public/user/ws + middleware: AuthMiddleware +) + +service ppanel { + @doc "Webosocket Device Connect" + @handler DeviceWsConnect + get /device_ws_connect +} \ No newline at end of file diff --git a/internal/handler/public/user/deviceOnlineStatisticsHandler.go b/internal/handler/public/user/deviceOnlineStatisticsHandler.go new file mode 100644 index 0000000..aa4afef --- /dev/null +++ b/internal/handler/public/user/deviceOnlineStatisticsHandler.go @@ -0,0 +1,18 @@ +package user + +import ( + "github.com/gin-gonic/gin" + "github.com/perfect-panel/server/internal/logic/public/user" + "github.com/perfect-panel/server/internal/svc" + "github.com/perfect-panel/server/pkg/result" +) + +// Device Online Statistics +func DeviceOnlineStatisticsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { + return func(c *gin.Context) { + + l := user.NewDeviceOnlineStatisticsLogic(c.Request.Context(), svcCtx) + resp, err := l.DeviceOnlineStatistics() + result.HttpResult(c, resp, err) + } +} diff --git a/internal/handler/public/user/ws/deviceWsConnectHandler.go b/internal/handler/public/user/ws/deviceWsConnectHandler.go new file mode 100644 index 0000000..d07562c --- /dev/null +++ b/internal/handler/public/user/ws/deviceWsConnectHandler.go @@ -0,0 +1,29 @@ +package ws + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" + wslogic "github.com/perfect-panel/server/internal/logic/public/user/ws" + "github.com/perfect-panel/server/internal/svc" + "github.com/perfect-panel/server/pkg/result" +) + +var upGrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { + return true // 允许所有来源,生产环境中应该根据需求限制 + }, +} + +// Webosocket Device Connect +func DeviceWsConnectHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) { + return func(c *gin.Context) { + + l := wslogic.NewDeviceWsConnectLogic(c.Request.Context(), svcCtx) + err := l.DeviceWsConnect(c) + result.HttpResult(c, nil, err) + } +} diff --git a/internal/handler/routes.go b/internal/handler/routes.go index d42ac7e..94e0fe4 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -33,6 +33,7 @@ import ( publicSubscribe "github.com/perfect-panel/server/internal/handler/public/subscribe" publicTicket "github.com/perfect-panel/server/internal/handler/public/ticket" publicUser "github.com/perfect-panel/server/internal/handler/public/user" + publicUserWs "github.com/perfect-panel/server/internal/handler/public/user/ws" server "github.com/perfect-panel/server/internal/handler/server" "github.com/perfect-panel/server/internal/middleware" "github.com/perfect-panel/server/internal/svc" @@ -795,6 +796,9 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { // Query User Commission Log publicUserGroupRouter.GET("/commission_log", publicUser.QueryUserCommissionLogHandler(serverCtx)) + // Device Online Statistics + publicUserGroupRouter.GET("/device_online_statistics", publicUser.DeviceOnlineStatisticsHandler(serverCtx)) + // Get Device List publicUserGroupRouter.GET("/devices", publicUser.GetDeviceListHandler(serverCtx)) @@ -841,6 +845,14 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { publicUserGroupRouter.POST("/verify_email", publicUser.VerifyEmailHandler(serverCtx)) } + publicUserWsGroupRouter := router.Group("/v1/public/user") + publicUserWsGroupRouter.Use(middleware.AuthMiddleware(serverCtx)) + + { + // Webosocket Device Connect + publicUserWsGroupRouter.GET("/device_ws_connect", publicUserWs.DeviceWsConnectHandler(serverCtx)) + } + serverGroupRouter := router.Group("/v1/server") serverGroupRouter.Use(middleware.ServerMiddleware(serverCtx)) diff --git a/internal/svc/devce.go b/internal/svc/devce.go index 2d1fd23..1a1556c 100644 --- a/internal/svc/devce.go +++ b/internal/svc/devce.go @@ -51,7 +51,7 @@ func NewDeviceManager(srv *ServiceContext) *device.DeviceManager { //获取设备昨日在线记录 var onlineRecord user.DeviceOnlineRecord - if err := srv.DB.Model(&onlineRecord).Where("user_id = ? and create_at >= ? and create_at < ?", userID, startTime, endTime).First(&onlineRecord).Error; err != nil { + if err := srv.DB.Model(&onlineRecord).Where("user_id = ? and created_at >= ? and created_at < ?", userID, startTime, endTime).First(&onlineRecord).Error; err != nil { //昨日未在线,连续在线天数为1 deviceOnlineRecord.DurationDays = 1 } else { diff --git a/internal/types/types.go b/internal/types/types.go index fd113bd..0e56390 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -239,6 +239,12 @@ type CommissionLog struct { Timestamp int64 `json:"timestamp"` } +type ConnectionRecords struct { + CurrentContinuousDays int64 `json:"current_continuous_days"` + HistoryContinuousDays int64 `json:"history_continuous_days"` + LongestSingleConnection int64 `json:"longest_single_connection"` +} + type Coupon struct { Id int64 `json:"id"` Name string `json:"name"` @@ -822,6 +828,11 @@ type GetDeviceListResponse struct { Total int64 `json:"total"` } +type GetDeviceOnlineStatsResponse struct { + WeeklyStats []WeeklyStat `json:"weekly_stats"` + ConnectionRecords ConnectionRecords `json:"connection_records"` +} + type GetDocumentDetailRequest struct { Id int64 `json:"id" validate:"required"` } @@ -2734,3 +2745,9 @@ type VmessProtocol struct { Network string `json:"network"` Transport string `json:"transport"` } + +type WeeklyStat struct { + Day int `json:"day"` + DayName string `json:"day_name"` + Hours float64 `json:"hours"` +}