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(); } }