mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-08-01 17:55:59 +08:00
feat: ✨ 框架代码同步
This commit is contained in:
@ -68,6 +68,7 @@ XML注释文件不存在
|
|||||||
消息内容不能为空
|
消息内容不能为空
|
||||||
父节点不存在
|
父节点不存在
|
||||||
用户不存在
|
用户不存在
|
||||||
|
用户名不符合要求
|
||||||
用户名不能为空
|
用户名不能为空
|
||||||
用户名不能是手机号码
|
用户名不能是手机号码
|
||||||
用户名或密码错误
|
用户名或密码错误
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.13.0.120203">
|
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.14.0.120626">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -15,7 +15,8 @@ public static class ISelectExtensions
|
|||||||
where TQuery : DataAbstraction, new()
|
where TQuery : DataAbstraction, new()
|
||||||
{
|
{
|
||||||
if (req.IgnoreOwner) {
|
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;
|
return me;
|
||||||
|
@ -62,6 +62,23 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
|
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 唯一索引冲突处理
|
||||||
|
/// </summary>
|
||||||
|
protected static async Task OnUniqueIndexConflictAsync(Func<Task> actionTry, Func<Task> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新实体
|
/// 更新实体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -85,7 +102,8 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
whereExp ??= a => a.Id.Equals(newValue.Id);
|
whereExp ??= a => a.Id.Equals(newValue.Id);
|
||||||
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
|
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
|
||||||
if (disableGlobalDataFilter) {
|
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();
|
return update.ExecuteEffectsAsync();
|
||||||
@ -106,8 +124,8 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
TEntity newValue //
|
TEntity newValue //
|
||||||
, List<string> includeFields = null //
|
, List<string> includeFields = null //
|
||||||
, List<string> excludeFields = null //
|
, List<string> excludeFields = null //
|
||||||
, Expression<Func<TEntity, bool>> whereExp = null //
|
, Expression<Func<TEntity, bool>> whereExp = null //
|
||||||
, string whereSql = null //
|
, string whereSql = null //
|
||||||
, bool ignoreVersion = false)
|
, bool ignoreVersion = false)
|
||||||
{
|
{
|
||||||
// 默认匹配主键
|
// 默认匹配主键
|
||||||
|
@ -19,7 +19,7 @@ public sealed class UserNameAttribute : RegexAttribute
|
|||||||
public override bool IsValid(object value)
|
public override bool IsValid(object value)
|
||||||
{
|
{
|
||||||
if (!base.IsValid(value)) {
|
if (!base.IsValid(value)) {
|
||||||
ErrorMessageResourceName = nameof(Ln.用户名长度4位以上);
|
ErrorMessageResourceName = nameof(Ln.用户名不符合要求);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,23 @@ namespace NetAdmin.Domain;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据基类
|
/// 数据基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract record DataAbstraction
|
public abstract record DataAbstraction : IValidatableObject
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已验证
|
||||||
|
/// </summary>
|
||||||
|
protected bool HasValidated { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 如果数据校验失败,抛出异常
|
/// 如果数据校验失败,抛出异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="NetAdminValidateException">NetAdminValidateException</exception>
|
/// <exception cref="NetAdminValidateException">NetAdminValidateException</exception>
|
||||||
public void ThrowIfInvalid()
|
public void ThrowIfInvalid()
|
||||||
{
|
{
|
||||||
|
if (HasValidated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var validationResult = this.TryValidate();
|
var validationResult = this.TryValidate();
|
||||||
if (!validationResult.IsValid) {
|
if (!validationResult.IsValid) {
|
||||||
throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( //
|
throw new NetAdminValidateException(validationResult.ValidationResults.ToDictionary( //
|
||||||
@ -45,4 +54,19 @@ public abstract record DataAbstraction
|
|||||||
property.SetValue(this, s);
|
property.SetValue(this, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
HasValidated = true;
|
||||||
|
return ValidateInternal(validationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部验证
|
||||||
|
/// </summary>
|
||||||
|
protected virtual IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
yield return ValidationResult.Success;
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
namespace NetAdmin.Domain.Dto.Dependency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工作批请求
|
||||||
|
/// </summary>
|
||||||
|
public record JobReq : DataAbstraction
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 处理数量
|
||||||
|
/// </summary>
|
||||||
|
public int? Count { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// n秒以前
|
||||||
|
/// </summary>
|
||||||
|
public int? SecondsAgo { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直到n秒前
|
||||||
|
/// </summary>
|
||||||
|
public int? UntilSecondsAgo { get; init; }
|
||||||
|
}
|
@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.DepositOrder;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:创建充值订单
|
/// 请求:创建充值订单
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject
|
public record CreateDepositOrderReq : Sys_DepositOrder
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" />
|
/// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" />
|
||||||
public override long ActualPayAmount { get; init; }
|
public override long ActualPayAmount { get; init; }
|
||||||
@ -25,7 +25,7 @@ public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject
|
|||||||
public override int ToPointRate { get; init; }
|
public override int ToPointRate { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
if (PaymentMode != PaymentModes.USDT) {
|
if (PaymentMode != PaymentModes.USDT) {
|
||||||
yield return new ValidationResult(Ln.支付方式不正确, [nameof(PaymentMode)]);
|
yield return new ValidationResult(Ln.支付方式不正确, [nameof(PaymentMode)]);
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
namespace NetAdmin.Domain.Dto.Sys.DepositOrder;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 请求:到账确认
|
|
||||||
/// </summary>
|
|
||||||
public record ReceivedConfirmationReq : DataAbstraction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 读取前n条记录
|
|
||||||
/// </summary>
|
|
||||||
public int ReadRecordCount { get; init; }
|
|
||||||
}
|
|
@ -5,9 +5,8 @@ namespace NetAdmin.Domain.Dto.Sys.Dept;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateDeptReq : Sys_Dept
|
public record CreateDeptReq : Sys_Dept
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
/// <inheritdoc />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
public override bool Enabled { get; init; } = true;
|
||||||
public override bool Enabled { get; init; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_Dept.Name" />
|
/// <inheritdoc cref="Sys_Dept.Name" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.Role;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:创建角色
|
/// 请求:创建角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateRoleReq : Sys_Role, IValidatableObject
|
public record CreateRoleReq : Sys_Role
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色-接口映射
|
/// 角色-接口映射
|
||||||
@ -58,7 +58,7 @@ public record CreateRoleReq : Sys_Role, IValidatableObject
|
|||||||
public override string Summary { get; init; }
|
public override string Summary { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
if (validationContext.MemberName != null) {
|
if (validationContext.MemberName != null) {
|
||||||
DashboardLayout = JsonSerializer.Serialize(JsonDocument.Parse(DashboardLayout));
|
DashboardLayout = JsonSerializer.Serialize(JsonDocument.Parse(DashboardLayout));
|
||||||
|
@ -27,6 +27,11 @@ public record QueryUserRsp : Sys_User
|
|||||||
/// <inheritdoc cref="Sys_User.Dept" />
|
/// <inheritdoc cref="Sys_User.Dept" />
|
||||||
public new virtual QueryDeptRsp Dept { get; init; }
|
public new virtual QueryDeptRsp Dept { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本部门以及子部门编号
|
||||||
|
/// </summary>
|
||||||
|
public List<long?> DeptIds { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_User.Email" />
|
/// <inheritdoc cref="Sys_User.Email" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override string Email { get; init; }
|
public override string Email { get; init; }
|
||||||
|
@ -6,7 +6,7 @@ namespace NetAdmin.Domain.Dto.Sys.VerifyCode;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:发送验证码
|
/// 请求:发送验证码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject
|
public sealed record SendVerifyCodeReq : Sys_VerifyCode
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Sys_VerifyCode.DestDevice" />
|
/// <inheritdoc cref="Sys_VerifyCode.DestDevice" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
@ -35,7 +35,7 @@ public sealed record SendVerifyCodeReq : Sys_VerifyCode, IValidatableObject
|
|||||||
public VerifyCaptchaReq VerifyCaptchaReq { get; init; }
|
public VerifyCaptchaReq VerifyCaptchaReq { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
ValidationResult validationResult;
|
ValidationResult validationResult;
|
||||||
switch (DeviceType) {
|
switch (DeviceType) {
|
||||||
|
@ -3,7 +3,7 @@ namespace NetAdmin.Domain.Dto.Sys.WalletTrade;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:创建钱包交易
|
/// 请求:创建钱包交易
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
|
public record CreateWalletTradeReq : Sys_WalletTrade
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="Sys_WalletTrade.Amount" />
|
/// <inheritdoc cref="Sys_WalletTrade.Amount" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
@ -39,7 +39,7 @@ public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
protected override IEnumerable<ValidationResult> ValidateInternal(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
var tradeDirection = TradeType.Attr<TradeAttribute>().Direction;
|
var tradeDirection = TradeType.Attr<TradeAttribute>().Direction;
|
||||||
if (Amount == 0 || (tradeDirection == TradeDirections.Income && Amount < 0) || (tradeDirection == TradeDirections.Expense && Amount > 0)) {
|
if (Amount == 0 || (tradeDirection == TradeDirections.Income && Amount < 0) || (tradeDirection == TradeDirections.Expense && Amount > 0)) {
|
||||||
|
@ -46,10 +46,11 @@ public static class Chars
|
|||||||
public const string FLG_DB_FIELD_TYPE_VARCHAR_7 = "varchar(7)";
|
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_INDEX_PREFIX = "idx_{tablename}_";
|
||||||
public const string FLG_DB_TABLE_NAME_PREFIX = "";
|
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_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_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_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_FRONT_APP_SET_HOME_GRID = "APP_SET_HOME_GRID";
|
||||||
public const string FLG_HTTP_HEADER_KEY_ACCESS_TOKEN = "ACCESS-TOKEN";
|
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_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_UP_AND_LOWER_NUMBER = """^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$""";
|
||||||
public const string RGX_URL = """^(https?|ftp):\/\/[^\s/$.?#].[^\s]*\.[^\s]{2,}$""";
|
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 RGX_VERIFY_CODE = """^\d{4}$""";
|
||||||
|
|
||||||
public const string RGXL_CHINESE_NAME
|
public const string RGXL_CHINESE_NAME
|
||||||
|
@ -5,7 +5,7 @@ namespace NetAdmin.Infrastructure.Utils;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class PhoneNumberHelper
|
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
|
#pragma warning disable S3963
|
||||||
static PhoneNumberHelper()
|
static PhoneNumberHelper()
|
||||||
@ -21,7 +21,8 @@ public static class PhoneNumberHelper
|
|||||||
.OrderBy(x => x.Item1)
|
.OrderBy(x => x.Item1)
|
||||||
.ThenByDescending(x => x.x.Attr<CountryInfoAttribute>().IsPreferred)
|
.ThenByDescending(x => x.x.Attr<CountryInfoAttribute>().IsPreferred)
|
||||||
.DistinctBy(x => x.Item1)
|
.DistinctBy(x => x.Item1)
|
||||||
.OrderByDescending(x => x.Item1.Length);
|
.OrderByDescending(x => x.Item1.Length)
|
||||||
|
.ToImmutableList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -29,7 +30,11 @@ public static class PhoneNumberHelper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static CountryCodes? PhoneNumberToCountryCode(string phoneNumber)
|
public static CountryCodes? PhoneNumberToCountryCode(string phoneNumber)
|
||||||
{
|
{
|
||||||
return _countryList.FirstOrDefault(x => phoneNumber.Replace("+", string.Empty).Trim().StartsWith(x.CallingCode, StringComparison.Ordinal))
|
phoneNumber = phoneNumber.Trim();
|
||||||
.CountryCode;
|
if (phoneNumber.StartsWith('+')) {
|
||||||
|
phoneNumber = phoneNumber[1..];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _countryList.FirstOrDefault(x => phoneNumber.StartsWith(x.CallingCode, StringComparison.Ordinal)).CountryCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,5 +24,5 @@ public interface IDepositOrderModule : ICrudModule<CreateDepositOrderReq, QueryD
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 到账确认
|
/// 到账确认
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req);
|
Task<int> ReceivedConfirmationAsync(JobReq req);
|
||||||
}
|
}
|
@ -3,4 +3,10 @@ namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 部门服务
|
/// 部门服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDeptService : IService, IDeptModule;
|
public interface IDeptService : IService, IDeptModule
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有子部门编号
|
||||||
|
/// </summary>
|
||||||
|
Task<IEnumerable<long>> GetChildDeptIdsAsync(long deptId);
|
||||||
|
}
|
@ -3,4 +3,10 @@ namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户角-色映射服务
|
/// 用户角-色映射服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUserRoleService : IService, IUserRoleModule;
|
public interface IUserRoleService : IService, IUserRoleModule
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 通过用户id删除
|
||||||
|
/// </summary>
|
||||||
|
Task<int> BulkDeleteByUserIdAsync(long userId);
|
||||||
|
}
|
@ -146,7 +146,7 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req)
|
public async Task<int> ReceivedConfirmationAsync(JobReq req)
|
||||||
{
|
{
|
||||||
req.ThrowIfInvalid();
|
req.ThrowIfInvalid();
|
||||||
var ret = 0;
|
var ret = 0;
|
||||||
@ -165,7 +165,7 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
|
|||||||
})
|
})
|
||||||
.ConfigureAwait(false)).ToList();
|
.ConfigureAwait(false)).ToList();
|
||||||
var apiResult = await S<ITronScanClient>()
|
var apiResult = await S<ITronScanClient>()
|
||||||
.TransfersAsync(S<IOptions<TronScanOptions>>().Value.Token, req.ReadRecordCount, config.Trc20ReceiptAddress)
|
.TransfersAsync(S<IOptions<TronScanOptions>>().Value.Token, req.Count!.Value, config.Trc20ReceiptAddress)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
foreach (var apiItem in apiResult.TokenTransfers.Where(x => x.TokenInfo.TokenAbbr == "USDT" && x.Confirmed && x.ContractRet == "SUCCESS" &&
|
foreach (var apiItem in apiResult.TokenTransfers.Where(x => x.TokenInfo.TokenAbbr == "USDT" && x.Confirmed && x.ContractRet == "SUCCESS" &&
|
||||||
x.FinalResult == "SUCCESS")) {
|
x.FinalResult == "SUCCESS")) {
|
||||||
|
@ -104,6 +104,12 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
|
|||||||
return ret.Adapt<QueryDeptRsp>();
|
return ret.Adapt<QueryDeptRsp>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<IEnumerable<long>> GetChildDeptIdsAsync(long deptId)
|
||||||
|
{
|
||||||
|
return await Rpo.Where(a => a.Id == deptId).AsTreeCte().ToListAsync(a => a.Id).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<PagedQueryRsp<QueryDeptRsp>> PagedQueryAsync(PagedQueryReq<QueryDeptReq> req)
|
public Task<PagedQueryRsp<QueryDeptRsp>> PagedQueryAsync(PagedQueryReq<QueryDeptReq> req)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,9 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
|
|||||||
|
|
||||||
private ISelect<Sys_DicCatalog> QueryInternal(QueryReq<QueryDicCatalogReq> req)
|
private ISelect<Sys_DicCatalog> QueryInternal(QueryReq<QueryDicCatalogReq> 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
|
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||||
switch (req.Order) {
|
switch (req.Order) {
|
||||||
|
@ -83,9 +83,15 @@ public sealed class UserInviteService(BasicRepository<Sys_UserInvite, long> rpo)
|
|||||||
public Task<List<long>> GetAssociatedUserIdAsync(long userId)
|
public Task<List<long>> GetAssociatedUserIdAsync(long userId)
|
||||||
{
|
{
|
||||||
return Rpo.Orm.Select<Sys_UserInvite>()
|
return Rpo.Orm.Select<Sys_UserInvite>()
|
||||||
.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)
|
.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);
|
.ToListAsync(a => a.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,12 @@ public sealed class UserRoleService(BasicRepository<Sys_UserRole, long> rpo) //
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<int> BulkDeleteByUserIdAsync(long userId)
|
||||||
|
{
|
||||||
|
return Rpo.DeleteAsync(a => a.UserId == userId);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<long> CountAsync(QueryReq<QueryUserRoleReq> req)
|
public Task<long> CountAsync(QueryReq<QueryUserRoleReq> req)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@ using NetAdmin.Application.Extensions;
|
|||||||
using NetAdmin.Domain.Attributes.DataValidation;
|
using NetAdmin.Domain.Attributes.DataValidation;
|
||||||
using NetAdmin.Domain.Contexts;
|
using NetAdmin.Domain.Contexts;
|
||||||
using NetAdmin.Domain.DbMaps.Sys;
|
using NetAdmin.Domain.DbMaps.Sys;
|
||||||
|
using NetAdmin.Domain.Dto.Sys.Dept;
|
||||||
using NetAdmin.Domain.Dto.Sys.User;
|
using NetAdmin.Domain.Dto.Sys.User;
|
||||||
using NetAdmin.Domain.Dto.Sys.UserInvite;
|
using NetAdmin.Domain.Dto.Sys.UserInvite;
|
||||||
using NetAdmin.Domain.Dto.Sys.UserProfile;
|
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.Dto.Sys.VerifyCode;
|
||||||
using NetAdmin.Domain.Events.Sys;
|
using NetAdmin.Domain.Events.Sys;
|
||||||
using NetAdmin.Domain.Extensions;
|
using NetAdmin.Domain.Extensions;
|
||||||
|
using Yitter.IdGenerator;
|
||||||
|
|
||||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||||
|
|
||||||
@ -108,8 +110,10 @@ public sealed class UserService(
|
|||||||
req.ThrowIfInvalid();
|
req.ThrowIfInvalid();
|
||||||
var roles = await CreateEditCheckAsync(req).ConfigureAwait(false);
|
var roles = await CreateEditCheckAsync(req).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var newDeptId = YitIdHelper.NextId();
|
||||||
|
|
||||||
// 主表
|
// 主表
|
||||||
var entity = req.Adapt<Sys_User>();
|
var entity = req.Adapt<Sys_User>() with { DeptId = newDeptId };
|
||||||
var dbUser = await Rpo.InsertAsync(entity).ConfigureAwait(false);
|
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);
|
_ = await userInviteService.CreateAsync((req.Invite ?? new CreateUserInviteReq()) with { Id = dbUser.Id }).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// 创建一个用户自己的部门
|
||||||
|
_ = S<IDeptService>().CreateAsync(new CreateDeptReq { Id = newDeptId, Name = $"{req.UserName}的部门", ParentId = req.Invite?.OwnerDeptId ?? 0 });
|
||||||
|
|
||||||
// 发布用户创建事件
|
// 发布用户创建事件
|
||||||
var ret = userList.First();
|
var ret = userList.First();
|
||||||
await eventPublisher.PublishAsync(new UserCreatedEvent(ret.Adapt<UserInfoRsp>())).ConfigureAwait(false);
|
await eventPublisher.PublishAsync(new UserCreatedEvent(ret.Adapt<UserInfoRsp>())).ConfigureAwait(false);
|
||||||
@ -477,7 +484,9 @@ public sealed class UserService(
|
|||||||
.IncludeMany(a => a.Roles, OtherIncludes)
|
.IncludeMany(a => a.Roles, OtherIncludes)
|
||||||
.ToOneAsync()
|
.ToOneAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return dbUser.Adapt<UserInfoRsp>();
|
|
||||||
|
var deptIds = await S<IDeptService>().GetChildDeptIdsAsync(dbUser.DeptId).ConfigureAwait(false);
|
||||||
|
return dbUser.Adapt<UserInfoRsp>() with { DeptIds = deptIds.ToList().ConvertAll(x => (long?)x) };
|
||||||
|
|
||||||
static void OtherIncludes(ISelect<Sys_Role> select)
|
static void OtherIncludes(ISelect<Sys_Role> select)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ public sealed class DepositOrderCache(IDistributedCache cache, IDepositOrderServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req)
|
public Task<int> ReceivedConfirmationAsync(JobReq req)
|
||||||
{
|
{
|
||||||
return Service.ReceivedConfirmationAsync(req);
|
return Service.ReceivedConfirmationAsync(req);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ public sealed class DepositOrderController(IDepositOrderCache cache)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 到账确认
|
/// 到账确认
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req)
|
public Task<int> ReceivedConfirmationAsync(JobReq req)
|
||||||
{
|
{
|
||||||
return Cache.ReceivedConfirmationAsync(req);
|
return Cache.ReceivedConfirmationAsync(req);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.7"/>
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.7"/>
|
||||||
<PackageReference Include="xunit" Version="2.9.3"/>
|
<PackageReference Include="xunit" Version="2.9.3"/>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.2">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -21,9 +21,21 @@ public static class ServiceCollectionExtensions
|
|||||||
(Startup.Args.SyncStructure ? FreeSqlInitMethods.SyncStructure : FreeSqlInitMethods.None) |
|
(Startup.Args.SyncStructure ? FreeSqlInitMethods.SyncStructure : FreeSqlInitMethods.None) |
|
||||||
(Startup.Args.InsertSeedData ? FreeSqlInitMethods.InsertSeedData : FreeSqlInitMethods.None), freeSql => {
|
(Startup.Args.InsertSeedData ? FreeSqlInitMethods.InsertSeedData : FreeSqlInitMethods.None), freeSql => {
|
||||||
// 数据权限过滤器
|
// 数据权限过滤器
|
||||||
|
// 本人
|
||||||
_ = freeSql.GlobalFilter.ApplyOnlyIf<IFieldOwner>( //
|
_ = freeSql.GlobalFilter.ApplyOnlyIf<IFieldOwner>( //
|
||||||
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);
|
, a => a.OwnerId == ContextUserInfo.Create().Id);
|
||||||
|
|
||||||
|
// 本部门
|
||||||
|
_ = freeSql.GlobalFilter.ApplyOnlyIf<IFieldOwner>( //
|
||||||
|
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<IFieldOwner>( //
|
||||||
|
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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-table-column v-bind="$attrs">
|
<el-table-column v-bind="$attrs">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div :style="{ display: $TOOL.getNestedProperty(row, $attrs.prop) ? 'flex' : 'none' }" class="el-table-column-avatar">
|
<div
|
||||||
|
:style="{
|
||||||
|
display: $TOOL.getNestedProperty(row, $attrs.prop) ? 'flex' : 'none',
|
||||||
|
' justify-content': 'center',
|
||||||
|
'align-items': 'center',
|
||||||
|
gap: '0.5rem',
|
||||||
|
}">
|
||||||
<el-avatar
|
<el-avatar
|
||||||
v-if="$TOOL.getNestedProperty(row, $attrs.nestProp)"
|
v-if="$TOOL.getNestedProperty(row, $attrs.nestProp)"
|
||||||
:src="getAvatar(row, $attrs.nestProp)"
|
:src="getAvatar(row, $attrs.nestProp)"
|
||||||
@click="click($TOOL.getNestedProperty(row, $attrs.prop))"
|
@click="click($TOOL.getNestedProperty(row, $attrs.prop))"
|
||||||
size="small"
|
size="small"
|
||||||
style="cursor: pointer" />
|
style="cursor: pointer" />
|
||||||
<div>
|
<div style="line-height: 1.2rem">
|
||||||
<p>{{ $TOOL.getNestedProperty(row, $attrs.nestProp) }}</p>
|
<p>{{ $TOOL.getNestedProperty(row, $attrs.nestProp) }}</p>
|
||||||
<p v-if="$attrs.nestProp2">{{ $TOOL.getNestedProperty(row, $attrs.nestProp2) }}</p>
|
<p v-if="$attrs.nestProp2" style="color: var(--el-color-info-light-3)">{{ $TOOL.getNestedProperty(row, $attrs.nestProp2) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<save-dialog v-if="dialog.save" @closed="dialog.save = null" @mounted="$refs.saveDialog.open(dialog.save)" ref="saveDialog" />
|
<save-dialog v-if="dialog.save" @closed="dialog.save = null" @mounted="$refs.saveDialog.open(dialog.save)" ref="saveDialog" />
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<sc-dialog v-model="visible" :full-screen="dialogFullScreen" :title="titleMap[mode]" @closed="$emit(`closed`)" destroy-on-close>
|
<sc-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:full-screen="dialogFullScreen.includes(mode)"
|
||||||
|
:title="titleMap[mode]"
|
||||||
|
@closed="$emit(`closed`)"
|
||||||
|
destroy-on-close
|
||||||
|
ref="dialog">
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<el-tabs v-model="tabId" :class="{ 'hide-tabs': !tabs || !tabs[mode] || tabs[mode].length === 0 }">
|
<el-tabs v-model="tabId" :class="{ 'hide-tabs': !tabs || !tabs[mode] || tabs[mode].length === 0 }">
|
||||||
<el-tab-pane :label="$t(`基本信息`)" name="basic">
|
<el-tab-pane :label="$t(`基本信息`)" name="basic">
|
||||||
@ -35,12 +41,14 @@
|
|||||||
v-else-if="typeof form[i] === `boolean` || item.isBoolean"
|
v-else-if="typeof form[i] === `boolean` || item.isBoolean"
|
||||||
v-model="form[i]"
|
v-model="form[i]"
|
||||||
:disabled="item.disabled?.includes(mode)" />
|
:disabled="item.disabled?.includes(mode)" />
|
||||||
<component
|
<template v-else-if="item.detail?.vModelValue">
|
||||||
v-bind="item.detail?.props"
|
<component
|
||||||
v-else-if="item.detail?.vModelValue"
|
v-bind="item.detail?.props"
|
||||||
v-model:value="form[i]"
|
v-if="this.opened"
|
||||||
:disabled="item.disabled?.includes(mode)"
|
v-model:value="form[i]"
|
||||||
:is="item.detail?.is ?? `el-input`" />
|
:disabled="item.disabled?.includes(mode)"
|
||||||
|
:is="item.detail.is" />
|
||||||
|
</template>
|
||||||
<component
|
<component
|
||||||
v-bind="item.detail?.props"
|
v-bind="item.detail?.props"
|
||||||
v-else
|
v-else
|
||||||
@ -52,7 +60,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane v-bind="item" v-for="(item, i) in tabs[mode]" v-if="tabs" :key="i" :name="item.name">
|
<el-tab-pane v-bind="item" v-for="(item, i) in tabs[mode]" v-if="tabs" :key="i" :name="item.name">
|
||||||
<component v-if="item.name === tabId" :is="item.component" :ref="item.ref" @closed="paneClosed" />
|
<component v-bind="item.props" v-if="item.name === tabId" :is="item.component" :row="form" @closed="paneClosed" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
@ -66,12 +74,20 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: {},
|
||||||
|
watch: {
|
||||||
|
mode(n) {
|
||||||
|
if (this.dialogFullScreen.includes(n) && !this.$refs.dialog.isFullscreen) {
|
||||||
|
this.$refs.dialog.setFullscreen()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
mode: '',
|
||||||
|
opened: false,
|
||||||
tabId: `basic`,
|
tabId: `basic`,
|
||||||
rules: {},
|
rules: {},
|
||||||
visible: false,
|
visible: false,
|
||||||
mode: `add`,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
form: {},
|
form: {},
|
||||||
titleMap: {
|
titleMap: {
|
||||||
@ -115,11 +131,14 @@ export default {
|
|||||||
|
|
||||||
if (data.row?.id) {
|
if (data.row?.id) {
|
||||||
const res = await this.$API[this.entityName].get.post({ id: data.row.id })
|
const res = await this.$API[this.entityName].get.post({ id: data.row.id })
|
||||||
Object.assign(this.form, res.data)
|
Object.assign(this.form, this.$TOOL.nestedToDotNotation(res.data))
|
||||||
this.titleMap.edit = this.$t(`编辑{summary}: {id}`, { summary: this.summary, id: this.form.id })
|
this.titleMap.edit = this.$t(`编辑{summary}: {id}`, { summary: this.summary, id: this.form.id })
|
||||||
this.titleMap.view = this.$t(`查看{summary}: {id}`, { summary: this.summary, id: this.form.id })
|
this.titleMap.view = this.$t(`查看{summary}: {id}`, { summary: this.summary, id: this.form.id })
|
||||||
|
} else {
|
||||||
|
Object.assign(this.form, this.$TOOL.nestedToDotNotation(data.row))
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
this.opened = true
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -134,7 +153,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const method = this.mode === `add` ? this.$API[this.entityName].create : this.$API[this.entityName].edit
|
const method = this.mode === `add` ? this.$API[this.entityName].create : this.$API[this.entityName].edit
|
||||||
try {
|
try {
|
||||||
const res = await method.post(this.form)
|
const res = await method.post(this.$TOOL.dotNotationToNested(this.form))
|
||||||
this.$emit(`success`, res.data, this.mode)
|
this.$emit(`success`, res.data, this.mode)
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$message.success(this.$t(`操作成功`))
|
this.$message.success(this.$t(`操作成功`))
|
||||||
@ -155,7 +174,7 @@ export default {
|
|||||||
entityName: { type: String },
|
entityName: { type: String },
|
||||||
summary: { type: String },
|
summary: { type: String },
|
||||||
columns: { type: Array },
|
columns: { type: Array },
|
||||||
dialogFullScreen: { type: Boolean },
|
dialogFullScreen: { type: Array },
|
||||||
tabs: { type: Array },
|
tabs: { type: Array },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -45,21 +45,29 @@
|
|||||||
<!-- 表格主体-->
|
<!-- 表格主体-->
|
||||||
<el-main class="nopadding">
|
<el-main class="nopadding">
|
||||||
<sc-table
|
<sc-table
|
||||||
|
v-bind="
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
queryApi: $API[entityName].pagedQuery,
|
||||||
|
exportApi: $API[entityName].export,
|
||||||
|
remoteFilter: true,
|
||||||
|
remoteSort: true,
|
||||||
|
rowKey: `id`,
|
||||||
|
stripe: true,
|
||||||
|
pageSize: 20,
|
||||||
|
defaultSort: { prop: `id`, order: `descending` },
|
||||||
|
},
|
||||||
|
tableProps,
|
||||||
|
)
|
||||||
|
"
|
||||||
:context-extra="this.table.menu.extra"
|
:context-extra="this.table.menu.extra"
|
||||||
:context-menus="Object.keys(this.columns)"
|
:context-menus="Object.keys(this.columns)"
|
||||||
:context-opers="this.operations"
|
:context-opers="this.operations"
|
||||||
:default-sort="{ prop: `id`, order: `descending` }"
|
|
||||||
:export-api="$API[entityName].export"
|
|
||||||
:params="query"
|
:params="query"
|
||||||
:query-api="$API[entityName].pagedQuery"
|
|
||||||
:vue="this"
|
:vue="this"
|
||||||
@data-change="onDataChange"
|
@data-change="onDataChange"
|
||||||
@selection-change="onSelectionChange"
|
@selection-change="onSelectionChange"
|
||||||
ref="table"
|
ref="table">
|
||||||
remote-filter
|
|
||||||
remote-sort
|
|
||||||
row-key="id"
|
|
||||||
stripe>
|
|
||||||
<el-table-column type="selection" width="50" />
|
<el-table-column type="selection" width="50" />
|
||||||
<template v-for="(item, i) in columns" :key="i">
|
<template v-for="(item, i) in columns" :key="i">
|
||||||
<component
|
<component
|
||||||
@ -160,6 +168,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
for (const f of this.dyFilters) {
|
||||||
|
this.query.dynamicFilter.filters.push(f)
|
||||||
|
}
|
||||||
|
|
||||||
const searchFields = []
|
const searchFields = []
|
||||||
this.searchControls = []
|
this.searchControls = []
|
||||||
for (const item in this.columns) {
|
for (const item in this.columns) {
|
||||||
@ -274,7 +286,7 @@ export default {
|
|||||||
|
|
||||||
// ---------------------------- ↓ 搜索栏事件 ----------------------------
|
// ---------------------------- ↓ 搜索栏事件 ----------------------------
|
||||||
async onReset() {
|
async onReset() {
|
||||||
Object.entries(this.$refs.selectFilter.selected).forEach(([key, _]) => (this.$refs.selectFilter.selected[key] = [``]))
|
Object.entries(this.$refs.selectFilter?.selected ?? []).forEach(([key, _]) => (this.$refs.selectFilter.selected[key] = [``]))
|
||||||
},
|
},
|
||||||
async onSearch(form) {
|
async onSearch(form) {
|
||||||
if (Array.isArray(form.dy.createdTime)) {
|
if (Array.isArray(form.dy.createdTime)) {
|
||||||
@ -299,6 +311,13 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const item of this.dyFilters) {
|
||||||
|
const exists = this.query.dynamicFilter.filters.find((x) => x.field === item.field)
|
||||||
|
if (!exists) {
|
||||||
|
this.query.dynamicFilter.filters.push(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await this.$refs.table.upData()
|
await this.$refs.table.upData()
|
||||||
},
|
},
|
||||||
// ---------------------------- 搜索栏事件 ↑ ----------------------------
|
// ---------------------------- 搜索栏事件 ↑ ----------------------------
|
||||||
@ -352,7 +371,13 @@ export default {
|
|||||||
loading?.close()
|
loading?.close()
|
||||||
},
|
},
|
||||||
async onAddClick() {
|
async onAddClick() {
|
||||||
this.dialog.detail = { mode: `add` }
|
const row = {}
|
||||||
|
for (const i in this.columns) {
|
||||||
|
if (this.columns[i].default) {
|
||||||
|
Object.assign(row, Object.fromEntries([[i, this.columns[i].default]]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dialog.detail = { mode: `add`, row }
|
||||||
},
|
},
|
||||||
async onSwitchChange(row, method) {
|
async onSwitchChange(row, method) {
|
||||||
try {
|
try {
|
||||||
@ -420,8 +445,19 @@ export default {
|
|||||||
type: `root`,
|
type: `root`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const f of this.dyFilters) {
|
||||||
|
this.$refs.search.selectInputKey = f.field
|
||||||
|
this.$refs.search.form.dy[f.field] = f.value
|
||||||
|
this.$refs.search.keeps.push({
|
||||||
|
field: f.field,
|
||||||
|
value: f.value,
|
||||||
|
type: 'dy',
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
dyFilters: { type: Array, default: [] },
|
||||||
keywords: { type: String },
|
keywords: { type: String },
|
||||||
entityName: { type: String },
|
entityName: { type: String },
|
||||||
summary: { type: String },
|
summary: { type: String },
|
||||||
@ -431,8 +467,9 @@ export default {
|
|||||||
operations: { type: Array, default: [`view`, `add`, `edit`, `del`] },
|
operations: { type: Array, default: [`view`, `add`, `edit`, `del`] },
|
||||||
rowButtons: { type: Array, default: [] },
|
rowButtons: { type: Array, default: [] },
|
||||||
rightButtons: { type: Array, default: [] },
|
rightButtons: { type: Array, default: [] },
|
||||||
dialogFullScreen: { type: Boolean },
|
dialogFullScreen: { type: Array, default: [] },
|
||||||
tabs: { type: Array },
|
tabs: { type: Array },
|
||||||
|
tableProps: { type: Object, default: {} },
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
}
|
}
|
||||||
|
@ -634,4 +634,8 @@ textarea {
|
|||||||
* {
|
* {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ace_placeholder {
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
}
|
}
|
@ -55,7 +55,7 @@ export default {
|
|||||||
global.user?.roles.findIndex((x) => x.ignorePermissionControl) >= 0
|
global.user?.roles.findIndex((x) => x.ignorePermissionControl) >= 0
|
||||||
? ['*/*/*']
|
? ['*/*/*']
|
||||||
: preloads[1]?.data?.roles
|
: preloads[1]?.data?.roles
|
||||||
?.map((x) => x.apiIds.join(','))
|
?.map((x) => (x.apiIds ?? []).join(','))
|
||||||
?.join(',')
|
?.join(',')
|
||||||
.split(',')
|
.split(',')
|
||||||
},
|
},
|
||||||
|
@ -251,6 +251,59 @@ tool.objCopy = function (obj) {
|
|||||||
return JSON.parse(JSON.stringify(obj))
|
return JSON.parse(JSON.stringify(obj))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 带点属性转嵌套对象 */
|
||||||
|
tool.dotNotationToNested = function (obj) {
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (key.includes('.')) {
|
||||||
|
// 处理带点的键
|
||||||
|
const keys = key.split('.')
|
||||||
|
let current = result
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const part = keys[i]
|
||||||
|
|
||||||
|
// 如果是最后一个部分,设置值
|
||||||
|
if (i === keys.length - 1) {
|
||||||
|
current[part] = obj[key]
|
||||||
|
} else {
|
||||||
|
// 如果不是最后一个部分,确保对象存在
|
||||||
|
current[part] = current[part] || {}
|
||||||
|
current = current[part]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 直接复制不带点的键
|
||||||
|
result[key] = obj[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
/* 将嵌套对象转带点属性 */
|
||||||
|
tool.nestedToDotNotation = function (obj, prefix = '', result = {}) {
|
||||||
|
// 处理 null 或 undefined 的情况
|
||||||
|
if (obj === null || obj === undefined) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
// 更安全的属性检查方式
|
||||||
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||||
|
const newKey = prefix ? `${prefix}.${key}` : key
|
||||||
|
|
||||||
|
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
||||||
|
// 递归处理嵌套对象
|
||||||
|
this.nestedToDotNotation(obj[key], newKey, result)
|
||||||
|
} else {
|
||||||
|
// 基本类型或数组,直接赋值
|
||||||
|
result[newKey] = obj[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
/* 获取嵌套属性 */
|
/* 获取嵌套属性 */
|
||||||
tool.getNestedProperty = function (obj, path) {
|
tool.getNestedProperty = function (obj, path) {
|
||||||
if (!path) return null
|
if (!path) return null
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<common-page :title="$t('注册新账号')">
|
<common-page :title="$t('注册新账号')">
|
||||||
<el-steps :active="stepActive" finish-status="success" simple>
|
<el-steps :active="stepActive" finish-status="success" simple>
|
||||||
<el-step :title="$t('填写账号')" />
|
<el-step :title="$t('填写账号')" />
|
||||||
<el-step v-if="config.registerInviteRequired" :title="$t('验证手机')" />
|
<el-step v-if="config.registerMobileRequired" :title="$t('验证手机')" />
|
||||||
<el-step :title="$t('注册成功')" />
|
<el-step :title="$t('注册成功')" />
|
||||||
</el-steps>
|
</el-steps>
|
||||||
<el-form v-if="stepActive === 0" :model="form" :rules="rules" @keyup.enter="next" label-width="15rem" ref="stepForm_0" size="large">
|
<el-form v-if="stepActive === 0" :model="form" :rules="rules" @keyup.enter="next" label-width="15rem" ref="stepForm_0" size="large">
|
||||||
@ -49,11 +49,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-form size="large" style="text-align: center">
|
<el-form size="large" style="text-align: center">
|
||||||
<el-button v-if="stepActive > 0 && stepActive < 2" @click="pre" size="large">{{ $t('上一步') }}</el-button>
|
<el-button v-if="stepActive > 0 && stepActive < 2" @click="pre" size="large">{{ $t('上一步') }}</el-button>
|
||||||
<el-button v-if="stepActive < (this.config.registerInviteRequired ? 1 : 0)" @click="next" size="large" type="primary">{{
|
<el-button v-if="stepActive < (this.config.registerMobileRequired ? 1 : 0)" @click="next" size="large" type="primary">{{
|
||||||
$t('下一步')
|
$t('下一步')
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="stepActive === (this.config.registerInviteRequired ? 1 : 0)"
|
v-if="stepActive === (this.config.registerMobileRequired ? 1 : 0)"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@click="save"
|
@click="save"
|
||||||
size="large"
|
size="large"
|
||||||
|
@ -1,202 +1,79 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container>
|
<na-table-page
|
||||||
<el-header v-loading="statistics.total === '...'" class="el-header-statistics">
|
:columns="{
|
||||||
<el-row :gutter="15">
|
'user.userName': {
|
||||||
<el-col :lg="24">
|
label: $t(`邀请关系`),
|
||||||
<el-card shadow="never">
|
show: [`list`],
|
||||||
<sc-statistic :title="$t('总数')" :value="statistics.total" group-separator />
|
width: 300,
|
||||||
</el-card>
|
},
|
||||||
</el-col>
|
id: {
|
||||||
</el-row>
|
headerAlign: `center`,
|
||||||
</el-header>
|
is: `na-col-user`,
|
||||||
<el-header>
|
clickOpenDialog: this.$GLOBAL.hasApiPermission(`api/sys/user/get`),
|
||||||
<div class="left-panel">
|
nestProp: `user.userName`,
|
||||||
<na-search
|
nestProp2: `id`,
|
||||||
:controls="[
|
width: 170,
|
||||||
{
|
label: $t(`新用户`),
|
||||||
type: 'select-input',
|
show: [`list`],
|
||||||
field: [
|
},
|
||||||
'dy',
|
createdTime: {
|
||||||
[
|
label: $t(`注册时间`),
|
||||||
{ label: $t('用户编号'), key: 'id' },
|
align: `right`,
|
||||||
{ label: $t('用户名'), key: 'user.userName' },
|
show: [`list`],
|
||||||
],
|
width: 170,
|
||||||
],
|
},
|
||||||
placeholder: $t('匹配内容'),
|
ownerId: {
|
||||||
style: 'width:25rem',
|
headerAlign: `center`,
|
||||||
selectStyle: 'width:8rem',
|
is: `na-col-user`,
|
||||||
},
|
clickOpenDialog: this.$GLOBAL.hasApiPermission(`api/sys/user/get`),
|
||||||
]"
|
nestProp: `owner.userName`,
|
||||||
:vue="this"
|
nestProp2: `ownerId`,
|
||||||
@reset="onReset"
|
width: 170,
|
||||||
@search="onSearch"
|
label: $t(`邀请人`),
|
||||||
dateFormat="YYYY-MM-DD HH:mm:ss"
|
show: [`list`],
|
||||||
dateType="datetimerange"
|
},
|
||||||
dateValueFormat="YYYY-MM-DD HH:mm:ss"
|
}"
|
||||||
ref="search" />
|
:dy-filters="dyFilters"
|
||||||
</div>
|
:operations="operations"
|
||||||
<div class="right-panel">
|
:row-buttons="[{ title: $t(`更改邀请人`), click: modifyInviter }]"
|
||||||
<el-dropdown v-show="this.selection.length > 0">
|
:summary="$t(`号码明细`)"
|
||||||
<el-button type="primary">
|
:table-props="{
|
||||||
{{ $t('批量操作') }}
|
queryApi: $API.sys_userinvite.query,
|
||||||
<el-icon>
|
defaultExpandAll: true,
|
||||||
<el-icon-arrow-down />
|
hidePagination: true,
|
||||||
</el-icon>
|
}"
|
||||||
</el-button>
|
entity-name="sys_userinvite" />
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item @click="setCommissionRatio">设置返佣比率</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<el-main class="nopadding">
|
|
||||||
<sc-table
|
|
||||||
:context-menus="['id', 'user.userName', 'createdTime', 'commissionRatio']"
|
|
||||||
:context-opers="[]"
|
|
||||||
:default-sort="{ prop: 'sort', order: 'descending' }"
|
|
||||||
:params="query"
|
|
||||||
:query-api="$API.sys_userinvite.query"
|
|
||||||
:vue="this"
|
|
||||||
@data-change="getStatistics"
|
|
||||||
@selection-change="
|
|
||||||
(items) => {
|
|
||||||
selection = items
|
|
||||||
}
|
|
||||||
"
|
|
||||||
default-expand-all
|
|
||||||
hidePagination
|
|
||||||
ref="table"
|
|
||||||
remote-filter
|
|
||||||
remote-sort
|
|
||||||
row-key="id"
|
|
||||||
stripe>
|
|
||||||
<el-table-column type="selection" width="50" />
|
|
||||||
<el-table-column :label="$t('用户编号')" prop="id" sortable="custom" />
|
|
||||||
<na-col-avatar :label="$t('用户名')" prop="user.userName" />
|
|
||||||
<el-table-column
|
|
||||||
:formatter="(row) => `${(row.commissionRatio / 100).toFixed(2)}%`"
|
|
||||||
:label="$t('返佣比率')"
|
|
||||||
align="right"
|
|
||||||
prop="commissionRatio"
|
|
||||||
sortable="custom" />
|
|
||||||
<el-table-column :label="$t('注册时间')" align="right" prop="createdTime" sortable="custom" />
|
|
||||||
</sc-table>
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
<set-inviter-dialog
|
||||||
|
v-if="dialog.setInviter"
|
||||||
|
@closed="dialog.setInviter = null"
|
||||||
|
@mounted="$refs.setInviterDialog.open(dialog.setInviter)"
|
||||||
|
@success="(data, mode) => table.handleUpdate($refs.table, data, mode)"
|
||||||
|
ref="setInviterDialog"></set-inviter-dialog>
|
||||||
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import table from '@/config/table'
|
const setInviterDialog = defineAsyncComponent(() => import('./set-inviter'))
|
||||||
import naColOperation from '@/config/na-col-operation'
|
|
||||||
|
|
||||||
const naColAvatar = defineAsyncComponent(() => import('@/components/na-col-avatar'))
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
naColAvatar,
|
setInviterDialog,
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
naColOperation() {
|
|
||||||
return naColOperation
|
|
||||||
},
|
|
||||||
table() {
|
|
||||||
return table
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
created() {},
|
created() {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
statistics: {
|
|
||||||
total: '...',
|
|
||||||
},
|
|
||||||
dialog: {},
|
dialog: {},
|
||||||
loading: false,
|
dyFilters: [],
|
||||||
query: {
|
operations: [],
|
||||||
dynamicFilter: {
|
|
||||||
filters: [],
|
|
||||||
},
|
|
||||||
filter: {},
|
|
||||||
keywords: this.keywords,
|
|
||||||
},
|
|
||||||
selection: [],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inject: ['reload'],
|
|
||||||
methods: {
|
methods: {
|
||||||
async setCommissionRatio() {
|
modifyInviter(row) {
|
||||||
let loading
|
// this.dialog.setInviter = { data: row }
|
||||||
try {
|
|
||||||
const prompt = await this.$prompt(this.$t('1 代表 0.01%'), this.$t('设置返佣比率'), {
|
|
||||||
inputPattern: /^[0-9]\d*$/,
|
|
||||||
inputErrorMessage: this.$t('返佣比率不正确'),
|
|
||||||
})
|
|
||||||
loading = this.$loading()
|
|
||||||
const res = await Promise.all(
|
|
||||||
this.selection.map((x) => this.$API.sys_userinvite.setCommissionRatio.post(Object.assign(x, { commissionRatio: prompt.value }))),
|
|
||||||
)
|
|
||||||
this.$message.success(
|
|
||||||
this.$t(`操作成功 {count}/{total} 项`, {
|
|
||||||
count: this.selection.length,
|
|
||||||
total: res.map((x) => x.data ?? 0).reduce((a, b) => a + b, 0),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
this.$refs.table.refresh()
|
|
||||||
} catch {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
loading?.close()
|
|
||||||
},
|
|
||||||
async getStatistics() {
|
|
||||||
this.statistics.total = this.$refs.table?.tableData?.length
|
|
||||||
},
|
|
||||||
//重置
|
|
||||||
onReset() {},
|
|
||||||
//搜索
|
|
||||||
async onSearch(form) {
|
|
||||||
if (Array.isArray(form.dy.createdTime)) {
|
|
||||||
this.query.dynamicFilter.filters.push({
|
|
||||||
field: 'createdTime',
|
|
||||||
operator: 'dateRange',
|
|
||||||
value: form.dy.createdTime.map((x) => x.replace(/ 00:00:00$/, '')),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof form.dy['id'] === 'string' && form.dy['id'].trim() !== '') {
|
|
||||||
this.query.dynamicFilter.filters.push({
|
|
||||||
field: 'id',
|
|
||||||
operator: 'eq',
|
|
||||||
value: form.dy['id'],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof form.dy['user.userName'] === 'string' && form.dy['user.userName'].trim() !== '') {
|
|
||||||
this.query.dynamicFilter.filters.push({
|
|
||||||
field: 'user.userName',
|
|
||||||
operator: 'eq',
|
|
||||||
value: form.dy['user.userName'],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.$refs.table.upData()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
props: {
|
||||||
if (this.keywords) {
|
row: { type: Object },
|
||||||
this.$refs.search.form.root.keywords = this.keywords
|
|
||||||
this.$refs.search.keeps.push({
|
|
||||||
field: 'keywords',
|
|
||||||
value: this.keywords,
|
|
||||||
type: 'root',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onReset()
|
|
||||||
},
|
},
|
||||||
props: ['keywords'],
|
|
||||||
watch: {},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped />
|
<style scoped />
|
59
src/frontend/admin/src/views/sys/invite/set-inviter.vue
Normal file
59
src/frontend/admin/src/views/sys/invite/set-inviter.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<sc-dialog v-model="visible" :title="$t(`修改邀请人`)" @closed="$emit('closed')" destroy-on-close>
|
||||||
|
<el-form :model="form" label-position="right" label-width="12rem" ref="form">
|
||||||
|
<el-form-item :label="$t(`用户`)">
|
||||||
|
<el-input v-model="form.user.userName" disabled placeholder="placeholder"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t(`邀请人`)">
|
||||||
|
<sc-select
|
||||||
|
v-model="form.ownerId"
|
||||||
|
:config="{ props: { label: `userName`, value: `id` } }"
|
||||||
|
:query-api="$API.sys_user.query"
|
||||||
|
clearable
|
||||||
|
filterable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button :disabled="loading" :loading="loading" @click="submit" type="primary">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</sc-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
visible: false,
|
||||||
|
form: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['success', 'closed', 'mounted'],
|
||||||
|
methods: {
|
||||||
|
//显示
|
||||||
|
async open(data) {
|
||||||
|
this.visible = true
|
||||||
|
this.loading = true
|
||||||
|
Object.assign(this.form, data.data)
|
||||||
|
this.loading = false
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
//表单提交方法
|
||||||
|
async submit() {
|
||||||
|
this.loading = true
|
||||||
|
this.$API.sys_userinvite.edit.post(this.form)
|
||||||
|
this.$emit('success')
|
||||||
|
this.visible = false
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$emit('mounted')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped />
|
@ -158,7 +158,7 @@
|
|||||||
align="center"
|
align="center"
|
||||||
prop="dataScope"
|
prop="dataScope"
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
width="120" />
|
width="180" />
|
||||||
<el-table-column :label="$t('显示仪表板')" align="center" prop="displayDashboard" sortable="custom" width="120">
|
<el-table-column :label="$t('显示仪表板')" align="center" prop="displayDashboard" sortable="custom" width="120">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-switch v-model="row.displayDashboard" @change="changeDisplayDashboard($event, row)" />
|
<el-switch v-model="row.displayDashboard" @change="changeDisplayDashboard($event, row)" />
|
||||||
|
@ -295,7 +295,7 @@ export default {
|
|||||||
userName: [
|
userName: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '4位以上字母、数字或下划线',
|
message: '2位以上中文数字或字母',
|
||||||
pattern: this.$GLOBAL.chars.RGX_USERNAME,
|
pattern: this.$GLOBAL.chars.RGX_USERNAME,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user