Merge remote-tracking branch 'origin/master'
# Conflicts: # api/task/v1/task.go
This commit is contained in:
@ -287,7 +287,8 @@ type GetUserRewardsCanClaimListReq struct {
|
|||||||
g.Meta `path:"/reward/canClaim" method:"get" tags:"PC/Reward" summary:"(PC)获取用户可领取的奖励列表"`
|
g.Meta `path:"/reward/canClaim" method:"get" tags:"PC/Reward" summary:"(PC)获取用户可领取的奖励列表"`
|
||||||
StoreId int64 `json:"storeId" dc:"门店id"`
|
StoreId int64 `json:"storeId" dc:"门店id"`
|
||||||
NetbarAccount string `json:"netbarAccount" dc:"网吧账号"`
|
NetbarAccount string `json:"netbarAccount" dc:"网吧账号"`
|
||||||
TaskId string `json:"taskId" dc:"任务id" v:"required#任务id不能为空"`
|
TaskId string `json:"taskId" dc:"任务id,任务列表使用"`
|
||||||
|
UserTaskId int64 `json:"userTaskId" dc:"用户任务记录id, 任务记录列表使用"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetUserRewardsCanClaimListRes struct {
|
type GetUserRewardsCanClaimListRes struct {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func (c *ControllerV1) GetUserRewardsCanClaimList(ctx context.Context, req *v1.GetUserRewardsCanClaimListReq) (res *v1.GetUserRewardsCanClaimListRes, err error) {
|
func (c *ControllerV1) GetUserRewardsCanClaimList(ctx context.Context, req *v1.GetUserRewardsCanClaimListReq) (res *v1.GetUserRewardsCanClaimListRes, err error) {
|
||||||
userId := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
|
userId := g.RequestFromCtx(ctx).GetCtxVar("id").Int64()
|
||||||
out, err := service.Reward().GetUserClaimList(ctx, &model.GetUserClaimListIn{NetbarAccount: req.NetbarAccount, StoreId: req.StoreId, TaskId: req.TaskId, UserId: userId})
|
out, err := service.Reward().GetUserClaimList(ctx, &model.GetUserClaimListIn{NetbarAccount: req.NetbarAccount, StoreId: req.StoreId, TaskId: req.TaskId, UserId: userId, UserTaskId: req.UserTaskId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import (
|
|||||||
func (c *ControllerV1) GetUserTaskRecordsList(ctx context.Context, req *v1.GetUserTaskRecordsListReq) (res *v1.GetUserTaskRecordsListRes, err error) {
|
func (c *ControllerV1) GetUserTaskRecordsList(ctx context.Context, req *v1.GetUserTaskRecordsListReq) (res *v1.GetUserTaskRecordsListRes, err error) {
|
||||||
fromCtx := g.RequestFromCtx(ctx)
|
fromCtx := g.RequestFromCtx(ctx)
|
||||||
userId := fromCtx.GetCtxVar("id").Int()
|
userId := fromCtx.GetCtxVar("id").Int()
|
||||||
out, err := service.Task().GetUserTaskRecordsList(ctx, &model.UserTaskRecordsListIn{UserId: userId})
|
out, err := service.Task().GetUserTaskRecordsList(ctx, &model.UserTaskRecordsListIn{UserId: userId, StoreId: req.StoreId, Page: req.Page, Size: req.Size, TimeType: req.TimeType, RewardTypeId: req.RewardTypeId, GameId: req.GameId, NetBarAccount: req.NetbarAccount})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -698,25 +698,30 @@ func (s *sReward) CallBack(ctx context.Context, in *model.RewardCallbackIn) (out
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *sReward) GetUserClaimList(ctx context.Context, in *model.GetUserClaimListIn) (out *model.GetUserClaimListOut, err error) {
|
func (s *sReward) GetUserClaimList(ctx context.Context, in *model.GetUserClaimListIn) (out *model.GetUserClaimListOut, err error) {
|
||||||
// Input validation
|
|
||||||
if in == nil || in.UserId == 0 || in.TaskId == "" {
|
|
||||||
return nil, ecode.Params.Sub("用户任务记录不存在")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize result slice
|
// Initialize result slice
|
||||||
rewards := make([]model.Reward, 0)
|
rewards := make([]model.Reward, 0)
|
||||||
var totalCount int
|
var totalCount int
|
||||||
|
|
||||||
// Query user task record
|
var userTaskId int64
|
||||||
userTask, err := dao.UserTasks.Ctx(ctx).
|
if in.UserTaskId == 0 {
|
||||||
Where(do.UserTasks{UserId: in.UserId, TaskId: in.TaskId}).
|
value, err := dao.UserTasks.Ctx(ctx).
|
||||||
Fields(dao.UserTasks.Columns().Id).
|
Where(do.UserTasks{UserId: in.UserId, TaskId: in.TaskId}).
|
||||||
One()
|
Fields(dao.UserTasks.Columns().Id).
|
||||||
if err != nil {
|
Value()
|
||||||
return nil, ecode.Fail.Sub("查询用户任务记录异常")
|
if err != nil {
|
||||||
}
|
return nil, ecode.Fail.Sub("查询用户任务失败")
|
||||||
if userTask == nil {
|
}
|
||||||
return nil, ecode.Params.Sub("用户任务记录不存在")
|
if value.IsEmpty() {
|
||||||
|
return nil, ecode.Fail.Sub("用户任务不存在")
|
||||||
|
}
|
||||||
|
userTaskId = value.Int64()
|
||||||
|
} else {
|
||||||
|
exist, err := dao.UserTasks.Ctx(ctx).WherePri(in.UserTaskId).Exist()
|
||||||
|
if err != nil || !exist {
|
||||||
|
return nil, ecode.Fail.Sub("用户任务不存在")
|
||||||
|
}
|
||||||
|
userTaskId = in.UserTaskId
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build base query for rewards
|
// Build base query for rewards
|
||||||
@ -729,7 +734,7 @@ func (s *sReward) GetUserClaimList(ctx context.Context, in *model.GetUserClaimLi
|
|||||||
Where(fmt.Sprintf("%s.%s = ?",
|
Where(fmt.Sprintf("%s.%s = ?",
|
||||||
dao.UserTaskRewards.Table(),
|
dao.UserTaskRewards.Table(),
|
||||||
dao.UserTaskRewards.Columns().UserTaskId),
|
dao.UserTaskRewards.Columns().UserTaskId),
|
||||||
userTask["id"].Int64()).
|
userTaskId).
|
||||||
Where(dao.UserTaskRewards.Columns().DeletedAt, nil).
|
Where(dao.UserTaskRewards.Columns().DeletedAt, nil).
|
||||||
Where(dao.Rewards.Columns().DeletedAt, nil)
|
Where(dao.Rewards.Columns().DeletedAt, nil)
|
||||||
|
|
||||||
|
|||||||
@ -411,10 +411,22 @@ func (s *sTask) GetUserTaskRecordsList(ctx context.Context, in *model.UserTaskRe
|
|||||||
var total int
|
var total int
|
||||||
orm := dao.UserTasks.Ctx(ctx).Where(dao.UserTasks.Columns().UserId, in.UserId)
|
orm := dao.UserTasks.Ctx(ctx).Where(dao.UserTasks.Columns().UserId, in.UserId)
|
||||||
|
|
||||||
if in.StoreId != 0 {
|
if in.StoreId != 0 && in.NetBarAccount == "" {
|
||||||
orm = orm.Where(dao.UserTasks.Columns().StoreId, in.StoreId)
|
orm = orm.Where(dao.UserTasks.Columns().StoreId, in.StoreId)
|
||||||
}
|
}
|
||||||
err = orm.Page(in.Page, in.Size).WithAll().ScanAndCount(&list, &total, false)
|
if in.NetBarAccount != "" && in.StoreId == 0 {
|
||||||
|
value, err := dao.Stores.Ctx(ctx).Where(do.Stores{NetbarAccount: in.NetBarAccount}).Fields(dao.Stores.Columns().Id).Value()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
orm = orm.Where(dao.UserTasks.Columns().StoreId, value.Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.GameId != 0 {
|
||||||
|
orm = orm.Where(dao.UserTasks.Columns().GameId, in.GameId)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = orm.Page(in.Page, in.Size).ScanAndCount(&list, &total, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取用户任务列表失败")
|
return nil, ecode.Fail.Sub("获取用户任务列表失败")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,19 +32,19 @@ type TaskReward struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserTask2 struct {
|
type UserTask2 struct {
|
||||||
Id int64 `json:"id" orm:"id" description:"用户任务唯一标识符"` // 用户任务唯一标识符
|
Id int64 `json:"id" orm:"id" description:"用户任务唯一标识符"` // 用户任务唯一标识符
|
||||||
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
|
UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID
|
||||||
TaskId string `json:"taskId" orm:"task_id" description:"腾讯任务ID"` // 腾讯任务ID
|
TaskId string `json:"taskId" orm:"task_id" description:"腾讯任务ID"` // 腾讯任务ID
|
||||||
Status int `json:"status" orm:"status" description:"任务状态:1=进行中,2=已完成中,3=未完成"` // 任务状态:1=进行中(显示领取按钮),2=已完成
|
Status int `json:"status" orm:"status" description:"任务状态:1=进行中,2=已完成中,3=未完成"` // 任务状态:1=进行中(显示领取按钮),2=已完成
|
||||||
SerialNumber string `json:"serialNumber" orm:"serial_number" description:"流水号,确保用户任务唯一性"` // 流水号,确保用户任务唯一性
|
SerialNumber string `json:"serialNumber" orm:"serial_number" description:"流水号,确保用户任务唯一性"` // 流水号,确保用户任务唯一性
|
||||||
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
|
||||||
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
|
||||||
CompletedAt *gtime.Time `json:"completedAt" orm:"completed_at" description:"任务完成时间"` // 任务完成时间
|
CompletedAt *gtime.Time `json:"completedAt" orm:"completed_at" description:"任务完成时间"` // 任务完成时间
|
||||||
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
|
||||||
StoreId int64 `json:"storeId" orm:"store_id" description:"门店 id"` // 门店 id
|
StoreId int64 `json:"storeId" orm:"store_id" description:"门店 id"` // 门店 id
|
||||||
TaskName string `json:"taskName" orm:"task_name" description:"任务名称"` // 任务名称
|
TaskName string `json:"taskName" orm:"task_name" description:"任务名称"` // 任务名称
|
||||||
GameId int64 `json:"gameId" orm:"game_id" description:"游戏 id"` // 游戏 id
|
GameId int64 `json:"gameId" orm:"game_id" description:"游戏 id"` // 游戏 id
|
||||||
TaskRewards []TaskReward `json:"taskRewards" orm:"with:task_id=task_id"`
|
//TaskRewards []TaskReward `json:"taskRewards" orm:"with:task_id=task_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserTaskRankingIn 任务排行榜入参
|
// UserTaskRankingIn 任务排行榜入参
|
||||||
@ -100,6 +100,9 @@ type UserTaskRecordsListIn struct {
|
|||||||
Size int
|
Size int
|
||||||
StoreId int
|
StoreId int
|
||||||
NetBarAccount string
|
NetBarAccount string
|
||||||
|
RewardTypeId int
|
||||||
|
TimeType int
|
||||||
|
GameId int
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserTaskRecordsListOut struct {
|
type UserTaskRecordsListOut struct {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import "github.com/gogf/gf/v2/os/gtime"
|
|||||||
|
|
||||||
type GetUserClaimListIn struct {
|
type GetUserClaimListIn struct {
|
||||||
UserId int64
|
UserId int64
|
||||||
|
UserTaskId int64
|
||||||
TaskId string
|
TaskId string
|
||||||
NetbarAccount string
|
NetbarAccount string
|
||||||
StoreId int64
|
StoreId int64
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import (
|
|||||||
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
_ "server/utility/gamelife"
|
_ "server/utility/gamelife"
|
||||||
//_ "server/utility/mqtt/emqx"
|
_ "server/utility/mqtt/emqx"
|
||||||
_ "server/utility/myCasbin"
|
_ "server/utility/myCasbin"
|
||||||
_ "server/utility/oss/aliyun"
|
_ "server/utility/oss/aliyun"
|
||||||
_ "server/utility/rsa"
|
_ "server/utility/rsa"
|
||||||
|
|||||||
@ -63,7 +63,7 @@ type (
|
|||||||
func GenerateToken(in *TokenIn) (string, error) {
|
func GenerateToken(in *TokenIn) (string, error) {
|
||||||
expire := in.ExpireTime
|
expire := in.ExpireTime
|
||||||
if expire <= 0 {
|
if expire <= 0 {
|
||||||
expire = 24 * time.Hour
|
expire = 24 * time.Hour * 30
|
||||||
}
|
}
|
||||||
|
|
||||||
claims := jwtClaims{
|
claims := jwtClaims{
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gogf/gf/v2/encoding/gjson"
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
"server/internal/consts"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
|
"server/internal/dao"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -116,9 +117,10 @@ func init() {
|
|||||||
|
|
||||||
glog.Infof(ctx, "EMQX 客户端注册完成,broker=%s, clientID=%s", broker, clientId)
|
glog.Infof(ctx, "EMQX 客户端注册完成,broker=%s, clientID=%s", broker, clientId)
|
||||||
// 订阅设备上线消息
|
// 订阅设备上线消息
|
||||||
|
// 订阅设备上线消息
|
||||||
go func() {
|
go func() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := client.Subscribe("/up", func(topic string, payload []byte) {
|
err := client.Subscribe("/+/up", func(topic string, payload []byte) {
|
||||||
glog.Infof(ctx, "收到 MQTT 消息,topic=%s", topic)
|
glog.Infof(ctx, "收到 MQTT 消息,topic=%s", topic)
|
||||||
|
|
||||||
var data DeviceData
|
var data DeviceData
|
||||||
@ -127,35 +129,101 @@ func init() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 增加门店在线设备计数
|
deviceId := data.DeviceId
|
||||||
key := fmt.Sprintf(consts.NetbarOnlineNumberKey, data.NetbarAccount)
|
netbarAccount := data.NetbarAccount
|
||||||
if _, err := g.Redis().Incr(ctx, key); err != nil {
|
now := time.Now().Unix()
|
||||||
glog.Errorf(ctx, "增加 Redis 计数失败 %s: %v", key, err)
|
|
||||||
|
// Redis 统一 key
|
||||||
|
onlineDevicesKey := "system_device:online_devices"
|
||||||
|
lastOnlineKey := fmt.Sprintf("system_device:last_online:%s", deviceId)
|
||||||
|
deviceInfoKey := fmt.Sprintf("system_device:info:%s", deviceId)
|
||||||
|
netbarDeviceCountKey := fmt.Sprintf("system_device:netbar_device_count:%s", netbarAccount)
|
||||||
|
|
||||||
|
// 判断设备是否在线
|
||||||
|
exists, err := g.Redis().HExists(ctx, onlineDevicesKey, deviceId)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(ctx, "查询设备在线状态失败 %s: %v", deviceId, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新在线设备集合
|
// 获取上次上线时间,判断是否断线重连
|
||||||
setKey := "system:online:devices"
|
lastOnlineStr, err := g.Redis().Get(ctx, lastOnlineKey)
|
||||||
if _, err := g.Redis().HSet(ctx, setKey, map[string]interface{}{
|
shouldSend := false
|
||||||
data.DeviceId: time.Now().Unix(),
|
needIncr := false
|
||||||
|
|
||||||
|
if exists != 1 {
|
||||||
|
// 设备不在线,首次上线
|
||||||
|
shouldSend = true
|
||||||
|
needIncr = true
|
||||||
|
} else if err != nil || lastOnlineStr.IsEmpty() {
|
||||||
|
// 无上线时间记录,断线重连
|
||||||
|
shouldSend = true
|
||||||
|
needIncr = true
|
||||||
|
} else {
|
||||||
|
lastOnline, err := strconv.ParseInt(lastOnlineStr.String(), 10, 64)
|
||||||
|
if err != nil || now-lastOnline > 10 {
|
||||||
|
// 超过10秒断线重连
|
||||||
|
shouldSend = true
|
||||||
|
needIncr = true
|
||||||
|
} else {
|
||||||
|
// 在线且未断线,不加计数,不发送配置
|
||||||
|
shouldSend = false
|
||||||
|
needIncr = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新上线时间并设置20秒过期
|
||||||
|
if _, err := g.Redis().Set(ctx, lastOnlineKey, now); err != nil {
|
||||||
|
glog.Errorf(ctx, "更新上线时间失败 %s: %v", lastOnlineKey, err)
|
||||||
|
}
|
||||||
|
if _, err := g.Redis().Expire(ctx, lastOnlineKey, 20); err != nil {
|
||||||
|
glog.Errorf(ctx, "设置上线时间过期失败 %s: %v", lastOnlineKey, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要时增加在线设备计数
|
||||||
|
if needIncr {
|
||||||
|
if _, err := g.Redis().Incr(ctx, netbarDeviceCountKey); err != nil {
|
||||||
|
glog.Errorf(ctx, "增加 Netbar 在线设备数失败 %s: %v", netbarDeviceCountKey, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新在线设备集合(时间戳)
|
||||||
|
if _, err := g.Redis().HSet(ctx, onlineDevicesKey, map[string]interface{}{
|
||||||
|
deviceId: now,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
glog.Errorf(ctx, "更新在线设备集合失败 %s: %v", setKey, err)
|
glog.Errorf(ctx, "更新在线设备集合失败 %s: %v", onlineDevicesKey, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 存储设备信息(用于离线检测时获取 NetbarAccount)
|
// 更新设备基础信息,并设置1小时过期
|
||||||
deviceKey := fmt.Sprintf("device:%s", data.DeviceId)
|
if _, err := g.Redis().HSet(ctx, deviceInfoKey, map[string]interface{}{
|
||||||
if _, err := g.Redis().HSet(ctx, deviceKey, map[string]interface{}{
|
"netbarAccount": netbarAccount,
|
||||||
"netbarAccount": data.NetbarAccount,
|
|
||||||
"deviceName": data.DeviceName,
|
"deviceName": data.DeviceName,
|
||||||
"ip": data.IP,
|
"ip": data.IP,
|
||||||
"macAddress": data.MACAddress,
|
"macAddress": data.MACAddress,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
glog.Errorf(ctx, "存储设备信息失败 %s: %v", deviceKey, err)
|
glog.Errorf(ctx, "存储设备信息失败 %s: %v", deviceInfoKey, err)
|
||||||
}
|
}
|
||||||
|
if _, err := g.Redis().Expire(ctx, deviceInfoKey, 3600); err != nil {
|
||||||
|
glog.Errorf(ctx, "设置设备信息过期失败 %s: %v", deviceInfoKey, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首次或断线重连发送配置
|
||||||
|
if shouldSend {
|
||||||
|
one, err := dao.Stores.Ctx(ctx).InnerJoin(dao.StoreDesktopSettings.Table(), "sds", "sds.store_id = stores.id").
|
||||||
|
Where("stores.netbar_account = ?", netbarAccount).
|
||||||
|
Fields("stores.netbar_account netbarAccount, sds.top_component_visible topComponentVisible, sds.right_component_visible rightComponentVisible").One()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(ctx, "获取门店信息失败 %s: %v", deviceInfoKey, err)
|
||||||
|
}
|
||||||
|
if err = client.Publish(fmt.Sprintf("/%s/down", netbarAccount), gconv.Bytes(one.Json())); err != nil {
|
||||||
|
glog.Errorf(ctx, "发布消息失败 %s: %v", deviceInfoKey, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "订阅 /up 失败: %v", err)
|
glog.Errorf(ctx, "订阅 /+/up 失败: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -171,14 +239,13 @@ func init() {
|
|||||||
glog.Info(ctx, "停止离线设备监控")
|
glog.Info(ctx, "停止离线设备监控")
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
setKey := "system:online:devices"
|
onlineDevicesKey := "system_device:online_devices"
|
||||||
devicesVar, err := g.Redis().HGetAll(ctx, setKey)
|
devicesVar, err := g.Redis().HGetAll(ctx, onlineDevicesKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "获取在线设备失败: %v", err)
|
glog.Errorf(ctx, "获取在线设备失败: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为 map[string]string
|
|
||||||
devices := devicesVar.MapStrStr()
|
devices := devicesVar.MapStrStr()
|
||||||
if len(devices) == 0 {
|
if len(devices) == 0 {
|
||||||
continue
|
continue
|
||||||
@ -186,24 +253,21 @@ func init() {
|
|||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
for deviceId, timestampStr := range devices {
|
for deviceId, timestampStr := range devices {
|
||||||
// 使用 strconv.ParseInt 替代 time.ParseInt
|
|
||||||
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
|
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "无效时间戳 for 设备 %s: %v", deviceId, err)
|
glog.Errorf(ctx, "无效时间戳 for 设备 %s: %v", deviceId, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查设备是否离线(超过 10 秒未更新)
|
|
||||||
if now-timestamp > 10 {
|
if now-timestamp > 10 {
|
||||||
// 获取设备信息
|
// 超过10秒未更新,认定离线
|
||||||
dataKey := fmt.Sprintf("device:%s", deviceId)
|
deviceInfoKey := fmt.Sprintf("system_device:info:%s", deviceId)
|
||||||
dataVar, err := g.Redis().HGetAll(ctx, dataKey)
|
dataVar, err := g.Redis().HGetAll(ctx, deviceInfoKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "获取设备数据失败 %s: %v", dataKey, err)
|
glog.Errorf(ctx, "获取设备数据失败 %s: %v", deviceInfoKey, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为 map[string]string
|
|
||||||
data := dataVar.MapStrStr()
|
data := dataVar.MapStrStr()
|
||||||
netbarAccount, exists := data["netbarAccount"]
|
netbarAccount, exists := data["netbarAccount"]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -211,14 +275,14 @@ func init() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 减少在线设备计数
|
// 新增:system_device命名空间,按账号统计在线设备数 -1
|
||||||
key := fmt.Sprintf(consts.NetbarOnlineNumberKey, netbarAccount)
|
netbarDeviceCountKey := fmt.Sprintf("system_device:netbar_device_count:%s", netbarAccount)
|
||||||
if _, err := g.Redis().Decr(ctx, key); err != nil {
|
if _, err := g.Redis().Decr(ctx, netbarDeviceCountKey); err != nil {
|
||||||
glog.Errorf(ctx, "减少 Redis 计数失败 %s: %v", key, err)
|
glog.Errorf(ctx, "减少 Netbar 在线设备数失败 %s: %v", netbarDeviceCountKey, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从在线设备集合中移除
|
// 从在线设备集合中删除
|
||||||
if _, err := g.Redis().HDel(ctx, setKey, deviceId); err != nil {
|
if _, err := g.Redis().HDel(ctx, onlineDevicesKey, deviceId); err != nil {
|
||||||
glog.Errorf(ctx, "移除设备 %s 从在线集合失败: %v", deviceId, err)
|
glog.Errorf(ctx, "移除设备 %s 从在线集合失败: %v", deviceId, err)
|
||||||
} else {
|
} else {
|
||||||
glog.Infof(ctx, "设备 %s 已标记为离线", deviceId)
|
glog.Infof(ctx, "设备 %s 已标记为离线", deviceId)
|
||||||
|
|||||||
Reference in New Issue
Block a user