mirror of
				https://github.com/nsnail/NetAdmin.git
				synced 2025-10-30 19:09:25 +08:00 
			
		
		
		
	feat: ✨ 自助充值
This commit is contained in:
		| @@ -1,3 +1,4 @@ | ||||
| USDT | ||||
| 上次执行时间 | ||||
| 上次执行状态 | ||||
| 上次执行耗时 | ||||
| @@ -19,6 +20,8 @@ | ||||
| 作业状态 | ||||
| 信息 | ||||
| 倒序排序 | ||||
| 充值成功 | ||||
| 充值订单导出 | ||||
| 全部数据 | ||||
| 公告 | ||||
| 共青团员 | ||||
| @@ -26,6 +29,7 @@ | ||||
| 创建时间 | ||||
| 初中 | ||||
| 删除 | ||||
| 到账确认中 | ||||
| 包含 | ||||
| 博士 | ||||
| 博士后 | ||||
| @@ -53,10 +57,11 @@ | ||||
| 已校验 | ||||
| 已读 | ||||
| 并且 | ||||
| 微信支付 | ||||
| 成功 | ||||
| 或者 | ||||
| 所属角色 | ||||
| 所属部门 | ||||
| 归属角色 | ||||
| 归属部门 | ||||
| 手机 | ||||
| 手机号 | ||||
| 执行耗时 | ||||
| @@ -71,6 +76,8 @@ | ||||
| 接口路径 | ||||
| 插入种子数据 | ||||
| 操作系统 | ||||
| 支付宝 | ||||
| 支付超时 | ||||
| 支出 | ||||
| 收入 | ||||
| 数据范围 | ||||
| @@ -114,6 +121,7 @@ | ||||
| 站内信导出 | ||||
| 等于 | ||||
| 等待发送 | ||||
| 等待支付 | ||||
| 管理员充值 | ||||
| 管理员扣费 | ||||
| 管理模块 | ||||
|   | ||||
| @@ -33,6 +33,7 @@ XML注释文件不存在 | ||||
| 手机号码不能为空 | ||||
| 接口编码不存在 | ||||
| 支付宝账号 | ||||
| 支付方式不正确 | ||||
| 政治面貌不正确 | ||||
| 数据库同步开始 | ||||
| 数据库服务器时钟偏移 | ||||
|   | ||||
| @@ -1,8 +1,11 @@ | ||||
| [ | ||||
|   { | ||||
|     "CnyToPointRate": 100, | ||||
|     "Enabled": true, | ||||
|     "Trc20ReceiptAddress": "TMTByCrcZkY7o8YMax1pXiYV5SUQBZEnCu", | ||||
|     "UsdToPointRate": 700, | ||||
|     "UserRegisterConfirm": false, | ||||
|     "UserRegisterDeptId": 372119301627909, | ||||
|     "UserRegisterRoleId": 371729946431493 | ||||
|     "UserRegisterRoleId": 371729946431493, | ||||
|   } | ||||
| ] | ||||
| @@ -2,12 +2,21 @@ | ||||
|   { | ||||
|     "Enabled": true, | ||||
|     "ExecutionCron": "0 * * * * ?", | ||||
|     "HttpMethod": 3, | ||||
|     "JobName": "HTTP 请求测试", | ||||
|     "NextExecTime": "2020-09-13 12:26:40", | ||||
|     "NextTimeId": 1600000000, | ||||
|     "RequestUrl": "https://httpbin.org/ip", | ||||
|     "Status": 1, | ||||
|     "UserId": 370942943322181, | ||||
|   } | ||||
|     "HttpMethod": 7, | ||||
|     "JobName": "用户收入支出统计", | ||||
|     "RequestBody": "{\"Sql\":\"UPDATE Sys_UserWallet SET TotalIncome = (SELECT COALESCE(SUM(Amount), 0) FROM Sys_WalletTrade WHERE Sys_WalletTrade.OwnerId = Sys_UserWallet.Id AND Sys_WalletTrade.TradeDirection = 1);UPDATE Sys_UserWallet SET TotalExpenditure = (SELECT COALESCE(SUM(Amount), 0) FROM Sys_WalletTrade WHERE Sys_WalletTrade.OwnerId = Sys_UserWallet.Id AND Sys_WalletTrade.TradeDirection = 2);\",\"TimeoutSecs\":60}", | ||||
|     "RequestHeader": "{\"Content-Type\":\"application/json\"}", | ||||
|     "RequestUrl": "https://na.tools92.top/api/sys/tools/execute.sql", | ||||
|     "UserId": 664362432344581, | ||||
|   }, | ||||
|   { | ||||
|     "Enabled": true, | ||||
|     "ExecutionCron": "0 * * * * ?", | ||||
|     "HttpMethod": 7, | ||||
|     "JobName": "充值到账确认", | ||||
|     "RequestBody": "{\"readRecordCount\":100}", | ||||
|     "RequestHeader": "{\"Content-Type\":\"application/json\"}", | ||||
|     "RequestUrl": "https://na.tools92.top/api/sys/deposit.order/received.confirmation", | ||||
|     "UserId": 664362432344581, | ||||
|   }, | ||||
| ] | ||||
| @@ -96,6 +96,17 @@ | ||||
|     "Title": "交易流水", | ||||
|     "Type": 1 | ||||
|   }, | ||||
|   { | ||||
|     "Component": "sys/order", | ||||
|     "Icon": "el-icon-shopping-cart", | ||||
|     "Id": 690907673255944, | ||||
|     "Name": "sys/order", | ||||
|     "ParentId": 690906994118665, | ||||
|     "Path": "/finance/order", | ||||
|     "Sort": 98, | ||||
|     "Title": "充值订单", | ||||
|     "Type": 1 | ||||
|   }, | ||||
|   // ------------------------------  系统管理 ------------------------------ | ||||
|   { | ||||
|     "Icon": "sc-icon-App", | ||||
|   | ||||
| @@ -78,5 +78,29 @@ | ||||
|   { | ||||
|     "ApiId": "api/sys/wallet.trade/get", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/paged.query", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/count.by", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/create", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/get", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/get.deposit.config", | ||||
|     "RoleId": 371729946431493, | ||||
|   }, | ||||
|   { | ||||
|     "ApiId": "api/sys/deposit.order/pay.confirm", | ||||
|     "RoleId": 371729946431493, | ||||
|   } | ||||
| ] | ||||
| @@ -26,5 +26,9 @@ | ||||
|   { | ||||
|     "MenuId": 690907673255943, | ||||
|     "RoleId": 371729946431493 | ||||
|   }, | ||||
|   { | ||||
|     "MenuId": 690907673255944, | ||||
|     "RoleId": 371729946431493 | ||||
|   } | ||||
| ] | ||||
| @@ -14,5 +14,13 @@ | ||||
|     "Password": "A8E87D23-49BC-25A1-1C7C-59186BEF5D15", | ||||
|     "Token": "4208EA97-B32F-4E39-A290-4C0D27B61EBF", | ||||
|     "UserName": "user" | ||||
|   }, | ||||
|   { | ||||
|     "DeptId": 372119301627909, | ||||
|     "Enabled": true, | ||||
|     "Id": 664362432344581, | ||||
|     "Password": "A8E87D23-49BC-25A1-1C7C-59186BEF5D15", | ||||
|     "Token": "751D599B-2B8C-417C-9565-CCF2363F5F6F", | ||||
|     "UserName": "jobs" | ||||
|   } | ||||
| ] | ||||
| @@ -3,6 +3,10 @@ | ||||
|     "Id": 370942943322181, | ||||
|     "AppConfig": "[]" | ||||
|   }, | ||||
|   { | ||||
|     "Id": 664362432344581, | ||||
|     "AppConfig": "[]" | ||||
|   }, | ||||
|   { | ||||
|     "Id": 560217289236492, | ||||
|     "AppConfig": "[]" | ||||
|   | ||||
| @@ -3,6 +3,10 @@ | ||||
|     "RoleId": 370943613149253, | ||||
|     "UserId": 370942943322181 | ||||
|   }, | ||||
|   { | ||||
|     "RoleId": 370943613149253, | ||||
|     "UserId": 664362432344581 | ||||
|   }, | ||||
|   { | ||||
|     "RoleId": 371729946431493, | ||||
|     "UserId": 560217289236492 | ||||
|   | ||||
| @@ -4,6 +4,11 @@ | ||||
|     "OwnerDeptId": 372119301627909, | ||||
|     "OwnerId": 370942943322181, | ||||
|   }, | ||||
|   { | ||||
|     "Id": 664362432344581, | ||||
|     "OwnerDeptId": 372119301627909, | ||||
|     "OwnerId": 664362432344581, | ||||
|   }, | ||||
|   { | ||||
|     "Id": 560217289236492, | ||||
|     "OwnerDeptId": 372119301627909, | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| namespace NetAdmin.Domain.DbMaps.Dependency.Fields; | ||||
|  | ||||
| /// <summary> | ||||
| ///     所有者字段接口 | ||||
| ///     归属字段接口 | ||||
| /// </summary> | ||||
| public interface IFieldOwner | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     long? OwnerId { get; init; } | ||||
| } | ||||
| @@ -6,6 +6,14 @@ namespace NetAdmin.Domain.DbMaps.Sys; | ||||
| [Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_Config))] | ||||
| public record Sys_Config : VersionEntity, IFieldEnabled | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     人民币兑点数比率 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual int CnyToPointRate { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     是否启用 | ||||
|     /// </summary> | ||||
| @@ -14,6 +22,22 @@ public record Sys_Config : VersionEntity, IFieldEnabled | ||||
|     [JsonIgnore] | ||||
|     public virtual bool Enabled { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     Trc20收款地址 | ||||
|     /// </summary> | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_CHAR_34)] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual string Trc20ReceiptAddress { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     美元兑点数比率 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual int UsdToPointRate { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     用户注册是否需要人工确认 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -0,0 +1,115 @@ | ||||
| namespace NetAdmin.Domain.DbMaps.Sys; | ||||
|  | ||||
| /// <summary> | ||||
| ///     充值订单表 | ||||
| /// </summary> | ||||
| [Table(Name = Chars.FLG_DB_TABLE_NAME_PREFIX + nameof(Sys_DepositOrder))] | ||||
| [SqlIndex( // | ||||
|     $"{Chars.FLG_DB_INDEX_PREFIX}{nameof(ActualPayAmount)}_{nameof(FinishTimestamp)}", $"{nameof(ActualPayAmount)},{nameof(FinishTimestamp)}", true)] | ||||
| [SqlIndex(Chars.FLG_DB_INDEX_PREFIX + nameof(PaymentFinger), nameof(PaymentFinger), true, WhenNotNull = true)] | ||||
| public record Sys_DepositOrder : LiteVersionEntity, IFieldOwner | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     实际支付金额 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual long ActualPayAmount { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     订单状态 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual DepositOrderStatues DepositOrderStatus { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     充值点数 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual long DepositPoint { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     完成时间戳 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual long FinishTimestamp { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     [Navigate(nameof(OwnerId))] | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual long? OwnerId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     付款账号 | ||||
|     /// </summary> | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual string PaidAccount { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     付款时间 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual DateTime? PaidTime { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     付款指纹 | ||||
|     /// </summary> | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual string PaymentFinger { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     支付方式 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual PaymentModes PaymentMode { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     收款账号 | ||||
|     /// </summary> | ||||
|     [Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual string ReceiptAccount { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     兑点数比率 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|     public virtual int ToPointRate { get; init; } | ||||
| } | ||||
| @@ -40,7 +40,7 @@ public record Sys_DocCatalog : VersionEntity, IFieldOwner | ||||
|     public virtual string Name { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -48,7 +48,7 @@ public record Sys_DocCatalog : VersionEntity, IFieldOwner | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -56,7 +56,7 @@ public record Sys_DocCatalog : VersionEntity, IFieldOwner | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -41,7 +41,7 @@ public record Sys_DocContent : VersionEntity, IFieldEnabled, IFieldOwner | ||||
|     public virtual bool Enabled { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -49,7 +49,7 @@ public record Sys_DocContent : VersionEntity, IFieldEnabled, IFieldOwner | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -57,7 +57,7 @@ public record Sys_DocContent : VersionEntity, IFieldEnabled, IFieldOwner | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -35,7 +35,7 @@ public record Sys_JobRecord : LiteImmutableEntity | ||||
|     public int HttpStatusCode { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者信息 | ||||
|     ///     归属信息 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|   | ||||
| @@ -66,7 +66,7 @@ public record Sys_LoginLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFiel | ||||
|     public virtual string LoginUserName { get; protected init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -74,7 +74,7 @@ public record Sys_LoginLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFiel | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -82,7 +82,7 @@ public record Sys_LoginLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFiel | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -76,7 +76,7 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFi | ||||
|     public virtual int HttpStatusCode { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -84,7 +84,7 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFi | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -92,7 +92,7 @@ public record Sys_RequestLog : SimpleEntity, IFieldCreatedTime, IFieldOwner, IFi | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -20,7 +20,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister | ||||
|     public virtual string Avatar { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所属部门 | ||||
|     ///     归属部门 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -84,7 +84,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister | ||||
|     public Sys_UserProfile Profile { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所属角色 | ||||
|     ///     归属角色 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
|   | ||||
| @@ -23,7 +23,7 @@ public record Sys_UserWallet : LiteVersionEntity, IFieldOwner | ||||
|     public virtual long FrozenBalance { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -31,7 +31,7 @@ public record Sys_UserWallet : LiteVersionEntity, IFieldOwner | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -39,7 +39,7 @@ public record Sys_UserWallet : LiteVersionEntity, IFieldOwner | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -31,7 +31,7 @@ public record Sys_WalletTrade : ImmutableEntity, IFieldOwner, IFieldSummary | ||||
|     public virtual long? BusinessOrderNumber { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者 | ||||
|     ///     归属用户 | ||||
|     /// </summary> | ||||
|     [CsvIgnore] | ||||
|     [JsonIgnore] | ||||
| @@ -39,7 +39,7 @@ public record Sys_WalletTrade : ImmutableEntity, IFieldOwner, IFieldSummary | ||||
|     public Sys_User Owner { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者部门编号 | ||||
|     ///     归属部门编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
| @@ -47,7 +47,7 @@ public record Sys_WalletTrade : ImmutableEntity, IFieldOwner, IFieldSummary | ||||
|     public virtual long? OwnerDeptId { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所有者用户编号 | ||||
|     ///     归属用户编号 | ||||
|     /// </summary> | ||||
|     [Column] | ||||
|     [CsvIgnore] | ||||
|   | ||||
| @@ -5,10 +5,25 @@ namespace NetAdmin.Domain.Dto.Sys.Config; | ||||
| /// </summary> | ||||
| public record CreateConfigReq : Sys_Config | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_Config.CnyToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     [Range(1, int.MaxValue)] | ||||
|     public override int CnyToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldEnabled.Enabled" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool Enabled { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.Trc20ReceiptAddress" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     [Length(34, 34)] | ||||
|     public override string Trc20ReceiptAddress { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.UsdToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     [Range(1, int.MaxValue)] | ||||
|     public override int UsdToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.UserRegisterConfirm" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool UserRegisterConfirm { get; init; } | ||||
|   | ||||
| @@ -8,6 +8,10 @@ namespace NetAdmin.Domain.Dto.Sys.Config; | ||||
| /// </summary> | ||||
| public record QueryConfigRsp : Sys_Config | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_Config.CnyToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override int CnyToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldCreatedTime.CreatedTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override DateTime CreatedTime { get; init; } | ||||
| @@ -20,6 +24,14 @@ public record QueryConfigRsp : Sys_Config | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.Trc20ReceiptAddress" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string Trc20ReceiptAddress { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.UsdToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override int UsdToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.UserRegisterConfirm" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override bool UserRegisterConfirm { get; init; } | ||||
|   | ||||
| @@ -0,0 +1,36 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:创建充值订单 | ||||
| /// </summary> | ||||
| public record CreateDepositOrderReq : Sys_DepositOrder, IValidatableObject | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" /> | ||||
|     public override long ActualPayAmount { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.DepositOrderStatus" /> | ||||
|     public override DepositOrderStatues DepositOrderStatus { get; init; } = DepositOrderStatues.WaitingForPayment; | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.DepositPoint" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     [Range(100, long.MaxValue)] | ||||
|     public override long DepositPoint { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.PaymentMode" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     [EnumDataType(typeof(PaymentModes))] | ||||
|     public override PaymentModes PaymentMode { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.ToPointRate" /> | ||||
|     public override int ToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) | ||||
|     { | ||||
|         if (PaymentMode != PaymentModes.USDT) { | ||||
|             yield return new ValidationResult(Ln.支付方式不正确, [nameof(PaymentMode)]); | ||||
|         } | ||||
|  | ||||
|         yield return ValidationResult.Success; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:编辑充值订单 | ||||
| /// </summary> | ||||
| public record EditDepositOrderReq : CreateDepositOrderReq | ||||
| { | ||||
|     /// <inheritdoc cref="EntityBase{T}.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,19 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     响应:查询充值订单 | ||||
| /// </summary> | ||||
| public sealed record GetDepositConfigRsp : Sys_Config | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_Config.CnyToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override int CnyToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.Trc20ReceiptAddress" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string Trc20ReceiptAddress { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_Config.UsdToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override int UsdToPointRate { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:支付确认 | ||||
| /// </summary> | ||||
| public record PayConfirmReq : Sys_DepositOrder | ||||
| { | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:查询充值订单 | ||||
| /// </summary> | ||||
| public sealed record QueryDepositOrderReq : Sys_DepositOrder | ||||
| { | ||||
|     /// <inheritdoc cref="EntityBase{T}.Id" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Id { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,73 @@ | ||||
| using NetAdmin.Domain.Dto.Sys.User; | ||||
|  | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     响应:查询充值订单 | ||||
| /// </summary> | ||||
| public record QueryDepositOrderRsp : Sys_DepositOrder | ||||
| { | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long ActualPayAmount { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldCreatedTime.CreatedTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override DateTime CreatedTime { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.DepositOrderStatus" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override DepositOrderStatues DepositOrderStatus { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.DepositPoint" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long DepositPoint { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="EntityBase{T}.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_DepositOrder.Owner" /> | ||||
|     [CsvIgnore] | ||||
|     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_DepositOrder.PaidAccount" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string PaidAccount { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.PaidTime" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override DateTime? PaidTime { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.PaymentFinger" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string PaymentFinger { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.PaymentMode" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override PaymentModes PaymentMode { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.ReceiptAccount" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] | ||||
|     public override string ReceiptAccount { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="Sys_DepositOrder.ToPointRate" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override int ToPointRate { get; init; } | ||||
|  | ||||
|     /// <inheritdoc cref="IFieldVersion.Version" /> | ||||
|     [JsonIgnore(Condition = JsonIgnoreCondition.Never)] | ||||
|     public override long Version { get; init; } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| namespace NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| /// <summary> | ||||
| ///     请求:到账确认 | ||||
| /// </summary> | ||||
| public record ReceivedConfirmationReq : DataAbstraction | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     读取前n条记录 | ||||
|     /// </summary> | ||||
|     public int ReadRecordCount { get; init; } | ||||
| } | ||||
| @@ -19,10 +19,10 @@ public sealed record ExportUserRsp : QueryUserRsp | ||||
|     public override QueryDeptRsp Dept { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所属部门 | ||||
|     ///     归属部门 | ||||
|     /// </summary> | ||||
|     [CsvIndex(5)] | ||||
|     [CsvName(nameof(Ln.所属部门))] | ||||
|     [CsvName(nameof(Ln.归属部门))] | ||||
|     public string DeptName { get; init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
| @@ -56,10 +56,10 @@ public sealed record ExportUserRsp : QueryUserRsp | ||||
|     public override string Mobile { get; init; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     所属角色 | ||||
|     ///     归属角色 | ||||
|     /// </summary> | ||||
|     [CsvIndex(4)] | ||||
|     [CsvName(nameof(Ln.所属角色))] | ||||
|     [CsvName(nameof(Ln.归属角色))] | ||||
|     public string RoleNames { get; init; } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|   | ||||
| @@ -10,6 +10,11 @@ public abstract record ApiClientOptions : OptionAbstraction | ||||
|     /// </summary> | ||||
|     public string Gateway { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     超时时间 | ||||
|     /// </summary> | ||||
|     public int TimeoutSecs { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     密钥 | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| using NetAdmin.Infrastructure.Configuration.Dependency; | ||||
|  | ||||
| namespace NetAdmin.Infrastructure.Configuration.Options; | ||||
|  | ||||
| /// <summary> | ||||
| ///     TronScan 配置 | ||||
| /// </summary> | ||||
| public sealed record TronScanOptions : ApiClientOptions; | ||||
| @@ -18,6 +18,7 @@ public static class Chars | ||||
|     public const string FLG_DB_EXCEPTION_IDX                           = "idx_"; | ||||
|     public const string FLG_DB_EXCEPTION_PRIMARY_KEY_CONFLICT          = "PRIMARY KEY"; | ||||
|     public const string FLG_DB_EXCEPTION_UNIQUE_CONSTRAINT_CONFLICT    = "UNIQUE constraint"; | ||||
|     public const string FLG_DB_FIELD_TYPE_CHAR_34                      = "char(34)"; | ||||
|     public const string FLG_DB_FIELD_TYPE_NVARCHAR                     = "nvarchar"; | ||||
|     public const string FLG_DB_FIELD_TYPE_NVARCHAR_1022                = "nvarchar(1022)"; | ||||
|     public const string FLG_DB_FIELD_TYPE_NVARCHAR_127                 = "nvarchar(127)"; | ||||
| @@ -53,6 +54,7 @@ public static class Chars | ||||
|     public const string FLG_HTTP_HEADER_KEY_ACCESS_TOKEN               = "ACCESS-TOKEN"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_AUTHORIZATION              = "Authorization"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_REFERER                    = "Referer"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_TRON_PRO_API_KEY           = "TRON-PRO-API-KEY"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_USER_AGENT                 = "User-Agent"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN             = "X-ACCESS-TOKEN"; | ||||
|     public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN_HEADER_KEY  = "X-Authorization"; | ||||
|   | ||||
| @@ -28,5 +28,6 @@ public static class Numbers | ||||
|     public const int  SECS_CACHE_LOGIN_BY_USER_ID    = 3600 * 24 * 30;  // 缓存时间(秒):通过用户编号登录的用户信息 | ||||
|     public const int  SECS_REDIS_LOCK_EXPIRY         = 60;              // 秒:Redis锁过期时间 | ||||
|     public const int  SECS_REDIS_LOCK_RETRY_DELAY    = 1;               // 秒:Redis锁重试间隔 | ||||
|     public const int  SECS_TIMEOUT_HTTP_CLIENT       = 15;              // 超时时间(秒):HTTP 客户端 | ||||
|     public const int  SECS_TIMEOUT_JOB               = 180;             // 超时时间(秒):作业 | ||||
| } | ||||
| @@ -0,0 +1,38 @@ | ||||
| namespace NetAdmin.Infrastructure.Enums; | ||||
|  | ||||
| /// <summary> | ||||
| ///     充值订单状态 | ||||
| /// </summary> | ||||
| [Export] | ||||
| public enum DepositOrderStatues | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     等待支付 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.等待支付))] | ||||
|     WaitingForPayment = 1 | ||||
|  | ||||
|    , | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     到账确认中 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.到账确认中))] | ||||
|     PaymentConfirming = 2 | ||||
|  | ||||
|    , | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     充值成功 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.充值成功))] | ||||
|     Succeeded = 3 | ||||
|  | ||||
|    , | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     支付超时 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.支付超时))] | ||||
|     PaymentTimeout = 4 | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| namespace NetAdmin.Infrastructure.Enums; | ||||
|  | ||||
| /// <summary> | ||||
| ///     支付方式 | ||||
| /// </summary> | ||||
| [Export] | ||||
| public enum PaymentModes | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     USDT | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.USDT))] | ||||
|     USDT = 1 | ||||
|  | ||||
|    , | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     支付宝 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.支付宝))] | ||||
|     Alipay = 2 | ||||
|  | ||||
|    , | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     微信支付 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.微信支付))] | ||||
|     WeChat = 3 | ||||
| } | ||||
| @@ -10,7 +10,7 @@ public enum TradeDirections | ||||
|     ///     收入 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.收入))] | ||||
|     Income = 4 | ||||
|     Income = 1 | ||||
|  | ||||
|    , | ||||
|  | ||||
| @@ -18,5 +18,5 @@ public enum TradeDirections | ||||
|     ///     支出 | ||||
|     /// </summary> | ||||
|     [ResourceDescription<Ln>(nameof(Ln.支出))] | ||||
|     Expense = 5 | ||||
|     Expense = 2 | ||||
| } | ||||
| @@ -0,0 +1,43 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     云码平台 客户端 | ||||
| /// </summary> | ||||
| public interface ITronScanClient : IHttpDispatchProxy | ||||
| { | ||||
|     private static readonly ILogger<ITronScanClient> _logger = App.GetService<ILogger<ITronScanClient>>(); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     异常拦截 | ||||
|     /// </summary> | ||||
|     [Interceptor(InterceptorTypes.Exception)] | ||||
|     static Task OnExceptionAsync(HttpClient _, HttpResponseMessage rsp, string errors) | ||||
|     { | ||||
|         return rsp.LogExceptionAsync(errors, _logger); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     请求拦截 | ||||
|     /// </summary> | ||||
|     [Interceptor(InterceptorTypes.Request)] | ||||
|     static Task OnRequestAsyncAsync(HttpClient _, HttpRequestMessage req) | ||||
|     { | ||||
|         return req.LogAsync(_logger); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     响应拦截 | ||||
|     /// </summary> | ||||
|     [Interceptor(InterceptorTypes.Response)] | ||||
|     static Task OnResponsingAsync(HttpClient _, HttpResponseMessage rsp) | ||||
|     { | ||||
|         return rsp.LogAsync(_logger); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取交易记录 | ||||
|     /// </summary> | ||||
|     [Client(nameof(TronScanOptions))] | ||||
|     [Get("api/filter/trc20/transfers?limit={limit}&toAddress={toAddress}")] | ||||
|     Task<TransfersRsp> TransfersAsync([Headers(Chars.FLG_HTTP_HEADER_KEY_TRON_PRO_API_KEY)] string token, int limit, string toAddress); | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     表示一个普通的地址信息记录。 | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| ///     该记录包含一个布尔值属性,用于指示地址是否存在风险。 | ||||
| /// </remarks> | ||||
| public record NormalAddressInfo | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取或设置地址是否存在风险的标识。 | ||||
|     /// </summary> | ||||
|     public bool Risk { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     表示一个令牌的信息,包括发行者地址、令牌缩写、显示属性等详细信息。 | ||||
| /// </summary> | ||||
| public record TokenInfo | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取或设置发行者的地址。 | ||||
|     /// </summary> | ||||
|     public string IssuerAddr { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的缩写。 | ||||
|     /// </summary> | ||||
|     public string TokenAbbr { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌可显示的数量。 | ||||
|     /// </summary> | ||||
|     public int TokenCanShow { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的小数位数。 | ||||
|     /// </summary> | ||||
|     public int TokenDecimal { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的唯一标识符。 | ||||
|     /// </summary> | ||||
|     public string TokenId { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的级别。 | ||||
|     /// </summary> | ||||
|     public string TokenLevel { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的Logo URL或路径。 | ||||
|     /// </summary> | ||||
|     public string TokenLogo { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的名称。 | ||||
|     /// </summary> | ||||
|     public string TokenName { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌的类型。 | ||||
|     /// </summary> | ||||
|     public string TokenType { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置是否为VIP令牌。 | ||||
|     /// </summary> | ||||
|     public bool Vip { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,116 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     表示一个代币转账事件。 | ||||
| /// </summary> | ||||
| public record TokenTransferInfo | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取或设置批准的转账金额。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("approval_amount")] | ||||
|     public string ApprovalAmount { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置发生转账事件的区块编号。 | ||||
|     /// </summary> | ||||
|     public int Block { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置发生转账事件的区块的时间戳。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("block_ts")] | ||||
|     public long BlockTs { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置一个值,指示转账是否已确认。 | ||||
|     /// </summary> | ||||
|     public bool Confirmed { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置代币的合约地址。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("contract_address")] | ||||
|     public string ContractAddress { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约执行的返回结果。 | ||||
|     /// </summary> | ||||
|     public string ContractRet { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约类型。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("contract_type")] | ||||
|     public string ContractType { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置事件类型。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("event_type")] | ||||
|     public string EventType { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置转账的最终结果。 | ||||
|     /// </summary> | ||||
|     public string FinalResult { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置发送方地址。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("from_address")] | ||||
|     public string FromAddress { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置一个值,指示发送方地址是否为合约地址。 | ||||
|     /// </summary> | ||||
|     public bool FromAddressIsContract { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置转账数量。 | ||||
|     /// </summary> | ||||
|     public string Quant { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置一个值,指示转账是否已回滚。 | ||||
|     /// </summary> | ||||
|     public bool Revert { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置一个值,指示转账是否为风险交易。 | ||||
|     /// </summary> | ||||
|     public bool RiskTransaction { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置转账状态。 | ||||
|     /// </summary> | ||||
|     public int Status { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置接收方地址。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("to_address")] | ||||
|     public string ToAddress { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置一个值,指示接收方地址是否为合约地址。 | ||||
|     /// </summary> | ||||
|     public bool ToAddressIsContract { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置代币信息。 | ||||
|     /// </summary> | ||||
|     public TokenInfo TokenInfo { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置交易ID。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("transaction_id")] | ||||
|     public string TransactionId { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约触发信息。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("trigger_info")] | ||||
|     public TriggerInfo TriggerInfo { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     表示包含合约信息及相关数据的根响应对象。 | ||||
| /// </summary> | ||||
| public record TransfersRsp | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取或设置按地址键入的正常地址信息字典。 | ||||
|     /// </summary> | ||||
|     public Dictionary<string, NormalAddressInfo> NormalAddressInfo { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置范围内的项目总数。 | ||||
|     /// </summary> | ||||
|     public int RangeTotal { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置令牌转账列表。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("token_transfers")] | ||||
|     public IReadOnlyCollection<TokenTransferInfo> TokenTransfers { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置项目的总数。 | ||||
|     /// </summary> | ||||
|     public int Total { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| namespace NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| /// <summary> | ||||
| ///     表示触发智能合约的信息。 | ||||
| /// </summary> | ||||
| public record TriggerInfo | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取或设置调用合约时传递的值。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("call_value")] | ||||
|     public int CallValue { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约的地址。 | ||||
|     /// </summary> | ||||
|     [JsonPropertyName("contract_address")] | ||||
|     public string ContractAddress { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置调用合约方法的数据。 | ||||
|     /// </summary> | ||||
|     public string Data { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约方法的标识符。 | ||||
|     /// </summary> | ||||
|     public string Method { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取或设置合约方法的名称。 | ||||
|     /// </summary> | ||||
|     public string MethodName { get; set; } | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| using NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| namespace NetAdmin.SysComponent.Application.Modules.Sys; | ||||
|  | ||||
| /// <summary> | ||||
| ///     充值订单模块 | ||||
| /// </summary> | ||||
| public interface IDepositOrderModule : ICrudModule<CreateDepositOrderReq, QueryDepositOrderRsp // 创建类型 | ||||
|   , EditDepositOrderReq                                                                        // 编辑类型 | ||||
|   , QueryDepositOrderReq, QueryDepositOrderRsp                                                 // 查询类型 | ||||
|   , DelReq                                                                                     // 删除类型 | ||||
| > | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     获取充值配置 | ||||
|     /// </summary> | ||||
|     Task<GetDepositConfigRsp> GetDepositConfigAsync(); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     支付确认 | ||||
|     /// </summary> | ||||
|     Task<int> PayConfirmAsync(PayConfirmReq req); | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     到账确认 | ||||
|     /// </summary> | ||||
|     Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req); | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| namespace NetAdmin.SysComponent.Application.Services.Sys.Dependency; | ||||
|  | ||||
| /// <summary> | ||||
| ///     充值订单服务 | ||||
| /// </summary> | ||||
| public interface IDepositOrderService : IService, IDepositOrderModule; | ||||
| @@ -0,0 +1,235 @@ | ||||
| using NetAdmin.Application.Extensions; | ||||
| using NetAdmin.Domain.DbMaps.Sys; | ||||
| using NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
| using NetAdmin.Domain.Dto.Sys.WalletTrade; | ||||
| using NetAdmin.Domain.Extensions; | ||||
| using NetAdmin.Infrastructure.Rpc.TronScan; | ||||
|  | ||||
| namespace NetAdmin.SysComponent.Application.Services.Sys; | ||||
|  | ||||
| /// <inheritdoc cref="IDepositOrderService" /> | ||||
| public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long> rpo) // | ||||
|     : RepositoryService<Sys_DepositOrder, long, IDepositOrderService>(rpo), IDepositOrderService | ||||
| { | ||||
|     /// <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<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return QueryInternal(req).WithNoLockNoWait().CountAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         var ret = await QueryInternal(req with { Order = Orders.None }) | ||||
|                         .WithNoLockNoWait() | ||||
|                         .GroupBy(req.GetToListExp<Sys_DepositOrder>()) | ||||
|                         .ToDictionaryAsync(a => a.Count()) | ||||
|                         .ConfigureAwait(false); | ||||
|         return ret.Select(x => new KeyValuePair<IImmutableDictionary<string, string>, int>( | ||||
|                               req.RequiredFields.ToImmutableDictionary( | ||||
|                                   y => y, y => typeof(Sys_DepositOrder).GetProperty(y)!.GetValue(x.Key)?.ToString()), x.Value)) | ||||
|                   .Where(x => x.Key.Any(y => !y.Value.NullOrEmpty())) | ||||
|                   .OrderByDescending(x => x.Value); | ||||
|     } | ||||
|  | ||||
|     /// <exception cref="ArgumentOutOfRangeException">req</exception> | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<QueryDepositOrderRsp> CreateAsync(CreateDepositOrderReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|  | ||||
|         var config = await GetDepositConfigAsync().ConfigureAwait(false); | ||||
|  | ||||
|         var toPointRate = req.PaymentMode switch { | ||||
|                               PaymentModes.USDT   => config.UsdToPointRate | ||||
|                             , PaymentModes.Alipay => config.CnyToPointRate | ||||
|                             , PaymentModes.WeChat => config.CnyToPointRate | ||||
|                             , _                   => throw new ArgumentOutOfRangeException(nameof(req)) | ||||
|                           }; | ||||
|  | ||||
|         var ret = await Rpo.InsertAsync(req with { | ||||
|                                                      ActualPayAmount = (long)(((decimal)req.DepositPoint / toPointRate).Round(3) * 1000) | ||||
|                                                    , ToPointRate = toPointRate | ||||
|                                                    , ReceiptAccount = config.Trc20ReceiptAddress | ||||
|                                                  }) | ||||
|                            .ConfigureAwait(false); | ||||
|         return ret.Adapt<QueryDepositOrderRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> DeleteAsync(DelReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return Rpo.DeleteAsync(a => a.Id == req.Id); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<QueryDepositOrderRsp> EditAsync(EditDepositOrderReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         #if DBTYPE_SQLSERVER | ||||
|         return (await UpdateReturnListAsync(req).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryDepositOrderRsp>(); | ||||
|         #else | ||||
|         return await UpdateAsync(req).ConfigureAwait(false) > 0 | ||||
|             ? await GetAsync(new QueryDepositOrderReq { Id = req.Id }).ConfigureAwait(false) | ||||
|             : null; | ||||
|         #endif | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<IActionResult> ExportAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return ExportAsync<QueryDepositOrderReq, QueryDepositOrderRsp>(QueryInternal, req, Ln.充值订单导出); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<QueryDepositOrderRsp> GetAsync(QueryDepositOrderReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         var ret = await QueryInternal(new QueryReq<QueryDepositOrderReq> { Filter = req, Order = Orders.None }).ToOneAsync().ConfigureAwait(false); | ||||
|         return ret.Adapt<QueryDepositOrderRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<GetDepositConfigRsp> GetDepositConfigAsync() | ||||
|     { | ||||
|         var ret = await S<IConfigService>().GetLatestConfigAsync().ConfigureAwait(false); | ||||
|         return ret.Adapt<GetDepositConfigRsp>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<PagedQueryRsp<QueryDepositOrderRsp>> PagedQueryAsync(PagedQueryReq<QueryDepositOrderReq> 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<QueryDepositOrderRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryDepositOrderRsp>>()); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> PayConfirmAsync(PayConfirmReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         return UpdateAsync(req with { DepositOrderStatus = DepositOrderStatues.PaymentConfirming }, [nameof(req.DepositOrderStatus)], null | ||||
|                          , a => a.DepositOrderStatus == DepositOrderStatues.WaitingForPayment && a.Id == req.Id, null, true); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<IEnumerable<QueryDepositOrderRsp>> QueryAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         var ret = await QueryInternal(req).WithNoLockNoWait().Take(req.Count).ToListAsync(req).ConfigureAwait(false); | ||||
|         return ret.Adapt<IEnumerable<QueryDepositOrderRsp>>(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public async Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req) | ||||
|     { | ||||
|         req.ThrowIfInvalid(); | ||||
|         var ret    = 0; | ||||
|         var config = await S<IConfigService>().GetLatestConfigAsync().ConfigureAwait(false); | ||||
|         var waitConfirmList = (await QueryAsync(new QueryReq<QueryDepositOrderReq> { | ||||
|                                                                                        Count = Numbers.MAX_LIMIT_QUERY_PAGE_SIZE | ||||
|                                                                                      , DynamicFilter | ||||
|                                                                                            = new DynamicFilterInfo { | ||||
|                                                                                                  Field = nameof( | ||||
|                                                                                                      QueryDepositOrderReq.DepositOrderStatus) | ||||
|                                                                                                , Operator = DynamicFilterOperators.Eq | ||||
|                                                                                                , Value    = DepositOrderStatues.PaymentConfirming | ||||
|                                                                                              } | ||||
|                                                                                      , Order = Orders.Ascending | ||||
|                                                                                      , Prop  = nameof(QueryDepositOrderReq.Id) | ||||
|                                                                                    }) | ||||
|             .ConfigureAwait(false)).ToList(); | ||||
|         var apiResult = await S<ITronScanClient>() | ||||
|                               .TransfersAsync(S<IOptions<TronScanOptions>>().Value.Token, req.ReadRecordCount, config.Trc20ReceiptAddress) | ||||
|                               .ConfigureAwait(false); | ||||
|         foreach (var apiItem in apiResult.TokenTransfers.Where(x => x.TokenInfo.TokenAbbr == "USDT" && x.Confirmed && x.ContractRet == "SUCCESS" && | ||||
|                                                                     x.FinalResult         == "SUCCESS")) { | ||||
|             var order = waitConfirmList.SingleOrDefault(x => x.ActualPayAmount == apiItem.Quant.Int64() / 1000); | ||||
|             if (order == null || order.CreatedTime > apiItem.BlockTs.Time()) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 await S<UnitOfWorkManager>() | ||||
|                       .AtomicOperateAsync(async () => { | ||||
|                           var updated = await UpdateAsync( // | ||||
|                                   new Sys_DepositOrder { | ||||
|                                                            DepositOrderStatus = DepositOrderStatues.Succeeded | ||||
|                                                          , Version = order.Version | ||||
|                                                          , FinishTimestamp = DateTime.Now.TimeUnixUtcMs() | ||||
|                                                          , PaidAccount = apiItem.FromAddress | ||||
|                                                          , PaidTime = apiItem.BlockTs.Time() | ||||
|                                                          , PaymentFinger = apiItem.TransactionId | ||||
|                                                        }, [nameof(Sys_DepositOrder.DepositOrderStatus), nameof(Sys_DepositOrder.FinishTimestamp), nameof(Sys_DepositOrder.PaidAccount), nameof(Sys_DepositOrder.PaidTime), nameof(Sys_DepositOrder.PaymentFinger)] | ||||
|                                 , null, a => a.Id == order.Id && a.DepositOrderStatus == DepositOrderStatues.PaymentConfirming) | ||||
|                               .ConfigureAwait(false); | ||||
|                           if (updated != 1) { | ||||
|                               throw new NetAdminUnexpectedException(Ln.结果非预期); | ||||
|                           } | ||||
|  | ||||
|                           _ = await S<IWalletTradeService>() | ||||
|                                     .CreateAsync(new CreateWalletTradeReq { | ||||
|                                                                               Amount              = order.DepositPoint | ||||
|                                                                             , BusinessOrderNumber = order.Id | ||||
|                                                                             , TradeDirection      = TradeDirections.Income | ||||
|                                                                             , TradeType           = TradeTypes.SelfDeposit | ||||
|                                                                             , OwnerId             = order.OwnerId | ||||
|                                                                           }) | ||||
|                                     .ConfigureAwait(false) ?? throw new NetAdminUnexpectedException(Ln.结果非预期); | ||||
|                       }) | ||||
|                       .ConfigureAwait(false); | ||||
|                 ret++; | ||||
|             } | ||||
|             catch { | ||||
|                 // ignore | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     private ISelect<Sys_DepositOrder> QueryInternal(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter); | ||||
|  | ||||
|         // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault | ||||
|         switch (req.Order) { | ||||
|             case Orders.None: | ||||
|                 return ret; | ||||
|             case Orders.Random: | ||||
|                 return ret.OrderByRandom(); | ||||
|         } | ||||
|  | ||||
|         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; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| namespace NetAdmin.SysComponent.Cache.Sys.Dependency; | ||||
|  | ||||
| /// <summary> | ||||
| ///     充值订单缓存 | ||||
| /// </summary> | ||||
| public interface IDepositOrderCache : ICache<IDistributedCache, IDepositOrderService>, IDepositOrderModule; | ||||
| @@ -0,0 +1,86 @@ | ||||
| using NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| namespace NetAdmin.SysComponent.Cache.Sys; | ||||
|  | ||||
| /// <inheritdoc cref="IDepositOrderCache" /> | ||||
| public sealed class DepositOrderCache(IDistributedCache cache, IDepositOrderService service) | ||||
|     : DistributedCache<IDepositOrderService>(cache, service), IScoped, IDepositOrderCache | ||||
| { | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> BulkDeleteAsync(BulkReq<DelReq> req) | ||||
|     { | ||||
|         return Service.BulkDeleteAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<long> CountAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Service.CountAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Service.CountByAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<QueryDepositOrderRsp> CreateAsync(CreateDepositOrderReq req) | ||||
|     { | ||||
|         return Service.CreateAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> DeleteAsync(DelReq req) | ||||
|     { | ||||
|         return Service.DeleteAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<QueryDepositOrderRsp> EditAsync(EditDepositOrderReq req) | ||||
|     { | ||||
|         return Service.EditAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<IActionResult> ExportAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Service.ExportAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<QueryDepositOrderRsp> GetAsync(QueryDepositOrderReq req) | ||||
|     { | ||||
|         return Service.GetAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<GetDepositConfigRsp> GetDepositConfigAsync() | ||||
|     { | ||||
|         return Service.GetDepositConfigAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<PagedQueryRsp<QueryDepositOrderRsp>> PagedQueryAsync(PagedQueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Service.PagedQueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> PayConfirmAsync(PayConfirmReq req) | ||||
|     { | ||||
|         return Service.PayConfirmAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<IEnumerable<QueryDepositOrderRsp>> QueryAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Service.QueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req) | ||||
|     { | ||||
|         return Service.ReceivedConfirmationAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,122 @@ | ||||
| using NetAdmin.Domain.Dto.Sys.DepositOrder; | ||||
|  | ||||
| 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 DepositOrderController(IDepositOrderCache cache) | ||||
|     : ControllerBase<IDepositOrderCache, IDepositOrderService>(cache), IDepositOrderModule | ||||
| { | ||||
|     /// <summary> | ||||
|     ///     批量删除充值订单 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task<int> BulkDeleteAsync(BulkReq<DelReq> req) | ||||
|     { | ||||
|         return Cache.BulkDeleteAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     充值订单计数 | ||||
|     /// </summary> | ||||
|     public Task<long> CountAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Cache.CountAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     充值订单分组计数 | ||||
|     /// </summary> | ||||
|     public Task<IOrderedEnumerable<KeyValuePair<IImmutableDictionary<string, string>, int>>> CountByAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Cache.CountByAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     创建充值订单 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task<QueryDepositOrderRsp> CreateAsync(CreateDepositOrderReq req) | ||||
|     { | ||||
|         return Cache.CreateAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     删除充值订单 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task<int> DeleteAsync(DelReq req) | ||||
|     { | ||||
|         return Cache.DeleteAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     编辑充值订单 | ||||
|     /// </summary> | ||||
|     [Transaction] | ||||
|     public Task<QueryDepositOrderRsp> EditAsync(EditDepositOrderReq req) | ||||
|     { | ||||
|         return Cache.EditAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     导出充值订单 | ||||
|     /// </summary> | ||||
|     [NonAction] | ||||
|     public Task<IActionResult> ExportAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Cache.ExportAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取单个充值订单 | ||||
|     /// </summary> | ||||
|     public Task<QueryDepositOrderRsp> GetAsync(QueryDepositOrderReq req) | ||||
|     { | ||||
|         return Cache.GetAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     获取充值配置 | ||||
|     /// </summary> | ||||
|     public Task<GetDepositConfigRsp> GetDepositConfigAsync() | ||||
|     { | ||||
|         return Cache.GetDepositConfigAsync(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     分页查询充值订单 | ||||
|     /// </summary> | ||||
|     public Task<PagedQueryRsp<QueryDepositOrderRsp>> PagedQueryAsync(PagedQueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Cache.PagedQueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     支付确认 | ||||
|     /// </summary> | ||||
|     public Task<int> PayConfirmAsync(PayConfirmReq req) | ||||
|     { | ||||
|         return Cache.PayConfirmAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     查询充值订单 | ||||
|     /// </summary> | ||||
|     [NonAction] | ||||
|     public Task<IEnumerable<QueryDepositOrderRsp>> QueryAsync(QueryReq<QueryDepositOrderReq> req) | ||||
|     { | ||||
|         return Cache.QueryAsync(req); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     到账确认 | ||||
|     /// </summary> | ||||
|     public Task<int> ReceivedConfirmationAsync(ReceivedConfirmationReq req) | ||||
|     { | ||||
|         return Cache.ReceivedConfirmationAsync(req); | ||||
|     } | ||||
| } | ||||
| @@ -3,6 +3,7 @@ using NetAdmin.Domain.Contexts; | ||||
| using NetAdmin.Domain.Events; | ||||
| using NetAdmin.Host.Filters; | ||||
| using NetAdmin.Host.Middlewares; | ||||
| using NetAdmin.Infrastructure.Configuration.Dependency; | ||||
| using NetAdmin.Infrastructure.Schedule; | ||||
| using NetAdmin.SysComponent.Host.Utils; | ||||
| using FreeSqlBuilder = NetAdmin.Infrastructure.Utils.FreeSqlBuilder; | ||||
| @@ -104,6 +105,31 @@ public static class ServiceCollectionExtensions | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     添加 TronScan 客户端 | ||||
|     /// </summary> | ||||
|     public static IServiceCollection AddTronScanClient(this IServiceCollection me) | ||||
|     { | ||||
|         _ = me.AddHttpClient(nameof(TronScanOptions), ConfigClient<TronScanOptions>); | ||||
|         return me; | ||||
|     } | ||||
|  | ||||
|     private static void ConfigClient<T>(HttpClient client) | ||||
|         where T : ApiClientOptions, new() | ||||
|     { | ||||
|         ConfigClient<T>(client, Numbers.SECS_TIMEOUT_HTTP_CLIENT); | ||||
|     } | ||||
|  | ||||
|     private static void ConfigClient<T>(HttpClient client, int timeoutSecs) | ||||
|         where T : ApiClientOptions, new() | ||||
|     { | ||||
|         var options = App.GetOptions<T>(); | ||||
|  | ||||
|         client.Timeout = TimeSpan.FromSeconds(options.TimeoutSecs > 0 ? options.TimeoutSecs : timeoutSecs); | ||||
|         client.DefaultRequestHeaders.Add("User-Agent", nameof(NetAdmin)); | ||||
|         client.BaseAddress = new Uri($"{options.Gateway}/"); | ||||
|     } | ||||
|  | ||||
|     private static void RunJob(IEnumerable<KeyValuePair<Type, JobConfigAttribute>> jobTypes) | ||||
|     { | ||||
|         foreach (var job in jobTypes) { | ||||
|   | ||||
| @@ -149,7 +149,7 @@ public sealed class SqlAuditor : ISingleton | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     ///     设置所有者 | ||||
|     ///     设置归属 | ||||
|     /// </summary> | ||||
|     private static void SetOwner(AuditValueEventArgs e, ContextUserInfo userInfo) | ||||
|     { | ||||
|   | ||||
| @@ -37,7 +37,7 @@ public sealed class JwtHandler : AppAuthorizeHandler | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 获取所属角色接口权限 进行核对 | ||||
|             // 获取归属角色接口权限 进行核对 | ||||
|             if (role.ApiIds?.Contains(path) ?? false) { | ||||
|                 return true; | ||||
|             } | ||||
|   | ||||
| @@ -95,6 +95,7 @@ namespace YourSolution.AdmServer.Host | ||||
|                         .AddContextUserInfo()  // 添加上下文用户信息 | ||||
|                         .AddRedisCache()       // 添加 Redis 缓存 | ||||
|                         .AddSchedules()        // 添加计划任务 | ||||
|                         .AddTronScanClient()   // 添加 TronScan 客户端 | ||||
|  | ||||
|                         // IMvcBuilder | ||||
|                         .AddControllers()             // 添加控制器 | ||||
|   | ||||
| @@ -94,4 +94,9 @@ | ||||
|       "Secure": false | ||||
|     } | ||||
|   }, | ||||
|   // TronScan 客户端配置 | ||||
|   "TronScan": { | ||||
|     "Gateway": "https://apilist.tronscanapi.com", | ||||
|     "Token": "fc6629dc-0139-4238-bead-8db7c45ec1e2" | ||||
|   }, | ||||
| } | ||||
| @@ -21,6 +21,7 @@ | ||||
|         "markdown-it": "14.1.0", | ||||
|         "markdown-it-emoji": "3.0.0", | ||||
|         "nprogress": "0.2.0", | ||||
|         "qrcode-svg": "1.1.0", | ||||
|         "sortablejs": "1.15.6", | ||||
|         "vkbeautify": "0.99.3", | ||||
|         "vue": "3.5.17", | ||||
|   | ||||
							
								
								
									
										117
									
								
								src/frontend/admin/src/api/sys/depositorder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/frontend/admin/src/api/sys/depositorder.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /** | ||||
|  *  充值订单服务 | ||||
|  *  @module @/api/sys/deposit.order | ||||
|  */ | ||||
| import config from '@/config' | ||||
| import http from '@/utils/request' | ||||
| export default { | ||||
|     /** | ||||
|      * 批量删除充值订单 | ||||
|      */ | ||||
|     bulkDelete: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/bulk.delete`, | ||||
|         name: `批量删除充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 充值订单计数 | ||||
|      */ | ||||
|     count: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/count`, | ||||
|         name: `充值订单计数`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 充值订单分组计数 | ||||
|      */ | ||||
|     countBy: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/count.by`, | ||||
|         name: `充值订单分组计数`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 创建充值订单 | ||||
|      */ | ||||
|     create: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/create`, | ||||
|         name: `创建充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 删除充值订单 | ||||
|      */ | ||||
|     delete: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/delete`, | ||||
|         name: `删除充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 编辑充值订单 | ||||
|      */ | ||||
|     edit: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/edit`, | ||||
|         name: `编辑充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 获取单个充值订单 | ||||
|      */ | ||||
|     get: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/get`, | ||||
|         name: `获取单个充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 获取充值配置 | ||||
|      */ | ||||
|     getDepositConfig: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/get.deposit.config`, | ||||
|         name: `获取充值配置`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 分页查询充值订单 | ||||
|      */ | ||||
|     pagedQuery: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/paged.query`, | ||||
|         name: `分页查询充值订单`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * 支付确认 | ||||
|      */ | ||||
|     payConfirm: { | ||||
|         url: `${config.API_URL}/api/sys/deposit.order/pay.confirm`, | ||||
|         name: `支付确认`, | ||||
|         post: async function (data = {}, config = {}) { | ||||
|             return await http.post(this.url, data, config) | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
| @@ -188,7 +188,7 @@ | ||||
|         <scContextmenuItem :title="$t('复制')" command="copy" divided icon="el-icon-copy-document" suffix="C"></scContextmenuItem> | ||||
|         <scContextmenuItem | ||||
|             v-if="contextOpers.includes('add')" | ||||
|             :title="$t('新增')" | ||||
|             :title="$t('新建')" | ||||
|             command="add" | ||||
|             divided | ||||
|             icon="el-icon-plus" | ||||
|   | ||||
| @@ -90,6 +90,8 @@ export default { | ||||
|             //         Object.keys(item).forEach((x) => delete item[x]) | ||||
|             //         Object.assign(item, data) | ||||
|             //     }) | ||||
|         } else { | ||||
|             table.refresh() | ||||
|         } | ||||
|     }, | ||||
| } | ||||
| @@ -99,9 +99,9 @@ export default { | ||||
|     性别: 'Gender', | ||||
|     成功: 'Successful', | ||||
|     我的消息: 'My messages', | ||||
|     所属字典: 'Dictionary', | ||||
|     所属角色: 'Role', | ||||
|     所属部门: 'Department', | ||||
|     归属字典: 'Dictionary', | ||||
|     归属角色: 'Role', | ||||
|     归属部门: 'Department', | ||||
|     手机号: 'Mobile', | ||||
|     手机号码: 'Mobile phone number', | ||||
|     手风琴菜单: 'Accordion menu', | ||||
| @@ -131,13 +131,13 @@ export default { | ||||
|     整页路由: 'Full page routing', | ||||
|     文化程度: 'Educational level', | ||||
|     斑马纹: 'Zebra pattern', | ||||
|     新增作业: 'Add job', | ||||
|     新增字典项: 'Add Dictionary Item', | ||||
|     新增消息: 'Add Message', | ||||
|     新增用户: 'Add User', | ||||
|     新增角色: 'Add Role', | ||||
|     新增部门: 'Add Department', | ||||
|     新增配置: 'Add Configuration', | ||||
|     新建作业: 'Add job', | ||||
|     新建字典项: 'Add Dictionary Item', | ||||
|     新建消息: 'Add Message', | ||||
|     新建用户: 'Add User', | ||||
|     新建角色: 'Add Role', | ||||
|     新建部门: 'Add Department', | ||||
|     新建配置: 'Add Configuration', | ||||
|     新密码: 'New password', | ||||
|     新手机号码: 'New mobile phone number', | ||||
|     新手机验证码: 'New mobile verification code', | ||||
| @@ -379,7 +379,7 @@ export default { | ||||
|     响应体: 'Response body', | ||||
|     响应头: 'Response header', | ||||
|     执行时间编号: 'Execution time ID', | ||||
|     新增字典目录: 'Add dictionary catalog', | ||||
|     新建字典目录: 'Add dictionary catalog', | ||||
|     字典名称: 'Dictionary name', | ||||
|     字典编码: 'Dictionary code', | ||||
|     父路径: 'Parent path', | ||||
| @@ -579,7 +579,7 @@ export default { | ||||
|     '结束值(毫秒)': 'End Value (ms)', | ||||
|     '起始值(毫秒)': 'Starting Value (ms)', | ||||
|     复制: 'Copy', | ||||
|     新增: 'New', | ||||
|     新建: 'New', | ||||
|     '数据已导出(上限 {n} 条)': 'Data exported (Maximum {n} entries)', | ||||
|     同步成功: 'Synchronization succeeded', | ||||
|     缓存详情: 'Cache details', | ||||
| @@ -587,11 +587,11 @@ export default { | ||||
|     数据权限: 'Data Permissions', | ||||
|     首页视图: 'Home view', | ||||
|     删除配置: 'Delete the configuration', | ||||
|     所属字典目录: 'Dictionary catalog', | ||||
|     归属字典目录: 'Dictionary catalog', | ||||
|     删除字典项: 'Delete dictionary entries', | ||||
|     接口总数: 'Total number of apis', | ||||
|     所属文档分类: 'Document catalog', | ||||
|     请选择所属文档分类: 'Please select the document category', | ||||
|     归属文档分类: 'Document catalog', | ||||
|     请选择归属文档分类: 'Please select the document category', | ||||
|     请输入文档标题: 'Please enter a title for the document', | ||||
|     请输入文档内容: 'Please enter the content of the document', | ||||
|     请选择档案可见性: 'Please select profile visibility', | ||||
|   | ||||
| @@ -99,9 +99,9 @@ export default { | ||||
|     性别: '性别', | ||||
|     成功: '成功', | ||||
|     我的消息: '我的消息', | ||||
|     所属字典: '所属字典', | ||||
|     所属角色: '所属角色', | ||||
|     所属部门: '所属部门', | ||||
|     归属字典: '归属字典', | ||||
|     归属角色: '归属角色', | ||||
|     归属部门: '归属部门', | ||||
|     手机号: '手机号', | ||||
|     手机号码: '手机号码', | ||||
|     手风琴菜单: '手风琴菜单', | ||||
| @@ -131,13 +131,13 @@ export default { | ||||
|     整页路由: '整页路由', | ||||
|     文化程度: '文化程度', | ||||
|     斑马纹: '斑马纹', | ||||
|     新增作业: '新增作业', | ||||
|     新增字典项: '新增字典项', | ||||
|     新增消息: '新增消息', | ||||
|     新增用户: '新增用户', | ||||
|     新增角色: '新增角色', | ||||
|     新增部门: '新增部门', | ||||
|     新增配置: '新增配置', | ||||
|     新建作业: '新建作业', | ||||
|     新建字典项: '新建字典项', | ||||
|     新建消息: '新建消息', | ||||
|     新建用户: '新建用户', | ||||
|     新建角色: '新建角色', | ||||
|     新建部门: '新建部门', | ||||
|     新建配置: '新建配置', | ||||
|     新密码: '新密码', | ||||
|     新手机号码: '新手机号码', | ||||
|     新手机验证码: '新手机验证码', | ||||
| @@ -378,7 +378,7 @@ export default { | ||||
|     响应体: '响应体', | ||||
|     响应头: '响应头', | ||||
|     执行时间编号: '执行时间编号', | ||||
|     新增字典目录: '新增字典目录', | ||||
|     新建字典目录: '新建字典目录', | ||||
|     字典名称: '字典名称', | ||||
|     字典编码: '字典编码', | ||||
|     父路径: '父路径', | ||||
| @@ -577,7 +577,7 @@ export default { | ||||
|     '结束值(毫秒)': '结束值(毫秒)', | ||||
|     '起始值(毫秒)': '起始值(毫秒)', | ||||
|     复制: '复制', | ||||
|     新增: '新增', | ||||
|     新建: '新建', | ||||
|     '数据已导出(上限 {n} 条)': '数据已导出(上限 {n} 条)', | ||||
|     同步成功: '同步成功', | ||||
|     缓存详情: '缓存详情', | ||||
| @@ -585,11 +585,11 @@ export default { | ||||
|     数据权限: '数据权限', | ||||
|     首页视图: '首页视图', | ||||
|     删除配置: '删除配置', | ||||
|     所属字典目录: '所属字典目录', | ||||
|     归属字典目录: '归属字典目录', | ||||
|     删除字典项: '删除字典项', | ||||
|     接口总数: '接口总数', | ||||
|     所属文档分类: '所属文档分类', | ||||
|     请选择所属文档分类: '请选择所属文档分类', | ||||
|     归属文档分类: '归属文档分类', | ||||
|     请选择归属文档分类: '请选择归属文档分类', | ||||
|     请输入文档标题: '请输入文档标题', | ||||
|     请输入文档内容: '请输入文档内容', | ||||
|     请选择档案可见性: '请选择档案可见性', | ||||
|   | ||||
| @@ -85,6 +85,11 @@ | ||||
|                         </template> | ||||
|                     </el-table-column> | ||||
|                 </el-table-column> | ||||
|                 <el-table-column :label="$t('财务配置')" align="center"> | ||||
|                     <el-table-column :label="$t('人民币兑点数比率')" align="center" prop="cnyToPointRate" width="150" /> | ||||
|                     <el-table-column :label="$t('美元兑点数比率')" align="center" prop="usdToPointRate" width="150" /> | ||||
|                     <el-table-column :label="$t('USDT 收款地址')" align="center" prop="trc20ReceiptAddress" width="300" /> | ||||
|                 </el-table-column> | ||||
|                 <el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="100"> | ||||
|                     <template #default="{ row }"> | ||||
|                         <el-switch v-model="row.enabled" @change="changeSwitch($event, row)"></el-switch> | ||||
| @@ -93,7 +98,7 @@ | ||||
|                 <naColOperation | ||||
|                     :buttons="naColOperation.buttons.concat(naColOperation.delButton(this.$t('删除配置'), $API.sys_config.delete))" | ||||
|                     :vue="this" | ||||
|                     width="150" /> | ||||
|                     width="120" /> | ||||
|             </scTable> | ||||
|         </el-main> | ||||
|     </el-container> | ||||
|   | ||||
| @@ -25,6 +25,19 @@ | ||||
|                                     </el-form-item> | ||||
|                                 </div> | ||||
|                             </el-collapse-item> | ||||
|                             <el-collapse-item :title="$t('财务配置')" name="2"> | ||||
|                                 <div style="margin: 1rem"> | ||||
|                                     <el-form-item :label="$t('人民币兑点数比率')" prop="cnyToPointRate"> | ||||
|                                         <el-input-number v-model="form.cnyToPointRate" :max="999999999" :min="1"></el-input-number> | ||||
|                                     </el-form-item> | ||||
|                                     <el-form-item :label="$t('美元兑点数比率')" prop="usdToPointRate"> | ||||
|                                         <el-input-number v-model="form.usdToPointRate" :max="999999999" :min="1"></el-input-number> | ||||
|                                     </el-form-item> | ||||
|                                     <el-form-item :label="$t('USDT 收款地址')" prop="trc20ReceiptAddress"> | ||||
|                                         <el-input v-model="form.trc20ReceiptAddress" maxlength="34" placeholder="placeholder"></el-input> | ||||
|                                     </el-form-item> | ||||
|                                 </div> | ||||
|                             </el-collapse-item> | ||||
|                         </el-collapse> | ||||
|  | ||||
|                         <el-form-item :label="$t('启用')" prop="enabled"> | ||||
| @@ -70,7 +83,7 @@ export default { | ||||
|                 userRegisterRoleId: [{ required: true, message: '请选择默认角色' }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增配置'), | ||||
|                 add: this.$t('新建配置'), | ||||
|                 edit: this.$t('编辑配置'), | ||||
|                 view: this.$t('查看配置'), | ||||
|             }, | ||||
|   | ||||
| @@ -81,7 +81,7 @@ export default { | ||||
|             }, | ||||
|             tabId: '0', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增部门'), | ||||
|                 add: this.$t('新建部门'), | ||||
|                 edit: this.$t('编辑部门'), | ||||
|                 view: this.$t('查看部门'), | ||||
|             }, | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|             <el-tabs tab-position="top"> | ||||
|                 <el-tab-pane :label="$t('基本信息')"> | ||||
|                     <el-form :disabled="mode === 'view'" :model="form" :rules="rules" label-width="10rem" ref="dialogForm"> | ||||
|                         <el-form-item :label="$t('所属字典目录')" prop="catalogId"> | ||||
|                         <el-form-item :label="$t('归属字典目录')" prop="catalogId"> | ||||
|                             <catalog-select v-model="form.catalogId" class="w100p" /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('项名')" prop="key"> | ||||
| @@ -49,12 +49,12 @@ export default { | ||||
|             mode: 'add', | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 catalogId: [{ required: true, message: '请选择所属字典目录' }], | ||||
|                 catalogId: [{ required: true, message: '请选择归属字典目录' }], | ||||
|                 key: [{ required: true, message: '请输入项名' }], | ||||
|                 value: [{ required: true, message: '请输入项值' }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增字典项'), | ||||
|                 add: this.$t('新建字典项'), | ||||
|                 edit: this.$t('编辑字典项'), | ||||
|                 view: this.$t('查看字典项'), | ||||
|             }, | ||||
|   | ||||
| @@ -35,7 +35,7 @@ export default { | ||||
|                 name: [{ required: true, message: '请输入字典目录名称' }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增字典目录'), | ||||
|                 add: this.$t('新建字典目录'), | ||||
|                 edit: this.$t('编辑字典目录'), | ||||
|             }, | ||||
|             visible: false, | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|             <el-tabs tab-position="top"> | ||||
|                 <el-tab-pane :label="$t('基本信息')"> | ||||
|                     <el-form :disabled="mode === 'view'" :model="form" :rules="rules" label-width="10rem" ref="dialogForm"> | ||||
|                         <el-form-item :label="$t('所属文档分类')" prop="catalogId"> | ||||
|                         <el-form-item :label="$t('归属文档分类')" prop="catalogId"> | ||||
|                             <catalog-select v-model="form.catalogId" class="w100p" /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('文档标题')" prop="title"> | ||||
| @@ -60,13 +60,13 @@ export default { | ||||
|             mode: 'add', | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 catalogId: [{ required: true, message: this.$t('请选择所属文档分类') }], | ||||
|                 catalogId: [{ required: true, message: this.$t('请选择归属文档分类') }], | ||||
|                 title: [{ required: true, message: this.$t('请输入文档标题') }], | ||||
|                 body: [{ required: true, message: this.$t('请输入文档内容') }], | ||||
|                 visibility: [{ required: true, message: this.$t('请选择档案可见性') }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增文档'), | ||||
|                 add: this.$t('新建文档'), | ||||
|                 edit: this.$t('编辑文档'), | ||||
|                 view: this.$t('查看文档'), | ||||
|             }, | ||||
|   | ||||
| @@ -35,7 +35,7 @@ export default { | ||||
|                 name: [{ required: true, message: '请输入文档分类名称' }], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增文档分类'), | ||||
|                 add: this.$t('新建文档分类'), | ||||
|                 edit: this.$t('编辑文档分类'), | ||||
|             }, | ||||
|             visible: false, | ||||
|   | ||||
| @@ -204,7 +204,7 @@ export default { | ||||
|             }, | ||||
|             tabId: '0', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增作业'), | ||||
|                 add: this.$t('新建作业'), | ||||
|                 edit: this.$t('编辑作业'), | ||||
|                 view: this.$t('查看作业'), | ||||
|             }, | ||||
|   | ||||
| @@ -133,7 +133,7 @@ export default { | ||||
|             //验证规则 | ||||
|             rules: {}, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增作业记录'), | ||||
|                 add: this.$t('新建作业记录'), | ||||
|                 edit: this.$t('编辑作业记录'), | ||||
|                 view: this.$t('查看作业记录'), | ||||
|             }, | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|         </el-col> | ||||
|         <template v-else> | ||||
|             <el-col> | ||||
|                 <h2>{{ form.meta.title || '新增菜单' }}</h2> | ||||
|                 <h2>{{ form.meta.title || '新建菜单' }}</h2> | ||||
|                 <el-form :model="form" :rules="rules" label-width="15rem" ref="dialogForm"> | ||||
|                     <el-form-item :label="$t('显示名称')" prop="meta.title"> | ||||
|                         <el-input v-model="form.meta.title" :placeholder="$t('菜单显示名字')" clearable></el-input> | ||||
|   | ||||
| @@ -117,7 +117,7 @@ export default { | ||||
|                 ], | ||||
|             }, | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增消息'), | ||||
|                 add: this.$t('新建消息'), | ||||
|                 edit: this.$t('编辑消息'), | ||||
|                 view: this.$t('查看消息'), | ||||
|             }, | ||||
|   | ||||
							
								
								
									
										351
									
								
								src/frontend/admin/src/views/sys/order/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								src/frontend/admin/src/views/sys/order/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,351 @@ | ||||
| <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"> | ||||
|                         <scStatistic :title="$t('总数')" :value="statistics.total" group-separator></scStatistic> | ||||
|                     </el-card> | ||||
|                 </el-col> | ||||
|             </el-row> | ||||
|         </el-header> | ||||
|         <el-header class="el-header-select-filter"> | ||||
|             <scSelectFilter | ||||
|                 :data="[ | ||||
|                     { | ||||
|                         title: $t('订单状态'), | ||||
|                         key: 'depositOrderStatus', | ||||
|                         options: [ | ||||
|                             { label: '全部', value: '' }, | ||||
|                             ...Object.entries(this.$GLOBAL.enums.depositOrderStatues).map((x) => { | ||||
|                                 return { | ||||
|                                     value: x[0], | ||||
|                                     label: x[1][1], | ||||
|                                     badge: this.statistics.depositOrderStatus?.find( | ||||
|                                         (y) => y.key.depositOrderStatus.toLowerCase() === x[0].toLowerCase(), | ||||
|                                     )?.value, | ||||
|                                 } | ||||
|                             }), | ||||
|                         ], | ||||
|                     }, | ||||
|                     { | ||||
|                         title: $t('支付方式'), | ||||
|                         key: 'paymentMode', | ||||
|                         options: [ | ||||
|                             { label: '全部', value: '' }, | ||||
|                             ...Object.entries(this.$GLOBAL.enums.paymentModes).map((x) => { | ||||
|                                 return { | ||||
|                                     value: x[0], | ||||
|                                     label: x[1][1], | ||||
|                                     badge: this.statistics.paymentMode?.find((y) => y.key.paymentMode.toLowerCase() === x[0].toLowerCase())?.value, | ||||
|                                 } | ||||
|                             }), | ||||
|                         ], | ||||
|                     }, | ||||
|                 ]" | ||||
|                 :label-width="15" | ||||
|                 @on-change="filterChange" | ||||
|                 ref="selectFilter"></scSelectFilter> | ||||
|         </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' }, | ||||
|                                     { label: $t('充值点数'), key: 'depositPoint' }, | ||||
|                                 ], | ||||
|                             ], | ||||
|                             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"> | ||||
|                 <el-button @click="this.dialog.save = { mode: 'add' }" icon="el-icon-plus" type="primary"></el-button> | ||||
|             </div> | ||||
|         </el-header> | ||||
|         <el-main class="nopadding"> | ||||
|             <scTable | ||||
|                 :context-menus="[ | ||||
|                     'id', | ||||
|                     'ownerId', | ||||
|                     'createdTime', | ||||
|                     'paymentMode', | ||||
|                     'amount', | ||||
|                     'depositPoint', | ||||
|                     'toPointRate', | ||||
|                     'owner.userName', | ||||
|                     'depositOrderStatus', | ||||
|                     'actualPayAmount', | ||||
|                 ]" | ||||
|                 :context-multi="{ id: ['createdTime'], ownerId: ['owner.userName'] }" | ||||
|                 :context-opers="['view']" | ||||
|                 :default-sort="{ prop: 'id', order: 'descending' }" | ||||
|                 :export-api="$API.sys_depositorder.export" | ||||
|                 :params="query" | ||||
|                 :query-api="$API.sys_depositorder.pagedQuery" | ||||
|                 :vue="this" | ||||
|                 @data-change="getStatistics" | ||||
|                 @selection-change=" | ||||
|                     (items) => { | ||||
|                         selection = items | ||||
|                     } | ||||
|                 " | ||||
|                 ref="table" | ||||
|                 remote-filter | ||||
|                 remote-sort | ||||
|                 row-key="id" | ||||
|                 stripe> | ||||
|                 <naColId :label="$t('订单编号')" prop="id" sortable="custom" width="170" /> | ||||
|                 <naColUser | ||||
|                     :clickOpenDialog="$GLOBAL.hasApiPermission('api/sys/user/get')" | ||||
|                     :label="$t('归属用户')" | ||||
|                     header-align="center" | ||||
|                     nestProp="owner.userName" | ||||
|                     nestProp2="ownerId" | ||||
|                     prop="ownerId" | ||||
|                     sortable="custom" | ||||
|                     width="170"></naColUser> | ||||
|                 <naColIndicator | ||||
|                     :label="$t('订单状态')" | ||||
|                     :options=" | ||||
|                         Object.entries(this.$GLOBAL.enums.depositOrderStatues).map((x) => { | ||||
|                             return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' } | ||||
|                         }) | ||||
|                     " | ||||
|                     align="center" | ||||
|                     prop="depositOrderStatus" | ||||
|                     sortable="custom" /> | ||||
|                 <el-table-column | ||||
|                     :formatter="(row) => $TOOL.groupSeparator(row.depositPoint)" | ||||
|                     :label="$t('充值点数')" | ||||
|                     align="right" | ||||
|                     prop="depositPoint" | ||||
|                     sortable="custom" /> | ||||
|                 <el-table-column | ||||
|                     :formatter="(row) => $TOOL.groupSeparator(row.toPointRate)" | ||||
|                     :label="$t('兑换比率')" | ||||
|                     align="right" | ||||
|                     prop="toPointRate" | ||||
|                     sortable="custom" /> | ||||
|                 <el-table-column | ||||
|                     :formatter="(row) => $TOOL.groupSeparator(row.actualPayAmount / 1000)" | ||||
|                     :label="$t('支付金额')" | ||||
|                     align="right" | ||||
|                     prop="actualPayAmount" | ||||
|                     sortable="custom" /> | ||||
|                 <naColIndicator | ||||
|                     :label="$t('支付方式')" | ||||
|                     :options=" | ||||
|                         Object.entries(this.$GLOBAL.enums.paymentModes).map((x) => { | ||||
|                             return { value: x[0], text: `${x[1][1]}`, type: x[1][2], pulse: x[1][3] === 'true' } | ||||
|                         }) | ||||
|                     " | ||||
|                     align="center" | ||||
|                     prop="paymentMode" | ||||
|                     sortable="custom" /> | ||||
|                 <naColOperation | ||||
|                     :buttons="[ | ||||
|                         naColOperation.buttons[0], | ||||
|                         { | ||||
|                             icon: 'el-icon-credit-card', | ||||
|                             title: '支付', | ||||
|                             click: async (row, vue) => { | ||||
|                                 vue.dialog.save = { row, mode: 'pay' } | ||||
|                             }, | ||||
|                             condition: (row) => { | ||||
|                                 return row.depositOrderStatus === 'waitingForPayment' | ||||
|                             }, | ||||
|                         }, | ||||
|                     ]" | ||||
|                     :vue="this" | ||||
|                     width="120" /> | ||||
|             </scTable> | ||||
|         </el-main> | ||||
|     </el-container> | ||||
|  | ||||
|     <save-dialog | ||||
|         v-if="dialog.save" | ||||
|         @closed="dialog.save = null" | ||||
|         @mounted="$refs.saveDialog.open(dialog.save)" | ||||
|         @success="(data, mode) => table.handleUpdate($refs.table, data, mode)" | ||||
|         ref="saveDialog"></save-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { defineAsyncComponent } from 'vue' | ||||
| import table from '@/config/table' | ||||
| import naColOperation from '@/config/naColOperation' | ||||
| const naColUser = defineAsyncComponent(() => import('@/components/naColUser')) | ||||
| const saveDialog = defineAsyncComponent(() => import('./save.vue')) | ||||
| 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_depositorder.countBy.post({ | ||||
|                     dynamicFilter: { | ||||
|                         filters: this.query.dynamicFilter.filters, | ||||
|                     }, | ||||
|                     requiredFields: ['PaymentMode'], | ||||
|                 }), | ||||
|                 this.$API.sys_depositorder.countBy.post({ | ||||
|                     dynamicFilter: { | ||||
|                         filters: this.query.dynamicFilter.filters, | ||||
|                     }, | ||||
|                     requiredFields: ['DepositOrderStatus'], | ||||
|                 }), | ||||
|             ]) | ||||
|             this.statistics.paymentMode = res[0].data | ||||
|             this.statistics.depositOrderStatus = 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['paymentMode'] === 'string' && form.dy['paymentMode'].trim() !== '') { | ||||
|                 this.query.dynamicFilter.filters.push({ | ||||
|                     field: 'paymentMode', | ||||
|                     operator: 'eq', | ||||
|                     value: form.dy['paymentMode'], | ||||
|                 }) | ||||
|             } | ||||
|  | ||||
|             if (typeof form.dy['depositOrderStatus'] === 'string' && form.dy['depositOrderStatus'].trim() !== '') { | ||||
|                 this.query.dynamicFilter.filters.push({ | ||||
|                     field: 'depositOrderStatus', | ||||
|                     operator: 'eq', | ||||
|                     value: form.dy['depositOrderStatus'], | ||||
|                 }) | ||||
|             } | ||||
|  | ||||
|             if (typeof form.dy['depositPoint'] === 'string' && form.dy['depositPoint'].trim() !== '') { | ||||
|                 this.query.dynamicFilter.filters.push({ | ||||
|                     field: 'depositPoint', | ||||
|                     operator: 'eq', | ||||
|                     value: form.dy['depositPoint'], | ||||
|                 }) | ||||
|             } | ||||
|             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></style> | ||||
							
								
								
									
										197
									
								
								src/frontend/admin/src/views/sys/order/save.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								src/frontend/admin/src/views/sys/order/save.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <template> | ||||
|     <scDialog v-model="visible" :title="`${titleMap[mode]}:${form?.id ?? '...'}`" @closed="$emit('closed')" destroy-on-close> | ||||
|         <div v-loading="loading"> | ||||
|             <el-tabs v-model="tabId" @tab-change="tabChange" tab-position="top"> | ||||
|                 <el-tab-pane :label="$t('基本信息')" name="basic"> | ||||
|                     <el-form :disabled="mode === 'view' || mode === 'pay'" :model="form" :rules="rules" label-width="15rem" ref="dialogForm"> | ||||
|                         <el-form-item v-if="mode !== 'add'" :label="$t('订单编号')" prop="id"> | ||||
|                             <el-input v-model="form.id" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item v-if="mode !== 'add'" :label="$t('订单状态')" prop="depositOrderStatus"> | ||||
|                             <el-select v-model="form.depositOrderStatus" filterable> | ||||
|                                 <el-option v-for="(item, i) in $GLOBAL.enums.depositOrderStatues" :key="i" :label="item[1]" :value="i" /> | ||||
|                             </el-select> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('充值点数')" prop="depositPoint"> | ||||
|                             <el-input-number | ||||
|                                 :max="999999999" | ||||
|                                 :min="100" | ||||
|                                 :model-value="form.depositPoint" | ||||
|                                 :step="100" | ||||
|                                 @input=" | ||||
|                                     (e) => { | ||||
|                                         if (e < 0) e = 0 | ||||
|                                         if (e % 10 === 0) { | ||||
|                                             e += Math.floor(Math.random() * 9) + 1 | ||||
|                                         } | ||||
|                                         if (e < 100) { | ||||
|                                             e += 100 | ||||
|                                         } | ||||
|  | ||||
|                                         this.form.depositPoint = e | ||||
|                                     } | ||||
|                                 " | ||||
|                                 clearable | ||||
|                                 style="width: 15rem" /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('支付方式')" prop="paymentMode"> | ||||
|                             <el-select v-model="form.paymentMode" filterable> | ||||
|                                 <el-option v-for="(item, i) in $GLOBAL.enums.paymentModes" :key="i" :label="item[1]" :value="i" /> | ||||
|                             </el-select> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('货币兑点数比率')" prop="toPointRate"> | ||||
|                             <el-input :model-value="form.toPointRate ? `1:${form.toPointRate}` : ''" disabled /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('支付货币金额')" prop="actualPayAmount"> | ||||
|                             <el-input :model-value="form.actualPayAmount ? form.actualPayAmount / 1000 : ''" disabled /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item v-if="mode === 'pay'" :label="$t('收款账号')" prop="receiptAccount"> | ||||
|                             <el-input v-model="form.receiptAccount" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item v-if="mode === 'pay'" :label="$t('收款二维码')"> | ||||
|                             <div v-html="form.receiptAccountQrCode"></div> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item v-if="mode !== 'add'" :label="$t('创建时间')" prop="createdTime"> | ||||
|                             <el-input v-model="form.createdTime" clearable /> | ||||
|                         </el-form-item> | ||||
|                     </el-form> | ||||
|                 </el-tab-pane> | ||||
|                 <el-tab-pane v-if="mode === 'view'" :label="$t('原始数据')"> | ||||
|                     <JsonViewer | ||||
|                         :expand-depth="5" | ||||
|                         :theme="this.$TOOL.data.get('APP_SET_DARK') || this.$CONFIG.APP_SET_DARK ? 'dark' : 'light'" | ||||
|                         :value="form" | ||||
|                         copyable | ||||
|                         expanded | ||||
|                         sort></JsonViewer> | ||||
|                 </el-tab-pane> | ||||
|             </el-tabs> | ||||
|         </div> | ||||
|         <template #footer> | ||||
|             <el-button @click="visible = false">{{ $t('取消') }}</el-button> | ||||
|             <el-button v-if="mode === 'add'" :disabled="loading" :loading="loading" @click="submit" type="primary">{{ $t('提交订单') }}</el-button> | ||||
|             <el-button | ||||
|                 v-if="mode === 'pay'" | ||||
|                 :disabled="loading" | ||||
|                 :loading="loading" | ||||
|                 @click=" | ||||
|                     async () => { | ||||
|                         this.loading = true | ||||
|                         try { | ||||
|                             const res = await this.$API.sys_depositorder.payConfirm.post(this.form) | ||||
|                             this.$emit('success', res.data, this.mode) | ||||
|                             this.visible = false | ||||
|                             this.$message.success(this.$t('操作成功')) | ||||
|                         } catch {} | ||||
|                         this.loading = false | ||||
|                     } | ||||
|                 " | ||||
|                 type="danger" | ||||
|                 >{{ $t('确认已支付') }}</el-button | ||||
|             > | ||||
|         </template> | ||||
|     </scDialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import QRCode from 'qrcode-svg' | ||||
|  | ||||
| export default { | ||||
|     computed: {}, | ||||
|     components: {}, | ||||
|  | ||||
|     watch: { | ||||
|         'form.paymentMode': { | ||||
|             immediate: true, | ||||
|             handler(n, o) { | ||||
|                 if (n === 'alipay' || n === 'weChat') { | ||||
|                     this.form.toPointRate = this.config?.cnyToPointRate | ||||
|                 } else if (n === 'usdt') { | ||||
|                     this.form.toPointRate = this.config?.usdToPointRate | ||||
|                 } else { | ||||
|                     delete this.form.toPointRate | ||||
|                 } | ||||
|                 if (this.form.toPointRate && this.form.depositPoint) { | ||||
|                     this.form.actualPayAmount = (this.form.depositPoint / this.form.toPointRate).toFixed(3) * 1000 | ||||
|                 } else { | ||||
|                     delete this.form.actualPayAmount | ||||
|                 } | ||||
|             }, | ||||
|         }, | ||||
|         'form.depositPoint': { | ||||
|             immediate: true, | ||||
|             handler(n, o) { | ||||
|                 if (this.form.toPointRate) { | ||||
|                     this.form.actualPayAmount = (n / this.form.toPointRate).toFixed(3) * 1000 | ||||
|                 } | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             config: null, | ||||
|             //表单数据 | ||||
|             form: {}, | ||||
|             loading: true, | ||||
|             mode: 'add', | ||||
|             //验证规则 | ||||
|             rules: { | ||||
|                 depositPoint: [{ required: true, message: this.$t('请输入充值点数') }], | ||||
|                 paymentMode: [{ required: true, message: this.$t('请选择支付方式') }], | ||||
|             }, | ||||
|             tabId: 'basic', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新建充值订单'), | ||||
|                 view: this.$t('查看充值订单'), | ||||
|                 pay: this.$t('支付充值订单'), | ||||
|             }, | ||||
|             visible: false, | ||||
|         } | ||||
|     }, | ||||
|     emits: ['success', 'closed', 'mounted'], | ||||
|     methods: { | ||||
|         //显示 | ||||
|         async open(data) { | ||||
|             this.visible = true | ||||
|             this.config = (await this.$API.sys_depositorder.getDepositConfig.post({})).data | ||||
|             if (data.mode === 'add') { | ||||
|                 this.loading = false | ||||
|                 return this | ||||
|             } | ||||
|             this.loading = true | ||||
|             this.mode = data.mode | ||||
|             if (data.row?.id) { | ||||
|                 const res = await this.$API.sys_depositorder.get.post({ id: data.row.id }) | ||||
|                 if (res.data) { | ||||
|                     Object.assign(this.form, res.data) | ||||
|                     this.form.receiptAccountQrCode = new QRCode(this.form.receiptAccount).svg() | ||||
|                     this.loading = false | ||||
|                     return this | ||||
|                 } | ||||
|             } | ||||
|             this.$message.error(`未找到该数据`) | ||||
|             return this | ||||
|         }, | ||||
|         //表单提交方法 | ||||
|         async submit() { | ||||
|             const valid = await this.$refs.dialogForm.validate().catch(() => {}) | ||||
|             if (!valid) { | ||||
|                 return false | ||||
|             } | ||||
|             this.loading = true | ||||
|             try { | ||||
|                 const res = await this.$API.sys_depositorder.create.post(this.form) | ||||
|                 this.$emit('success', res.data, this.mode) | ||||
|                 this.visible = false | ||||
|                 this.$message.success(this.$t('操作成功')) | ||||
|             } catch {} | ||||
|             this.loading = false | ||||
|         }, | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.$emit('mounted') | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped></style> | ||||
| @@ -134,7 +134,7 @@ export default { | ||||
|             }, | ||||
|             tabId: '0', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增角色'), | ||||
|                 add: this.$t('新建角色'), | ||||
|                 edit: this.$t('编辑角色'), | ||||
|                 view: this.$t('查看角色'), | ||||
|             }, | ||||
|   | ||||
| @@ -109,7 +109,7 @@ | ||||
|                 <naColId :label="$t('交易编号')" prop="id" sortable="custom" width="170" /> | ||||
|                 <naColUser | ||||
|                     :clickOpenDialog="$GLOBAL.hasApiPermission('api/sys/user/get')" | ||||
|                     :label="$t('所属用户')" | ||||
|                     :label="$t('归属用户')" | ||||
|                     header-align="center" | ||||
|                     nestProp="owner.userName" | ||||
|                     nestProp2="ownerId" | ||||
|   | ||||
| @@ -22,16 +22,16 @@ | ||||
|                         <el-form-item :label="$t('交易后余额')"> | ||||
|                             <el-input :value="form.balanceBefore + form.amount" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('所有者部门编号')" prop="ownerDeptId"> | ||||
|                         <el-form-item :label="$t('归属部门编号')" prop="ownerDeptId"> | ||||
|                             <el-input v-model="form.ownerDeptId" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('所有者用户编号')" prop="ownerId"> | ||||
|                         <el-form-item :label="$t('归属用户编号')" prop="ownerId"> | ||||
|                             <el-input v-model="form.ownerId" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('创建者用户编号')" prop="createdUserId"> | ||||
|                             <el-input v-model="form.createdUserId" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('所有者用户名')" prop="createdUserName"> | ||||
|                         <el-form-item :label="$t('归属用户名')" prop="createdUserName"> | ||||
|                             <el-input v-model="form.createdUserName" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('创建时间')" prop="createdTime"> | ||||
| @@ -70,7 +70,7 @@ export default { | ||||
|             rules: {}, | ||||
|             tabId: 'basic', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增交易'), | ||||
|                 add: this.$t('新建交易'), | ||||
|                 edit: this.$t('编辑交易'), | ||||
|                 view: this.$t('查看交易'), | ||||
|             }, | ||||
|   | ||||
| @@ -41,7 +41,7 @@ | ||||
|                             field: ['filter', 'roleId'], | ||||
|                             api: $API.sys_role.query, | ||||
|                             config: { props: { label: 'name', value: 'id' } }, | ||||
|                             placeholder: $t('所属角色'), | ||||
|                             placeholder: $t('归属角色'), | ||||
|                             style: 'width:15rem', | ||||
|                         }, | ||||
|                     ]" | ||||
| @@ -121,13 +121,13 @@ | ||||
|                             </template> | ||||
|                         </el-table-column> | ||||
|                         <naColTags | ||||
|                             :label="$t('所属部门')" | ||||
|                             :label="$t('归属部门')" | ||||
|                             @click="(item) => (this.dialog.deptSave = { row: item, mode: 'view' })" | ||||
|                             field="name" | ||||
|                             prop="dept" | ||||
|                             width="120" /> | ||||
|                         <naColTags | ||||
|                             :label="$t('所属角色')" | ||||
|                             :label="$t('归属角色')" | ||||
|                             @click="(item) => (this.dialog.roleSave = { row: item, mode: 'view' })" | ||||
|                             field="name" | ||||
|                             min-width="200" | ||||
|   | ||||
| @@ -50,7 +50,7 @@ | ||||
|                         </div> | ||||
|                     </el-form-item> | ||||
|  | ||||
|                     <el-form-item :label="$t('所属角色')" prop="roleIds"> | ||||
|                     <el-form-item :label="$t('归属角色')" prop="roleIds"> | ||||
|                         <scSelect | ||||
|                             v-if="!this.loading" | ||||
|                             v-model="form.roleIds" | ||||
| @@ -61,7 +61,7 @@ | ||||
|                             filterable | ||||
|                             multiple /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item :label="$t('所属部门')" prop="deptId"> | ||||
|                     <el-form-item :label="$t('归属部门')" prop="deptId"> | ||||
|                         <naDept v-model="form.deptId" class="w100p"></naDept> | ||||
|                     </el-form-item> | ||||
|  | ||||
| @@ -315,18 +315,18 @@ export default { | ||||
|                         pattern: this.$GLOBAL.chars.RGX_PASSWORD, | ||||
|                     }, | ||||
|                 ], | ||||
|                 deptId: [{ required: true, message: '请选择所属部门' }], | ||||
|                 deptId: [{ required: true, message: '请选择归属部门' }], | ||||
|                 roleIds: [ | ||||
|                     { | ||||
|                         required: true, | ||||
|                         message: '请选择所属角色', | ||||
|                         message: '请选择归属角色', | ||||
|                         trigger: 'change', | ||||
|                     }, | ||||
|                 ], | ||||
|             }, | ||||
|             tabId: '0', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增用户'), | ||||
|                 add: this.$t('新建用户'), | ||||
|                 edit: this.$t('编辑用户'), | ||||
|                 view: this.$t('查看用户'), | ||||
|             }, | ||||
|   | ||||
| @@ -33,7 +33,7 @@ | ||||
|                             field: ['filter', 'deptId'], | ||||
|                             api: $API.sys_dept.query, | ||||
|                             config: { props: { label: 'name', value: 'id' } }, | ||||
|                             placeholder: $t('所属部门'), | ||||
|                             placeholder: $t('归属部门'), | ||||
|                             style: 'width:15rem', | ||||
|                             condition: () => $GLOBAL.hasApiPermission('api/sys/dept/query'), | ||||
|                         }, | ||||
| @@ -42,7 +42,7 @@ | ||||
|                             field: ['filter', 'roleId'], | ||||
|                             api: $API.sys_role.query, | ||||
|                             config: { props: { label: 'name', value: 'id' } }, | ||||
|                             placeholder: $t('所属角色'), | ||||
|                             placeholder: $t('归属角色'), | ||||
|                             style: 'width:15rem', | ||||
|                             condition: () => $GLOBAL.hasApiPermission('api/sys/dept/query'), | ||||
|                         }, | ||||
| @@ -92,7 +92,7 @@ | ||||
|                 <naColId :label="$t('钱包编号')" prop="id" sortable="custom" width="170" /> | ||||
|                 <naColUser | ||||
|                     :clickOpenDialog="$GLOBAL.hasApiPermission('api/sys/user/get')" | ||||
|                     :label="$t('所属用户')" | ||||
|                     :label="$t('归属用户')" | ||||
|                     nestProp="owner.userName" | ||||
|                     nestProp2="ownerId" | ||||
|                     prop="ownerId" | ||||
|   | ||||
| @@ -22,10 +22,10 @@ | ||||
|                         <el-form-item :label="$t('总支出')" prop="totalExpenditure"> | ||||
|                             <el-input v-model="form.totalExpenditure" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('所有者部门编号')" prop="ownerDeptId"> | ||||
|                         <el-form-item :label="$t('归属部门编号')" prop="ownerDeptId"> | ||||
|                             <el-input v-model="form.ownerDeptId" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('所有者用户编号')" prop="ownerId"> | ||||
|                         <el-form-item :label="$t('归属用户编号')" prop="ownerId"> | ||||
|                             <el-input v-model="form.ownerId" clearable /> | ||||
|                         </el-form-item> | ||||
|                         <el-form-item :label="$t('创建时间')" prop="createdTime"> | ||||
| @@ -75,7 +75,7 @@ export default { | ||||
|             rules: {}, | ||||
|             tabId: 'basic', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增钱包'), | ||||
|                 add: this.$t('新建钱包'), | ||||
|                 edit: this.$t('编辑钱包'), | ||||
|                 view: this.$t('查看钱包'), | ||||
|             }, | ||||
|   | ||||
| @@ -48,7 +48,7 @@ export default { | ||||
|             }, | ||||
|             tabId: '0', | ||||
|             titleMap: { | ||||
|                 add: this.$t('新增用户'), | ||||
|                 add: this.$t('新建用户'), | ||||
|                 edit: this.$t('编辑用户'), | ||||
|                 view: this.$t('查看用户'), | ||||
|             }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user