From 03d4b54e77fe90fefd456f0684ca3f2b52c7f9d2 Mon Sep 17 00:00:00 2001 From: nsnail Date: Tue, 30 Sep 2025 15:16:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=E6=A1=86=E6=9E=B6=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=90=8C=E6=AD=A5=20(#346)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] Co-authored-by: tk --- Dockerfile | 2 +- assets/res/NetAdmin.Fields.ln | 2 + .../Services/RepositoryService.cs | 4 + .../Sys/DepositOrder/CreateDepositOrderReq.cs | 3 - .../NetAdmin.Domain/NetAdmin.Domain.csproj | 2 +- .../NetAdmin.Infrastructure/Constant/Chars.cs | 2 +- .../Exceptions/NetAdminException.cs | 3 +- .../NetAdminExternalErrorException.cs | 7 +- .../Exceptions/NetAdminGetLockerException.cs | 7 +- .../NetAdminInvalidInputException.cs | 7 +- .../NetAdminInvalidOperationException.cs | 7 +- .../Exceptions/NetAdminUnexpectedException.cs | 3 +- .../Exceptions/NetAdminValidateException.cs | 6 +- .../NetAdmin.Infrastructure.csproj | 2 +- .../Utils/FreeSqlBuilder.cs | 4 +- .../Modules/Sys/IWalletTradeModule.cs | 11 ++ .../Sys/Dependency/IUserInviteService.cs | 2 +- .../Services/Sys/DepositOrderService.cs | 105 +++++++++++------- .../Services/Sys/UserWalletService.cs | 1 + .../Services/Sys/WalletTradeService.cs | 39 ++++++- .../Sys/RequestLogCache.cs | 2 +- .../Sys/WalletTradeCache.cs | 11 ++ .../Controllers/Sys/WalletTradeController.cs | 15 +++ .../NetAdmin.Tests/NetAdmin.Tests.csproj | 2 +- src/frontend/admin/package.json | 20 ++-- .../admin/src/assets/icon/android.vue | 9 ++ src/frontend/admin/src/assets/icon/apple.vue | 6 + src/frontend/admin/src/assets/icon/index.js | 4 +- .../src/components/na-table-page/detail.vue | 5 +- .../src/components/na-table-page/index.vue | 1 + src/frontend/admin/src/config/icon-select.js | 2 +- src/frontend/admin/src/style/app.scss | 16 +++ .../admin/src/views/home/widgets/index.vue | 4 +- .../views/profile/account/set-password.vue | 2 +- .../src/views/sys/market/invite/index.vue | 2 +- 35 files changed, 220 insertions(+), 100 deletions(-) create mode 100644 src/frontend/admin/src/assets/icon/android.vue create mode 100644 src/frontend/admin/src/assets/icon/apple.vue diff --git a/Dockerfile b/Dockerfile index d1d1dece..d3df1166 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:9.0.8 AS base +FROM mcr.microsoft.com/dotnet/aspnet:9.0.9 AS base WORKDIR /app EXPOSE 8080 RUN apt update diff --git a/assets/res/NetAdmin.Fields.ln b/assets/res/NetAdmin.Fields.ln index 78c9445f..a2740e95 100644 --- a/assets/res/NetAdmin.Fields.ln +++ b/assets/res/NetAdmin.Fields.ln @@ -106,6 +106,7 @@ USDT 本部门和下一级部门数据 本部门和所有子部门数据 本部门数据 +来自 框架 比较数据库结构 注册 @@ -153,6 +154,7 @@ USDT 请求日志导出 调试 身份证 +转给 转账支出 转账收入 运行 diff --git a/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs b/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs index 7a8c92c8..25808d7f 100644 --- a/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs +++ b/src/backend/NetAdmin/NetAdmin.Application/Services/RepositoryService.cs @@ -144,10 +144,14 @@ public abstract class RepositoryService(BasicReposit #endif #pragma warning disable S2326 + // ReSharper disable UnusedTypeParameter + // ReSharper disable UnusedParameter.Local private static Task GetExportFileStreamAsync( string fileName , object list ) { + // ReSharper restore UnusedParameter.Local + // ReSharper restore UnusedTypeParameter #pragma warning restore S2326 throw new NotImplementedException(); diff --git a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs index 9af08d20..5fbf741d 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs +++ b/src/backend/NetAdmin/NetAdmin.Domain/Dto/Sys/DepositOrder/CreateDepositOrderReq.cs @@ -7,9 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.DepositOrder; /// public record CreateDepositOrderReq : Sys_DepositOrder { - /// - public override long ActualPayAmount { get; init; } - /// public override DepositOrderStatues DepositOrderStatus { get; init; } = DepositOrderStatues.WaitingForPayment; diff --git a/src/backend/NetAdmin/NetAdmin.Domain/NetAdmin.Domain.csproj b/src/backend/NetAdmin/NetAdmin.Domain/NetAdmin.Domain.csproj index b0727c65..5cc311f2 100644 --- a/src/backend/NetAdmin/NetAdmin.Domain/NetAdmin.Domain.csproj +++ b/src/backend/NetAdmin/NetAdmin.Domain/NetAdmin.Domain.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs index d53a3b6c..03df6572 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Constant/Chars.cs @@ -110,7 +110,7 @@ public static class Chars public const string RGX_PAY_PASSWORD = """^\d{6}$"""; public const string RGX_TELEPHONE = """^((\d{3,4}\-)|)\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$"""; public const string RGX_UP_AND_LOWER_NUMBER = """^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"""; - public const string RGX_URL = """^https?://[\x00-\x1F\x21-\x7F]+$"""; + public const string RGX_URL = """^https?://[\x21-\x7E]+$"""; public const string RGX_USERNAME = """^[\u4e00-\u9fa5a-zA-Z0-9_-]{2,16}$"""; public const string RGX_VERIFY_CODE = """^\d{4}$"""; diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminException.cs index af922e68..b54ca1ce 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminException.cs @@ -1,11 +1,10 @@ +#pragma warning disable RCS1194 namespace NetAdmin.Infrastructure.Exceptions; /// /// NetAdmin异常基类 /// -#pragma warning disable RCS1194 public abstract class NetAdminException(string message, Exception innerException) : Exception(message, innerException) -#pragma warning restore RCS1194 { /// /// Initializes a new instance of the class. diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminExternalErrorException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminExternalErrorException.cs index 997c534f..f1ea37fe 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminExternalErrorException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminExternalErrorException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194 namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 外部接口调用未得到预期的结果 /// -#pragma warning disable RCS1194 public sealed class NetAdminExternalErrorException(string message, Exception innerException = null) - #pragma warning restore RCS1194 - : NetAdminException(ErrorCodes.ExternalError, message, innerException) -{ -} \ No newline at end of file + : NetAdminException(ErrorCodes.ExternalError, message, innerException); \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminGetLockerException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminGetLockerException.cs index 0e9f4f71..d0d6a013 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminGetLockerException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminGetLockerException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194 namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,8 +7,4 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 并发执行时锁竞争失败 /// -#pragma warning disable RCS1194 -public sealed class NetAdminGetLockerException(string message = null) : NetAdminInvalidOperationException(message) -{ -} -#pragma warning restore RCS1194 \ No newline at end of file +public sealed class NetAdminGetLockerException(string message = null) : NetAdminInvalidOperationException(message); \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidInputException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidInputException.cs index 2830ad52..bb9ea33e 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidInputException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidInputException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194, DesignedForInheritance namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 参数格式错误、内容校验错误等 /// -#pragma warning disable DesignedForInheritance, RCS1194 public class NetAdminInvalidInputException(string message = null, Exception innerException = null) - #pragma warning restore RCS1194, DesignedForInheritance - : NetAdminException(ErrorCodes.InvalidInput, message, innerException) -{ -} \ No newline at end of file + : NetAdminException(ErrorCodes.InvalidInput, message, innerException); \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidOperationException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidOperationException.cs index 87840412..4ef84e98 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidOperationException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminInvalidOperationException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194, DesignedForInheritance namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 非正常的业务流程或逻辑 /// -#pragma warning disable DesignedForInheritance, RCS1194 public class NetAdminInvalidOperationException(string message, Exception innerException = null) - #pragma warning restore RCS1194, DesignedForInheritance - : NetAdminException(ErrorCodes.InvalidOperation, message, innerException) -{ -} \ No newline at end of file + : NetAdminException(ErrorCodes.InvalidOperation, message, innerException); \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminUnexpectedException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminUnexpectedException.cs index 72830a6e..dcfd8ad8 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminUnexpectedException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminUnexpectedException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194 namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,7 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 运行结果是非预期的,例如事务失败回滚 /// -#pragma warning disable RCS1194 public sealed class NetAdminUnexpectedException(string message, Exception innerException = null) - #pragma warning restore RCS1194 : NetAdminException(ErrorCodes.Unexpected, message, innerException); \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs index 79260bd5..78c89424 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Exceptions/NetAdminValidateException.cs @@ -1,3 +1,4 @@ +#pragma warning disable RCS1194 namespace NetAdmin.Infrastructure.Exceptions; /// @@ -6,10 +7,7 @@ namespace NetAdmin.Infrastructure.Exceptions; /// /// 手动调用模型验证方法抛出 /// -#pragma warning disable RCS1194 -public sealed class NetAdminValidateException(Dictionary validateResults) - #pragma warning restore RCS1194 - : NetAdminInvalidInputException +public sealed class NetAdminValidateException(Dictionary validateResults) : NetAdminInvalidInputException { /// /// 验证结果 diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj b/src/backend/NetAdmin/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj index 3ec0ecfa..d08f3ef2 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/NetAdmin.Infrastructure.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs b/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs index 9eaea114..1a77c5bf 100644 --- a/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs +++ b/src/backend/NetAdmin/NetAdmin.Infrastructure/Utils/FreeSqlBuilder.cs @@ -19,8 +19,8 @@ public sealed class FreeSqlBuilder(DatabaseOptions databaseOptions) ) { var freeSql = new FreeSql.FreeSqlBuilder() #if DBTYPE_SQLSERVER - .UseConnectionFactory(databaseOptions.DbType, () => new SqlConnection(databaseOptions.ConnStr)) - .UseAdoConnectionPool(true) + .UseConnectionFactory(databaseOptions.DbType, () => new SqlConnection(databaseOptions.ConnStr)) + .UseAdoConnectionPool(true) #else .UseConnectionString(databaseOptions.DbType, databaseOptions.ConnStr) #endif diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IWalletTradeModule.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IWalletTradeModule.cs index 4d2bab43..f9a612f0 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IWalletTradeModule.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Modules/Sys/IWalletTradeModule.cs @@ -1,3 +1,4 @@ +using NetAdmin.Domain.Dto.Sys; using NetAdmin.Domain.Dto.Sys.WalletTrade; namespace NetAdmin.SysComponent.Application.Modules.Sys; @@ -11,6 +12,16 @@ public interface IWalletTradeModule : ICrudModule { + /// + /// 获取自助充值条形图数据 + /// + Task> GetSelfDepositBarChartAsync(QueryReq req); + + /// + /// 消费总数计数 + /// + Task TotalAmountAsync(QueryReq req); + /// /// 从他人账户转账给自己 /// diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserInviteService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserInviteService.cs index 303288d1..6029e704 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserInviteService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/Dependency/IUserInviteService.cs @@ -10,6 +10,6 @@ public interface IUserInviteService : IService, IUserInviteModule /// Task> GetAssociatedUserIdAsync( long userId - , bool up = true + , bool up = true ); } \ No newline at end of file diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs index 4557a60f..39e961d2 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/DepositOrderService.cs @@ -94,8 +94,7 @@ public sealed class DepositOrderService(BasicRepository var toPointRate = req.PaymentMode switch { PaymentModes.USDT => config.UsdToPointRate - , PaymentModes.Alipay => config.CnyToPointRate - , PaymentModes.WeChat => config.CnyToPointRate + , PaymentModes.Alipay or PaymentModes.WeChat => config.CnyToPointRate , _ => throw new ArgumentOutOfRangeException(nameof(req)) }; @@ -221,8 +220,14 @@ public sealed class DepositOrderService(BasicRepository /// public async Task ReceivedConfirmationAsync(JobReq req) { req.ThrowIfInvalid(); + + // 初始化返回值 var ret = 0; + + // 获取最新配置信息 var config = await S().GetLatestConfigAsync().ConfigureAwait(false); + + // 查询所有状态为“待确认”的充值订单 var waitConfirmList = (await QueryAsync( new QueryReq { @@ -239,59 +244,36 @@ public sealed class DepositOrderService(BasicRepository } ) .ConfigureAwait(false)).ToList(); + + // 调用 TronScan API 获取指定地址的代币转账记录 var apiResult = await S() .TransfersAsync(S>().Value.Token, req.Count!.Value, config.Trc20ReceiptAddress) .ConfigureAwait(false); + + // 如果没有获取到交易数据,则直接返回 0 + if (apiResult.TokenTransfers == null) { + return ret; + } + + // 遍历所有已确认且成功的 USDT 交易 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() - .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() - .CreateAsync( - new CreateWalletTradeReq - { - Amount = order.DepositPoint - , BusinessOrderNumber = order.Id - , TradeDirection = TradeDirections.Income - , TradeType = TradeTypes.SelfDeposit - , OwnerId = order.OwnerId - , OwnerDeptId = order.OwnerDeptId - } - ) - .ConfigureAwait(false) - ?? throw new NetAdminUnexpectedException(Ln.结果非预期); - } - ) + .AtomicOperateAsync(async () => await OrderSuccessAsync(order, apiItem).ConfigureAwait(false)) .ConfigureAwait(false); ret++; } catch { - // ignore + // 忽略异常,防止中断整个流程 } } @@ -304,6 +286,53 @@ public sealed class DepositOrderService(BasicRepository return QueryInternal(req with { Order = Orders.None }).WithNoLockNoWait().SumAsync(req.GetSumExp()); } + /// + /// 将指定订单标记为成功,并创建对应的钱包交易记录。 + /// + /// 本地待处理的订单信息。 + /// 来自链上的交易信息。 + /// 当发生未预期的网络管理异常时抛出此异常 + private async Task OrderSuccessAsync( + QueryDepositOrderRsp order + , TokenTransferInfo apiItem + ) { + // 更新订单状态为成功,并填充支付相关信息 + 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); + + // 如果更新失败(影响行数不为1),抛出异常 + if (updated != 1) { + throw new NetAdminUnexpectedException(Ln.结果非预期); + } + + // 创建钱包交易记录 + _ = await S() + .CreateAsync( + new CreateWalletTradeReq + { + Amount = order.DepositPoint + , BusinessOrderNumber = order.Id + , TradeDirection = TradeDirections.Income + , TradeType = TradeTypes.SelfDeposit + , OwnerId = order.OwnerId + , OwnerDeptId = order.OwnerDeptId + } + ) + .ConfigureAwait(false) + ?? throw new NetAdminUnexpectedException(Ln.结果非预期); + } + private ISelect QueryInternal(QueryReq req) { var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereIf(req.Filter?.Id > 0, a => a.Id == req.Filter.Id); diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserWalletService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserWalletService.cs index 4d5794fa..69b4fdbb 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserWalletService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/UserWalletService.cs @@ -20,6 +20,7 @@ public sealed class UserWalletService(BasicRepository rpo) , Owner = new Sys_User { Id = a.Owner.Id + , DeptId = a.Owner.DeptId , UserName = a.Owner.UserName , Avatar = a.Owner.Avatar , Roles = a.Owner.Roles diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/WalletTradeService.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/WalletTradeService.cs index 5c4c82bb..8741aad4 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/WalletTradeService.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Application/Services/Sys/WalletTradeService.cs @@ -2,6 +2,7 @@ using System.Net.Http.Headers; using Ganss.Excel; using NetAdmin.Application.Extensions; using NetAdmin.Domain.DbMaps.Sys; +using NetAdmin.Domain.Dto.Sys; using NetAdmin.Domain.Dto.Sys.User; using NetAdmin.Domain.Dto.Sys.UserInvite; using NetAdmin.Domain.Dto.Sys.UserWallet; @@ -99,7 +100,7 @@ public sealed class WalletTradeService(BasicRepository rp .ConfigureAwait(false) ?? throw new NetAdminUnexpectedException(Ln.交易失败); var ret = await Rpo - .InsertAsync(req with { BalanceBefore = wallet.AvailableBalance + wallet.FrozenBalance, OwnerDeptId = wallet.OwnerDeptId }) + .InsertAsync(req with { BalanceBefore = wallet.AvailableBalance + wallet.FrozenBalance, OwnerDeptId = wallet.Owner.DeptId }) .ConfigureAwait(false); return ret.Adapt(); } @@ -172,6 +173,27 @@ public sealed class WalletTradeService(BasicRepository rp return ret.Adapt(); } + /// + public async Task> GetSelfDepositBarChartAsync(QueryReq req) { + req.ThrowIfInvalid(); + var df = new DynamicFilterInfo + { + Field = nameof(Sys_WalletTrade.TradeType), Operator = DynamicFilterOperators.Eq, Value = TradeTypes.SelfDeposit + }; + var newdf = req.DynamicFilter.Add(df); + var ret = await QueryInternal(req with { Order = Orders.None, DynamicFilter = newdf }) + .WithNoLockNoWait() + .GroupBy(a => new { a.CreatedTime.Year, a.CreatedTime.Month, a.CreatedTime.Day, a.CreatedTime.Hour }) + .ToListAsync(a => new GetBarChartRsp + { + Timestamp = new DateTime(a.Key.Year, a.Key.Month, a.Key.Day, a.Key.Hour, 0, 0, DateTimeKind.Unspecified) + , Value = (int)Math.Floor(a.Sum(a.Value.Amount) / 100) + } + ) + .ConfigureAwait(false); + return ret.OrderBy(x => x.Timestamp); + } + /// public async Task> PagedQueryAsync(PagedQueryReq req) { req.ThrowIfInvalid(); @@ -208,6 +230,13 @@ public sealed class WalletTradeService(BasicRepository rp .ConfigureAwait(false); } + /// + public Task TotalAmountAsync(QueryReq req) { + req.ThrowIfInvalid(); + var total = QueryInternal(req with { Order = Orders.None }).WithNoLockNoWait().Sum(a => a.Amount) / 100; + return Task.FromResult((long)Math.Abs(Math.Floor(total))); + } + /// public async Task TransferFromAnotherAccountAsync(TransferReq req) { // 检查源账户是不是自己的下级 @@ -230,7 +259,7 @@ public sealed class WalletTradeService(BasicRepository rp OwnerDeptId = fromUser.DeptId , Amount = -req.Amount , OwnerId = fromUser.Id - , Summary = req.Summary + , Summary = $"{req.Summary} ({Ln.转给}: {UserToken.UserName}/{UserToken.Id})" , TradeDirection = TradeDirections.Expense , TradeType = TradeTypes.TransferExpense } @@ -242,7 +271,7 @@ public sealed class WalletTradeService(BasicRepository rp new CreateWalletTradeReq { Amount = req.Amount - , Summary = req.Summary + , Summary = $"{req.Summary} ({Ln.来自}: {fromUser.UserName}/{fromUser.Id})" , TradeDirection = TradeDirections.Income , TradeType = TradeTypes.TransferIncome , OwnerId = UserToken.Id @@ -267,7 +296,7 @@ public sealed class WalletTradeService(BasicRepository rp new CreateWalletTradeReq { Amount = -req.Amount - , Summary = req.Summary + , Summary = $"{req.Summary} ({Ln.转给}: {toUser.UserName}/{toUser.Id})" , TradeDirection = TradeDirections.Expense , TradeType = TradeTypes.TransferExpense , OwnerId = UserToken.Id @@ -283,7 +312,7 @@ public sealed class WalletTradeService(BasicRepository rp OwnerDeptId = toUser.DeptId , Amount = req.Amount , OwnerId = toUser.Id - , Summary = req.Summary + , Summary = $"{req.Summary} ({Ln.来自}: {UserToken.UserName}/{UserToken.Id})" , TradeDirection = TradeDirections.Income , TradeType = TradeTypes.TransferIncome } diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/RequestLogCache.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/RequestLogCache.cs index 2fdcfdc7..d9da5d7e 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/RequestLogCache.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/RequestLogCache.cs @@ -15,7 +15,7 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService /// #if !DEBUG public async Task CountAsync(QueryReq req) - #else + #else public Task CountAsync(QueryReq req) #endif { diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/WalletTradeCache.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/WalletTradeCache.cs index 68d56e05..894e12ab 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/WalletTradeCache.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Cache/Sys/WalletTradeCache.cs @@ -1,3 +1,4 @@ +using NetAdmin.Domain.Dto.Sys; using NetAdmin.Domain.Dto.Sys.WalletTrade; namespace NetAdmin.SysComponent.Cache.Sys; @@ -46,6 +47,11 @@ public sealed class WalletTradeCache(IDistributedCache cache, IWalletTradeServic return Service.GetAsync(req); } + /// + public Task> GetSelfDepositBarChartAsync(QueryReq req) { + return Service.GetSelfDepositBarChartAsync(req); + } + /// public Task> PagedQueryAsync(PagedQueryReq req) { return Service.PagedQueryAsync(req); @@ -61,6 +67,11 @@ public sealed class WalletTradeCache(IDistributedCache cache, IWalletTradeServic return Service.SumAsync(req); } + /// + public Task TotalAmountAsync(QueryReq req) { + return Service.TotalAmountAsync(req); + } + /// public Task TransferFromAnotherAccountAsync(TransferReq req) { return Service.TransferFromAnotherAccountAsync(req); diff --git a/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/WalletTradeController.cs b/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/WalletTradeController.cs index d100eeed..d668926b 100644 --- a/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/WalletTradeController.cs +++ b/src/backend/NetAdmin/NetAdmin.SysComponent.Host/Controllers/Sys/WalletTradeController.cs @@ -1,3 +1,4 @@ +using NetAdmin.Domain.Dto.Sys; using NetAdmin.Domain.Dto.Sys.WalletTrade; namespace NetAdmin.SysComponent.Host.Controllers.Sys; @@ -70,6 +71,13 @@ public sealed class WalletTradeController(IWalletTradeCache cache) : ControllerB return Cache.GetAsync(req); } + /// + /// 获取自助充值条形图数据 + /// + public Task> GetSelfDepositBarChartAsync(QueryReq req) { + return Cache.GetSelfDepositBarChartAsync(req); + } + /// /// 分页查询钱包交易 /// @@ -92,6 +100,13 @@ public sealed class WalletTradeController(IWalletTradeCache cache) : ControllerB return Cache.SumAsync(req); } + /// + /// 消费总数计数 + /// + public Task TotalAmountAsync(QueryReq req) { + return Cache.TotalAmountAsync(req); + } + /// /// 从他人账户转账给自己 /// diff --git a/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj b/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj index 06e17130..c33a802b 100644 --- a/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj +++ b/src/backend/NetAdmin/NetAdmin.Tests/NetAdmin.Tests.csproj @@ -3,7 +3,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/frontend/admin/package.json b/src/frontend/admin/package.json index c6a06efc..bd6abea3 100644 --- a/src/frontend/admin/package.json +++ b/src/frontend/admin/package.json @@ -10,13 +10,13 @@ }, "dependencies": { "@element-plus/icons-vue": "2.3.2", - "ace-builds": "1.43.2", - "aieditor": "1.4.0", - "axios": "1.11.0", + "ace-builds": "1.43.3", + "aieditor": "1.4.1", + "axios": "1.12.2", "crypto-js": "4.2.0", - "dayjs": "1.11.14", + "dayjs": "1.11.18", "echarts": "6.0.0", - "element-plus": "2.11.1", + "element-plus": "2.11.4", "json-bigint": "1.0.0", "markdown-it": "14.1.0", "markdown-it-emoji": "3.0.0", @@ -24,8 +24,8 @@ "qrcode-svg": "1.1.0", "sortablejs": "1.15.6", "vkbeautify": "0.99.3", - "vue": "3.5.20", - "vue-i18n": "11.1.11", + "vue": "3.5.22", + "vue-i18n": "11.1.12", "vue-router": "4.5.1", "vue3-ace-editor": "2.2.4", "vue3-json-viewer": "2.4.1", @@ -36,9 +36,9 @@ "@vitejs/plugin-vue": "6.0.1", "prettier": "3.6.2", "prettier-plugin-organize-attributes": "1.0.0", - "sass": "1.91.0", - "terser": "5.43.1", - "vite": "7.1.3" + "sass": "1.93.2", + "terser": "5.44.0", + "vite": "7.1.7" }, "browserslist": [ "> 1%", diff --git a/src/frontend/admin/src/assets/icon/android.vue b/src/frontend/admin/src/assets/icon/android.vue new file mode 100644 index 00000000..79297c35 --- /dev/null +++ b/src/frontend/admin/src/assets/icon/android.vue @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/src/frontend/admin/src/assets/icon/apple.vue b/src/frontend/admin/src/assets/icon/apple.vue new file mode 100644 index 00000000..22b4fd2d --- /dev/null +++ b/src/frontend/admin/src/assets/icon/apple.vue @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/src/frontend/admin/src/assets/icon/index.js b/src/frontend/admin/src/assets/icon/index.js index f4596060..793106e0 100644 --- a/src/frontend/admin/src/assets/icon/index.js +++ b/src/frontend/admin/src/assets/icon/index.js @@ -80,4 +80,6 @@ export { default as template } from './template.vue' export { default as order } from './order.vue' export { default as income } from './income.vue' export { default as transfer } from './transfer.vue' -export { default as deposit } from './deposit.vue' \ No newline at end of file +export { default as deposit } from './deposit.vue' +export { default as apple } from './apple.vue' +export { default as android } from './android.vue' \ No newline at end of file diff --git a/src/frontend/admin/src/components/na-table-page/detail.vue b/src/frontend/admin/src/components/na-table-page/detail.vue index 44983cd9..75604325 100644 --- a/src/frontend/admin/src/components/na-table-page/detail.vue +++ b/src/frontend/admin/src/components/na-table-page/detail.vue @@ -3,6 +3,7 @@ v-model="visible" :full-screen="dialogFullScreen.includes(mode)" :title="titleMap[mode]" + :width="dialogWidth" @closed="$emit(`closed`)" destroy-on-close ref="dialog"> @@ -25,7 +26,7 @@ :prop="i"> @@ -229,6 +231,7 @@ export default { dialogFullScreen: { type: Array }, tabs: { type: Array }, formInline: { type: Boolean }, + dialogWidth: { type: String, default: '50%' }, formLabelWidth: { type: Number, default: 12 }, }, } diff --git a/src/frontend/admin/src/components/na-table-page/index.vue b/src/frontend/admin/src/components/na-table-page/index.vue index dd31e7c3..88dbc05b 100644 --- a/src/frontend/admin/src/components/na-table-page/index.vue +++ b/src/frontend/admin/src/components/na-table-page/index.vue @@ -598,6 +598,7 @@ export default { showSelection: { type: Boolean, default: true }, showSearchMine: { type: Boolean, default: false }, totalCountLabel: { type: String, default: `总数` }, + dialogWidth: { type: String, default: '50%' }, }, watch: {}, } diff --git a/src/frontend/admin/src/config/icon-select.js b/src/frontend/admin/src/config/icon-select.js index dc1110da..4d1ffb3c 100644 --- a/src/frontend/admin/src/config/icon-select.js +++ b/src/frontend/admin/src/config/icon-select.js @@ -1 +1 @@ -export default{"icons":[{"icons":["el-icon-add-location","el-icon-aim","el-icon-alarm-clock","el-icon-apple","el-icon-arrow-down-bold","el-icon-arrow-down","el-icon-arrow-left-bold","el-icon-arrow-left","el-icon-arrow-right-bold","el-icon-arrow-right","el-icon-arrow-up-bold","el-icon-arrow-up","el-icon-avatar","el-icon-back","el-icon-baseball","el-icon-basketball","el-icon-bell-filled","el-icon-bell","el-icon-bicycle","el-icon-bottom-left","el-icon-bottom-right","el-icon-bottom","el-icon-bowl","el-icon-box","el-icon-briefcase","el-icon-brush-filled","el-icon-brush","el-icon-burger","el-icon-calendar","el-icon-camera-filled","el-icon-camera","el-icon-caret-bottom","el-icon-caret-left","el-icon-caret-right","el-icon-caret-top","el-icon-cellphone","el-icon-chat-dot-round","el-icon-chat-dot-square","el-icon-chat-line-round","el-icon-chat-line-square","el-icon-chat-round","el-icon-chat-square","el-icon-check","el-icon-checked","el-icon-cherry","el-icon-chicken","el-icon-circle-check-filled","el-icon-circle-check","el-icon-circle-close-filled","el-icon-circle-close","el-icon-circle-plus-filled","el-icon-circle-plus","el-icon-clock","el-icon-close-bold","el-icon-close","el-icon-cloudy","el-icon-coffee-cup","el-icon-coffee","el-icon-coin","el-icon-cold-drink","el-icon-collection-tag","el-icon-collection","el-icon-comment","el-icon-compass","el-icon-connection","el-icon-coordinate","el-icon-copy-document","el-icon-cpu","el-icon-credit-card","el-icon-crop","el-icon-d-arrow-left","el-icon-d-arrow-right","el-icon-d-caret","el-icon-data-analysis","el-icon-data-board","el-icon-data-line","el-icon-delete-filled","el-icon-delete-location","el-icon-delete","el-icon-dessert","el-icon-discount","el-icon-dish-dot","el-icon-dish","el-icon-document-add","el-icon-document-checked","el-icon-document-copy","el-icon-document-delete","el-icon-document-remove","el-icon-document","el-icon-download","el-icon-drizzling","el-icon-edit-pen","el-icon-edit","el-icon-eleme-filled","el-icon-eleme","el-icon-element-plus","el-icon-expand","el-icon-failed","el-icon-female","el-icon-files","el-icon-film","el-icon-filter","el-icon-finished","el-icon-first-aid-kit","el-icon-flag","el-icon-fold","el-icon-folder-add","el-icon-folder-checked","el-icon-folder-delete","el-icon-folder-opened","el-icon-folder-remove","el-icon-folder","el-icon-food","el-icon-football","el-icon-fork-spoon","el-icon-fries","el-icon-full-screen","el-icon-goblet-full","el-icon-goblet-square-full","el-icon-goblet-square","el-icon-goblet","el-icon-goods-filled","el-icon-goods","el-icon-grape","el-icon-grid","el-icon-guide","el-icon-headset","el-icon-help-filled","el-icon-help","el-icon-hide","el-icon-histogram","el-icon-home-filled","el-icon-hot-water","el-icon-house","el-icon-ice-cream-round","el-icon-ice-cream-square","el-icon-ice-cream","el-icon-ice-drink","el-icon-ice-tea","el-icon-info-filled","el-icon-iphone","el-icon-key","el-icon-knife-fork","el-icon-lightning","el-icon-link","el-icon-list","el-icon-loading","el-icon-location-filled","el-icon-location-information","el-icon-location","el-icon-lock","el-icon-lollipop","el-icon-magic-stick","el-icon-magnet","el-icon-male","el-icon-management","el-icon-map-location","el-icon-medal","el-icon-menu","el-icon-message-box","el-icon-message","el-icon-mic","el-icon-microphone","el-icon-milk-tea","el-icon-minus","el-icon-money","el-icon-monitor","el-icon-moon-night","el-icon-moon","el-icon-more-filled","el-icon-more","el-icon-mostly-cloudy","el-icon-mouse","el-icon-mug","el-icon-mute-notification","el-icon-mute","el-icon-no-smoking","el-icon-notebook","el-icon-notification","el-icon-odometer","el-icon-office-building","el-icon-open","el-icon-operation","el-icon-opportunity","el-icon-orange","el-icon-paperclip","el-icon-partly-cloudy","el-icon-pear","el-icon-phone-filled","el-icon-phone","el-icon-picture-filled","el-icon-picture-rounded","el-icon-picture","el-icon-pie-chart","el-icon-place","el-icon-platform","el-icon-plus","el-icon-pointer","el-icon-position","el-icon-postcard","el-icon-pouring","el-icon-present","el-icon-price-tag","el-icon-printer","el-icon-promotion","el-icon-question-filled","el-icon-rank","el-icon-reading-lamp","el-icon-reading","el-icon-refresh-left","el-icon-refresh-right","el-icon-refresh","el-icon-refrigerator","el-icon-remove-filled","el-icon-remove","el-icon-right","el-icon-scale-to-original","el-icon-school","el-icon-scissor","el-icon-search","el-icon-select","el-icon-sell","el-icon-semi-select","el-icon-service","el-icon-set-up","el-icon-setting","el-icon-share","el-icon-ship","el-icon-shop","el-icon-shopping-bag","el-icon-shopping-cart-full","el-icon-shopping-cart","el-icon-smoking","el-icon-soccer","el-icon-sold-out","el-icon-sort-down","el-icon-sort-up","el-icon-sort","el-icon-stamp","el-icon-star-filled","el-icon-star","el-icon-stopwatch","el-icon-success-filled","el-icon-sugar","el-icon-suitcase","el-icon-sunny","el-icon-sunrise","el-icon-sunset","el-icon-switch-button","el-icon-switch","el-icon-takeaway-box","el-icon-ticket","el-icon-tickets","el-icon-timer","el-icon-toilet-paper","el-icon-tools","el-icon-top-left","el-icon-top-right","el-icon-top","el-icon-trend-charts","el-icon-trophy","el-icon-turn-off","el-icon-umbrella","el-icon-unlock","el-icon-upload-filled","el-icon-upload","el-icon-user-filled","el-icon-user","el-icon-van","el-icon-video-camera-filled","el-icon-video-camera","el-icon-video-pause","el-icon-video-play","el-icon-view","el-icon-wallet-filled","el-icon-wallet","el-icon-warning-filled","el-icon-warning","el-icon-watch","el-icon-watermelon","el-icon-wind-power","el-icon-zoom-in","el-icon-zoom-out"],"name":"默认"},{"icons":["sc-icon-account-report","sc-icon-alert","sc-icon-api-doc","sc-icon-api","sc-icon-app","sc-icon-app2","sc-icon-archive","sc-icon-bug-fill","sc-icon-bug-line","sc-icon-business","sc-icon-code","sc-icon-code2","sc-icon-collect","sc-icon-country","sc-icon-csharp","sc-icon-daily","sc-icon-dashboard","sc-icon-demo","sc-icon-dept","sc-icon-device-log","sc-icon-device","sc-icon-dic","sc-icon-docker","sc-icon-download","sc-icon-drone","sc-icon-echarts","sc-icon-elastic","sc-icon-element","sc-icon-email","sc-icon-error","sc-icon-ex-log","sc-icon-exception","sc-icon-file-excel","sc-icon-file-ppt","sc-icon-file-word","sc-icon-free-sql","sc-icon-gitea","sc-icon-grafana","sc-icon-help","sc-icon-home","sc-icon-js","sc-icon-kafka","sc-icon-key","sc-icon-kibana","sc-icon-link","sc-icon-log","sc-icon-login-log","sc-icon-mail-code","sc-icon-memory","sc-icon-meter","sc-icon-mobile","sc-icon-nick-name","sc-icon-open-door","sc-icon-oper-log","sc-icon-organization","sc-icon-performance","sc-icon-position","sc-icon-product-category","sc-icon-product","sc-icon-proxy","sc-icon-report","sc-icon-resource","sc-icon-robot","sc-icon-role","sc-icon-scheduled-job","sc-icon-send","sc-icon-sms-code","sc-icon-stats","sc-icon-sync","sc-icon-task","sc-icon-telegram","sc-icon-tpl","sc-icon-unlink","sc-icon-upload","sc-icon-version","sc-icon-vue","sc-icon-warning","sc-icon-wechat","sc-icon-template","sc-icon-business","sc-icon-order","sc-icon-income","sc-icon-transfer","sc-icon-deposit"],"name":"扩展"}]} \ No newline at end of file +export default{"icons":[{"icons":["el-icon-add-location","el-icon-aim","el-icon-alarm-clock","el-icon-apple","el-icon-arrow-down-bold","el-icon-arrow-down","el-icon-arrow-left-bold","el-icon-arrow-left","el-icon-arrow-right-bold","el-icon-arrow-right","el-icon-arrow-up-bold","el-icon-arrow-up","el-icon-avatar","el-icon-back","el-icon-baseball","el-icon-basketball","el-icon-bell-filled","el-icon-bell","el-icon-bicycle","el-icon-bottom-left","el-icon-bottom-right","el-icon-bottom","el-icon-bowl","el-icon-box","el-icon-briefcase","el-icon-brush-filled","el-icon-brush","el-icon-burger","el-icon-calendar","el-icon-camera-filled","el-icon-camera","el-icon-caret-bottom","el-icon-caret-left","el-icon-caret-right","el-icon-caret-top","el-icon-cellphone","el-icon-chat-dot-round","el-icon-chat-dot-square","el-icon-chat-line-round","el-icon-chat-line-square","el-icon-chat-round","el-icon-chat-square","el-icon-check","el-icon-checked","el-icon-cherry","el-icon-chicken","el-icon-circle-check-filled","el-icon-circle-check","el-icon-circle-close-filled","el-icon-circle-close","el-icon-circle-plus-filled","el-icon-circle-plus","el-icon-clock","el-icon-close-bold","el-icon-close","el-icon-cloudy","el-icon-coffee-cup","el-icon-coffee","el-icon-coin","el-icon-cold-drink","el-icon-collection-tag","el-icon-collection","el-icon-comment","el-icon-compass","el-icon-connection","el-icon-coordinate","el-icon-copy-document","el-icon-cpu","el-icon-credit-card","el-icon-crop","el-icon-d-arrow-left","el-icon-d-arrow-right","el-icon-d-caret","el-icon-data-analysis","el-icon-data-board","el-icon-data-line","el-icon-delete-filled","el-icon-delete-location","el-icon-delete","el-icon-dessert","el-icon-discount","el-icon-dish-dot","el-icon-dish","el-icon-document-add","el-icon-document-checked","el-icon-document-copy","el-icon-document-delete","el-icon-document-remove","el-icon-document","el-icon-download","el-icon-drizzling","el-icon-edit-pen","el-icon-edit","el-icon-eleme-filled","el-icon-eleme","el-icon-element-plus","el-icon-expand","el-icon-failed","el-icon-female","el-icon-files","el-icon-film","el-icon-filter","el-icon-finished","el-icon-first-aid-kit","el-icon-flag","el-icon-fold","el-icon-folder-add","el-icon-folder-checked","el-icon-folder-delete","el-icon-folder-opened","el-icon-folder-remove","el-icon-folder","el-icon-food","el-icon-football","el-icon-fork-spoon","el-icon-fries","el-icon-full-screen","el-icon-goblet-full","el-icon-goblet-square-full","el-icon-goblet-square","el-icon-goblet","el-icon-goods-filled","el-icon-goods","el-icon-grape","el-icon-grid","el-icon-guide","el-icon-headset","el-icon-help-filled","el-icon-help","el-icon-hide","el-icon-histogram","el-icon-home-filled","el-icon-hot-water","el-icon-house","el-icon-ice-cream-round","el-icon-ice-cream-square","el-icon-ice-cream","el-icon-ice-drink","el-icon-ice-tea","el-icon-info-filled","el-icon-iphone","el-icon-key","el-icon-knife-fork","el-icon-lightning","el-icon-link","el-icon-list","el-icon-loading","el-icon-location-filled","el-icon-location-information","el-icon-location","el-icon-lock","el-icon-lollipop","el-icon-magic-stick","el-icon-magnet","el-icon-male","el-icon-management","el-icon-map-location","el-icon-medal","el-icon-menu","el-icon-message-box","el-icon-message","el-icon-mic","el-icon-microphone","el-icon-milk-tea","el-icon-minus","el-icon-money","el-icon-monitor","el-icon-moon-night","el-icon-moon","el-icon-more-filled","el-icon-more","el-icon-mostly-cloudy","el-icon-mouse","el-icon-mug","el-icon-mute-notification","el-icon-mute","el-icon-no-smoking","el-icon-notebook","el-icon-notification","el-icon-odometer","el-icon-office-building","el-icon-open","el-icon-operation","el-icon-opportunity","el-icon-orange","el-icon-paperclip","el-icon-partly-cloudy","el-icon-pear","el-icon-phone-filled","el-icon-phone","el-icon-picture-filled","el-icon-picture-rounded","el-icon-picture","el-icon-pie-chart","el-icon-place","el-icon-platform","el-icon-plus","el-icon-pointer","el-icon-position","el-icon-postcard","el-icon-pouring","el-icon-present","el-icon-price-tag","el-icon-printer","el-icon-promotion","el-icon-question-filled","el-icon-rank","el-icon-reading-lamp","el-icon-reading","el-icon-refresh-left","el-icon-refresh-right","el-icon-refresh","el-icon-refrigerator","el-icon-remove-filled","el-icon-remove","el-icon-right","el-icon-scale-to-original","el-icon-school","el-icon-scissor","el-icon-search","el-icon-select","el-icon-sell","el-icon-semi-select","el-icon-service","el-icon-set-up","el-icon-setting","el-icon-share","el-icon-ship","el-icon-shop","el-icon-shopping-bag","el-icon-shopping-cart-full","el-icon-shopping-cart","el-icon-smoking","el-icon-soccer","el-icon-sold-out","el-icon-sort-down","el-icon-sort-up","el-icon-sort","el-icon-stamp","el-icon-star-filled","el-icon-star","el-icon-stopwatch","el-icon-success-filled","el-icon-sugar","el-icon-suitcase","el-icon-sunny","el-icon-sunrise","el-icon-sunset","el-icon-switch-button","el-icon-switch","el-icon-takeaway-box","el-icon-ticket","el-icon-tickets","el-icon-timer","el-icon-toilet-paper","el-icon-tools","el-icon-top-left","el-icon-top-right","el-icon-top","el-icon-trend-charts","el-icon-trophy","el-icon-turn-off","el-icon-umbrella","el-icon-unlock","el-icon-upload-filled","el-icon-upload","el-icon-user-filled","el-icon-user","el-icon-van","el-icon-video-camera-filled","el-icon-video-camera","el-icon-video-pause","el-icon-video-play","el-icon-view","el-icon-wallet-filled","el-icon-wallet","el-icon-warning-filled","el-icon-warning","el-icon-watch","el-icon-watermelon","el-icon-wind-power","el-icon-zoom-in","el-icon-zoom-out"],"name":"默认"},{"icons":["sc-icon-account-report","sc-icon-alert","sc-icon-api-doc","sc-icon-api","sc-icon-app","sc-icon-app2","sc-icon-archive","sc-icon-bug-fill","sc-icon-bug-line","sc-icon-business","sc-icon-code","sc-icon-code2","sc-icon-collect","sc-icon-country","sc-icon-csharp","sc-icon-daily","sc-icon-dashboard","sc-icon-demo","sc-icon-dept","sc-icon-device-log","sc-icon-device","sc-icon-dic","sc-icon-docker","sc-icon-download","sc-icon-drone","sc-icon-echarts","sc-icon-elastic","sc-icon-element","sc-icon-email","sc-icon-error","sc-icon-ex-log","sc-icon-exception","sc-icon-file-excel","sc-icon-file-ppt","sc-icon-file-word","sc-icon-free-sql","sc-icon-gitea","sc-icon-grafana","sc-icon-help","sc-icon-home","sc-icon-js","sc-icon-kafka","sc-icon-key","sc-icon-kibana","sc-icon-link","sc-icon-log","sc-icon-login-log","sc-icon-mail-code","sc-icon-memory","sc-icon-meter","sc-icon-mobile","sc-icon-nick-name","sc-icon-open-door","sc-icon-oper-log","sc-icon-organization","sc-icon-performance","sc-icon-position","sc-icon-product-category","sc-icon-product","sc-icon-proxy","sc-icon-report","sc-icon-resource","sc-icon-robot","sc-icon-role","sc-icon-scheduled-job","sc-icon-send","sc-icon-sms-code","sc-icon-stats","sc-icon-sync","sc-icon-task","sc-icon-telegram","sc-icon-tpl","sc-icon-unlink","sc-icon-upload","sc-icon-version","sc-icon-vue","sc-icon-warning","sc-icon-wechat","sc-icon-template","sc-icon-business","sc-icon-order","sc-icon-income","sc-icon-transfer","sc-icon-deposit","sc-icon-apple","sc-icon-android"],"name":"扩展"}]} \ No newline at end of file diff --git a/src/frontend/admin/src/style/app.scss b/src/frontend/admin/src/style/app.scss index ca67c1ce..ddd43856 100644 --- a/src/frontend/admin/src/style/app.scss +++ b/src/frontend/admin/src/style/app.scss @@ -493,6 +493,14 @@ textarea { margin-top: 1rem; } +.ml-2 { + margin-left: 0.5rem; +} + +.ml-4 { + margin-left: 1rem; +} + .mr-2 { margin-right: 0.5rem; } @@ -504,9 +512,11 @@ textarea { .mt-8 { margin-top: 2rem; } + .mb-4 { margin-bottom: 1rem; } + .mb-8 { margin-bottom: 2rem; } @@ -646,7 +656,13 @@ textarea { margin-right: 0 !important; width: 50%; } + .el-form-item-w33p { margin-right: 0 !important; width: 33%; +} + +.el-form-item-w25p { + margin-right: 0 !important; + width: 25%; } \ No newline at end of file diff --git a/src/frontend/admin/src/views/home/widgets/index.vue b/src/frontend/admin/src/views/home/widgets/index.vue index 7496814c..50d41fe9 100644 --- a/src/frontend/admin/src/views/home/widgets/index.vue +++ b/src/frontend/admin/src/views/home/widgets/index.vue @@ -3,7 +3,7 @@
-
+
@@ -181,7 +181,7 @@ export default { return this.allCompsList.filter((item) => !item.disabled && !myGrid?.includes(item.key)) }, nowCompsList() { - return this.grid.compsList.reduce(function (a, b) { + return this.grid.compsList?.reduce(function (a, b) { return a.concat(b) }) }, diff --git a/src/frontend/admin/src/views/profile/account/set-password.vue b/src/frontend/admin/src/views/profile/account/set-password.vue index 59491773..29b36f3e 100644 --- a/src/frontend/admin/src/views/profile/account/set-password.vue +++ b/src/frontend/admin/src/views/profile/account/set-password.vue @@ -31,7 +31,7 @@