feat: 框架代码同步 (#346)

[skip ci]

Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
2025-09-30 15:16:58 +08:00
committed by GitHub
parent c8896896ed
commit 03d4b54e77
35 changed files with 220 additions and 100 deletions

View File

@@ -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

View File

@@ -106,6 +106,7 @@ USDT
本部门和下一级部门数据
本部门和所有子部门数据
本部门数据
来自
框架
比较数据库结构
注册
@@ -153,6 +154,7 @@ USDT
请求日志导出
调试
身份证
转给
转账支出
转账收入
运行

View File

@@ -144,10 +144,14 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
#endif
#pragma warning disable S2326
// ReSharper disable UnusedTypeParameter
// ReSharper disable UnusedParameter.Local
private static Task<IActionResult> GetExportFileStreamAsync<TExport>(
string fileName
, object list
) {
// ReSharper restore UnusedParameter.Local
// ReSharper restore UnusedTypeParameter
#pragma warning restore S2326
throw new NotImplementedException();

View File

@@ -7,9 +7,6 @@ namespace NetAdmin.Domain.Dto.Sys.DepositOrder;
/// </summary>
public record CreateDepositOrderReq : Sys_DepositOrder
{
/// <inheritdoc cref="Sys_DepositOrder.ActualPayAmount" />
public override long ActualPayAmount { get; init; }
/// <inheritdoc cref="Sys_DepositOrder.DepositOrderStatus" />
public override DepositOrderStatues DepositOrderStatus { get; init; } = DepositOrderStatues.WaitingForPayment;

View File

@@ -6,7 +6,7 @@
<ItemGroup>
<PackageReference Include="CronExpressionDescriptor" Version="2.44.0"/>
<PackageReference Include="Cronos" Version="0.11.1"/>
<PackageReference Include="ExcelMapper" Version="6.0.611"/>
<PackageReference Include="ExcelMapper" Version="6.0.612"/>
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14"/>
</ItemGroup>
<ItemGroup>

View File

@@ -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}$""";

View File

@@ -1,11 +1,10 @@
#pragma warning disable RCS1194
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
/// NetAdmin异常基类
/// </summary>
#pragma warning disable RCS1194
public abstract class NetAdminException(string message, Exception innerException) : Exception(message, innerException)
#pragma warning restore RCS1194
{
/// <summary>
/// Initializes a new instance of the <see cref="NetAdminException" /> class.

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 外部接口调用未得到预期的结果
/// </remarks>
#pragma warning disable RCS1194
public sealed class NetAdminExternalErrorException(string message, Exception innerException = null)
#pragma warning restore RCS1194
: NetAdminException(ErrorCodes.ExternalError, message, innerException)
{
}
: NetAdminException(ErrorCodes.ExternalError, message, innerException);

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,8 +7,4 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 并发执行时锁竞争失败
/// </remarks>
#pragma warning disable RCS1194
public sealed class NetAdminGetLockerException(string message = null) : NetAdminInvalidOperationException(message)
{
}
#pragma warning restore RCS1194
public sealed class NetAdminGetLockerException(string message = null) : NetAdminInvalidOperationException(message);

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194, DesignedForInheritance
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 参数格式错误、内容校验错误等
/// </remarks>
#pragma warning disable DesignedForInheritance, RCS1194
public class NetAdminInvalidInputException(string message = null, Exception innerException = null)
#pragma warning restore RCS1194, DesignedForInheritance
: NetAdminException(ErrorCodes.InvalidInput, message, innerException)
{
}
: NetAdminException(ErrorCodes.InvalidInput, message, innerException);

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194, DesignedForInheritance
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,9 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 非正常的业务流程或逻辑
/// </remarks>
#pragma warning disable DesignedForInheritance, RCS1194
public class NetAdminInvalidOperationException(string message, Exception innerException = null)
#pragma warning restore RCS1194, DesignedForInheritance
: NetAdminException(ErrorCodes.InvalidOperation, message, innerException)
{
}
: NetAdminException(ErrorCodes.InvalidOperation, message, innerException);

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,7 +7,5 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 运行结果是非预期的,例如事务失败回滚
/// </remarks>
#pragma warning disable RCS1194
public sealed class NetAdminUnexpectedException(string message, Exception innerException = null)
#pragma warning restore RCS1194
: NetAdminException(ErrorCodes.Unexpected, message, innerException);

View File

@@ -1,3 +1,4 @@
#pragma warning disable RCS1194
namespace NetAdmin.Infrastructure.Exceptions;
/// <summary>
@@ -6,10 +7,7 @@ namespace NetAdmin.Infrastructure.Exceptions;
/// <remarks>
/// 手动调用模型验证方法抛出
/// </remarks>
#pragma warning disable RCS1194
public sealed class NetAdminValidateException(Dictionary<string, string[]> validateResults)
#pragma warning restore RCS1194
: NetAdminInvalidInputException
public sealed class NetAdminValidateException(Dictionary<string, string[]> validateResults) : NetAdminInvalidInputException
{
/// <summary>
/// 验证结果

View File

@@ -6,7 +6,7 @@
<PackageReference Include="NetAdmin.FreeSql.DbContext" Version="1.1.8" Label="refs"/>
<PackageReference Include="NetAdmin.FreeSql.Provider.Sqlite" Version="1.1.8" Label="refs"/>
<PackageReference Include="Gurion" Version="1.2.17" Label="refs"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.8"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.9"/>
<PackageReference Include="Minio" Version="6.0.5"/>
<PackageReference Include="NSExt" Version="2.3.8"/>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7"/>

View File

@@ -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

View File

@@ -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<CreateWalletTradeReq, QueryWal
, DelReq // 删除类型
>
{
/// <summary>
/// 获取自助充值条形图数据
/// </summary>
Task<IEnumerable<GetBarChartRsp>> GetSelfDepositBarChartAsync(QueryReq<QueryWalletTradeReq> req);
/// <summary>
/// 消费总数计数
/// </summary>
Task<long> TotalAmountAsync(QueryReq<QueryWalletTradeReq> req);
/// <summary>
/// 从他人账户转账给自己
/// </summary>

View File

@@ -10,6 +10,6 @@ public interface IUserInviteService : IService, IUserInviteModule
/// </summary>
Task<List<long>> GetAssociatedUserIdAsync(
long userId
, bool up = true
, bool up = true
);
}

View File

@@ -94,8 +94,7 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
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<Sys_DepositOrder, long>
/// <inheritdoc />
public async Task<int> ReceivedConfirmationAsync(JobReq req) {
req.ThrowIfInvalid();
// 初始化返回值
var ret = 0;
// 获取最新配置信息
var config = await S<IConfigService>().GetLatestConfigAsync().ConfigureAwait(false);
// 查询所有状态为“待确认”的充值订单
var waitConfirmList = (await QueryAsync(
new QueryReq<QueryDepositOrderReq>
{
@@ -239,59 +244,36 @@ public sealed class DepositOrderService(BasicRepository<Sys_DepositOrder, long>
}
)
.ConfigureAwait(false)).ToList();
// 调用 TronScan API 获取指定地址的代币转账记录
var apiResult = await S<ITronScanClient>()
.TransfersAsync(S<IOptions<TronScanOptions>>().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<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
, 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<Sys_DepositOrder, long>
return QueryInternal(req with { Order = Orders.None }).WithNoLockNoWait().SumAsync(req.GetSumExp<Sys_DepositOrder>());
}
/// <summary>
/// 将指定订单标记为成功,并创建对应的钱包交易记录。
/// </summary>
/// <param name="order">本地待处理的订单信息。</param>
/// <param name="apiItem">来自链上的交易信息。</param>
/// <exception cref="NetAdminUnexpectedException">当发生未预期的网络管理异常时抛出此异常</exception>
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<IWalletTradeService>()
.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<Sys_DepositOrder> QueryInternal(QueryReq<QueryDepositOrderReq> req) {
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereIf(req.Filter?.Id > 0, a => a.Id == req.Filter.Id);

View File

@@ -20,6 +20,7 @@ public sealed class UserWalletService(BasicRepository<Sys_UserWallet, long> 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

View File

@@ -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<Sys_WalletTrade, long> 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<QueryWalletTradeRsp>();
}
@@ -172,6 +173,27 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> rp
return ret.Adapt<QueryWalletTradeRsp>();
}
/// <inheritdoc />
public async Task<IEnumerable<GetBarChartRsp>> GetSelfDepositBarChartAsync(QueryReq<QueryWalletTradeReq> 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);
}
/// <inheritdoc />
public async Task<PagedQueryRsp<QueryWalletTradeRsp>> PagedQueryAsync(PagedQueryReq<QueryWalletTradeReq> req) {
req.ThrowIfInvalid();
@@ -208,6 +230,13 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> rp
.ConfigureAwait(false);
}
/// <inheritdoc />
public Task<long> TotalAmountAsync(QueryReq<QueryWalletTradeReq> 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)));
}
/// <inheritdoc />
public async Task<int> TransferFromAnotherAccountAsync(TransferReq req) {
// 检查源账户是不是自己的下级
@@ -230,7 +259,7 @@ public sealed class WalletTradeService(BasicRepository<Sys_WalletTrade, long> 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<Sys_WalletTrade, long> 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<Sys_WalletTrade, long> 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<Sys_WalletTrade, long> 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
}

View File

@@ -15,7 +15,7 @@ public sealed class RequestLogCache(IDistributedCache cache, IRequestLogService
/// <inheritdoc />
#if !DEBUG
public async Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
#else
#else
public Task<long> CountAsync(QueryReq<QueryRequestLogReq> req)
#endif
{

View File

@@ -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);
}
/// <inheritdoc />
public Task<IEnumerable<GetBarChartRsp>> GetSelfDepositBarChartAsync(QueryReq<QueryWalletTradeReq> req) {
return Service.GetSelfDepositBarChartAsync(req);
}
/// <inheritdoc />
public Task<PagedQueryRsp<QueryWalletTradeRsp>> PagedQueryAsync(PagedQueryReq<QueryWalletTradeReq> req) {
return Service.PagedQueryAsync(req);
@@ -61,6 +67,11 @@ public sealed class WalletTradeCache(IDistributedCache cache, IWalletTradeServic
return Service.SumAsync(req);
}
/// <inheritdoc />
public Task<long> TotalAmountAsync(QueryReq<QueryWalletTradeReq> req) {
return Service.TotalAmountAsync(req);
}
/// <inheritdoc />
public Task<int> TransferFromAnotherAccountAsync(TransferReq req) {
return Service.TransferFromAnotherAccountAsync(req);

View File

@@ -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);
}
/// <summary>
/// 获取自助充值条形图数据
/// </summary>
public Task<IEnumerable<GetBarChartRsp>> GetSelfDepositBarChartAsync(QueryReq<QueryWalletTradeReq> req) {
return Cache.GetSelfDepositBarChartAsync(req);
}
/// <summary>
/// 分页查询钱包交易
/// </summary>
@@ -92,6 +100,13 @@ public sealed class WalletTradeController(IWalletTradeCache cache) : ControllerB
return Cache.SumAsync(req);
}
/// <summary>
/// 消费总数计数
/// </summary>
public Task<long> TotalAmountAsync(QueryReq<QueryWalletTradeReq> req) {
return Cache.TotalAmountAsync(req);
}
/// <summary>
/// 从他人账户转账给自己
/// </summary>

View File

@@ -3,7 +3,7 @@
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.8"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.9"/>
<PackageReference Include="xunit" Version="2.9.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -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%",

View File

@@ -0,0 +1,9 @@
<template>
<svg height="256" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
<path d="M436.8 212.8m-22.4 0a22.4 22.4 0 1 0 44.8 0 22.4 22.4 0 1 0-44.8 0Z" />
<path d="M572.8 212.8m-22.4 0a22.4 22.4 0 1 0 44.8 0 22.4 22.4 0 1 0-44.8 0Z" />
<path
d="M872 304c-11.2 0-22.4 1.6-32 4.8l-8-25.6c-19.2-57.6-51.2-107.2-94.4-145.6l57.6-62.4c14.4-16 14.4-41.6-1.6-56-16-14.4-41.6-14.4-56 1.6L672 91.2c-46.4-24-99.2-38.4-153.6-38.4-57.6 0-112 14.4-160 41.6L288 20.8c-14.4-16-40-17.6-56-1.6-16 14.4-17.6 40-1.6 56l62.4 67.2c-40 38.4-72 86.4-89.6 142.4l-9.6 28.8c-12.8-4.8-27.2-8-41.6-8C94.4 304 48 350.4 48 408v161.6C48 625.6 94.4 672 152 672h1.6c27.2 0 52.8-11.2 72-28.8v110.4c0 20.8 12.8 38.4 32 43.2v107.2c0 57.6 46.4 104 104 104h1.6c57.6 0 104-46.4 104-104V800h96v104c0 57.6 46.4 104 104 104h1.6c57.6 0 104-46.4 104-104V800h1.6c25.6 0 46.4-20.8 46.4-46.4V656c16 9.6 35.2 16 56 16h1.6c57.6 0 104-46.4 104-104v-160c-6.4-57.6-52.8-104-110.4-104z m-140.8-48H302.4c43.2-75.2 124.8-121.6 214.4-121.6 89.6 0 169.6 46.4 214.4 121.6zM176 568c0 12.8-11.2 24-24 24S128 580.8 128 568v-160c0-12.8 11.2-24 24-24s24 11.2 24 24v160z m208 336c0 12.8-11.2 24-24 24h-1.6c-12.8 0-24-11.2-24-24V800h48v104zM464 720H304V336h432v384H464z m224 184c0 12.8-11.2 24-24 24h-1.6c-12.8 0-24-11.2-24-24V800h48v104z m208-336c0 12.8-11.2 24-24 24h-1.6c-12.8 0-24-11.2-24-24v-160c0-12.8 11.2-24 24-24s24 11.2 24 24v160z" />
</svg>
</template>
<script lang="ts" setup></script>

View File

@@ -0,0 +1,6 @@
<template>
<svg height="256" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
<path
d="M704 106.666667a210.346667 210.346667 0 0 1-59.733333 132.266666A209.706667 209.706667 0 0 1 512 298.666667a204.8 204.8 0 0 1 192-192z m-45.226667 277.333333a131.626667 131.626667 0 0 0-69.333333 20.053333 138.88 138.88 0 0 1-146.56 0 130.986667 130.986667 0 0 0-69.333333-20.053333h-7.04c-69.12 3.626667-131.84 85.333333-131.84 170.666667 0 90.026667 30.08 160 100.693333 234.666666 40.96 42.666667 46.506667 42.666667 58.453333 42.666667a50.133333 50.133333 0 0 0 18.56-3.413333 290.773333 290.773333 0 0 1 207.786667 0 48.426667 48.426667 0 0 0 18.346667 3.413333c11.946667 0 17.493333 0 58.88-42.666667A395.946667 395.946667 0 0 0 768 689.493333 215.466667 215.466667 0 0 1 675.413333 512a217.6 217.6 0 0 1 33.493334-115.626667 106.666667 106.666667 0 0 0-42.666667-12.16h-7.253333m0-85.333333h11.733333A214.613333 214.613333 0 0 1 832 395.733333 128 128 0 0 0 760.746667 512 125.653333 125.653333 0 0 0 874.666667 640a422.613333 422.613333 0 0 1-115.626667 208.213333c-42.666667 44.586667-69.76 69.546667-120.533333 69.546667a139.093333 139.093333 0 0 1-49.066667-8.96 203.52 203.52 0 0 0-146.56 0 138.24 138.24 0 0 1-49.066667 8.96c-50.56 0-77.866667-24.96-120.32-69.546667C196.906667 768 149.333333 677.546667 149.333333 554.666667s92.373333-249.386667 213.333334-256h11.52a215.68 215.68 0 0 1 114.56 33.066666 53.76 53.76 0 0 0 56.106666 0A215.68 215.68 0 0 1 658.773333 298.666667z" />
</svg>
</template>

View File

@@ -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'
export { default as deposit } from './deposit.vue'
export { default as apple } from './apple.vue'
export { default as android } from './android.vue'

View File

@@ -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">
<el-date-picker
v-bind="item.detail?.props"
v-if="i.endsWith(`Time`)"
v-if="i.endsWith(`Time`) && !item.detail?.is"
v-model="form[i]"
:disabled="item.disabled?.includes(mode)"
type="datetime"
@@ -76,6 +77,7 @@
v-model:value3="form[item.detail.vModel[2]]"
v-model:value4="form[item.detail.vModel[3]]"
v-model:value5="form[item.detail.vModel[4]]"
v-model:value6="form[item.detail.vModel[5]]"
:disabled="item.disabled?.includes(mode)"
:is="item.detail.is" />
</template>
@@ -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 },
},
}

View File

@@ -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: {},
}

File diff suppressed because one or more lines are too long

View File

@@ -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%;
}

View File

@@ -3,7 +3,7 @@
<div class="widgets-content">
<div class="widgets" ref="widgets">
<div class="widgets-wrapper">
<div v-if="nowCompsList.length <= 0" class="no-widgets">
<div v-if="nowCompsList?.length <= 0" class="no-widgets">
<el-empty :description="$t('没有部件啦')" :image-size="280" />
</div>
<el-row :gutter="15">
@@ -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)
})
},

View File

@@ -31,7 +31,7 @@
<script>
import { defineAsyncComponent } from 'vue'
const scPasswordStrength = defineAsyncComponent(() => import('@/components/sc-password-strength'))
const naFormPassword = defineAsyncComponent(() => import('@/config/na-form-password'))
import naFormPassword from '@/config/na-form-password'
export default {
components: {

View File

@@ -65,7 +65,7 @@
isSwitch: { onChange: `setSelfDepositAllowed` },
},
'user.enabled': {
label: $t(`启用`),
label: $t(`账号已启用`),
width: 120,
align: `center`,
show: [`list`],