mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-08-01 01:36:00 +08:00
feat: ✨ 钱包冻结解冻
This commit is contained in:
@ -13,7 +13,10 @@ USDT
|
||||
中专
|
||||
中共党员
|
||||
为其中之一
|
||||
交易
|
||||
人工
|
||||
人工审核
|
||||
代码模板导出
|
||||
以什么开始
|
||||
以什么结束
|
||||
作业名称
|
||||
@ -52,9 +55,12 @@ USDT
|
||||
小于
|
||||
小于等于
|
||||
小学
|
||||
已冻结
|
||||
已发送
|
||||
已婚
|
||||
已校验
|
||||
已经冻结
|
||||
已解冻
|
||||
已读
|
||||
并且
|
||||
归属角色
|
||||
@ -116,7 +122,6 @@ USDT
|
||||
登录名
|
||||
登录日志导出
|
||||
硕士
|
||||
代码模板导出
|
||||
离异
|
||||
空闲
|
||||
站内信导出
|
||||
@ -129,6 +134,7 @@ USDT
|
||||
系统模块
|
||||
绑定手机号码
|
||||
结果非预期
|
||||
结算解冻
|
||||
群众
|
||||
自助充值
|
||||
自定义
|
||||
@ -143,6 +149,7 @@ USDT
|
||||
请求方式
|
||||
请求日志导出
|
||||
调试
|
||||
超时解冻
|
||||
身份证
|
||||
运行
|
||||
追踪
|
||||
@ -154,6 +161,7 @@ USDT
|
||||
配置导出
|
||||
重设密码
|
||||
钱包交易导出
|
||||
钱包冻结导出
|
||||
链接
|
||||
错误
|
||||
随机排序
|
||||
|
@ -12,6 +12,7 @@ XML注释文件不存在
|
||||
作业名称不能为空
|
||||
允许的文件大小
|
||||
允许的文件格式
|
||||
冻结状态不正确
|
||||
区号电话号码分机号
|
||||
参数格式不正确
|
||||
唯一编码不能为空
|
||||
@ -111,7 +112,7 @@ XML注释文件不存在
|
||||
部门可见
|
||||
部门名称不能为空
|
||||
配置文件初始化完毕
|
||||
钱包余额不足
|
||||
钱包可用余额不足
|
||||
键值不能为空
|
||||
键名称不能为空
|
||||
随机延时结束时间不正确
|
||||
|
@ -106,5 +106,17 @@
|
||||
{
|
||||
"ApiId": "api/sys/user.invite/query",
|
||||
"RoleId": 371729946431493,
|
||||
}
|
||||
},
|
||||
{
|
||||
"ApiId": "api/sys/wallet.frozen/get",
|
||||
"RoleId": 371729946431493,
|
||||
},
|
||||
{
|
||||
"ApiId": "api/sys/wallet.frozen/paged.query",
|
||||
"RoleId": 371729946431493,
|
||||
},
|
||||
{
|
||||
"ApiId": "api/sys/wallet.frozen/count.by",
|
||||
"RoleId": 371729946431493,
|
||||
},
|
||||
]
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "2.4.0",
|
||||
"devDependencies": {
|
||||
"cz-git": "^1.11.2",
|
||||
"cz-git": "^1.12.0",
|
||||
"commitizen": "^4.3.1",
|
||||
"prettier": "^3.6.2",
|
||||
"standard-version": "^9.5.0"
|
||||
|
@ -0,0 +1,23 @@
|
||||
using NetAdmin.Domain;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
namespace NetAdmin.Application.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// FreeSql Select 扩展方法
|
||||
/// </summary>
|
||||
public static class ISelectExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 附加其他过滤条件
|
||||
/// </summary>
|
||||
public static ISelect<T> AppendOtherFilters<T, TQuery>(this ISelect<T> me, QueryReq<TQuery> req)
|
||||
where TQuery : DataAbstraction, new()
|
||||
{
|
||||
if (req.IgnoreOwner) {
|
||||
me = me.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA);
|
||||
}
|
||||
|
||||
return me;
|
||||
}
|
||||
}
|
@ -42,12 +42,7 @@ public abstract class ServiceBase : IScoped, IService
|
||||
/// <summary>
|
||||
/// 获取服务
|
||||
/// </summary>
|
||||
#pragma warning disable RCS1036
|
||||
#pragma warning restore RCS1036
|
||||
|
||||
// ReSharper disable once MemberCanBeMadeStatic.Global
|
||||
#pragma warning disable CA1822, S2325
|
||||
protected T S<T>()
|
||||
protected static T S<T>()
|
||||
#pragma warning restore S2325, CA1822
|
||||
where T : class
|
||||
{
|
||||
|
@ -1,15 +1,10 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 代码模板表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_CodeTemplate))]
|
||||
public record Sys_CodeTemplate : VersionEntity, IFieldSummary, IFieldOwner, IFieldSort, IFieldEnabled
|
||||
public record Sys_CodeTemplate : VersionEntity, IFieldSort, IFieldSummary, IFieldEnabled, IFieldOwner
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
@ -20,6 +15,34 @@ public record Sys_CodeTemplate : VersionEntity, IFieldSummary, IFieldOwner, IFie
|
||||
[JsonIgnore]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别
|
||||
/// </summary>
|
||||
/// <example>Male</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual Genders? Gender { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
/// <example>123456</example>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Snowflake]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
/// <example>老王</example>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 归属用户
|
||||
/// </summary>
|
||||
@ -63,32 +86,4 @@ public record Sys_CodeTemplate : VersionEntity, IFieldSummary, IFieldOwner, IFie
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Summary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 代码模板编号
|
||||
/// </summary>
|
||||
/// <example>123456</example>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Snowflake]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
/// <example>老王</example>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别
|
||||
/// </summary>
|
||||
/// <example>Male</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual Genders? Gender { get; init; }
|
||||
}
|
@ -46,14 +46,6 @@ public record Sys_UserWallet : LiteVersionEntity, IFieldOwner
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 总余额
|
||||
/// </summary>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long TotalBalance { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 总支出
|
||||
/// </summary>
|
||||
|
@ -0,0 +1,99 @@
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_WalletFrozen))]
|
||||
public record Sys_WalletFrozen : LiteVersionEntity, IFieldOwner, IFieldSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 冻结金额
|
||||
/// </summary>
|
||||
/// <example>100</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long Amount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结前数值
|
||||
/// </summary>
|
||||
/// <example>100</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long FrozenBalanceBefore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结编号
|
||||
/// </summary>
|
||||
/// <example>123456</example>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Snowflake]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 归属用户
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(OwnerId))]
|
||||
public Sys_User Owner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 归属部门编号
|
||||
/// </summary>
|
||||
/// <example>370942943322181</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerDeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 归属用户编号
|
||||
/// </summary>
|
||||
/// <example>370942943322181</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual long? OwnerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结原因
|
||||
/// </summary>
|
||||
/// <example>Trade</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual WalletFrozenReasons Reason { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结状态
|
||||
/// </summary>
|
||||
/// <example>Frozen</example>
|
||||
[Column]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual WalletFrozenStatues Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
/// <example>备注文字</example>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
public virtual string Summary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 钱包
|
||||
/// </summary>
|
||||
[CsvIgnore]
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(OwnerId))]
|
||||
public Sys_UserWallet Wallet { get; init; }
|
||||
}
|
@ -22,6 +22,12 @@ public record QueryReq<T> : DataAbstraction
|
||||
/// </summary>
|
||||
public T Filter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 忽略归属
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public bool IgnoreOwner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询关键字
|
||||
/// </summary>
|
||||
|
@ -1,6 +1,3 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
|
||||
/// <summary>
|
||||
@ -11,13 +8,9 @@ public record CreateCodeTemplateReq : Sys_CodeTemplate
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
public override bool Enabled { get; init; } = true;
|
||||
|
||||
/// <inheritdoc cref="IFieldSort.Sort" />
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Sort { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
public override Genders? Gender { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
@ -27,8 +20,11 @@ public record CreateCodeTemplateReq : Sys_CodeTemplate
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
|
||||
/// <inheritdoc cref="IFieldSort.Sort" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[EnumDataType(typeof(Genders))]
|
||||
public override Genders? Gender { get; init; }
|
||||
public override long Sort { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,6 +1,3 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
|
||||
/// <summary>
|
||||
@ -8,7 +5,7 @@ namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
/// </summary>
|
||||
public sealed record QueryCodeTemplateReq : Sys_CodeTemplate
|
||||
{
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
@ -1,6 +1,3 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
@ -10,18 +7,10 @@ namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
/// </summary>
|
||||
public record QueryCodeTemplateRsp : Sys_CodeTemplate
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override DateTime? ModifiedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedUser.CreatedUserId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? CreatedUserId { get; init; }
|
||||
@ -30,6 +19,22 @@ public record QueryCodeTemplateRsp : Sys_CodeTemplate
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string CreatedUserName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override Genders? Gender { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override DateTime? ModifiedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldModifiedUser.ModifiedUserId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? ModifiedUserId { get; init; }
|
||||
@ -38,6 +43,10 @@ public record QueryCodeTemplateRsp : Sys_CodeTemplate
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string ModifiedUserName { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Name" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Owner" />
|
||||
public new virtual QueryUserRsp Owner { get; init; }
|
||||
|
||||
@ -60,16 +69,4 @@ public record QueryCodeTemplateRsp : Sys_CodeTemplate
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Name" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Gender" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override Genders? Gender { get; init; }
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:设置代码模板启用状态
|
||||
/// </summary>
|
||||
public sealed record SetCodeTemplateEnabledReq : Sys_CodeTemplate
|
||||
{
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override bool Enabled { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_CodeTemplate.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
|
||||
/// <summary>
|
||||
/// 信息:字段项信息
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:生成后端代码
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
namespace NetAdmin.Domain.Dto.Sys.Dev;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:获取所有数据类型
|
||||
|
@ -38,10 +38,6 @@ public record QueryUserWalletRsp : Sys_UserWallet
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? OwnerId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_UserWallet.TotalBalance" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long TotalBalance { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_UserWallet.TotalExpenditure" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long TotalExpenditure { get; init; }
|
||||
|
@ -0,0 +1,33 @@
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建钱包冻结
|
||||
/// </summary>
|
||||
public record CreateWalletFrozenReq : Sys_WalletFrozen
|
||||
{
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Amount" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Amount { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.OwnerId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? OwnerId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Reason" />
|
||||
[EnumDataType(typeof(WalletFrozenReasons))]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override WalletFrozenReasons Reason { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Status" />
|
||||
public override WalletFrozenStatues Status { get; init; } = WalletFrozenStatues.Frozen;
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:编辑钱包冻结
|
||||
/// </summary>
|
||||
public sealed record EditWalletFrozenReq : CreateWalletFrozenReq
|
||||
{
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询钱包冻结
|
||||
/// </summary>
|
||||
public sealed record QueryWalletFrozenReq : Sys_WalletFrozen
|
||||
{
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询钱包冻结
|
||||
/// </summary>
|
||||
public record QueryWalletFrozenRsp : Sys_WalletFrozen
|
||||
{
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Amount" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Amount { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.FrozenBalanceBefore" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long FrozenBalanceBefore { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldModifiedTime.ModifiedTime" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override DateTime? ModifiedTime { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Owner" />
|
||||
public new virtual QueryUserRsp Owner { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldOwner.OwnerDeptId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? OwnerDeptId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldOwner.OwnerId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override long? OwnerId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Reason" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override WalletFrozenReasons Reason { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Status" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override WalletFrozenStatues Status { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldVersion.Version" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Version { get; init; }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:将状态设置为解冻
|
||||
/// </summary>
|
||||
public record SetStatusToThawedReq : Sys_WalletFrozen
|
||||
{
|
||||
/// <inheritdoc cref="Sys_WalletFrozen.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Id { get; init; }
|
||||
}
|
@ -5,8 +5,6 @@ namespace NetAdmin.Domain.Dto.Sys.WalletTrade;
|
||||
/// </summary>
|
||||
public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
|
||||
{
|
||||
private readonly TradeTypes _tradeType;
|
||||
|
||||
/// <inheritdoc cref="Sys_WalletTrade.Amount" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Amount { get; init; }
|
||||
@ -33,9 +31,9 @@ public record CreateWalletTradeReq : Sys_WalletTrade, IValidatableObject
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
[EnumDataType(typeof(TradeTypes))]
|
||||
public override TradeTypes TradeType {
|
||||
get => _tradeType;
|
||||
get;
|
||||
init {
|
||||
_tradeType = value;
|
||||
field = value;
|
||||
TradeDirection = value.Attr<TradeAttribute>().Direction;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
namespace NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结原因
|
||||
/// </summary>
|
||||
[Export]
|
||||
public enum WalletFrozenReasons
|
||||
{
|
||||
/// <summary>
|
||||
/// 交易
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.交易))]
|
||||
Trade = 1
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 人工
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.人工))]
|
||||
Manual = 2
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
namespace NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结状态
|
||||
/// </summary>
|
||||
[Export]
|
||||
public enum WalletFrozenStatues
|
||||
{
|
||||
/// <summary>
|
||||
/// 已冻结
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.已冻结))]
|
||||
Frozen = 1
|
||||
|
||||
,
|
||||
|
||||
/// <summary>
|
||||
/// 已解冻
|
||||
/// </summary>
|
||||
[ResourceDescription<Ln>(nameof(Ln.已解冻))]
|
||||
Thawed = 2
|
||||
}
|
@ -24,9 +24,7 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 去掉尾部字符串“Async”
|
||||
/// </summary>
|
||||
#pragma warning disable RCS1047, ASA002, VSTHRD200
|
||||
public static string TrimSuffixAsync(this string me)
|
||||
#pragma warning restore VSTHRD200, ASA002, RCS1047
|
||||
public static string TrimAsyncSuffix(this string me)
|
||||
{
|
||||
return me.TrimSuffix("Async");
|
||||
}
|
||||
@ -34,7 +32,7 @@ public static class StringExtensions
|
||||
/// <summary>
|
||||
/// 去掉尾部字符串“Options”
|
||||
/// </summary>
|
||||
public static string TrimSuffixOptions(this string me)
|
||||
public static string TrimOptionsSuffix(this string me)
|
||||
{
|
||||
return me.TrimSuffix("Options");
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ public static class PhoneNumberHelper
|
||||
/// <summary>
|
||||
/// 电话号码转国家代码
|
||||
/// </summary>
|
||||
public static CountryCodes PhoneNumberToCountryCode(string phoneNumber)
|
||||
public static CountryCodes? PhoneNumberToCountryCode(string phoneNumber)
|
||||
{
|
||||
return _countryList.First(x => phoneNumber.Replace("+", string.Empty).Trim().StartsWith(x.CallingCode, StringComparison.Ordinal)).CountryCode;
|
||||
return _countryList.FirstOrDefault(x => phoneNumber.Replace("+", string.Empty).Trim().StartsWith(x.CallingCode, StringComparison.Ordinal))
|
||||
.CountryCode;
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ public sealed class XmlCommentReader : ISingleton
|
||||
public XmlCommentReader(IOptions<SpecificationDocumentSettingsOptions> specificationDocumentSettings)
|
||||
{
|
||||
var xmlComments = specificationDocumentSettings.Value.XmlComments //
|
||||
?? App.GetConfig<SpecificationDocumentSettingsOptions>(nameof(SpecificationDocumentSettingsOptions).TrimSuffixOptions())
|
||||
?? App.GetConfig<SpecificationDocumentSettingsOptions>(nameof(SpecificationDocumentSettingsOptions).TrimOptionsSuffix())
|
||||
.XmlComments;
|
||||
foreach (var commentFile in xmlComments) {
|
||||
var xmlDoc = new XmlDocument();
|
||||
|
@ -9,10 +9,4 @@ public interface ICodeTemplateModule : ICrudModule<CreateCodeTemplateReq, QueryC
|
||||
, EditCodeTemplateReq // 编辑类型
|
||||
, QueryCodeTemplateReq, QueryCodeTemplateRsp // 查询类型
|
||||
, DelReq // 删除类型
|
||||
>
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置代码模板启用状态
|
||||
/// </summary>
|
||||
Task<int> SetEnabledAsync(SetCodeTemplateEnabledReq req);
|
||||
}
|
||||
>;
|
@ -0,0 +1,18 @@
|
||||
using NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Modules.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结模块
|
||||
/// </summary>
|
||||
public interface IWalletFrozenModule : ICrudModule<CreateWalletFrozenReq, QueryWalletFrozenRsp // 创建类型
|
||||
, EditWalletFrozenReq // 编辑类型
|
||||
, QueryWalletFrozenReq, QueryWalletFrozenRsp // 查询类型
|
||||
, DelReq // 删除类型
|
||||
>
|
||||
{
|
||||
/// <summary>
|
||||
/// 将状态设置为解冻
|
||||
/// </summary>
|
||||
Task<int> SetStatusToThawedAsync(SetStatusToThawedReq req);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Api;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -176,7 +177,7 @@ public sealed class ApiService(
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -187,6 +188,6 @@ public sealed class ApiService(
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.CodeTemplate;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -113,13 +114,6 @@ public sealed class CodeTemplateService(BasicRepository<Sys_CodeTemplate, long>
|
||||
return ret.Adapt<IEnumerable<QueryCodeTemplateRsp>>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetCodeTemplateEnabledReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return UpdateAsync(req, [nameof(req.Enabled)]);
|
||||
}
|
||||
|
||||
private ISelect<Sys_CodeTemplate> QueryInternal(QueryReq<QueryCodeTemplateReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
@ -127,7 +121,7 @@ public sealed class CodeTemplateService(BasicRepository<Sys_CodeTemplate, long>
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -137,6 +131,6 @@ public sealed class CodeTemplateService(BasicRepository<Sys_CodeTemplate, long>
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Config;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -142,7 +143,7 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -152,6 +153,6 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -3,4 +3,10 @@ namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
/// <summary>
|
||||
/// 用户邀请服务
|
||||
/// </summary>
|
||||
public interface IUserInviteService : IService, IUserInviteModule;
|
||||
public interface IUserInviteService : IService, IUserInviteModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取关联用户Id
|
||||
/// </summary>
|
||||
Task<List<long>> GetAssociatedUserIdAsync(long userId);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结服务
|
||||
/// </summary>
|
||||
public interface IWalletFrozenService : IService, IWalletFrozenModule;
|
@ -220,7 +220,7 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -230,6 +230,6 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Dept;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -143,7 +144,7 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -158,6 +159,6 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -302,6 +302,87 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
|
||||
await WriteCsCodeAsync(Path.Combine(dir, $"{req.EntityName}Cache.cs"), templateContent).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Task GenerateDomainCreateReqFileAsync(GenerateCsCodeReq req, string project, string prefix)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"using {project}.DbMaps.{prefix};");
|
||||
if (!req.Interfaces.NullOrEmpty()) {
|
||||
_ = sb.AppendLine("using NetAdmin.Domain.DbMaps.Dependency.Fields;");
|
||||
}
|
||||
|
||||
_ = sb.AppendLine();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"namespace {project}.Dto.{prefix}.{req.EntityName};");
|
||||
_ = sb.AppendLine();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"""
|
||||
/// <summary>
|
||||
/// 请求:创建{req.Summary}
|
||||
/// </summary>
|
||||
""");
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"public record Create{req.EntityName}Req : {prefix}_{req.EntityName}");
|
||||
_ = sb.Append('{');
|
||||
if (req.Interfaces?.Contains(nameof(IFieldEnabled)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
public override bool Enabled { get; init; } = true;
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.BaseClass != nameof(SimpleEntity) && req.FieldList.Single(x => x.IsPrimary).Type == "string") {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required]
|
||||
public override string Id { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.Interfaces?.Contains(nameof(IFieldSort)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldSort.Sort" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Sort { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.Interfaces?.Contains(nameof(IFieldSummary)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
foreach (var field in req.FieldList) {
|
||||
var condition = field.IsStruct ? "Never" : "WhenWritingNull";
|
||||
var nul = field.IsStruct && field.IsNullable ? "?" : null;
|
||||
var isEnum = S<IConstantService>().GetEnums().FirstOrDefault(x => x.Key == field.Type);
|
||||
string enumConstraint = null;
|
||||
if (!isEnum.Key.NullOrEmpty()) {
|
||||
enumConstraint = $"""
|
||||
|
||||
[EnumDataType(typeof({field.Type}))]
|
||||
""";
|
||||
}
|
||||
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $$"""
|
||||
|
||||
/// <inheritdoc cref="{{prefix}}_{{req.EntityName}}.{{field.Name}}" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.{{condition}})]{{enumConstraint}}
|
||||
public override {{field.Type}}{{nul}} {{field.Name}} { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
_ = sb.Append('}');
|
||||
|
||||
var outPath = Path.Combine(Path.GetDirectoryName(req.Project)!, "Dto", prefix, req.EntityName);
|
||||
_ = Directory.CreateDirectory(outPath);
|
||||
return WriteCsCodeAsync(Path.Combine(outPath, $"Create{req.EntityName}Req.cs"), sb.ToString());
|
||||
}
|
||||
|
||||
private static Task GenerateDomainEditReqFileAsync(GenerateCsCodeReq req, string project, string prefix)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
@ -1002,85 +1083,4 @@ public sealed class DevService(IApiService apiService) : ServiceBase<DevService>
|
||||
content = string.Join('\n', usings) + sb;
|
||||
return File.WriteAllTextAsync(path, usings.Count == 0 ? content.Trim() : content);
|
||||
}
|
||||
|
||||
private Task GenerateDomainCreateReqFileAsync(GenerateCsCodeReq req, string project, string prefix)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"using {project}.DbMaps.{prefix};");
|
||||
if (!req.Interfaces.NullOrEmpty()) {
|
||||
_ = sb.AppendLine("using NetAdmin.Domain.DbMaps.Dependency.Fields;");
|
||||
}
|
||||
|
||||
_ = sb.AppendLine();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"namespace {project}.Dto.{prefix}.{req.EntityName};");
|
||||
_ = sb.AppendLine();
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"""
|
||||
/// <summary>
|
||||
/// 请求:创建{req.Summary}
|
||||
/// </summary>
|
||||
""");
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $"public record Create{req.EntityName}Req : {prefix}_{req.EntityName}");
|
||||
_ = sb.Append('{');
|
||||
if (req.Interfaces?.Contains(nameof(IFieldEnabled)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldEnabled.Enabled" />
|
||||
public override bool Enabled { get; init; } = true;
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.BaseClass != nameof(SimpleEntity) && req.FieldList.Single(x => x.IsPrimary).Type == "string") {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="EntityBase{T}.Id" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Required]
|
||||
public override string Id { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.Interfaces?.Contains(nameof(IFieldSort)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldSort.Sort" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public override long Sort { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
if (req.Interfaces?.Contains(nameof(IFieldSummary)) == true) {
|
||||
_ = sb.AppendLine("""
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
foreach (var field in req.FieldList) {
|
||||
var condition = field.IsStruct ? "Never" : "WhenWritingNull";
|
||||
var nul = field.IsStruct && field.IsNullable ? "?" : null;
|
||||
var isEnum = S<IConstantService>().GetEnums().FirstOrDefault(x => x.Key == field.Type);
|
||||
string enumConstraint = null;
|
||||
if (!isEnum.Key.NullOrEmpty()) {
|
||||
enumConstraint = $"""
|
||||
|
||||
[EnumDataType(typeof({field.Type}))]
|
||||
""";
|
||||
}
|
||||
|
||||
_ = sb.AppendLine(CultureInfo.InvariantCulture, $$"""
|
||||
|
||||
/// <inheritdoc cref="{{prefix}}_{{req.EntityName}}.{{field.Name}}" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.{{condition}})]{{enumConstraint}}
|
||||
public override {{field.Type}}{{nul}} {{field.Name}} { get; init; }
|
||||
""");
|
||||
}
|
||||
|
||||
_ = sb.Append('}');
|
||||
|
||||
var outPath = Path.Combine(Path.GetDirectoryName(req.Project)!, "Dto", prefix, req.EntityName);
|
||||
_ = Directory.CreateDirectory(outPath);
|
||||
return WriteCsCodeAsync(Path.Combine(outPath, $"Create{req.EntityName}Req.cs"), sb.ToString());
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Dic.Catalog;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -126,7 +127,7 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -136,6 +137,6 @@ public sealed class DicCatalogService(BasicRepository<Sys_DicCatalog, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Dic.Content;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -148,7 +149,7 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -158,6 +159,6 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Catalog;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -127,7 +128,7 @@ public sealed class DocCatalogService(BasicRepository<Sys_DocCatalog, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -137,6 +138,6 @@ public sealed class DocCatalogService(BasicRepository<Sys_DocCatalog, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Doc.Content;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
@ -171,7 +172,7 @@ public sealed class DocContentService(BasicRepository<Sys_DocContent, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -181,6 +182,6 @@ public sealed class DocContentService(BasicRepository<Sys_DocContent, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.JobRecord;
|
||||
@ -161,7 +162,7 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -171,6 +172,6 @@ public sealed class JobRecordService(BasicRepository<Sys_JobRecord, long> rpo) /
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using Cronos;
|
||||
using FreeSql.Internal;
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Job;
|
||||
@ -342,7 +343,7 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -352,6 +353,6 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
||||
ret = ret.OrderByDescending(a => a.LastExecTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.LoginLog;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -129,7 +130,7 @@ public sealed class LoginLogService(BasicRepository<Sys_LoginLog, long> rpo) //
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -139,6 +140,6 @@ public sealed class LoginLogService(BasicRepository<Sys_LoginLog, long> rpo) //
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Menu;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -130,7 +131,7 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
|
||||
return req.Order switch {
|
||||
ret = req.Order switch {
|
||||
Orders.None => ret
|
||||
, Orders.Random => ret.OrderByRandom()
|
||||
, _ => ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
@ -138,5 +139,6 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
|
||||
.OrderBy(a => a.Name)
|
||||
.OrderBy(a => a.Id)
|
||||
};
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.RequestLogDetail;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -113,7 +114,7 @@ public sealed class RequestLogDetailService(BasicRepository<Sys_RequestLogDetail
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -123,6 +124,6 @@ public sealed class RequestLogDetailService(BasicRepository<Sys_RequestLogDetail
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.LoginLog;
|
||||
@ -215,7 +216,7 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo,
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -226,6 +227,6 @@ public sealed class RequestLogService(BasicRepository<Sys_RequestLog, long> rpo,
|
||||
ret = ret.OrderByDescending(a => a.CreatedTime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Role;
|
||||
using NetAdmin.Domain.Dto.Sys.UserRole;
|
||||
@ -168,7 +169,7 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo, IUserRoleSe
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -183,6 +184,6 @@ public sealed class RoleService(BasicRepository<Sys_Role, long> rpo, IUserRoleSe
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsgDept;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -110,7 +111,7 @@ public sealed class SiteMsgDeptService(BasicRepository<Sys_SiteMsgDept, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -120,6 +121,6 @@ public sealed class SiteMsgDeptService(BasicRepository<Sys_SiteMsgDept, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsgFlag;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -117,7 +118,7 @@ public sealed class SiteMsgFlagService(BasicRepository<Sys_SiteMsgFlag, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -127,6 +128,6 @@ public sealed class SiteMsgFlagService(BasicRepository<Sys_SiteMsgFlag, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsgRole;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -110,7 +111,7 @@ public sealed class SiteMsgRoleService(BasicRepository<Sys_SiteMsgRole, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -120,6 +121,6 @@ public sealed class SiteMsgRoleService(BasicRepository<Sys_SiteMsgRole, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsg;
|
||||
@ -271,7 +272,7 @@ public sealed class SiteMsgService(BasicRepository<Sys_SiteMsg, long> rpo, Conte
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -281,7 +282,7 @@ public sealed class SiteMsgService(BasicRepository<Sys_SiteMsg, long> rpo, Conte
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
private ISelectGrouping //
|
||||
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.SiteMsgUser;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -110,7 +111,7 @@ public sealed class SiteMsgUserService(BasicRepository<Sys_SiteMsgUser, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
}
|
||||
@ -120,6 +121,6 @@ public sealed class SiteMsgUserService(BasicRepository<Sys_SiteMsgUser, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.UserInvite;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -78,6 +79,16 @@ public sealed class UserInviteService(BasicRepository<Sys_UserInvite, long> rpo)
|
||||
return ExportAsync<QueryUserInviteReq, QueryUserInviteRsp>(QueryInternal, req, Ln.用户邀请导出);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<long>> GetAssociatedUserIdAsync(long userId)
|
||||
{
|
||||
return Rpo.Orm.Select<Sys_UserInvite>()
|
||||
.DisableGlobalFilter(Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA)
|
||||
.Where(a => a.Id == userId)
|
||||
.AsTreeCte(up: true, disableGlobalFilters: [Chars.FLG_FREE_SQL_GLOBAL_FILTER_DATA])
|
||||
.ToListAsync(a => a.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserInviteRsp> GetAsync(QueryUserInviteReq req)
|
||||
{
|
||||
@ -128,9 +139,9 @@ public sealed class UserInviteService(BasicRepository<Sys_UserInvite, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -138,6 +149,6 @@ public sealed class UserInviteService(BasicRepository<Sys_UserInvite, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.Dic.Content;
|
||||
@ -188,9 +189,9 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -198,7 +199,7 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternalComplex(
|
||||
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.UserRole;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -110,9 +111,9 @@ public sealed class UserRoleService(BasicRepository<Sys_UserRole, long> rpo) //
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -120,6 +121,6 @@ public sealed class UserRoleService(BasicRepository<Sys_UserRole, long> rpo) //
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.Attributes.DataValidation;
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
@ -551,9 +552,9 @@ public sealed class UserService(
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -562,7 +563,7 @@ public sealed class UserService(
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
private ISelect<Sys_User> QueryInternal(QueryReq<QueryUserReq> req)
|
||||
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.UserWallet;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
@ -65,7 +66,8 @@ public sealed class UserWalletService(BasicRepository<Sys_UserWallet, long> rpo)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
#if DBTYPE_SQLSERVER
|
||||
return (await UpdateReturnListAsync(req).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryUserWalletRsp>();
|
||||
return (await UpdateReturnListAsync(req, [nameof(req.FrozenBalance), nameof(req.AvailableBalance)]).ConfigureAwait(false)).FirstOrDefault()
|
||||
?.Adapt<QueryUserWalletRsp>();
|
||||
#else
|
||||
return await UpdateAsync(req).ConfigureAwait(false) > 0 ? await GetAsync(new QueryUserWalletReq { Id = req.Id }).ConfigureAwait(false) : null;
|
||||
#endif
|
||||
@ -130,9 +132,9 @@ public sealed class UserWalletService(BasicRepository<Sys_UserWallet, long> rpo)
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -140,6 +142,6 @@ public sealed class UserWalletService(BasicRepository<Sys_UserWallet, long> rpo)
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.VerifyCode;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
@ -191,9 +192,9 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -201,6 +202,6 @@ public sealed class VerifyCodeService(BasicRepository<Sys_VerifyCode, long> rpo,
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
using NetAdmin.Domain.Dto.Sys.UserWallet;
|
||||
using NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using NetAdmin.Domain.Extensions;
|
||||
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IWalletFrozenService" />
|
||||
public sealed class WalletFrozenService(BasicRepository<Sys_WalletFrozen, long> rpo) //
|
||||
: RepositoryService<Sys_WalletFrozen, long, IWalletFrozenService>(rpo), IWalletFrozenService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = 0;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach (var item in req.Items) {
|
||||
ret += await DeleteAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return QueryInternal(req).WithNoLockNoWait().CountAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req with { Order = Orders.None })
|
||||
.WithNoLockNoWait()
|
||||
.GroupBy(req.GetToListExp<Sys_WalletFrozen>())
|
||||
.ToDictionaryAsync(a => a.Count())
|
||||
.ConfigureAwait(false);
|
||||
return ret.Select(x => new KeyValuePair<IImmutableDictionary<string, string>, int>(
|
||||
req.RequiredFields.ToImmutableDictionary(
|
||||
y => y
|
||||
, y => y.Contains('.')
|
||||
? typeof(Sys_WalletFrozen).GetRecursiveProperty(y)!.GetValue(
|
||||
x.Key.GetType().GetRecursiveProperty(y[..y.LastIndexOf('.')]).GetValue(x.Key))!.ToString()
|
||||
: typeof(Sys_WalletFrozen).GetProperty(y)!.GetValue(x.Key)!.ToString()), x.Value))
|
||||
.OrderByDescending(x => x.Value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryWalletFrozenRsp> CreateAsync(CreateWalletFrozenReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var userId = UserToken.Id;
|
||||
var userDeptId = UserToken.DeptId;
|
||||
if (req.OwnerId != null) {
|
||||
userId = req.OwnerId.Value;
|
||||
var owner = await S<IUserService>().GetAsync(new QueryUserReq { Id = userId }).ConfigureAwait(false);
|
||||
userDeptId = owner.DeptId;
|
||||
}
|
||||
|
||||
var wallet = await S<IUserWalletService>().GetAsync(new QueryUserWalletReq { Id = userId }).ConfigureAwait(false);
|
||||
if (wallet.AvailableBalance < req.Amount) {
|
||||
throw new NetAdminInvalidOperationException(Ln.钱包可用余额不足);
|
||||
}
|
||||
|
||||
var frozenBalanceBefore = wallet.FrozenBalance;
|
||||
if (await S<IUserWalletService>()
|
||||
.EditAsync(wallet.Adapt<EditUserWalletReq>() with {
|
||||
AvailableBalance = wallet.AvailableBalance - req.Amount
|
||||
, FrozenBalance = wallet.FrozenBalance + req.Amount
|
||||
})
|
||||
.ConfigureAwait(false) == null) {
|
||||
throw new NetAdminUnexpectedException(Ln.结果非预期);
|
||||
}
|
||||
|
||||
var ret = await Rpo.InsertAsync(req with { OwnerDeptId = userDeptId, FrozenBalanceBefore = frozenBalanceBefore }).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryWalletFrozenRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return Rpo.DeleteAsync(a => a.Id == req.Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryWalletFrozenRsp> EditAsync(EditWalletFrozenReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
#if DBTYPE_SQLSERVER
|
||||
return (await UpdateReturnListAsync(req).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryWalletFrozenRsp>();
|
||||
#else
|
||||
return await UpdateAsync(req).ConfigureAwait(false) > 0
|
||||
? await GetAsync(new QueryWalletFrozenReq { Id = req.Id }).ConfigureAwait(false)
|
||||
: null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
return ExportAsync<QueryWalletFrozenReq, QueryWalletFrozenRsp>(QueryInternal, req, Ln.钱包冻结导出);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryWalletFrozenRsp> GetAsync(QueryWalletFrozenReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(new QueryReq<QueryWalletFrozenReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false);
|
||||
return ret.Adapt<QueryWalletFrozenRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryWalletFrozenRsp>> PagedQueryAsync(PagedQueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var list = await QueryInternal(req)
|
||||
.Include(a => a.Owner)
|
||||
.Page(req.Page, req.PageSize)
|
||||
.WithNoLockNoWait()
|
||||
.Count(out var total)
|
||||
.ToListAsync(req)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new PagedQueryRsp<QueryWalletFrozenRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryWalletFrozenRsp>>());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryWalletFrozenRsp>> QueryAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
var ret = await QueryInternal(req).WithNoLockNoWait().Take(req.Count).ToListAsync(req).ConfigureAwait(false);
|
||||
return ret.Adapt<IEnumerable<QueryWalletFrozenRsp>>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> SetStatusToThawedAsync(SetStatusToThawedReq req)
|
||||
{
|
||||
req.ThrowIfInvalid();
|
||||
|
||||
var frozen = await GetAsync(new QueryWalletFrozenReq { Id = req.Id }).ConfigureAwait(false);
|
||||
if (frozen?.Status != WalletFrozenStatues.Frozen) {
|
||||
throw new NetAdminInvalidOperationException(Ln.冻结状态不正确);
|
||||
}
|
||||
|
||||
var updateCnt = await UpdateAsync(new Sys_WalletFrozen { Status = WalletFrozenStatues.Thawed }, [nameof(req.Status)], null
|
||||
, a => a.Status == WalletFrozenStatues.Frozen && a.Id == req.Id)
|
||||
.ConfigureAwait(false);
|
||||
if (updateCnt != 1) {
|
||||
throw new NetAdminUnexpectedException(Ln.结果非预期);
|
||||
}
|
||||
|
||||
var userWalletService = S<IUserWalletService>();
|
||||
var wallet = await userWalletService.GetAsync(new QueryUserWalletReq { Id = frozen.OwnerId!.Value }).ConfigureAwait(false);
|
||||
if (wallet.FrozenBalance < req.Amount) {
|
||||
throw new NetAdminUnexpectedException(Ln.结果非预期);
|
||||
}
|
||||
|
||||
_ = await userWalletService
|
||||
.EditAsync(wallet.Adapt<EditUserWalletReq>() with {
|
||||
AvailableBalance = wallet.AvailableBalance + frozen.Amount
|
||||
, FrozenBalance = wallet.FrozenBalance - frozen.Amount
|
||||
})
|
||||
.ConfigureAwait(false) ?? throw new NetAdminUnexpectedException(Ln.结果非预期);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private ISelect<Sys_WalletFrozen> QueryInternal(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
using NetAdmin.Application.Extensions;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
using NetAdmin.Domain.Dto.Sys.UserWallet;
|
||||
using NetAdmin.Domain.Dto.Sys.WalletTrade;
|
||||
@ -53,13 +54,10 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> rp
|
||||
var userWalletService = S<IUserWalletService>();
|
||||
var wallet = await userWalletService.GetAsync(new QueryUserWalletReq { Id = req.OwnerId!.Value }).ConfigureAwait(false);
|
||||
if (wallet.AvailableBalance + req.Amount < 0) {
|
||||
throw new NetAdminInvalidOperationException(Ln.钱包余额不足);
|
||||
throw new NetAdminInvalidOperationException(Ln.钱包可用余额不足);
|
||||
}
|
||||
|
||||
_ = await userWalletService.EditAsync(wallet.Adapt<EditUserWalletReq>() with {
|
||||
AvailableBalance = wallet.AvailableBalance + req.Amount
|
||||
, TotalBalance = wallet.TotalBalance + req.Amount
|
||||
})
|
||||
_ = await userWalletService.EditAsync(wallet.Adapt<EditUserWalletReq>() with { AvailableBalance = wallet.AvailableBalance + req.Amount })
|
||||
.ConfigureAwait(false) ?? throw new NetAdminUnexpectedException(Ln.交易失败);
|
||||
var ret = await Rpo.InsertAsync(req with { BalanceBefore = wallet.AvailableBalance, OwnerDeptId = wallet.OwnerDeptId }).ConfigureAwait(false);
|
||||
return ret.Adapt<QueryWalletTradeRsp>();
|
||||
@ -130,9 +128,9 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> rp
|
||||
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||
switch (req.Order) {
|
||||
case Orders.None:
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
case Orders.Random:
|
||||
return ret.OrderByRandom();
|
||||
return ret.OrderByRandom().AppendOtherFilters(req);
|
||||
}
|
||||
|
||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
@ -140,6 +138,6 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> rp
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret.AppendOtherFilters(req);
|
||||
}
|
||||
}
|
@ -65,10 +65,4 @@ public sealed class CodeTemplateCache(IDistributedCache cache, ICodeTemplateServ
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetEnabledAsync(SetCodeTemplateEnabledReq req)
|
||||
{
|
||||
return Service.SetEnabledAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结缓存
|
||||
/// </summary>
|
||||
public interface IWalletFrozenCache : ICache<IDistributedCache, IWalletFrozenService>, IWalletFrozenModule;
|
@ -0,0 +1,74 @@
|
||||
using NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
namespace NetAdmin.SysComponent.Cache.Sys;
|
||||
|
||||
/// <inheritdoc cref="IWalletFrozenCache" />
|
||||
public sealed class WalletFrozenCache(IDistributedCache cache, IWalletFrozenService service)
|
||||
: DistributedCache<IWalletFrozenService>(cache, service), IScoped, IWalletFrozenCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Service.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<long> CountAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Service.CountAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Service.CountByAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryWalletFrozenRsp> CreateAsync(CreateWalletFrozenReq req)
|
||||
{
|
||||
return Service.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Service.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryWalletFrozenRsp> EditAsync(EditWalletFrozenReq req)
|
||||
{
|
||||
return Service.EditAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Service.ExportAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<QueryWalletFrozenRsp> GetAsync(QueryWalletFrozenReq req)
|
||||
{
|
||||
return Service.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<PagedQueryRsp<QueryWalletFrozenRsp>> PagedQueryAsync(PagedQueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Service.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryWalletFrozenRsp>> QueryAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Service.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<int> SetStatusToThawedAsync(SetStatusToThawedReq req)
|
||||
{
|
||||
return Service.SetStatusToThawedAsync(req);
|
||||
}
|
||||
}
|
@ -95,12 +95,4 @@ public sealed class CodeTemplateController(ICodeTemplateCache cache)
|
||||
{
|
||||
return Cache.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置代码模板启用状态
|
||||
/// </summary>
|
||||
public Task<int> SetEnabledAsync(SetCodeTemplateEnabledReq req)
|
||||
{
|
||||
return Cache.SetEnabledAsync(req);
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
using NetAdmin.Domain.Dto.Sys.WalletFrozen;
|
||||
|
||||
namespace NetAdmin.SysComponent.Host.Controllers.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(nameof(Sys), Module = nameof(Sys))]
|
||||
[Produces(Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_JSON)]
|
||||
public sealed class WalletFrozenController(IWalletFrozenCache cache)
|
||||
: ControllerBase<IWalletFrozenCache, IWalletFrozenService>(cache), IWalletFrozenModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除钱包冻结
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
return Cache.BulkDeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结计数
|
||||
/// </summary>
|
||||
public Task<long> CountAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Cache.CountAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 钱包冻结分组计数
|
||||
/// </summary>
|
||||
public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Cache.CountByAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建钱包冻结
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryWalletFrozenRsp> CreateAsync(CreateWalletFrozenReq req)
|
||||
{
|
||||
return Cache.CreateAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除钱包冻结
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
return Cache.DeleteAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑钱包冻结
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<QueryWalletFrozenRsp> EditAsync(EditWalletFrozenReq req)
|
||||
{
|
||||
return Cache.EditAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出钱包冻结
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public Task<IActionResult> ExportAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Cache.ExportAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个钱包冻结
|
||||
/// </summary>
|
||||
public Task<QueryWalletFrozenRsp> GetAsync(QueryWalletFrozenReq req)
|
||||
{
|
||||
return Cache.GetAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询钱包冻结
|
||||
/// </summary>
|
||||
public Task<PagedQueryRsp<QueryWalletFrozenRsp>> PagedQueryAsync(PagedQueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Cache.PagedQueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询钱包冻结
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public Task<IEnumerable<QueryWalletFrozenRsp>> QueryAsync(QueryReq<QueryWalletFrozenReq> req)
|
||||
{
|
||||
return Cache.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将状态设置为解冻
|
||||
/// </summary>
|
||||
[Transaction]
|
||||
public Task<int> SetStatusToThawedAsync(SetStatusToThawedReq req)
|
||||
{
|
||||
return Cache.SetStatusToThawedAsync(req);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.7"/>
|
||||
<PackageReference Include="xunit" Version="2.9.3"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
@ -206,17 +206,6 @@ public class UserTests(WebTestApplicationFactory<Startup> factory, ITestOutputHe
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(null)]
|
||||
[Theory]
|
||||
[TestPriority(101600)]
|
||||
public async Task<IEnumerable<QueryUserRsp>> QueryRelationAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var rsp = await PostJsonAsync(typeof(UserController), req);
|
||||
Assert.True(rsp.IsSuccessStatusCode);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[InlineData(null)]
|
||||
[Theory]
|
||||
|
@ -1 +1 @@
|
||||
global using CsvIgnore = CsvHelper.Configuration.Attributes.IgnoreAttribute;
|
||||
global using CsvIgnore = CsvHelper.Configuration.Attributes.IgnoreAttribute;
|
@ -10,13 +10,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"ace-builds": "1.43.0",
|
||||
"ace-builds": "1.43.1",
|
||||
"aieditor": "1.4.0",
|
||||
"axios": "1.10.0",
|
||||
"crypto-js": "4.2.0",
|
||||
"dayjs": "1.11.13",
|
||||
"echarts": "5.6.0",
|
||||
"element-plus": "2.10.2",
|
||||
"element-plus": "2.10.3",
|
||||
"json-bigint": "1.0.0",
|
||||
"markdown-it": "14.1.0",
|
||||
"markdown-it-emoji": "3.0.0",
|
||||
@ -25,7 +25,7 @@
|
||||
"sortablejs": "1.15.6",
|
||||
"vkbeautify": "0.99.3",
|
||||
"vue": "3.5.17",
|
||||
"vue-i18n": "11.1.7",
|
||||
"vue-i18n": "11.1.9",
|
||||
"vue-router": "4.5.1",
|
||||
"vue3-ace-editor": "2.2.4",
|
||||
"vue3-json-viewer": "2.4.1",
|
||||
@ -38,7 +38,7 @@
|
||||
"prettier-plugin-organize-attributes": "1.0.0",
|
||||
"sass": "1.89.2",
|
||||
"terser": "5.43.1",
|
||||
"vite": "7.0.0"
|
||||
"vite": "7.0.4"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
@ -92,15 +92,4 @@ export default {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置代码模板启用状态
|
||||
*/
|
||||
setEnabled: {
|
||||
url: `${config.API_URL}/api/sys/code.template/set.enabled`,
|
||||
name: `设置代码模板启用状态`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
106
src/frontend/admin/src/api/sys/walletfrozen.js
Normal file
106
src/frontend/admin/src/api/sys/walletfrozen.js
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 钱包冻结服务
|
||||
* @module @/api/sys/wallet.frozen
|
||||
*/
|
||||
import config from '@/config'
|
||||
import http from '@/utils/request'
|
||||
export default {
|
||||
/**
|
||||
* 批量删除钱包冻结
|
||||
*/
|
||||
bulkDelete: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/bulk.delete`,
|
||||
name: `批量删除钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 钱包冻结计数
|
||||
*/
|
||||
count: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/count`,
|
||||
name: `钱包冻结计数`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 钱包冻结分组计数
|
||||
*/
|
||||
countBy: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/count.by`,
|
||||
name: `钱包冻结分组计数`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建钱包冻结
|
||||
*/
|
||||
create: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/create`,
|
||||
name: `创建钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除钱包冻结
|
||||
*/
|
||||
delete: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/delete`,
|
||||
name: `删除钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 编辑钱包冻结
|
||||
*/
|
||||
edit: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/edit`,
|
||||
name: `编辑钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单个钱包冻结
|
||||
*/
|
||||
get: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/get`,
|
||||
name: `获取单个钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询钱包冻结
|
||||
*/
|
||||
pagedQuery: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/paged.query`,
|
||||
name: `分页查询钱包冻结`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 将状态设置为解冻
|
||||
*/
|
||||
setStatusToThawed: {
|
||||
url: `${config.API_URL}/api/sys/wallet.frozen/set.status.to.thawed`,
|
||||
name: `将状态设置为解冻`,
|
||||
post: async function (data = {}, config = {}) {
|
||||
return await http.post(this.url, data, config)
|
||||
},
|
||||
},
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<svg class="icon" height="256" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M256 512h512v85.333333H256z" fill="" />
|
||||
<path d="M256 512h512v85.333333H256z" />
|
||||
<path
|
||||
d="M936.448 370.56l-85.333333-256.042667A42.538667 42.538667 0 0 0 810.666667 85.333333H213.333333a42.581333 42.581333 0 0 0-40.448 29.184l-85.333333 256 0.512 0.170667A39.594667 39.594667 0 0 0 85.333333 384v426.666667a42.666667 42.666667 0 0 0 42.666667 42.666666h768a42.666667 42.666667 0 0 0 42.666667-42.666666V384a41.088 41.088 0 0 0-2.688-13.312l0.469333-0.128zM244.096 170.666667H779.946667l56.874666 170.666666H187.178667l56.917333-170.666666zM853.333333 768H170.666667v-341.333333h682.666666v341.333333z" />
|
||||
</svg>
|
||||
|
15
src/frontend/admin/src/assets/icon/income.vue
Normal file
15
src/frontend/admin/src/assets/icon/income.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<svg class="icon" height="256" p-id="5898" t="1752220814991" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M512 954.181818c-218.763636 0-465.454545 0-465.454545-279.272727C46.545455 418.909091 256 209.454545 512 209.454545s465.454545 209.454545 465.454545 465.454546c0 279.272727-246.690909 279.272727-465.454545 279.272727z m0-698.181818c-230.4 0-418.909091 188.509091-418.909091 418.909091 0 216.436364 165.236364 232.727273 418.909091 232.727273s418.909091-16.290909 418.909091-232.727273c0-230.4-188.509091-418.909091-418.909091-418.909091z"
|
||||
fill="#424752"
|
||||
p-id="5899"></path>
|
||||
<path
|
||||
d="M679.563636 283.927273l-44.218181-13.963637 37.236363-128c0-2.327273 0-4.654545-2.327273-4.654545 0 0-2.327273-2.327273-6.981818 0l-41.890909 16.290909c-20.945455 6.981818-41.890909 4.654545-58.181818-11.636364l-58.181818-58.181818c-2.327273-2.327273-6.981818-2.327273-9.309091 0l-58.181818 58.181818c-16.290909 16.290909-37.236364 20.945455-58.181818 11.636364l-41.89091-16.290909c-4.654545-2.327273-6.981818 0-6.981818 0-2.327273 2.327273-2.327273 2.327273-2.327272 4.654545l37.236363 128-44.218182 13.963637-37.236363-128c-4.654545-18.618182 0-39.563636 13.963636-53.527273 16.290909-13.963636 37.236364-18.618182 55.854546-9.309091l41.890909 16.290909c2.327273 2.327273 4.654545 2.327273 6.981818-2.327273l58.181818-58.181818c20.945455-20.945455 53.527273-20.945455 74.472727 0l58.181818 58.181818c2.327273 2.327273 4.654545 2.327273 6.981819 2.327273l41.890909-16.290909c18.618182-6.981818 39.563636-4.654545 55.854545 9.309091 18.618182 16.290909 23.272727 37.236364 18.618182 55.854545l-37.236364 125.672728zM512 581.818182l-155.927273-155.927273 32.581818-32.581818 123.345455 123.345454 123.345455-123.345454 32.581818 32.581818z"
|
||||
fill="#424752"
|
||||
p-id="5900"></path>
|
||||
<path d="M325.818182 535.272727h372.363636v46.545455H325.818182z" fill="#424752" p-id="5901"></path>
|
||||
<path d="M488.727273 535.272727h46.545454v279.272728h-46.545454z" fill="#424752" p-id="5902"></path>
|
||||
<path d="M325.818182 674.909091h372.363636v46.545454H325.818182z" fill="#424752" p-id="5903"></path>
|
||||
</svg>
|
||||
</template>
|
@ -77,3 +77,5 @@ export { default as 'nick-name' } from './nick-name'
|
||||
export { default as telegram } from './telegram'
|
||||
export { default as country } from './country'
|
||||
export { default as template } from './template.vue'
|
||||
export { default as order } from './order.vue'
|
||||
export { default as income } from './income.vue'
|
6
src/frontend/admin/src/assets/icon/order.vue
Normal file
6
src/frontend/admin/src/assets/icon/order.vue
Normal file
@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<svg class="icon" height="256" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M856.006891 49.877991 793.57805 49.877991c-17.263176 0-37.193087 10.472516-37.193087 27.492144s19.929912 34.038234 37.193087 34.038234l62.428841 0c37.190017 0 62.425771 24.877597 62.425771 61.530378l0 708.23636c0 36.652781-25.235754 61.530378-62.425771 61.530378L183.931103 942.705486c-37.185924 0-78.360695-24.877597-78.360695-61.530378L105.570407 172.937724c0-36.652781 25.232684-61.530378 62.425771-61.530378l78.363765 0c17.270339 0 23.907503-17.019629 23.907503-34.038234s-6.638187-27.492144-23.907503-27.492144l-78.363765 0c-87.661525 0-124.853589 53.674457-124.853589 124.365472l0 700.384531c0 75.928297 46.486754 129.603777 131.494846 129.603777l674.722058 0c85.011162 0 131.497916-44.51382 131.497916-129.603777L980.857411 174.243463C980.857411 103.552447 937.03023 49.877991 856.006891 49.877991L856.006891 49.877991 856.006891 49.877991zM246.359944 327.412958c0 17.022699 14.609743 31.420617 31.873941 31.420617l468.857411 0c17.266245 0 31.880081-14.398942 31.880081-31.420617 0-17.019629-14.613836-31.420617-31.880081-31.420617L278.233885 295.992341C260.969687 295.991318 246.359944 310.393329 246.359944 327.412958L246.359944 327.412958 246.359944 327.412958zM745.766115 466.180442 278.233885 466.180442c-17.263176 0-31.873941 14.402011-31.873941 31.42471 0 17.015535 14.609743 31.414477 31.873941 31.414477l468.857411 0c17.266245 0 31.880081-14.398942 31.880081-31.414477C777.646196 479.273644 763.02929 466.180442 745.766115 466.180442L745.766115 466.180442 745.766115 466.180442zM745.766115 650.767484 278.233885 650.767484c-17.263176 0-31.873941 14.402011-31.873941 31.417547 0 17.019629 14.609743 31.417547 31.873941 31.417547l468.857411 0c17.266245 0 31.880081-14.398942 31.880081-31.417547C777.646196 663.860686 763.02929 650.767484 745.766115 650.767484L745.766115 650.767484 745.766115 650.767484zM404.415726 127.118166l217.828121 0c25.235754 0 46.486754-24.871457 46.486754-53.674457 0-28.79686-21.251-53.674457-47.818075-53.674457L404.415726 19.769252c-26.564006 0-47.811936 24.874527-47.811936 53.674457C356.603791 102.246709 377.851721 127.118166 404.415726 127.118166L404.415726 127.118166 404.415726 127.118166zM404.415726 127.118166"></path>
|
||||
</svg>
|
||||
</template>
|
@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<sc-dialog v-model="visible" :full-screen="dialogFullScreen" :title="titleMap[mode]" @closed="$emit(`closed`)" destroy-on-close>
|
||||
<div v-loading="loading">
|
||||
<el-tabs v-model="tabId" :class="{ 'hide-tabs': !tabs || !tabs[mode] || tabs[mode].length === 0 }">
|
||||
<el-tab-pane :label="$t(`基本信息`)" name="basic">
|
||||
<el-form
|
||||
:disabled="![`edit`, `add`].includes(mode)"
|
||||
:model="form"
|
||||
@ -10,7 +12,13 @@
|
||||
ref="dialogForm">
|
||||
<template v-for="(item, i) in columns" :key="i">
|
||||
<el-form-item v-if="item.show?.includes(mode)" :label="item.label" :prop="i">
|
||||
<el-date-picker v-if="i.endsWith(`Time`)" v-model="form[i]" :disabled="item.disabled?.includes(mode)" type="datetime" />
|
||||
<el-date-picker
|
||||
v-bind="item.detail?.props"
|
||||
v-if="i.endsWith(`Time`)"
|
||||
v-model="form[i]"
|
||||
:disabled="item.disabled?.includes(mode)"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" />
|
||||
<el-select v-else-if="item.enum" v-model="form[i]" :disabled="item.disabled?.includes(mode)" clearable filterable>
|
||||
<el-option
|
||||
v-for="e in Object.entries(this.$GLOBAL.enums[item.enum]).map((x) => {
|
||||
@ -27,6 +35,12 @@
|
||||
v-else-if="typeof form[i] === `boolean` || item.isBoolean"
|
||||
v-model="form[i]"
|
||||
:disabled="item.disabled?.includes(mode)" />
|
||||
<component
|
||||
v-bind="item.detail?.props"
|
||||
v-else-if="item.detail?.vModelValue"
|
||||
v-model:value="form[i]"
|
||||
:disabled="item.disabled?.includes(mode)"
|
||||
:is="item.detail?.is ?? `el-input`" />
|
||||
<component
|
||||
v-bind="item.detail?.props"
|
||||
v-else
|
||||
@ -36,6 +50,11 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<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" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">{{ $t(`取消`) }}</el-button>
|
||||
@ -49,6 +68,7 @@ export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
tabId: `basic`,
|
||||
rules: {},
|
||||
visible: false,
|
||||
mode: `add`,
|
||||
@ -64,6 +84,9 @@ export default {
|
||||
created() {},
|
||||
emits: [`success`, `closed`, `mounted`],
|
||||
methods: {
|
||||
async paneClosed() {
|
||||
this.visible = false
|
||||
},
|
||||
//显示
|
||||
async open(data) {
|
||||
this.visible = true
|
||||
@ -102,11 +125,13 @@ export default {
|
||||
|
||||
//表单提交方法
|
||||
async submit() {
|
||||
this.loading = true
|
||||
if (this.tabId === `basic`) {
|
||||
const valid = await this.$refs.dialogForm.validate().catch(() => {})
|
||||
if (!valid) {
|
||||
this.loading = false
|
||||
return false
|
||||
}
|
||||
this.loading = true
|
||||
const method = this.mode === `add` ? this.$API[this.entityName].create : this.$API[this.entityName].edit
|
||||
try {
|
||||
const res = await method.post(this.form)
|
||||
@ -114,6 +139,12 @@ export default {
|
||||
this.visible = false
|
||||
this.$message.success(this.$t(`操作成功`))
|
||||
} catch {}
|
||||
} else {
|
||||
if (await this.tabs.submit(this.$refs, this.tabId)) {
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
},
|
||||
@ -125,8 +156,13 @@ export default {
|
||||
summary: { type: String },
|
||||
columns: { type: Array },
|
||||
dialogFullScreen: { type: Boolean },
|
||||
tabs: { type: Array },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped />
|
||||
<style scoped>
|
||||
.hide-tabs :deep(.el-tabs__nav-scroll) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<el-container>
|
||||
<!-- 仪表板-->
|
||||
<el-header v-loading="statistics.total === `...`" class="el-header-statistics">
|
||||
@ -30,6 +30,7 @@
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button v-bind="item" v-for="(item, i) in rightButtons" :key="i">{{ item.title }}</el-button>
|
||||
<el-button v-if="operations.includes(`add`)" @click="onAddClick" icon="el-icon-plus" type="primary" />
|
||||
<el-button
|
||||
v-if="operations.includes(`del`)"
|
||||
@ -64,7 +65,7 @@
|
||||
<component
|
||||
v-bind="item"
|
||||
v-if="item.show.includes(`list`)"
|
||||
:formatter="item.thousands ? (row) => $TOOL.groupSeparator(row[i]) : undefined"
|
||||
:formatter="item.thousands ? (row) => $TOOL.groupSeparator($TOOL.getNestedProperty(row, i)) : undefined"
|
||||
:is="item.is ?? `el-table-column`"
|
||||
:options="
|
||||
item.options ??
|
||||
@ -96,11 +97,25 @@
|
||||
|
||||
<el-table-column :label="$t(`操作`)" align="right" fixed="right" width="150">
|
||||
<template #default="{ row }">
|
||||
<div class="flex justify-content-right">
|
||||
<el-button-group size="small">
|
||||
<el-button v-if="operations.includes(`view`)" @click="onViewClick(row)" icon="el-icon-view" />
|
||||
<el-button v-if="operations.includes(`edit`)" @click="onEditClick(row)" icon="el-icon-edit" />
|
||||
<el-button v-if="operations.includes(`del`)" @click="onDeleteClick(row)" icon="el-icon-delete" type="danger" />
|
||||
</el-button-group>
|
||||
<el-dropdown>
|
||||
<el-button size="small">...</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<template v-for="(button, j) in rowButtons?.filter((x) => !x.condition || x.condition(row))" :key="j">
|
||||
<el-dropdown-item v-bind="button.props" @click="onRowButtonClick(row, button)" size="small">{{
|
||||
button.title
|
||||
}}</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</sc-table>
|
||||
@ -122,6 +137,7 @@ import { defineAsyncComponent } from 'vue'
|
||||
import tableConfig from '@/config/table'
|
||||
import naColOperation from '@/config/na-col-operation'
|
||||
import config from '@/config'
|
||||
import naColTags from '@/components/na-col-tags'
|
||||
const naColAvatar = defineAsyncComponent(() => import('@/components/na-col-avatar'))
|
||||
const detailDialog = defineAsyncComponent(() => import('./detail'))
|
||||
const naColUser = defineAsyncComponent(() => import('@/components/na-col-user'))
|
||||
@ -130,6 +146,7 @@ export default {
|
||||
detailDialog,
|
||||
naColAvatar,
|
||||
naColUser,
|
||||
naColTags,
|
||||
},
|
||||
computed: {
|
||||
config() {
|
||||
@ -287,6 +304,12 @@ export default {
|
||||
// ---------------------------- 搜索栏事件 ↑ ----------------------------
|
||||
|
||||
// ---------------------------- ↓ 表格事件 ----------------------------
|
||||
async onRowButtonClick(row, button) {
|
||||
if (await button.click(row)) {
|
||||
this.$message.success(this.$t(`操作成功`))
|
||||
await this.$refs.table.upData()
|
||||
}
|
||||
},
|
||||
async onViewClick(row) {
|
||||
this.dialog.detail = { mode: `view`, row }
|
||||
},
|
||||
@ -352,6 +375,7 @@ export default {
|
||||
|
||||
calls.push(
|
||||
this.$API[this.entityName].countBy.post({
|
||||
filter: this.query.filter,
|
||||
dynamicFilter: { filters: this.query.dynamicFilter.filters },
|
||||
requiredFields: [col.replace(/(?:^|\.)[a-z]/g, (m) => m.toUpperCase())],
|
||||
}),
|
||||
@ -370,7 +394,16 @@ export default {
|
||||
}
|
||||
}
|
||||
for (const item of this.selectFilterData) {
|
||||
item.options.sort((x, y) => (y.label === this.$t(`全部`) ? 999999999 : (y.badge ?? 0 - x.badge ?? 0)))
|
||||
while (!this.$t) {
|
||||
await new Promise((x) => setTimeout(x, 100))
|
||||
}
|
||||
item.options.sort((x, y) => {
|
||||
if (y.label === this.$t(`全部`)) {
|
||||
return 999999999
|
||||
} else {
|
||||
return (y.badge ?? 0) - (x.badge ?? 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onSelectionChange(data) {
|
||||
@ -396,7 +429,10 @@ export default {
|
||||
customSearchControls: { type: Array, default: [] },
|
||||
columns: { type: Object },
|
||||
operations: { type: Array, default: [`view`, `add`, `edit`, `del`] },
|
||||
rowButtons: { type: Array, default: [] },
|
||||
rightButtons: { type: Array, default: [] },
|
||||
dialogFullScreen: { type: Boolean },
|
||||
tabs: { type: Array },
|
||||
},
|
||||
watch: {},
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<slot :open="open">
|
||||
<el-button @click="open" plain type="primary">{{ $t('导入') }}</el-button>
|
||||
<el-button @click="open" plain type="primary">{{ $t(`导入`) }}</el-button>
|
||||
</slot>
|
||||
<el-dialog v-model="dialog" :close-on-click-modal="false" :title="$t('导入')" :width="550" append-to-body destroy-on-close>
|
||||
<el-dialog v-model="dialog" :close-on-click-modal="false" :title="$t(`导入`)" :width="550" append-to-body destroy-on-close>
|
||||
<el-progress v-if="loading" :percentage="percentage" :stroke-width="20" :text-inside="true" style="margin-bottom: 1rem" />
|
||||
<div v-loading="loading">
|
||||
<el-upload
|
||||
@ -23,15 +23,15 @@
|
||||
<el-icon-upload-filled />
|
||||
</el-icon>
|
||||
<div class="el-upload__text">
|
||||
{{ $t('将文件拖到此处或 ') }}<em>{{ $t('点击选择文件上传') }}</em>
|
||||
{{ $t(`将文件拖到此处或 `) }}<em>{{ $t(`点击选择文件上传`) }}</em>
|
||||
</div>
|
||||
</slot>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
<template v-if="tip">{{ tip }}</template>
|
||||
<template v-else>{{ $t('请上传小于或等于 {{ maxSize }}M 的 {{ accept }} 格式文件') }}</template>
|
||||
<template v-else>{{ $t(`请上传小于或等于 {maxSize}M 的 {accept} 格式文件`) }}</template>
|
||||
<p v-if="templateUrl" style="margin-top: 7px">
|
||||
<el-link :href="templateUrl" :underline="false" target="_blank" type="primary">{{ $t('下载导入模板') }}</el-link>
|
||||
<el-link :href="templateUrl" :underline="false" target="_blank" type="primary">{{ $t(`下载导入模板`) }}</el-link>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits: ['success'],
|
||||
emits: [`success`],
|
||||
props: {
|
||||
apiObj: {
|
||||
type: Object,
|
||||
@ -55,10 +55,10 @@ export default {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
accept: { type: String, default: '.xls, .xlsx' },
|
||||
accept: { type: String, default: `.xls, .xlsx` },
|
||||
maxSize: { type: Number, default: 10 },
|
||||
tip: { type: String, default: '' },
|
||||
templateUrl: { type: String, default: '' },
|
||||
tip: { type: String, default: `` },
|
||||
templateUrl: { type: String, default: `` },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -80,7 +80,7 @@ export default {
|
||||
before(file) {
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`)
|
||||
this.$message.warning(this.$t(`上传文件大小不能超过 {maxSize}MB`, { maxSize: this.maxSize }))
|
||||
return false
|
||||
}
|
||||
this.loading = true
|
||||
@ -93,13 +93,13 @@ export default {
|
||||
this.$refs.uploader.clearFiles()
|
||||
this.loading = false
|
||||
this.percentage = 0
|
||||
this.$emit('success', res, this.close)
|
||||
this.$emit(`success`, res, this.close)
|
||||
},
|
||||
error(err) {
|
||||
this.loading = false
|
||||
this.percentage = 0
|
||||
this.$notify.error({
|
||||
title: '上传文件未成功',
|
||||
title: `上传文件未成功`,
|
||||
message: err,
|
||||
})
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div v-loading="menuLoading" class="sc-file-select__side">
|
||||
<div class="sc-file-select__side-menu">
|
||||
<el-tree
|
||||
:current-node-key="menu.length > 0 ? menu[0][treeProps.key] : ''"
|
||||
:current-node-key="menu.length > 0 ? menu[0][treeProps.key] : ``"
|
||||
:data="menu"
|
||||
:node-key="treeProps.key"
|
||||
:props="treeProps"
|
||||
@ -37,16 +37,16 @@
|
||||
action=""
|
||||
class="sc-file-select__upload"
|
||||
multiple>
|
||||
<el-button icon="el-icon-upload" type="primary">{{ $t('本地上传') }}</el-button>
|
||||
<el-button icon="el-icon-upload" type="primary">{{ $t(`本地上传`) }}</el-button>
|
||||
</el-upload>
|
||||
<span class="tips"
|
||||
><el-icon><el-icon-warning />{{ $t('大小不超过{{ maxSize }}MB') }} </el-icon></span
|
||||
><el-icon><el-icon-warning />{{ $t(`大小不超过 {maxSize} MB`) }} </el-icon></span
|
||||
>
|
||||
</div>
|
||||
<div class="keyword">
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
:placeholder="$t('文件名搜索')"
|
||||
:placeholder="$t(`文件名搜索`)"
|
||||
@clear="search"
|
||||
@keyup.enter="search"
|
||||
clearable
|
||||
@ -55,7 +55,7 @@
|
||||
</div>
|
||||
<div class="sc-file-select__list">
|
||||
<el-scrollbar ref="scrollbar">
|
||||
<el-empty v-if="fileList.length === 0 && data.length === 0" :description="$t('无数据')" :image-size="80" />
|
||||
<el-empty v-if="fileList.length === 0 && data.length === 0" :description="$t(`无数据`)" :image-size="80" />
|
||||
<div v-for="(file, index) in fileList" :key="index" class="sc-file-select__item">
|
||||
<div class="sc-file-select__item__file">
|
||||
<div class="sc-file-select__item__upload">
|
||||
@ -108,7 +108,7 @@
|
||||
</div>
|
||||
<div class="sc-file-select__do">
|
||||
<slot name="do" />
|
||||
<el-button :disabled="value.length <= 0" @click="submit" type="primary">{{ $t('确定') }}</el-button>
|
||||
<el-button :disabled="value.length <= 0" @click="submit" type="primary">{{ $t(`确定`) }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -134,10 +134,10 @@ export default {
|
||||
currentPage: 1,
|
||||
data: [],
|
||||
menu: [],
|
||||
menuId: '',
|
||||
value: this.multiple ? [] : '',
|
||||
menuId: ``,
|
||||
value: this.multiple ? [] : ``,
|
||||
fileList: [],
|
||||
accept: this.onlyImage ? 'image/gif, image/jpeg, image/png' : '',
|
||||
accept: this.onlyImage ? `image/gif, image/jpeg, image/png` : ``,
|
||||
listLoading: false,
|
||||
menuLoading: false,
|
||||
treeProps: config.menuProps,
|
||||
@ -147,8 +147,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
multiple() {
|
||||
this.value = this.multiple ? [] : ''
|
||||
this.$emit('update:modelValue', JSON.parse(JSON.stringify(this.value)))
|
||||
this.value = this.multiple ? [] : ``
|
||||
this.$emit(`update:modelValue`, JSON.parse(JSON.stringify(this.value)))
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
@ -173,7 +173,7 @@ export default {
|
||||
[config.request.keyword]: this.keyword,
|
||||
}
|
||||
if (this.onlyImage) {
|
||||
reqData.type = 'image'
|
||||
reqData.type = `image`
|
||||
}
|
||||
const res = await config.listApiObj.get(reqData)
|
||||
const parseData = config.listParseData(res)
|
||||
@ -210,7 +210,7 @@ export default {
|
||||
}
|
||||
} else {
|
||||
if (this.value.includes(itemUrl)) {
|
||||
this.value = ''
|
||||
this.value = ``
|
||||
} else {
|
||||
this.value = itemUrl
|
||||
}
|
||||
@ -218,8 +218,8 @@ export default {
|
||||
},
|
||||
submit() {
|
||||
const value = JSON.parse(JSON.stringify(this.value))
|
||||
this.$emit('update:modelValue', value)
|
||||
this.$emit('submit', value)
|
||||
this.$emit(`update:modelValue`, value)
|
||||
this.$emit(`submit`, value)
|
||||
},
|
||||
//上传处理
|
||||
uploadChange(file, fileList) {
|
||||
@ -229,14 +229,14 @@ export default {
|
||||
uploadBefore(file) {
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`)
|
||||
this.$message.warning(this.$t(`上传文件大小不能超过 {maxSize}MB`, { maxSize: this.maxSize }))
|
||||
return false
|
||||
}
|
||||
},
|
||||
uploadRequest(param) {
|
||||
const apiObj = config.apiObj
|
||||
const data = new FormData()
|
||||
data.append('file', param.file)
|
||||
data.append(`file`, param.file)
|
||||
data.append([config.request.menuKey], this.menuId)
|
||||
apiObj
|
||||
.post(data, {
|
||||
@ -271,18 +271,18 @@ export default {
|
||||
},
|
||||
uploadError(err) {
|
||||
this.$notify.error({
|
||||
title: '上传文件错误',
|
||||
title: this.$t(`上传文件错误`),
|
||||
message: err,
|
||||
})
|
||||
},
|
||||
//内置函数
|
||||
_isImg(fileUrl) {
|
||||
const imgExt = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
|
||||
const fileExt = fileUrl.substring(fileUrl.lastIndexOf('.'))
|
||||
const imgExt = [`.jpg`, `.jpeg`, `.png`, `.gif`, `.bmp`]
|
||||
const fileExt = fileUrl.substring(fileUrl.lastIndexOf(`.`))
|
||||
return imgExt.indexOf(fileExt) !== -1
|
||||
},
|
||||
_getExt(fileUrl) {
|
||||
return fileUrl.substring(fileUrl.lastIndexOf('.') + 1)
|
||||
return fileUrl.substring(fileUrl.lastIndexOf(`.`) + 1)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
<el-scrollbar>
|
||||
<ul @click="selectIcon">
|
||||
<el-empty v-if="item.icons.length === 0" :description="$t('未查询到相关图标')" :image-size="100" />
|
||||
<li v-for="icon in item.icons" :key="icon">
|
||||
<li v-copy="icon" v-for="icon in item.icons" :key="icon">
|
||||
<span :data-icon="icon"></span>
|
||||
<el-icon>
|
||||
<component :is="icon" />
|
||||
|
@ -19,7 +19,7 @@
|
||||
:on-success="success"
|
||||
:show-file-list="showFileList">
|
||||
<slot>
|
||||
<el-button :disabled="disabled" type="primary">点击上传</el-button>
|
||||
<el-button :disabled="disabled" type="primary">{{ $t(`点击上传`) }}</el-button>
|
||||
</slot>
|
||||
<template #tip>
|
||||
<div v-if="tip" class="el-upload__tip">{{ tip }}</div>
|
||||
@ -34,9 +34,9 @@ import config from '@/config/upload'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
modelValue: { type: [String, Array], default: '' },
|
||||
tip: { type: String, default: '' },
|
||||
action: { type: String, default: '' },
|
||||
modelValue: { type: [String, Array], default: `` },
|
||||
tip: { type: String, default: `` },
|
||||
action: { type: String, default: `` },
|
||||
apiObj: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
@ -46,7 +46,7 @@ export default {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
accept: { type: String, default: '' },
|
||||
accept: { type: String, default: `` },
|
||||
maxSize: { type: Number, default: config.maxSizeFile },
|
||||
limit: { type: Number, default: 0 },
|
||||
autoUpload: { type: Boolean, default: true },
|
||||
@ -63,7 +63,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
value: ``,
|
||||
defaultFileList: [],
|
||||
}
|
||||
},
|
||||
@ -83,7 +83,7 @@ export default {
|
||||
},
|
||||
defaultFileList: {
|
||||
handler(val) {
|
||||
this.$emit('update:modelValue', Array.isArray(this.modelValue) ? this.formatArr(val) : this.toStr(val))
|
||||
this.$emit(`update:modelValue`, Array.isArray(this.modelValue) ? this.formatArr(val) : this.toStr(val))
|
||||
this.value = this.toStr(val)
|
||||
},
|
||||
deep: true,
|
||||
@ -97,10 +97,10 @@ export default {
|
||||
//默认值转换为数组
|
||||
toArr(str) {
|
||||
const _arr = []
|
||||
const arr = str.split(',')
|
||||
const arr = str.split(`,`)
|
||||
arr.forEach((item) => {
|
||||
if (item) {
|
||||
const urlArr = item.split('/')
|
||||
const urlArr = item.split(`/`)
|
||||
const fileName = urlArr[urlArr.length - 1]
|
||||
_arr.push({
|
||||
name: fileName,
|
||||
@ -112,7 +112,7 @@ export default {
|
||||
},
|
||||
//数组转换为原始值
|
||||
toStr(arr) {
|
||||
return arr.map((v) => v.url).join(',')
|
||||
return arr.map((v) => v.url).join(`,`)
|
||||
},
|
||||
//格式化数组值
|
||||
formatArr(arr) {
|
||||
@ -130,7 +130,7 @@ export default {
|
||||
before(file) {
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`)
|
||||
this.$message.warning(this.$t(`上传文件大小不能超过 {maxSize}MB`, { maxSize: this.maxSize }))
|
||||
return false
|
||||
}
|
||||
},
|
||||
@ -145,13 +145,13 @@ export default {
|
||||
},
|
||||
error(err) {
|
||||
this.$notify.error({
|
||||
title: '上传文件未成功',
|
||||
title: this.$t(`上传文件未成功`),
|
||||
message: err,
|
||||
})
|
||||
},
|
||||
beforeRemove(uploadFile) {
|
||||
return this.$confirm(`是否移除 ${uploadFile.name} ?`, '提示', {
|
||||
type: 'warning',
|
||||
return this.$confirm(this.$t(`是否移除 {name} ?`, { name: uploadFile.name }), `提示`, {
|
||||
type: `warning`,
|
||||
})
|
||||
.then(() => {
|
||||
return true
|
||||
@ -161,7 +161,7 @@ export default {
|
||||
})
|
||||
},
|
||||
handleExceed() {
|
||||
this.$message.warning(`当前设置最多上传 ${this.limit} 个文件,请移除后上传!`)
|
||||
this.$message.warning(this.$t(`当前设置最多上传 {limit} 个文件,请移除后上传!`, { limit: this.limit }))
|
||||
},
|
||||
handlePreview(uploadFile) {
|
||||
window.open(uploadFile.url)
|
||||
@ -188,7 +188,7 @@ export default {
|
||||
if (response.code === config.successCode) {
|
||||
param.onSuccess(res)
|
||||
} else {
|
||||
param.onError(response.msg || '未知错误')
|
||||
param.onError(response.msg || this.$t(`未知错误`))
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
@ -199,7 +199,7 @@ export default {
|
||||
}
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`)
|
||||
this.$message.warning(this.$t(`上传文件大小不能超过 {maxSize}MB`, { maxSize: this.maxSize }))
|
||||
this.clearFiles()
|
||||
return false
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ export default {
|
||||
}
|
||||
const maxSize = file.size / 1024 / 1024 < this.maxSize
|
||||
if (!maxSize) {
|
||||
this.$message.warning(`上传文件大小不能超过 ${this.maxSize}MB!`)
|
||||
this.$message.warning(this.$t(`上传文件大小不能超过 {maxSize}MB`, { maxSize: this.maxSize }))
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
File diff suppressed because one or more lines are too long
@ -628,4 +628,5 @@ export default {
|
||||
'编辑{summary}: {id}': '编辑{summary}: {id}',
|
||||
'{field} 不能为空': '{field} 不能为空',
|
||||
'{field} 不正确': '{field} 不正确',
|
||||
'上传文件大小不能超过 {maxSize}MB': '上传文件大小不能超过 {maxSize}MB',
|
||||
}
|
@ -7,33 +7,29 @@
|
||||
extra: [`createdTime`],
|
||||
width: 170,
|
||||
show: [`list`, `view`],
|
||||
searchable: true,
|
||||
searchable: `eq`,
|
||||
},
|
||||
name: {
|
||||
label: $t(`名称`),
|
||||
label: $t(`名字`),
|
||||
width: 150,
|
||||
show: [`list`, `view`, `add`, `edit`],
|
||||
rule: {
|
||||
required: true,
|
||||
},
|
||||
show: [`list`, `view`, `add`, `edit`],
|
||||
searchable: true,
|
||||
operator: `contains`,
|
||||
searchable: `eq`,
|
||||
},
|
||||
gender: {
|
||||
label: $t(`性别`),
|
||||
is: `na-col-indicator`,
|
||||
enum: `genders`,
|
||||
width: 200,
|
||||
width: 100,
|
||||
align: `center`,
|
||||
rule: {
|
||||
required: true,
|
||||
},
|
||||
countBy: true,
|
||||
show: [`list`, `view`, `add`, `edit`],
|
||||
},
|
||||
sort: {
|
||||
label: $t(`排序`),
|
||||
align: `right`,
|
||||
thousands: true,
|
||||
width: 100,
|
||||
show: [`list`, `view`, `add`, `edit`],
|
||||
rule: {
|
||||
@ -47,8 +43,7 @@
|
||||
summary: {
|
||||
label: $t(`备注`),
|
||||
show: [`list`, `view`, `add`, `edit`],
|
||||
searchable: true,
|
||||
operator: `contains`,
|
||||
searchable: `contains`,
|
||||
},
|
||||
enabled: {
|
||||
label: $t(`启用`),
|
||||
@ -67,31 +62,47 @@
|
||||
show: [`view`],
|
||||
},
|
||||
}"
|
||||
:operations="operations"
|
||||
:summary="$t(`页面模板`)"
|
||||
:operations="[`add`, `del`, `edit`]"
|
||||
:search-controls="[
|
||||
{
|
||||
type: `input`,
|
||||
field: [`root`, `keywords`],
|
||||
placeholder: $t(`消息编号 / 消息主题 / 消息内容`),
|
||||
style: `width:25rem`,
|
||||
},
|
||||
]"
|
||||
:select-filters="[
|
||||
{
|
||||
title: $t(`是否启用`),
|
||||
key: `Enabled`,
|
||||
enumName: `Enabled`,
|
||||
isBoolean: [
|
||||
{ label: $t(`启用`), value: true },
|
||||
{ label: $t(`禁用`), value: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: $t(`性别`),
|
||||
key: `Gender`,
|
||||
enumName: `genders`,
|
||||
},
|
||||
]"
|
||||
:summary="$t(`代码模板`)"
|
||||
entity-name="sys_codetemplate" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
if (this.$GLOBAL.hasApiPermission(`api/sys/code.template/get`)) {
|
||||
this.operations.push(`view`)
|
||||
}
|
||||
if (this.$GLOBAL.hasApiPermission(`api/sys/code.template/edit`)) {
|
||||
this.operations.push(`edit`)
|
||||
}
|
||||
if (this.$GLOBAL.hasApiPermission(`api/sys/code.template/create`)) {
|
||||
this.operations.push(`add`)
|
||||
}
|
||||
if (this.$GLOBAL.hasApiPermission(`api/sys/code.template/delete`)) {
|
||||
this.operations.push(`del`)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
operations: [],
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
computed: {},
|
||||
created() {},
|
||||
data() {},
|
||||
inject: [`reload`],
|
||||
methods: {},
|
||||
mounted() {},
|
||||
props: [`keywords`],
|
||||
watch: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped />
|
121
src/frontend/admin/src/views/sys/trade/frozen/index.vue
Normal file
121
src/frontend/admin/src/views/sys/trade/frozen/index.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<na-table-page
|
||||
:buttons="[
|
||||
{
|
||||
title: $t(`解冻`),
|
||||
condition: (row) => {
|
||||
return row.status === `frozen` && this.$GLOBAL.hasApiPermission(`api/sys/wallet.frozen/set.status.to.thawed`)
|
||||
},
|
||||
click: async (row) => {
|
||||
try {
|
||||
await this.$confirm(`确定解冻该记录?`, '提示', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
await this.$API.sys_walletfrozen.setStatusToThawed.post({ id: row.id })
|
||||
return true
|
||||
},
|
||||
},
|
||||
]"
|
||||
:columns="{
|
||||
id: {
|
||||
label: $t(`日志编号`),
|
||||
is: `na-col-id`,
|
||||
extra: [`createdTime`],
|
||||
width: 170,
|
||||
show: [`list`, `view`],
|
||||
searchable: true,
|
||||
},
|
||||
ownerId: {
|
||||
rule: {
|
||||
type: `number`,
|
||||
required: true,
|
||||
},
|
||||
headerAlign: `center`,
|
||||
is: `na-col-user`,
|
||||
clickOpenDialog: this.$GLOBAL.hasApiPermission(`api/sys/user/get`),
|
||||
nestProp: `owner.userName`,
|
||||
nestProp2: `ownerId`,
|
||||
width: 170,
|
||||
label: $t(`归属用户`),
|
||||
show: [`list`, `view`, `add`],
|
||||
detail: {
|
||||
is: `sc-select`,
|
||||
props: {
|
||||
queryApi: $API.sys_user.query,
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
config: {
|
||||
props: {
|
||||
label: `userName`,
|
||||
value: `id`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
amount: {
|
||||
label: $t(`冻结金额`),
|
||||
align: `right`,
|
||||
thousands: true,
|
||||
width: 100,
|
||||
show: [`list`, `view`, `add`],
|
||||
rule: {
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (/^[1-9]\d*$/.test(value)) callback()
|
||||
else callback(new Error())
|
||||
},
|
||||
},
|
||||
},
|
||||
status: {
|
||||
is: `na-col-indicator`,
|
||||
enum: `walletFrozenStatues`,
|
||||
label: $t(`状态`),
|
||||
countBy: true,
|
||||
align: `center`,
|
||||
width: 100,
|
||||
show: [`list`, `view`],
|
||||
},
|
||||
reason: {
|
||||
rule: {
|
||||
required: true,
|
||||
},
|
||||
countBy: true,
|
||||
is: `na-col-indicator`,
|
||||
enum: `walletFrozenReasons`,
|
||||
label: $t(`冻结原因`),
|
||||
align: `center`,
|
||||
width: 100,
|
||||
show: [`list`, `view`, `add`],
|
||||
},
|
||||
modifiedTime: {
|
||||
label: $t(`更新时间`),
|
||||
show: [`list`, `view`],
|
||||
width: 170,
|
||||
},
|
||||
summary: {
|
||||
label: $t(`备注`),
|
||||
show: [`list`, `view`, `add`],
|
||||
searchable: true,
|
||||
operator: `contains`,
|
||||
},
|
||||
createdTime: {
|
||||
label: $t(`创建时间`),
|
||||
show: [`view`],
|
||||
},
|
||||
version: {
|
||||
label: $t(`数据版本`),
|
||||
show: [`view`],
|
||||
},
|
||||
}"
|
||||
:operations="[`view`, `add`]"
|
||||
:summary="$t(`冻结记录`)"
|
||||
entity-name="sys_walletfrozen" />
|
||||
</template>
|
||||
|
||||
<style scoped />
|
@ -1,323 +1,35 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-header v-loading="statistics.total === '...'" class="el-header-statistics">
|
||||
<el-row :gutter="15">
|
||||
<el-col :lg="24">
|
||||
<el-card shadow="never">
|
||||
<sc-statistic :title="$t('总数')" :value="statistics.total" group-separator />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
<el-header class="el-header-select-filter">
|
||||
<sc-select-filter
|
||||
:data="[
|
||||
{
|
||||
title: $t('交易方向'),
|
||||
key: 'tradeDirection',
|
||||
options: [
|
||||
{ label: '全部', value: '' },
|
||||
...Object.entries(this.$GLOBAL.enums.tradeDirections).map((x) => {
|
||||
return {
|
||||
value: x[0],
|
||||
label: x[1][1],
|
||||
badge: this.statistics.tradeDirection?.find((y) => y.key.tradeDirection.toLowerCase() === x[0].toLowerCase())
|
||||
?.value,
|
||||
}
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: $t('交易类型'),
|
||||
key: 'tradeType',
|
||||
options: [
|
||||
{ label: '全部', value: '' },
|
||||
...Object.entries(this.$GLOBAL.enums.tradeTypes).map((x) => {
|
||||
return {
|
||||
value: x[0],
|
||||
label: x[1][1],
|
||||
badge: this.statistics.tradeType?.find((y) => y.key.tradeType.toLowerCase() === x[0].toLowerCase())?.value,
|
||||
}
|
||||
}),
|
||||
],
|
||||
},
|
||||
]"
|
||||
:label-width="15"
|
||||
@on-change="filterChange"
|
||||
ref="selectFilter" />
|
||||
</el-header>
|
||||
<el-header>
|
||||
<div class="left-panel">
|
||||
<na-search
|
||||
:controls="[
|
||||
{
|
||||
type: 'select-input',
|
||||
field: [
|
||||
'dy',
|
||||
[
|
||||
{ label: $t('交易编号'), key: 'id' },
|
||||
{ label: $t('用户名'), key: 'owner.userName' },
|
||||
{ label: $t('用户编号'), key: 'ownerId' },
|
||||
],
|
||||
],
|
||||
placeholder: $t('匹配内容'),
|
||||
style: 'width:25rem',
|
||||
selectStyle: 'width:8rem',
|
||||
},
|
||||
]"
|
||||
:vue="this"
|
||||
@reset="onReset"
|
||||
@search="onSearch"
|
||||
dateFormat="YYYY-MM-DD HH:mm:ss"
|
||||
dateType="datetimerange"
|
||||
dateValueFormat="YYYY-MM-DD HH:mm:ss"
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel"></div>
|
||||
<el-header style="border: none; padding-bottom: 0">
|
||||
<el-tabs v-model="tabId" class="w100p">
|
||||
<el-tab-pane :label="$t(`交易记录`)" name="list"></el-tab-pane>
|
||||
<el-tab-pane :label="$t(`冻结记录`)" name="frozen"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<sc-table
|
||||
:context-extra="{ id: ['createdTime'], ownerId: ['owner.userName'] }"
|
||||
:context-menus="[
|
||||
'id',
|
||||
'ownerId',
|
||||
'createdTime',
|
||||
'tradeType',
|
||||
'amount',
|
||||
'balanceBefore',
|
||||
'summary',
|
||||
'owner.userName',
|
||||
'tradeDirection',
|
||||
]"
|
||||
:context-opers="['view']"
|
||||
:default-sort="{ prop: 'id', order: 'descending' }"
|
||||
:export-api="$API.sys_wallettrade.export"
|
||||
:params="query"
|
||||
:query-api="$API.sys_wallettrade.pagedQuery"
|
||||
:vue="this"
|
||||
@data-change="getStatistics"
|
||||
@selection-change="
|
||||
(items) => {
|
||||
selection = items
|
||||
}
|
||||
"
|
||||
ref="table"
|
||||
remote-filter
|
||||
remote-sort
|
||||
row-key="id"
|
||||
stripe>
|
||||
<na-col-id :label="$t('交易编号')" prop="id" sortable="custom" width="170" />
|
||||
<na-col-user
|
||||
:clickOpenDialog="$GLOBAL.hasApiPermission('api/sys/user/get')"
|
||||
:label="$t('归属用户')"
|
||||
header-align="center"
|
||||
nestProp="owner.userName"
|
||||
nestProp2="ownerId"
|
||||
prop="ownerId"
|
||||
sortable="custom"
|
||||
width="170" />
|
||||
<na-col-indicator
|
||||
:label="$t('交易方向')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.tradeDirections).map((x) => {
|
||||
return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' }
|
||||
})
|
||||
"
|
||||
align="center"
|
||||
prop="tradeDirection"
|
||||
sortable="custom" />
|
||||
<na-col-indicator
|
||||
:label="$t('交易类型')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.tradeTypes).map((x) => {
|
||||
return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' }
|
||||
})
|
||||
"
|
||||
align="center"
|
||||
prop="tradeType"
|
||||
sortable="custom" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.balanceBefore)"
|
||||
:label="$t('交易前余额')"
|
||||
align="right"
|
||||
prop="balanceBefore"
|
||||
sortable="custom" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.amount)"
|
||||
:label="$t('发生金额')"
|
||||
align="right"
|
||||
prop="amount"
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('交易后余额')" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ $TOOL.groupSeparator(row.balanceBefore + row.amount) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('备注')" min-width="100" prop="summary" show-overflow-tooltip sortable="custom" />
|
||||
<na-col-operation :buttons="[naColOperation.buttons[0]]" :vue="this" width="50" />
|
||||
</sc-table>
|
||||
<component :is="tabId" />
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => $refs.table.refresh()"
|
||||
ref="saveDialog" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import table from '@/config/table'
|
||||
import naColOperation from '@/config/na-col-operation'
|
||||
const naColUser = defineAsyncComponent(() => import('@/components/na-col-user'))
|
||||
const saveDialog = defineAsyncComponent(() => import('./save'))
|
||||
const list = defineAsyncComponent(() => import('./list'))
|
||||
const frozen = defineAsyncComponent(() => import('./frozen'))
|
||||
|
||||
export default {
|
||||
components: {
|
||||
naColUser,
|
||||
saveDialog,
|
||||
},
|
||||
computed: {
|
||||
naColOperation() {
|
||||
return naColOperation
|
||||
},
|
||||
table() {
|
||||
return table
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
if (this.ownerId) {
|
||||
this.query.dynamicFilter.filters.push({ field: 'ownerId', operator: 'eq', value: this.ownerId })
|
||||
}
|
||||
},
|
||||
components: { list, frozen },
|
||||
computed: {},
|
||||
created() {},
|
||||
data() {
|
||||
return {
|
||||
statistics: {
|
||||
total: '...',
|
||||
},
|
||||
dialog: {},
|
||||
loading: false,
|
||||
query: {
|
||||
dynamicFilter: {
|
||||
filters: [],
|
||||
},
|
||||
filter: {},
|
||||
keywords: this.keywords,
|
||||
},
|
||||
selection: [],
|
||||
tabId: 'list',
|
||||
}
|
||||
},
|
||||
inject: ['reload'],
|
||||
methods: {
|
||||
filterChange(data) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
this.$refs.search.form.dy[key] = value === 'true' ? true : value === 'false' ? false : value
|
||||
})
|
||||
this.$refs.search.search()
|
||||
},
|
||||
|
||||
async getStatistics() {
|
||||
this.statistics.total = this.$refs.table?.total
|
||||
const res = await Promise.all([
|
||||
this.$API.sys_wallettrade.countBy.post({
|
||||
dynamicFilter: {
|
||||
filters: this.query.dynamicFilter.filters,
|
||||
},
|
||||
requiredFields: ['TradeDirection'],
|
||||
}),
|
||||
this.$API.sys_wallettrade.countBy.post({
|
||||
dynamicFilter: {
|
||||
filters: this.query.dynamicFilter.filters,
|
||||
},
|
||||
requiredFields: ['TradeType'],
|
||||
}),
|
||||
])
|
||||
this.statistics.tradeDirection = res[0].data
|
||||
this.statistics.tradeType = res[1].data
|
||||
},
|
||||
//重置
|
||||
onReset() {
|
||||
Object.entries(this.$refs.selectFilter.selected).forEach(([key, _]) => (this.$refs.selectFilter.selected[key] = ['']))
|
||||
if (this.ownerId) {
|
||||
this.$refs.search.selectInputKey = 'ownerId'
|
||||
}
|
||||
},
|
||||
//搜索
|
||||
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['owner.userName'] === 'string' && form.dy['owner.userName'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'owner.userName',
|
||||
operator: 'eq',
|
||||
value: form.dy['owner.userName'],
|
||||
})
|
||||
}
|
||||
if (typeof form.dy['ownerId'] === 'string' && form.dy['ownerId'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'ownerId',
|
||||
operator: 'eq',
|
||||
value: form.dy['ownerId'],
|
||||
})
|
||||
}
|
||||
|
||||
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['tradeType'] === 'string' && form.dy['tradeType'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'tradeType',
|
||||
operator: 'eq',
|
||||
value: form.dy['tradeType'],
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy['tradeDirection'] === 'string' && form.dy['tradeDirection'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'tradeDirection',
|
||||
operator: 'eq',
|
||||
value: form.dy['tradeDirection'],
|
||||
})
|
||||
}
|
||||
await this.$refs.table.upData()
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
if (this.ownerId) {
|
||||
this.$refs.search.selectInputKey = 'ownerId'
|
||||
this.$refs.search.form.dy.ownerId = this.ownerId
|
||||
this.$refs.search.keeps.push({
|
||||
field: 'ownerId',
|
||||
value: this.ownerId,
|
||||
type: 'dy',
|
||||
})
|
||||
}
|
||||
|
||||
if (this.keywords) {
|
||||
this.$refs.search.form.root.keywords = this.keywords
|
||||
this.$refs.search.keeps.push({
|
||||
field: 'keywords',
|
||||
value: this.keywords,
|
||||
type: 'root',
|
||||
})
|
||||
}
|
||||
|
||||
this.onReset()
|
||||
},
|
||||
props: ['keywords', 'ownerId'],
|
||||
methods: {},
|
||||
mounted() {},
|
||||
watch: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped />
|
||||
<style scoped></style>
|
323
src/frontend/admin/src/views/sys/trade/list/index.vue
Normal file
323
src/frontend/admin/src/views/sys/trade/list/index.vue
Normal file
@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-header v-loading="statistics.total === '...'" class="el-header-statistics">
|
||||
<el-row :gutter="15">
|
||||
<el-col :lg="24">
|
||||
<el-card shadow="never">
|
||||
<sc-statistic :title="$t('总数')" :value="statistics.total" group-separator />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-header>
|
||||
<el-header class="el-header-select-filter">
|
||||
<sc-select-filter
|
||||
:data="[
|
||||
{
|
||||
title: $t('交易方向'),
|
||||
key: 'tradeDirection',
|
||||
options: [
|
||||
{ label: '全部', value: '' },
|
||||
...Object.entries(this.$GLOBAL.enums.tradeDirections).map((x) => {
|
||||
return {
|
||||
value: x[0],
|
||||
label: x[1][1],
|
||||
badge: this.statistics.tradeDirection?.find((y) => y.key.tradeDirection.toLowerCase() === x[0].toLowerCase())
|
||||
?.value,
|
||||
}
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: $t('交易类型'),
|
||||
key: 'tradeType',
|
||||
options: [
|
||||
{ label: '全部', value: '' },
|
||||
...Object.entries(this.$GLOBAL.enums.tradeTypes).map((x) => {
|
||||
return {
|
||||
value: x[0],
|
||||
label: x[1][1],
|
||||
badge: this.statistics.tradeType?.find((y) => y.key.tradeType.toLowerCase() === x[0].toLowerCase())?.value,
|
||||
}
|
||||
}),
|
||||
],
|
||||
},
|
||||
]"
|
||||
:label-width="15"
|
||||
@on-change="filterChange"
|
||||
ref="selectFilter" />
|
||||
</el-header>
|
||||
<el-header>
|
||||
<div class="left-panel">
|
||||
<na-search
|
||||
:controls="[
|
||||
{
|
||||
type: 'select-input',
|
||||
field: [
|
||||
'dy',
|
||||
[
|
||||
{ label: $t('交易编号'), key: 'id' },
|
||||
{ label: $t('用户名'), key: 'owner.userName' },
|
||||
{ label: $t('用户编号'), key: 'ownerId' },
|
||||
],
|
||||
],
|
||||
placeholder: $t('匹配内容'),
|
||||
style: 'width:25rem',
|
||||
selectStyle: 'width:8rem',
|
||||
},
|
||||
]"
|
||||
:vue="this"
|
||||
@reset="onReset"
|
||||
@search="onSearch"
|
||||
dateFormat="YYYY-MM-DD HH:mm:ss"
|
||||
dateType="datetimerange"
|
||||
dateValueFormat="YYYY-MM-DD HH:mm:ss"
|
||||
ref="search" />
|
||||
</div>
|
||||
<div class="right-panel"></div>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<sc-table
|
||||
:context-extra="{ id: ['createdTime'], ownerId: ['owner.userName'] }"
|
||||
:context-menus="[
|
||||
'id',
|
||||
'ownerId',
|
||||
'createdTime',
|
||||
'tradeType',
|
||||
'amount',
|
||||
'balanceBefore',
|
||||
'summary',
|
||||
'owner.userName',
|
||||
'tradeDirection',
|
||||
]"
|
||||
:context-opers="['view']"
|
||||
:default-sort="{ prop: 'id', order: 'descending' }"
|
||||
:export-api="$API.sys_wallettrade.export"
|
||||
:params="query"
|
||||
:query-api="$API.sys_wallettrade.pagedQuery"
|
||||
:vue="this"
|
||||
@data-change="getStatistics"
|
||||
@selection-change="
|
||||
(items) => {
|
||||
selection = items
|
||||
}
|
||||
"
|
||||
ref="table"
|
||||
remote-filter
|
||||
remote-sort
|
||||
row-key="id"
|
||||
stripe>
|
||||
<na-col-id :label="$t('交易编号')" prop="id" sortable="custom" width="170" />
|
||||
<na-col-user
|
||||
:clickOpenDialog="$GLOBAL.hasApiPermission('api/sys/user/get')"
|
||||
:label="$t('归属用户')"
|
||||
header-align="center"
|
||||
nestProp="owner.userName"
|
||||
nestProp2="ownerId"
|
||||
prop="ownerId"
|
||||
sortable="custom"
|
||||
width="170" />
|
||||
<na-col-indicator
|
||||
:label="$t('交易方向')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.tradeDirections).map((x) => {
|
||||
return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' }
|
||||
})
|
||||
"
|
||||
align="center"
|
||||
prop="tradeDirection"
|
||||
sortable="custom" />
|
||||
<na-col-indicator
|
||||
:label="$t('交易类型')"
|
||||
:options="
|
||||
Object.entries(this.$GLOBAL.enums.tradeTypes).map((x) => {
|
||||
return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' }
|
||||
})
|
||||
"
|
||||
align="center"
|
||||
prop="tradeType"
|
||||
sortable="custom" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.balanceBefore)"
|
||||
:label="$t('交易前余额')"
|
||||
align="right"
|
||||
prop="balanceBefore"
|
||||
sortable="custom" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.amount)"
|
||||
:label="$t('发生金额')"
|
||||
align="right"
|
||||
prop="amount"
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('交易后余额')" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ $TOOL.groupSeparator(row.balanceBefore + row.amount) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('备注')" min-width="100" prop="summary" show-overflow-tooltip sortable="custom" />
|
||||
<na-col-operation :buttons="[naColOperation.buttons[0]]" :vue="this" width="50" />
|
||||
</sc-table>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<save-dialog
|
||||
v-if="dialog.save"
|
||||
@closed="dialog.save = null"
|
||||
@mounted="$refs.saveDialog.open(dialog.save)"
|
||||
@success="(data, mode) => $refs.table.refresh()"
|
||||
ref="saveDialog" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import table from '@/config/table'
|
||||
import naColOperation from '@/config/na-col-operation'
|
||||
const naColUser = defineAsyncComponent(() => import('@/components/na-col-user'))
|
||||
const saveDialog = defineAsyncComponent(() => import('./save'))
|
||||
export default {
|
||||
components: {
|
||||
naColUser,
|
||||
saveDialog,
|
||||
},
|
||||
computed: {
|
||||
naColOperation() {
|
||||
return naColOperation
|
||||
},
|
||||
table() {
|
||||
return table
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
if (this.ownerId) {
|
||||
this.query.dynamicFilter.filters.push({ field: 'ownerId', operator: 'eq', value: this.ownerId })
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statistics: {
|
||||
total: '...',
|
||||
},
|
||||
dialog: {},
|
||||
loading: false,
|
||||
query: {
|
||||
dynamicFilter: {
|
||||
filters: [],
|
||||
},
|
||||
filter: {},
|
||||
keywords: this.keywords,
|
||||
},
|
||||
selection: [],
|
||||
}
|
||||
},
|
||||
inject: ['reload'],
|
||||
methods: {
|
||||
filterChange(data) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
this.$refs.search.form.dy[key] = value === 'true' ? true : value === 'false' ? false : value
|
||||
})
|
||||
this.$refs.search.search()
|
||||
},
|
||||
|
||||
async getStatistics() {
|
||||
this.statistics.total = this.$refs.table?.total
|
||||
const res = await Promise.all([
|
||||
this.$API.sys_wallettrade.countBy.post({
|
||||
dynamicFilter: {
|
||||
filters: this.query.dynamicFilter.filters,
|
||||
},
|
||||
requiredFields: ['TradeDirection'],
|
||||
}),
|
||||
this.$API.sys_wallettrade.countBy.post({
|
||||
dynamicFilter: {
|
||||
filters: this.query.dynamicFilter.filters,
|
||||
},
|
||||
requiredFields: ['TradeType'],
|
||||
}),
|
||||
])
|
||||
this.statistics.tradeDirection = res[0].data
|
||||
this.statistics.tradeType = res[1].data
|
||||
},
|
||||
//重置
|
||||
onReset() {
|
||||
Object.entries(this.$refs.selectFilter.selected).forEach(([key, _]) => (this.$refs.selectFilter.selected[key] = ['']))
|
||||
if (this.ownerId) {
|
||||
this.$refs.search.selectInputKey = 'ownerId'
|
||||
}
|
||||
},
|
||||
//搜索
|
||||
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['owner.userName'] === 'string' && form.dy['owner.userName'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'owner.userName',
|
||||
operator: 'eq',
|
||||
value: form.dy['owner.userName'],
|
||||
})
|
||||
}
|
||||
if (typeof form.dy['ownerId'] === 'string' && form.dy['ownerId'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'ownerId',
|
||||
operator: 'eq',
|
||||
value: form.dy['ownerId'],
|
||||
})
|
||||
}
|
||||
|
||||
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['tradeType'] === 'string' && form.dy['tradeType'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'tradeType',
|
||||
operator: 'eq',
|
||||
value: form.dy['tradeType'],
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof form.dy['tradeDirection'] === 'string' && form.dy['tradeDirection'].trim() !== '') {
|
||||
this.query.dynamicFilter.filters.push({
|
||||
field: 'tradeDirection',
|
||||
operator: 'eq',
|
||||
value: form.dy['tradeDirection'],
|
||||
})
|
||||
}
|
||||
await this.$refs.table.upData()
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
if (this.ownerId) {
|
||||
this.$refs.search.selectInputKey = 'ownerId'
|
||||
this.$refs.search.form.dy.ownerId = this.ownerId
|
||||
this.$refs.search.keeps.push({
|
||||
field: 'ownerId',
|
||||
value: this.ownerId,
|
||||
type: 'dy',
|
||||
})
|
||||
}
|
||||
|
||||
if (this.keywords) {
|
||||
this.$refs.search.form.root.keywords = this.keywords
|
||||
this.$refs.search.keeps.push({
|
||||
field: 'keywords',
|
||||
value: this.keywords,
|
||||
type: 'root',
|
||||
})
|
||||
}
|
||||
|
||||
this.onReset()
|
||||
},
|
||||
props: ['keywords', 'ownerId'],
|
||||
watch: {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped />
|
@ -65,7 +65,6 @@
|
||||
'ownerId',
|
||||
'owner.userName',
|
||||
'createdTime',
|
||||
'totalBalance',
|
||||
'availableBalance',
|
||||
'frozenBalance',
|
||||
'totalIncome',
|
||||
@ -98,12 +97,6 @@
|
||||
prop="ownerId"
|
||||
sortable="custom"
|
||||
width="170" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.totalBalance)"
|
||||
:label="$t('总余额')"
|
||||
align="right"
|
||||
prop="totalBalance"
|
||||
sortable="custom" />
|
||||
<el-table-column
|
||||
:formatter="(row) => $TOOL.groupSeparator(row.availableBalance)"
|
||||
:label="$t('可用余额')"
|
||||
|
@ -7,9 +7,6 @@
|
||||
<el-form-item :label="$t('唯一编码')" prop="id">
|
||||
<el-input v-model="form.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('总余额')" prop="totalBalance">
|
||||
<el-input v-model="form.totalBalance" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('可用余额')" prop="availableBalance">
|
||||
<el-input v-model="form.availableBalance" clearable />
|
||||
</el-form-item>
|
||||
|
Reference in New Issue
Block a user