接收移动端坐标上报

This commit is contained in:
yanghongwei 2025-06-16 17:09:38 +08:00
parent bca6baef65
commit a32912a460
4 changed files with 134 additions and 35 deletions

View File

@ -56,5 +56,13 @@
{ {
return $"white_list{sn}"; return $"white_list{sn}";
} }
/// <summary>
/// 所有用户位置
/// </summary>
/// <returns></returns>
public static string UserLocation(long userId)
{
return $"user_locationbyid_{userId}";
}
} }
} }

View File

@ -10,6 +10,7 @@ namespace LY.App.Common.Redis
public class RedisService public class RedisService
{ {
private readonly IDatabase _db; private readonly IDatabase _db;
private readonly IServer _redis;
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
@ -38,44 +39,82 @@ namespace LY.App.Common.Redis
string jsonData = await _db.StringGetAsync(key); string jsonData = await _db.StringGetAsync(key);
return jsonData is not null ? JsonSerializer.Deserialize<T>(jsonData) : default; return jsonData is not null ? JsonSerializer.Deserialize<T>(jsonData) : default;
} }
/// <summary> /// <summary>
/// 删除 Key /// 模糊 查询所有 Key
/// </summary> /// </summary>
public async Task<bool> DeleteAsync(string key) /// <param name="pattern"></param>
/// <returns></returns>
public async Task<List<RedisKey>> GetAllKeysAsync(string pattern)
{ {
return await _db.KeyDeleteAsync(key); var redis = _db.Multiplexer;
} var keys = new List<RedisKey>();
foreach (var endPoint in redis.GetEndPoints())
/// <summary>
/// 检查 Key 是否存在
/// </summary>
public async Task<bool> ExistsAsync(string key)
{
return await _db.KeyExistsAsync(key);
}
/// <summary>
/// 获取数据,如果不存在则从数据源获取并存入 Redis
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <param name="key">Redis Key</param>
/// <param name="factory">数据源方法</param>
/// <param name="expiry">可选的过期时间</param>
/// <returns>获取到的值</returns>
public async Task<T?> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
{
var value = await GetAsync<T>(key);
if (value is not null)
{ {
var server = redis.GetServer(endPoint);
if (!server.IsConnected)
continue;
// 使用 SCAN 获取匹配的 key避免 KEYS 阻塞
var scanKeys = server.Keys(pattern: pattern, pageSize: 1000);
keys.AddRange(scanKeys);
}
return keys;
//var result = new Dictionary<string, string>();
//if (keys.Count > 0)
//{
// // 一次批量获取 value
// var values = await _db.StringGetAsync(keys.ToArray());
// for (int i = 0; i < keys.Count; i++)
// {
// if (values[i].HasValue)
// {
// result[keys[i]] = values[i];
// }
// }
//}
//return result;
}
/// <summary>
/// 删除 Key
/// </summary>
public async Task<bool> DeleteAsync(string key)
{
return await _db.KeyDeleteAsync(key);
}
/// <summary>
/// 检查 Key 是否存在
/// </summary>
public async Task<bool> ExistsAsync(string key)
{
return await _db.KeyExistsAsync(key);
}
/// <summary>
/// 获取数据,如果不存在则从数据源获取并存入 Redis
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <param name="key">Redis Key</param>
/// <param name="factory">数据源方法</param>
/// <param name="expiry">可选的过期时间</param>
/// <returns>获取到的值</returns>
public async Task<T?> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiry = null)
{
var value = await GetAsync<T>(key);
if (value is not null)
{
return value;
}
value = await factory();
if (value is not null)
{
await SetAsync(key, value, expiry);
}
return value; return value;
} }
value = await factory();
if (value is not null)
{
await SetAsync(key, value, expiry);
}
return value;
} }
} }
}

View File

@ -4,6 +4,8 @@ using LY.App.Model;
using LY.App.Service; using LY.App.Service;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using StackExchange.Redis;
using System.Reactive.Joins;
namespace LY.App.Controllers namespace LY.App.Controllers
{ {
@ -51,14 +53,44 @@ namespace LY.App.Controllers
TimeSpan.FromDays(1)); TimeSpan.FromDays(1));
var weather = await _redisService.GetOrSetAsync(RedisKeyList.Index_Weather, var weather = await _redisService.GetOrSetAsync(RedisKeyList.Index_Weather,
async () => await _weatherService.GetWeather(), async () => await _weatherService.GetWeather(),
TimeSpan.FromHours(3)); TimeSpan.FromHours(3));
var data = await GetUserLocation();
result.data = new result.data = new
{ {
positions, positions,
alarmCount, alarmCount,
weather weather,
userLocation = data
}; };
return Ok(result); return Ok(result);
} }
private async Task<List<SyncLocation>> GetUserLocation()
{
var keys = await _redisService.GetAllKeysAsync("user_locationbyid_*");
List<SyncLocation> result = new List<SyncLocation>();
if (keys.Count > 0)
{
foreach (var item in keys)
{
result.Add(await _redisService.GetAsync<SyncLocation>(item));
}
}
return result;
}
/// <summary>
/// 同步移动端位置信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("syncLocation")]
public async Task<IActionResult> SyncLocation(SyncLocation input)
{
string key = RedisKeyList.UserLocation(input.userId);
await _redisService.SetAsync(key, new SyncLocation() { userId = input.userId, lat = input.lat, lon = input.lon }, TimeSpan.FromMinutes(1));
return Ok(new ApiResult());
}
} }
} }

20
Model/SyncLocation.cs Normal file
View File

@ -0,0 +1,20 @@
namespace LY.App.Model
{
/// <summary>
/// 移动端同步坐标信息
/// </summary>
public class SyncLocation
{
public long userId { get; set; }
public double lon { get; set; }
public double lat { get; set; }
}
/// <summary>
/// web 端同步坐标信息
/// </summary>
public class Location
{
public double lon { get; set; }
public double lat { get; set; }
}
}