优化共享屏幕id算法

This commit is contained in:
youngq 2024-08-07 16:22:35 +08:00
parent 58376482bf
commit bc77b85686
9 changed files with 94 additions and 25 deletions

View File

@ -1,8 +1,10 @@
using Mapster; using Mapster;
using Microsoft.AspNetCore.Components.Forms; using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
using SqlSugar; using SqlSugar;
using WGShare.API.Controllers.Basic; using WGShare.API.Controllers.Basic;
using WGShare.API.Helpers;
using WGShare.Domain.DTOs.User; using WGShare.Domain.DTOs.User;
using WGShare.Domain.Entities; using WGShare.Domain.Entities;
using WGShare.Domain.FriendlyException; using WGShare.Domain.FriendlyException;
@ -57,13 +59,7 @@ namespace WGShare.API.Controllers.Backend
public async Task<bool> Add([FromBody] UserInputDTO userInput) public async Task<bool> Add([FromBody] UserInputDTO userInput)
{ {
var entity = userInput.Adapt<User>(); var entity = userInput.Adapt<User>();
entity.ScreenShareId = UserShareIdHelper.GenerateUnique8DigitNumber();
// 获取当前时间的Unix时间戳以毫秒为单位
long unixTimeMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// 将Unix时间戳转换为字符串并截取最后7位
string last7Digits = unixTimeMilliseconds.ToString().Substring(unixTimeMilliseconds.ToString().Length - 7);
entity.ScreenShareId = $@"{last7Digits}{new Random().Next(10, 100)}";
if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == entity.Account)) if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == entity.Account))
{ {
@ -122,5 +118,17 @@ namespace WGShare.API.Controllers.Backend
await _sqlSugar.Insertable(entity).ExecuteCommandAsync(); await _sqlSugar.Insertable(entity).ExecuteCommandAsync();
} }
///// <summary>
///// Excel 导入用户
///// </summary>
///// <param name="file"></param>
///// <returns></returns>
//[HttpPost("import")]
//public async Task<bool> Import([FromForm] IFormFile file)
//{
// using var stream = file.OpenReadStream();
// MiniExcel.Query<ChannelUserInfo>(stream);
//}
} }
} }

View File

@ -359,7 +359,7 @@ namespace WGShare.API.Controllers.Frontend
// 获取全员观看用户 // 获取全员观看用户
var showUserId = RedisHelper.Instance.HGet(RedisKeyConstant.RoomManager.GetChannelShowUserKey(TenantId), roomNum); var showUserId = RedisHelper.Instance.HGet(RedisKeyConstant.RoomManager.GetChannelShowUserKey(TenantId), roomNum);
if (!string.IsNullOrWhiteSpace(showUserId) && channelUsers.Any(x => x.Value.UID == showUserId)) if (!string.IsNullOrWhiteSpace(showUserId))
{ {
return showUserId; return showUserId;
} }
@ -376,6 +376,12 @@ namespace WGShare.API.Controllers.Frontend
{ {
// 设置房间全员观看用户 // 设置房间全员观看用户
RedisHelper.Instance.HSet(RedisKeyConstant.RoomManager.GetChannelShowUserKey(TenantId), roomNum, uid); RedisHelper.Instance.HSet(RedisKeyConstant.RoomManager.GetChannelShowUserKey(TenantId), roomNum, uid);
var connectId = RedisHelper.Instance.HGet(RedisKeyConstant.SessionManage.GetOnlineUserKey(TenantId), UId);
if (!string.IsNullOrWhiteSpace(connectId))
{
await _hubContext.Clients.GroupExcept(roomNum, connectId).ShowUser();
}
} }
#region #region

View File

@ -1,6 +1,7 @@
using Mapster; using Mapster;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SqlSugar; using SqlSugar;
using System;
using WGShare.API.Controllers.Basic; using WGShare.API.Controllers.Basic;
using WGShare.API.Helpers; using WGShare.API.Helpers;
using WGShare.Domain.Constant; using WGShare.Domain.Constant;
@ -51,7 +52,8 @@ namespace WGShare.API.Controllers.Frontend
UserName = u.UserName, UserName = u.UserName,
Account = u.Account, Account = u.Account,
RoleId = r.Id, RoleId = r.Id,
RoleName = r.RoleName RoleName = r.RoleName,
ScreenShareId = u.ScreenShareId
}) })
.ToPageListAsync(pagedBaseDto.PageIndex, pagedBaseDto.PageSize, total); .ToPageListAsync(pagedBaseDto.PageIndex, pagedBaseDto.PageSize, total);
@ -73,13 +75,7 @@ namespace WGShare.API.Controllers.Frontend
var user = inputDTO.Adapt<User>(); var user = inputDTO.Adapt<User>();
//user.Id = YitIdHelper.NextId().ToString(); //user.Id = YitIdHelper.NextId().ToString();
user.TenantId = TenantId; user.TenantId = TenantId;
user.ScreenShareId = UserShareIdHelper.GenerateUnique8DigitNumber();
// 获取当前时间的Unix时间戳以毫秒为单位
long unixTimeMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// 将Unix时间戳转换为字符串并截取最后7位
string last7Digits = unixTimeMilliseconds.ToString().Substring(unixTimeMilliseconds.ToString().Length - 7);
user.ScreenShareId = $@"{last7Digits}{new Random().Next(10, 100)}";
if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == user.Account)) if (await _sqlSugar.Queryable<User>().AnyAsync(x => x.Account == user.Account))
{ {
@ -134,5 +130,6 @@ namespace WGShare.API.Controllers.Frontend
.SetColumns(x => x.IsDelete == true) .SetColumns(x => x.IsDelete == true)
.Where(x => ids.Contains(x.Id)).ExecuteCommandHasChangeAsync(); .Where(x => ids.Contains(x.Id)).ExecuteCommandHasChangeAsync();
} }
} }
} }

View File

@ -0,0 +1,26 @@
namespace WGShare.API.Helpers
{
public class UserShareIdHelper
{
/// <summary>
/// 生成用户共享ID 8位数字
/// </summary>
/// <returns></returns>
public static string GenerateUnique8DigitNumber()
{
int uniqueNumber;
Random random = new Random();
// 确保生成的数字不会重复
do
{
long ticks = DateTime.UtcNow.Ticks;
int randomPart = random.Next(1000, 10000); // 随机生成4位数字
uniqueNumber = int.Parse((ticks % 10000).ToString("D4") + randomPart.ToString("D4")); // 拼接成8位数字
} while (RedisHelper.Instance.SIsMember("screen_share_id", uniqueNumber));
RedisHelper.Instance.SAdd("screen_share_id", uniqueNumber);
return uniqueNumber.ToString();
}
}
}

View File

@ -62,5 +62,11 @@
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task RefreshView(string type); Task RefreshView(string type);
/// <summary>
/// 全员观看
/// </summary>
/// <returns></returns>
Task ShowUser();
} }
} }

View File

@ -25,13 +25,14 @@ namespace WGShare.API.Hubs
var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value; var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value;
var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value; var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value;
var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value; var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value;
var ssid = Context.User?.Claims.FirstOrDefault(x => x.Type == "ssid")?.Value;
Console.WriteLine($"{DateTime.Now}连接成功 当前租户:" + tenant); Console.WriteLine($"{DateTime.Now}连接成功 当前租户:" + tenant);
Console.WriteLine($"{DateTime.Now} 连接成功 account" + account); Console.WriteLine($"{DateTime.Now} 连接成功 account" + account);
Console.WriteLine($"{DateTime.Now} 连接成功 uid" + uid); Console.WriteLine($"{DateTime.Now} 连接成功 uid" + uid);
Console.WriteLine($"{DateTime.Now}连接成功 connectId" + Context.ConnectionId); Console.WriteLine($"{DateTime.Now}连接成功 connectId" + Context.ConnectionId);
await ClearUserChannel(uid, tenant, account); await ClearUserChannel(uid, tenant, account, ssid);
// 存储在线信息 // 存储在线信息
RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetOnlineUserKey(tenant), uid, Context.ConnectionId); RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetOnlineUserKey(tenant), uid, Context.ConnectionId);
} }
@ -41,6 +42,7 @@ namespace WGShare.API.Hubs
var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value; var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value;
var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value; var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value;
var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value; var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value;
var ssid = Context.User?.Claims.FirstOrDefault(x => x.Type == "ssid")?.Value;
Console.WriteLine($"{DateTime.Now}断开连接 当前租户:" + tenant); Console.WriteLine($"{DateTime.Now}断开连接 当前租户:" + tenant);
Console.WriteLine($"{DateTime.Now}断开连接 account" + account); Console.WriteLine($"{DateTime.Now}断开连接 account" + account);
@ -51,13 +53,13 @@ namespace WGShare.API.Hubs
{ {
Console.WriteLine($"{DateTime.Now}断开连接 未重连,开始删除用户频道信息"); Console.WriteLine($"{DateTime.Now}断开连接 未重连,开始删除用户频道信息");
// 断开后未重连则清退频道 // 断开后未重连则清退频道
await ClearUserChannel(uid, tenant, account); await ClearUserChannel(uid, tenant, account, ssid);
} }
} }
private async Task ClearUserChannel(string uid, string tenant, string account) private async Task ClearUserChannel(string uid, string tenant, string account, string ssid)
{ {
Console.WriteLine($"{DateTime.Now} 执行删除开始"); Console.WriteLine($"{DateTime.Now} 执行删除开始");
// 获取用户参加得频道 // 获取用户参加得频道
@ -72,9 +74,12 @@ namespace WGShare.API.Hubs
{ {
pipe.HDel(RedisKeyConstant.SessionManage.GetChannelUserKey(tenant, roomNum), uid); pipe.HDel(RedisKeyConstant.SessionManage.GetChannelUserKey(tenant, roomNum), uid);
var script = $@"if (redis.call('HGET', KEYS[1], ARGV[1]) == ARGV[2]) then return redis.call('HDEL', KEYS[1], ARGV[1]) else return -1 end"; var script = $@"local value = redis.call('HGET', KEYS[1], ARGV[1])
if value == ARGV[2] or value == ARGV[3] then
return redis.call('HDEL', KEYS[1], ARGV[1])
else return -1 end";
// 执行 eval 命令 // 执行 eval 命令
pipe.Eval(script, [RedisKeyConstant.RoomManager.GetChannelShowUserKey(tenant)], roomNum, uid); pipe.Eval(script, [RedisKeyConstant.RoomManager.GetChannelShowUserKey(tenant)], roomNum, uid, ssid);
}); });
} }
@ -131,6 +136,7 @@ namespace WGShare.API.Hubs
var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value; var tenant = Context.User?.Claims.FirstOrDefault(x => x.Type == "tenant")?.Value;
var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value; var uid = Context.User?.Claims.FirstOrDefault(x => x.Type == "uid")?.Value;
var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value; var account = Context.User?.Claims.FirstOrDefault(x => x.Type == "account")?.Value;
var ssid = Context.User?.Claims.FirstOrDefault(x => x.Type == "ssid")?.Value;
Console.WriteLine($" {DateTime.Now}离开频道 会议号:" + roomNum); Console.WriteLine($" {DateTime.Now}离开频道 会议号:" + roomNum);
@ -139,9 +145,12 @@ namespace WGShare.API.Hubs
using (var pipe = RedisHelper.Instance.StartPipe()) using (var pipe = RedisHelper.Instance.StartPipe())
{ {
var script = $@"if (redis.call('HGET', KEYS[1], ARGV[1]) == ARGV[2]) then return redis.call('HDEL', KEYS[1], ARGV[1]) else return -1 end"; var script = $@"local value = redis.call('HGET', KEYS[1], ARGV[1])
if value == ARGV[2] or value == ARGV[3] then
return redis.call('HDEL', KEYS[1], ARGV[1])
else return -1 end";
// 执行 eval 命令 // 执行 eval 命令
pipe.Eval(script, [RedisKeyConstant.RoomManager.GetChannelShowUserKey(tenant)], roomNum, uid); pipe.Eval(script, [RedisKeyConstant.RoomManager.GetChannelShowUserKey(tenant)], roomNum, uid, ssid);
pipe.HDel(RedisKeyConstant.SessionManage.GetChannelUserKey(tenant, roomNum), uid); pipe.HDel(RedisKeyConstant.SessionManage.GetChannelUserKey(tenant, roomNum), uid);
pipe.HDel(RedisKeyConstant.SessionManage.GetUserJoinChannelKey(uid), roomNum); pipe.HDel(RedisKeyConstant.SessionManage.GetUserJoinChannelKey(uid), roomNum);
pipe.EndPipe(); pipe.EndPipe();

View File

@ -15,6 +15,7 @@
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageReference Include="Hangfire.Core" Version="1.8.14" /> <PackageReference Include="Hangfire.Core" Version="1.8.14" />
<PackageReference Include="Hangfire.MemoryStorage" Version="1.8.1.1" /> <PackageReference Include="Hangfire.MemoryStorage" Version="1.8.1.1" />
<PackageReference Include="MiniExcel" Version="1.34.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>

View File

@ -309,6 +309,12 @@
<param name="maxTimeoutSeconds">最大秒数</param> <param name="maxTimeoutSeconds">最大秒数</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:WGShare.API.Helpers.UserShareIdHelper.GenerateUnique8DigitNumber">
<summary>
生成用户共享ID 8位数字
</summary>
<returns></returns>
</member>
<member name="T:WGShare.API.Hubs.IMessageClient"> <member name="T:WGShare.API.Hubs.IMessageClient">
<summary> <summary>
客户端消息 客户端消息
@ -371,6 +377,12 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:WGShare.API.Hubs.IMessageClient.ShowUser">
<summary>
全员观看
</summary>
<returns></returns>
</member>
<member name="M:WGShare.API.Hubs.SessionManageHub.JoinChannel(System.String,System.Boolean,System.Boolean)"> <member name="M:WGShare.API.Hubs.SessionManageHub.JoinChannel(System.String,System.Boolean,System.Boolean)">
<summary> <summary>
加入频道 加入频道

View File

@ -40,5 +40,9 @@ namespace WGShare.Domain.DTOs.User
/// 是否在线 /// 是否在线
/// </summary> /// </summary>
public bool IsOnline { get; set; } public bool IsOnline { get; set; }
/// <summary>
/// 共享屏幕ID
/// </summary>
public string ScreenShareId { get; set; }
} }
} }