using WenChuanyi.Api.Models;
namespace WenChuanyi.Api.Services;
/// 取件码/管理码生成与查重(冲突自动重生成)
public class CodeGeneratorService
{
// 排除易混淆 0/O/1/I/l
private const string AdminChars = "ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
private readonly IFreeSql _fsql;
public CodeGeneratorService(IFreeSql fsql) => _fsql = fsql;
/// 生成 length 位纯数字取件码(全局唯一)
public async Task GeneratePickCodeAsync(int length)
{
for (var i = 0; i < 30; i++)
{
var code = GenerateDigits(length);
var exists = await _fsql.Select().Where(f => f.PickCode == code).AnyAsync();
if (!exists)
{
return code;
}
}
throw new InvalidOperationException("取件码生成冲突次数过多,请重试");
}
/// 生成 8 位字母数字管理码(全局唯一)
public async Task GenerateAdminCodeAsync()
{
for (var i = 0; i < 30; i++)
{
var code = new string(Enumerable.Range(0, 8)
.Select(_ => AdminChars[Random.Shared.Next(AdminChars.Length)]).ToArray());
var exists = await _fsql.Select().Where(f => f.AdminCode == code).AnyAsync();
if (!exists)
{
return code;
}
}
throw new InvalidOperationException("管理码生成冲突次数过多,请重试");
}
private static string GenerateDigits(int length)
{
var first = Random.Shared.Next(1, 10); // 首位非 0
var sb = new System.Text.StringBuilder();
sb.Append(first);
for (var i = 1; i < length; i++)
{
sb.Append(Random.Shared.Next(0, 10));
}
return sb.ToString();
}
}