diff --git a/assets/res/NetAdmin.Statements.ln b/assets/res/NetAdmin.Statements.ln index c5887517..dcfd275a 100644 --- a/assets/res/NetAdmin.Statements.ln +++ b/assets/res/NetAdmin.Statements.ln @@ -68,6 +68,7 @@ XML注释文件不存在 消息内容不能为空 父节点不存在 用户不存在 +用户名不符合要求 用户名不能为空 用户名不能是手机号码 用户名或密码错误 diff --git a/build/code.quality.props b/build/code.quality.props index 5bc76084..47425c89 100644 --- a/build/code.quality.props +++ b/build/code.quality.props @@ -23,7 +23,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/backend/NetAdmin/NetAdmin.Application/Extensions/ISelectExtensions.cs b/src/backend/NetAdmin/NetAdmin.Application/Extensions/ISelectExtensions.cs index 9a3c4051..8512b512 100644 --- a/src/backend/NetAdmin/NetAdmin.Application/Extensions/ISelectExtensions.cs +++ b/src/backend/NetAdmin/NetAdmin.Application/Extensions/ISelectExtensions.cs @@ -15,7 +15,8 @@ public static class ISelectExtensions where TQuery : DataAbstraction, new() { if (req.IgnoreOwner) { - me = me.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA); + me = me.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT + , Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD); } return me; diff --git a/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs b/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs index 9ecdb515..e4b82017 100644 --- a/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs +++ b/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs @@ -62,6 +62,23 @@ public abstract class RepositoryService(BasicReposit return await GetExportFileStreamAsync(fileName, list).ConfigureAwait(false); } + /// + /// 唯一索引冲突处理 + /// + protected static async Task OnUniqueIndexConflictAsync(Func actionTry, Func actionCatch = null) + { + try { + await actionTry().ConfigureAwait(false); + } + catch (Exception ex) when (ex.Message.Contains(Chars.FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT) || + ex.Message.Contains(Chars.FLG_DB_EXCEPTION_UNIQUE_CONSTRAINT_CONFLICT) || + ex.Message.Contains(Chars.FLG_DB_EXCEPTION_IDX)) { + if (actionCatch != null) { + await actionCatch().ConfigureAwait(false); + } + } + } + /// /// 更新实体 /// @@ -85,7 +102,8 @@ public abstract class RepositoryService(BasicReposit whereExp ??= a => a.Id.Equals(newValue.Id); var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql); if (disableGlobalDataFilter) { - update = update.DisableGlobalFilter(nameof(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA)); + update = update.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT + , Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD); } return update.ExecuteEffectsAsync(); @@ -106,8 +124,8 @@ public abstract class RepositoryService(BasicReposit TEntity newValue // , List includeFields = null // , List excludeFields = null // - , Expression> whereExp = null // - , string whereSql = null // + , Expression> whereExp = null // + , string whereSql = null // , bool ignoreVersion = false) { // 默认匹配主键 diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Attributes/DataValidation/UserNameAttribute.cs b/src/backend/NetAdmin/NetAdmin.Domain/Attributes/DataValidation/UserNameAttribute.cs index ca17b04a..b901b5d4 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Attributes/DataValidation/UserNameAttribute.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Attributes/DataValidation/UserNameAttribute.cs @@ -19,7 +19,7 @@ public sealed class UserNameAttribute : RegexAttribute public override bool IsValid(object value) { if (!base.IsValid(value)) { - ErrorMessageResourceName = nameof(Ln.用户名长度4位以上); + ErrorMessageResourceName = nameof(Ln.用户名不符合要求); return false; } diff --git a/src/backend/NetAdmin/NetAdmin.Domain/DataAbstraction.cs b/src/backend/NetAdmin/NetAdmin.Domain/DataAbstraction.cs index 51ec5107..e09be2fc 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/DataAbstraction.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/DataAbstraction.cs @@ -3,14 +3,23 @@ namespace NetAdmin.Domain; /// /// 数据基类 /// -public abstract record DataAbstraction +public abstract record DataAbstraction : IValidatableObject { + /// + /// 是否已验证 + /// + protected bool HasValidated { get; set; } + /// /// 如果数据校验失败,抛出异常 /// /// NetAdminValidateException public void ThrowIfInvalid() { + if (HasValidated) { + return; + } + var validationResult = this.TryValidate(); if (!validationResult.IsValid) { throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( // @@ -45,4 +54,19 @@ public abstract record DataAbstraction property.SetValue(this, s); } } + + /// + public IEnumerable Validate(ValidationContext validationContext) + { + HasValidated = true; + return ValidateInternal(validationContext); + } + + /// + /// 内部验证 + /// + protected virtual IEnumerable ValidateInternal(ValidationContext validationContext) + { + yield return ValidationResult.Success; + } } \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Dependency/JobReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Dependency/JobReq.cs new file mode 100644 index 00000000..1ef4d968 --- /dev/null +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Dependency/JobReq.cs @@ -0,0 +1,22 @@ +namespace NetAdmin.Domain.Dto.Dependency; + +/// +/// 工作批请求 +/// +public record JobReq : DataAbstraction +{ + /// + /// 处理数量 + /// + public int? Count { get; init; } + + /// + /// n秒以前 + /// + public int? SecondsAgo { get; init; } + + /// + /// 直到n秒前 + /// + public int? UntilSecondsAgo { get; init; } +} \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs index e2d8ed6a..86cdd4f8 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs @@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.DepositOrder; /// /// 请求:创建充值订单 /// -public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject +public record CreateDepositOrderReq : Sys_DepositOrder { /// public override long ActualPayAmount { get; init; } @@ -25,7 +25,7 @@ public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject public override int ToPointRate { get; init; } /// - public IEnumerable Validate(ValidationContext validationContext) + protected override IEnumerable ValidateInternal(ValidationContext validationContext) { if (PaymentMode != PaymentModes.USDT) { yield return new ValidationResult(Ln.支付方式不正确, [nameof(PaymentMode)]); diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/ReceivedConfirmationReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/ReceivedConfirmationReq.cs deleted file mode 100644 index 418fb6ad..00000000 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/ReceivedConfirmationReq.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace NetAdmin.Domain.Dto.Sys.DepositOrder; - -/// -/// 请求:到账确认 -/// -public record ReceivedConfirmationReq : DataAbstraction -{ - /// - /// 读取前n条记录 - /// - public int ReadRecordCount { get; init; } -} \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Dept/CreateDeptReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Dept/CreateDeptReq.cs index 5ba80ce9..83667e8a 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Dept/CreateDeptReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Dept/CreateDeptReq.cs @@ -5,9 +5,8 @@ namespace NetAdmin.Domain.Dto.Sys.Dept; /// public record CreateDeptReq : Sys_Dept { - /// - [JsonIgnore(Condition = JsonIgnoreCondition.Never)] - public override bool Enabled { get; init; } + /// + public override bool Enabled { get; init; } = true; /// [JsonIgnore(Condition = JsonIgnoreCondition.Never)] diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Role/CreateRoleReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Role/CreateRoleReq.cs index b9332e93..43484ad7 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Role/CreateRoleReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/Role/CreateRoleReq.cs @@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.Role; /// /// 请求:创建角色 /// -public record CreateRoleReq : Sys_Role, IValidatableObject +public record CreateRoleReq : Sys_Role { /// /// 角色-接口映射 @@ -58,7 +58,7 @@ public record CreateRoleReq : Sys_Role, IValidatableObject public override string Summary { get; init; } /// - public IEnumerable Validate(ValidationContext validationContext) + protected override IEnumerable ValidateInternal(ValidationContext validationContext) { if (validationContext.MemberName != null) { DashboardLayout = JsonSerializer.Serialize(JsonDocument.Parse(DashboardLayout)); diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/User/QueryUserRsp.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/User/QueryUserRsp.cs index c5a03cf7..1383749f 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/User/QueryUserRsp.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/User/QueryUserRsp.cs @@ -27,6 +27,11 @@ public record QueryUserRsp : Sys_User /// public new virtual QueryDeptRsp Dept { get; init; } + /// + /// 本部门以及子部门编号 + /// + public List DeptIds { get; init; } + /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public override string Email { get; init; } diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/VerifyCode/SendVerifyCodeReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/VerifyCode/SendVerifyCodeReq.cs index 5894b168..e72bed6d 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/VerifyCode/SendVerifyCodeReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/VerifyCode/SendVerifyCodeReq.cs @@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.VerifyCode; /// /// 请求:发送验证码 /// -public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject +public sealed record SendVerifyCodeReq : Sys_VerifyCode { /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -35,7 +35,7 @@ public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject public VerifyCaptchaReq VerifyCaptchaReq { get; init; } /// - public IEnumerable Validate(ValidationContext validationContext) + protected override IEnumerable ValidateInternal(ValidationContext validationContext) { ValidationResult validationResult; switch (DeviceType) { diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/WalletTrade/CreateWalletTradeReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/WalletTrade/CreateWalletTradeReq.cs index b5455e79..4326e466 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/WalletTrade/CreateWalletTradeReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/WalletTrade/CreateWalletTradeReq.cs @@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.WalletTrade; /// /// 请求:创建钱包交易 /// -public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject +public record CreateWalletTradeReq : Sys_WalletTrade { /// [JsonIgnore(Condition = JsonIgnoreCondition.Never)] @@ -39,7 +39,7 @@ public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject } /// - public IEnumerable Validate(ValidationContext validationContext) + protected override IEnumerable ValidateInternal(ValidationContext validationContext) { var tradeDirection = TradeType.Attr().Direction; if (Amount == 0 || (tradeDirection == TradeDirections.Income && Amount < 0) || (tradeDirection == TradeDirections.Expense && Amount > 0)) { diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs index f1ef13da..ba3c5ebd 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs @@ -46,10 +46,11 @@ public static class Chars public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)"; public const string FLG_DB_INDEX_PREFIX = "idx_{tablename}_"; public const string FLG_DB_TABLE_NAME_PREFIX = ""; - public const string FLG_FREE_SQL_GLOBAL_FILTER_DATA = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DATA); + public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF); + public const string FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD); + public const string FLG_FREE_SQL_GLOBAL_FILTER_DEPT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DEPT); public const string FLG_FREE_SQL_GLOBAL_FILTER_DELETE = nameof(FLG_FREE_SQL_GLOBAL_FILTER_DELETE); public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER); - public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF); public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT); public const string FLG_FRONT_APP_SET_HOME_GRID = "APP_SET_HOME_GRID"; public const string FLG_HTTP_HEADER_KEY_ACCESS_TOKEN = "ACCESS-TOKEN"; @@ -108,7 +109,7 @@ public static class Chars public const string RGX_TELEPHONE = """^((\d{3,4}\-)|)\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$"""; public const string RGX_UP_AND_LOWER_NUMBER = """^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"""; public const string RGX_URL = """^(https?|ftp):\/\/[^\s/$.?#].[^\s]*\.[^\s]{2,}$"""; - public const string RGX_USERNAME = "^[a-zA-Z0-9_]{4,16}$"; + public const string RGX_USERNAME = """^[\u4e00-\u9fa5a-zA-Z0-9_-]{2,16}$"""; public const string RGX_VERIFY_CODE = """^\d{4}$"""; public const string RGXL_CHINESE_NAME diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/PhoneNumberHelper.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/PhoneNumberHelper.cs index 9e10facb..2a545776 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/PhoneNumberHelper.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/PhoneNumberHelper.cs @@ -5,7 +5,7 @@ namespace NetAdmin.Infrastructure.Utils; /// public static class PhoneNumberHelper { - private static readonly IEnumerable<(string CallingCode, CountryCodes CountryCode)> _countryList; + private static readonly ImmutableList<(string CallingCode, CountryCodes CountryCode)> _countryList; #pragma warning disable S3963 static PhoneNumberHelper() @@ -21,7 +21,8 @@ public static class PhoneNumberHelper .OrderBy(x => x.Item1) .ThenByDescending(x => x.x.Attr().IsPreferred) .DistinctBy(x => x.Item1) - .OrderByDescending(x => x.Item1.Length); + .OrderByDescending(x => x.Item1.Length) + .ToImmutableList(); } /// @@ -29,7 +30,11 @@ public static class PhoneNumberHelper /// public static CountryCodes? PhoneNumberToCountryCode(string phoneNumber) { - return _countryList.FirstOrDefault(x => phoneNumber.Replace("+", string.Empty).Trim().StartsWith(x.CallingCode, StringComparison.Ordinal)) - .CountryCode; + phoneNumber = phoneNumber.Trim(); + if (phoneNumber.StartsWith('+')) { + phoneNumber = phoneNumber[1..]; + } + + return _countryList.FirstOrDefault(x => phoneNumber.StartsWith(x.CallingCode, StringComparison.Ordinal)).CountryCode; } } \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IDepositOrderModule.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IDepositOrderModule.cs index e88230f7..fb0d22fd 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IDepositOrderModule.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IDepositOrderModule.cs @@ -24,5 +24,5 @@ public interface IDepositOrderModule : ICrudModule /// 到账确认 /// - Task ReceivedConfirmationAsync(ReceivedConfirmationReq req); + Task ReceivedConfirmationAsync(JobReq req); } \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IDeptService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IDeptService.cs index df8e6770..6ca02bdf 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IDeptService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IDeptService.cs @@ -3,4 +3,10 @@ namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency; /// /// 部门服务 /// -public interface IDeptService : IService, IDeptModule; \ No newline at end of file +public interface IDeptService : IService, IDeptModule +{ + /// + /// 获取所有子部门编号 + /// + Task> GetChildDeptIdsAsync(long deptId); +} \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserRoleService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserRoleService.cs index 0842ec17..5f712659 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserRoleService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserRoleService.cs @@ -3,4 +3,10 @@ namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency; /// /// 用户角-色映射服务 /// -public interface IUserRoleService : IService, IUserRoleModule; \ No newline at end of file +public interface IUserRoleService : IService, IUserRoleModule +{ + /// + /// 通过用户id删除 + /// + Task BulkDeleteByUserIdAsync(long userId); +} \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs index b8edb733..955922dc 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs @@ -146,7 +146,7 @@ public sealed class DepositOrderService(BasicRepository } /// - public async Task ReceivedConfirmationAsync(ReceivedConfirmationReq req) + public async Task ReceivedConfirmationAsync(JobReq req) { req.ThrowIfInvalid(); var ret = 0; @@ -165,7 +165,7 @@ public sealed class DepositOrderService(BasicRepository }) .ConfigureAwait(false)).ToList(); var apiResult = await S() - .TransfersAsync(S>().Value.Token, req.ReadRecordCount, config.Trc20ReceiptAddress) + .TransfersAsync(S>().Value.Token, req.Count!.Value, config.Trc20ReceiptAddress) .ConfigureAwait(false); foreach (var apiItem in apiResult.TokenTransfers.Where(x => x.TokenInfo.TokenAbbr == "USDT" && x.Confirmed && x.ContractRet == "SUCCESS" && x.FinalResult == "SUCCESS")) { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DeptService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DeptService.cs index 5976a2be..340ac45b 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DeptService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DeptService.cs @@ -104,6 +104,12 @@ public sealed class DeptService(BasicRepository rpo) // return ret.Adapt(); } + /// + public async Task> GetChildDeptIdsAsync(long deptId) + { + return await Rpo.Where(a => a.Id == deptId).AsTreeCte().ToListAsync(a => a.Id).ConfigureAwait(false); + } + /// public Task> PagedQueryAsync(PagedQueryReq req) { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DicCatalogService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DicCatalogService.cs index e8666cea..bffa0177 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DicCatalogService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DicCatalogService.cs @@ -122,7 +122,9 @@ public sealed class DicCatalogService(BasicRepository rpo) private ISelect QueryInternal(QueryReq req) { - var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter); + var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter) + .WhereIf(req.Filter?.Id > 0, a => a.Id == req.Filter.Id) + .WhereIf(req.Filter?.Code?.Length > 0, a => a.Code == req.Filter.Code); // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault switch (req.Order) { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserInviteService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserInviteService.cs index f88ac949..00207ee9 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserInviteService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserInviteService.cs @@ -83,9 +83,15 @@ public sealed class UserInviteService(BasicRepository rpo) public Task> GetAssociatedUserIdAsync(long userId) { return Rpo.Orm.Select() - .DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA) + .DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT +, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD) .Where(a => a.Id == userId) - .AsTreeCte(up: true, disableGlobalFilters: [Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA]) + .AsTreeCte( // + up: true + , disableGlobalFilters: [ + Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT + , Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD + ]) .ToListAsync(a => a.Id); } diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserRoleService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserRoleService.cs index 70018504..22ac2712 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserRoleService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserRoleService.cs @@ -23,6 +23,12 @@ public sealed class UserRoleService(BasicRepository rpo) // return ret; } + /// + public Task BulkDeleteByUserIdAsync(long userId) + { + return Rpo.DeleteAsync(a => a.UserId == userId); + } + /// public Task CountAsync(QueryReq req) { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs index 27b4af8f..1c9275d0 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs @@ -2,6 +2,7 @@ using NetAdmin.Application.Extensions; using NetAdmin.Domain.Attributes.DataValidation; using NetAdmin.Domain.Contexts; using NetAdmin.Domain.DbMaps.Sys; +using NetAdmin.Domain.Dto.Sys.Dept; using NetAdmin.Domain.Dto.Sys.User; using NetAdmin.Domain.Dto.Sys.UserInvite; using NetAdmin.Domain.Dto.Sys.UserProfile; @@ -9,6 +10,7 @@ using NetAdmin.Domain.Dto.Sys.UserWallet; using NetAdmin.Domain.Dto.Sys.VerifyCode; using NetAdmin.Domain.Events.Sys; using NetAdmin.Domain.Extensions; +using Yitter.IdGenerator; namespace NetAdmin.SysComponent.Application.Services.Sys; @@ -108,8 +110,10 @@ public sealed class UserService( req.ThrowIfInvalid(); var roles = await CreateEditCheckAsync(req).ConfigureAwait(false); + var newDeptId = YitIdHelper.NextId(); + // 主表 - var entity = req.Adapt(); + var entity = req.Adapt() with { DeptId = newDeptId }; var dbUser = await Rpo.InsertAsync(entity).ConfigureAwait(false); // 分表 @@ -134,6 +138,9 @@ public sealed class UserService( // 邀请表 _ = await userInviteService.CreateAsync((req.Invite ?? new CreateUserInviteReq()) with { Id = dbUser.Id }).ConfigureAwait(false); + // 创建一个用户自己的部门 + _ = S().CreateAsync(new CreateDeptReq { Id = newDeptId, Name = $"{req.UserName}的部门", ParentId = req.Invite?.OwnerDeptId ?? 0 }); + // 发布用户创建事件 var ret = userList.First(); await eventPublisher.PublishAsync(new UserCreatedEvent(ret.Adapt())).ConfigureAwait(false); @@ -477,7 +484,9 @@ public sealed class UserService( .IncludeMany(a => a.Roles, OtherIncludes) .ToOneAsync() .ConfigureAwait(false); - return dbUser.Adapt(); + + var deptIds = await S().GetChildDeptIdsAsync(dbUser.DeptId).ConfigureAwait(false); + return dbUser.Adapt() with { DeptIds = deptIds.ToList().ConvertAll(x => (long?)x) }; static void OtherIncludes(ISelect select) { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DepositOrderCache.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DepositOrderCache.cs index 460713f7..d130b623 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DepositOrderCache.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/DepositOrderCache.cs @@ -79,7 +79,7 @@ public sealed class DepositOrderCache(IDistributedCache cache, IDepositOrderServ } /// - public Task ReceivedConfirmationAsync(ReceivedConfirmationReq req) + public Task ReceivedConfirmationAsync(JobReq req) { return Service.ReceivedConfirmationAsync(req); } diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/DepositOrderController.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/DepositOrderController.cs index 270549d9..7a645028 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/DepositOrderController.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/DepositOrderController.cs @@ -115,7 +115,7 @@ public sealed class DepositOrderController(IDepositOrderCache cache) /// /// 到账确认 /// - public Task ReceivedConfirmationAsync(ReceivedConfirmationReq req) + public Task ReceivedConfirmationAsync(JobReq req) { return Cache.ReceivedConfirmationAsync(req); } diff --git a/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj b/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj index 19bad2c0..8b4d3c86 100644 --- a/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj +++ b/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj @@ -5,7 +5,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/backend/YourSolution.AdmServer.Host/Extensions/ServiceCollectionExtensions.cs b/src/backend/YourSolution.AdmServer.Host/Extensions/ServiceCollectionExtensions.cs index 4ff15ade..fa69df2c 100644 --- a/src/backend/YourSolution.AdmServer.Host/Extensions/ServiceCollectionExtensions.cs +++ b/src/backend/YourSolution.AdmServer.Host/Extensions/ServiceCollectionExtensions.cs @@ -21,9 +21,21 @@ public static class ServiceCollectionExtensions (Startup.Args.SyncStructure ? FreeSqlInitMethods.SyncStructure : FreeSqlInitMethods.None) | (Startup.Args.InsertSeedData ? FreeSqlInitMethods.InsertSeedData : FreeSqlInitMethods.None), freeSql => { // 数据权限过滤器 + // 本人 _ = freeSql.GlobalFilter.ApplyOnlyIf( // - Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA, () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.Self) ?? false + Chars.FLG_FREE_SQL_GLOBAL_FILTER_SELF, () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.Self) ?? false , a => a.OwnerId == ContextUserInfo.Create().Id); + + // 本部门 + _ = freeSql.GlobalFilter.ApplyOnlyIf( // + Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT, () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.Dept) ?? false + , a => ContextUserInfo.Create().DeptId == a.OwnerDeptId); + + // 本部门和子部门 + _ = freeSql.GlobalFilter.ApplyOnlyIf( // + Chars.FLG_FREE_SQL_GLOBAL_FILTER_DEPT_WITH_CHILD + , () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.DeptWithChild) ?? false + , a => ContextUserInfo.Create().DeptIds.Contains(a.OwnerDeptId)); }); } diff --git a/src/frontend/admin/src/components/na-col-user/index.vue b/src/frontend/admin/src/components/na-col-user/index.vue index 5280057e..c4b0fdcf 100644 --- a/src/frontend/admin/src/components/na-col-user/index.vue +++ b/src/frontend/admin/src/components/na-col-user/index.vue @@ -1,16 +1,22 @@