调整用户可领奖励列表和 用户任务记录列表接口

This commit is contained in:
2025-06-27 15:34:45 +08:00
parent ba28d0621a
commit f0dbc64eda
11 changed files with 158 additions and 72 deletions

View File

@ -4,7 +4,8 @@ import (
"context"
"fmt"
"github.com/gogf/gf/v2/encoding/gjson"
"server/internal/consts"
"github.com/gogf/gf/v2/util/gconv"
"server/internal/dao"
"strconv"
"sync"
"time"
@ -116,9 +117,10 @@ func init() {
glog.Infof(ctx, "EMQX 客户端注册完成broker=%s, clientID=%s", broker, clientId)
// 订阅设备上线消息
// 订阅设备上线消息
go func() {
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)
var data DeviceData
@ -127,35 +129,101 @@ func init() {
return
}
// 增加门店在线设备计数
key := fmt.Sprintf(consts.NetbarOnlineNumberKey, data.NetbarAccount)
if _, err := g.Redis().Incr(ctx, key); err != nil {
glog.Errorf(ctx, "增加 Redis 计数失败 %s: %v", key, err)
deviceId := data.DeviceId
netbarAccount := data.NetbarAccount
now := time.Now().Unix()
// 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
}
// 更新在线设备集合
setKey := "system:online:devices"
if _, err := g.Redis().HSet(ctx, setKey, map[string]interface{}{
data.DeviceId: time.Now().Unix(),
// 获取上次上线时间,判断是否断线重连
lastOnlineStr, err := g.Redis().Get(ctx, lastOnlineKey)
shouldSend := false
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 {
glog.Errorf(ctx, "更新在线设备集合失败 %s: %v", setKey, err)
glog.Errorf(ctx, "更新在线设备集合失败 %s: %v", onlineDevicesKey, err)
return
}
// 存储设备信息(用于离线检测时获取 NetbarAccount
deviceKey := fmt.Sprintf("device:%s", data.DeviceId)
if _, err := g.Redis().HSet(ctx, deviceKey, map[string]interface{}{
"netbarAccount": data.NetbarAccount,
// 更新设备基础信息并设置1小时过期
if _, err := g.Redis().HSet(ctx, deviceInfoKey, map[string]interface{}{
"netbarAccount": netbarAccount,
"deviceName": data.DeviceName,
"ip": data.IP,
"macAddress": data.MACAddress,
}); 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 {
glog.Errorf(ctx, "订阅 /up 失败: %v", err)
glog.Errorf(ctx, "订阅 /+/up 失败: %v", err)
}
}()
@ -171,14 +239,13 @@ func init() {
glog.Info(ctx, "停止离线设备监控")
return
case <-ticker.C:
setKey := "system:online:devices"
devicesVar, err := g.Redis().HGetAll(ctx, setKey)
onlineDevicesKey := "system_device:online_devices"
devicesVar, err := g.Redis().HGetAll(ctx, onlineDevicesKey)
if err != nil {
glog.Errorf(ctx, "获取在线设备失败: %v", err)
continue
}
// 转换为 map[string]string
devices := devicesVar.MapStrStr()
if len(devices) == 0 {
continue
@ -186,24 +253,21 @@ func init() {
now := time.Now().Unix()
for deviceId, timestampStr := range devices {
// 使用 strconv.ParseInt 替代 time.ParseInt
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
if err != nil {
glog.Errorf(ctx, "无效时间戳 for 设备 %s: %v", deviceId, err)
continue
}
// 检查设备是否离线(超过 10 秒未更新)
if now-timestamp > 10 {
// 获取设备信息
dataKey := fmt.Sprintf("device:%s", deviceId)
dataVar, err := g.Redis().HGetAll(ctx, dataKey)
// 超过10秒未更新认定离线
deviceInfoKey := fmt.Sprintf("system_device:info:%s", deviceId)
dataVar, err := g.Redis().HGetAll(ctx, deviceInfoKey)
if err != nil {
glog.Errorf(ctx, "获取设备数据失败 %s: %v", dataKey, err)
glog.Errorf(ctx, "获取设备数据失败 %s: %v", deviceInfoKey, err)
continue
}
// 转换为 map[string]string
data := dataVar.MapStrStr()
netbarAccount, exists := data["netbarAccount"]
if !exists {
@ -211,14 +275,14 @@ func init() {
continue
}
// 减少在线设备计数
key := fmt.Sprintf(consts.NetbarOnlineNumberKey, netbarAccount)
if _, err := g.Redis().Decr(ctx, key); err != nil {
glog.Errorf(ctx, "减少 Redis 计数失败 %s: %v", key, err)
// 新增system_device命名空间按账号统计在线设备数 -1
netbarDeviceCountKey := fmt.Sprintf("system_device:netbar_device_count:%s", netbarAccount)
if _, err := g.Redis().Decr(ctx, netbarDeviceCountKey); err != nil {
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)
} else {
glog.Infof(ctx, "设备 %s 已标记为离线", deviceId)