mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-06-19 18:28:17 +08:00
wip: 🧠 初步的框架
This commit is contained in:
69
src/backend/GlobalUsings.cs
Normal file
69
src/backend/GlobalUsings.cs
Normal file
@ -0,0 +1,69 @@
|
||||
// ReSharper disable RedundantUsingDirective.Global
|
||||
|
||||
global using System;
|
||||
global using System.Collections;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Collections.Immutable;
|
||||
global using System.ComponentModel;
|
||||
global using System.ComponentModel.DataAnnotations;
|
||||
global using System.Data;
|
||||
global using System.Diagnostics;
|
||||
global using System.Globalization;
|
||||
global using System.IO;
|
||||
global using System.Linq;
|
||||
global using System.Linq.Expressions;
|
||||
global using System.Net;
|
||||
global using System.Reflection;
|
||||
global using System.Text;
|
||||
global using System.Text.Encodings.Web;
|
||||
global using System.Text.Json;
|
||||
global using System.Text.Json.Serialization;
|
||||
global using System.Text.Json.Serialization.Metadata;
|
||||
global using System.Text.RegularExpressions;
|
||||
global using System.Threading.Tasks;
|
||||
global using FreeSql;
|
||||
global using FreeSql.Aop;
|
||||
global using FreeSql.DataAnnotations;
|
||||
global using FreeSql.Internal.Model;
|
||||
global using Furion;
|
||||
global using Furion.Authorization;
|
||||
global using Furion.ConfigurableOptions;
|
||||
global using Furion.DataEncryption;
|
||||
global using Furion.DataValidation;
|
||||
global using Furion.DependencyInjection;
|
||||
global using Furion.DynamicApiController;
|
||||
global using Furion.EventBus;
|
||||
global using Furion.SpecificationDocument;
|
||||
global using Furion.UnifyResult;
|
||||
global using Mapster;
|
||||
global using Microsoft.AspNetCore.Authorization;
|
||||
global using Microsoft.AspNetCore.Builder;
|
||||
global using Microsoft.AspNetCore.Diagnostics;
|
||||
global using Microsoft.AspNetCore.Http;
|
||||
global using Microsoft.AspNetCore.Mvc;
|
||||
global using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
global using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
global using Microsoft.AspNetCore.Mvc.Filters;
|
||||
global using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
global using Microsoft.Extensions.Caching.Distributed;
|
||||
global using Microsoft.Extensions.Caching.Memory;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
global using Microsoft.Extensions.Options;
|
||||
global using NetAdmin.Infrastructure;
|
||||
global using NetAdmin.Infrastructure.Attributes;
|
||||
global using NetAdmin.Infrastructure.Configuration.Options;
|
||||
global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Redis;
|
||||
global using NetAdmin.Infrastructure.Configuration.Options.SubNodes.Upload;
|
||||
global using NetAdmin.Infrastructure.Constant;
|
||||
global using NetAdmin.Infrastructure.Enums;
|
||||
global using NetAdmin.Infrastructure.Exceptions;
|
||||
global using NetAdmin.Infrastructure.Exceptions.InvalidInput;
|
||||
global using NetAdmin.Infrastructure.Exceptions.InvalidOperation;
|
||||
global using NetAdmin.Infrastructure.Exceptions.Unexpected;
|
||||
global using NetAdmin.Infrastructure.Extensions;
|
||||
global using NetAdmin.Infrastructure.Languages;
|
||||
global using NetAdmin.Infrastructure.Utils;
|
||||
global using NSExt.Attributes;
|
||||
global using NSExt.Extensions;
|
64
src/backend/NetAdmin.Application/Modules/ICrudModule.cs
Normal file
64
src/backend/NetAdmin.Application/Modules/ICrudModule.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using NetAdmin.Domain;
|
||||
using NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
namespace NetAdmin.Application.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// 增删改查模块接口
|
||||
/// </summary>
|
||||
/// <typeparam name="TCreateReq">创建请求类型</typeparam>
|
||||
/// <typeparam name="TCreateRsp">创建响应类型</typeparam>
|
||||
/// <typeparam name="TQueryReq">查询请求类型</typeparam>
|
||||
/// <typeparam name="TQueryRsp">查询响应类型</typeparam>
|
||||
/// <typeparam name="TUpdateReq">修改请求类型</typeparam>
|
||||
/// <typeparam name="TUpdateRsp">修改响应类型</typeparam>
|
||||
/// <typeparam name="TDelReq">删除请求类型</typeparam>
|
||||
public interface ICrudModule<in TCreateReq, TCreateRsp, TQueryReq, TQueryRsp, in TUpdateReq, TUpdateRsp, TDelReq>
|
||||
where TCreateReq : DataAbstraction, new()
|
||||
where TCreateRsp : DataAbstraction
|
||||
where TQueryReq : DataAbstraction, new()
|
||||
where TQueryRsp : DataAbstraction
|
||||
where TUpdateReq : DataAbstraction, new()
|
||||
where TUpdateRsp : DataAbstraction
|
||||
where TDelReq : DataAbstraction, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除实体
|
||||
/// </summary>
|
||||
Task<int> BulkDeleteAsync(BulkReq<TDelReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 创建实体
|
||||
/// </summary>
|
||||
Task<TCreateRsp> CreateAsync(TCreateReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 删除实体
|
||||
/// </summary>
|
||||
Task<int> DeleteAsync(TDelReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 判断实体是否存在
|
||||
/// </summary>
|
||||
Task<bool> ExistAsync(QueryReq<TQueryReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个实体
|
||||
/// </summary>
|
||||
Task<TQueryRsp> GetAsync(TQueryReq req);
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询实体
|
||||
/// </summary>
|
||||
Task<PagedQueryRsp<TQueryRsp>> PagedQueryAsync(PagedQueryReq<TQueryReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 查询实体
|
||||
/// </summary>
|
||||
Task<IEnumerable<TQueryRsp>> QueryAsync(QueryReq<TQueryReq> req);
|
||||
|
||||
/// <summary>
|
||||
/// 更新实体
|
||||
/// </summary>
|
||||
Task<TUpdateRsp> UpdateAsync(TUpdateReq req);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)/CodeQuality.props"/>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.Domain/NetAdmin.Domain.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
39
src/backend/NetAdmin.Application/Repositories/IRepository.cs
Normal file
39
src/backend/NetAdmin.Application/Repositories/IRepository.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Application.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 基础仓储接口
|
||||
/// </summary>
|
||||
public interface IRepository<TEntity> : IBaseRepository<TEntity>
|
||||
where TEntity : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前上下文关联的用户
|
||||
/// </summary>
|
||||
ContextUserToken UserToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 递归删除
|
||||
/// </summary>
|
||||
/// <param name="exp">exp</param>
|
||||
/// <param name="disableGlobalFilterNames">禁用全局过滤器名</param>
|
||||
Task<bool> DeleteRecursiveAsync(Expression<Func<TEntity, bool>> exp, params string[] disableGlobalFilterNames);
|
||||
|
||||
/// <summary>
|
||||
/// 获得Dto
|
||||
/// </summary>
|
||||
/// <param name="id">主键</param>
|
||||
Task<TDto> GetAsync<TDto>(long id);
|
||||
|
||||
/// <summary>
|
||||
/// 根据条件获取Dto
|
||||
/// </summary>
|
||||
Task<TDto> GetAsync<TDto>(Expression<Func<TEntity, bool>> exp);
|
||||
|
||||
/// <summary>
|
||||
/// 根据条件获取实体
|
||||
/// </summary>
|
||||
Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> exp);
|
||||
}
|
82
src/backend/NetAdmin.Application/Repositories/Repository.cs
Normal file
82
src/backend/NetAdmin.Application/Repositories/Repository.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Application.Repositories;
|
||||
|
||||
/// <inheritdoc cref="IRepository{TEntity}" />
|
||||
public sealed class Repository<TEntity> : DefaultRepository<TEntity, long>, IRepository<TEntity>
|
||||
where TEntity : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Repository{TEntity}" /> class.
|
||||
/// </summary>
|
||||
public Repository(IFreeSql fSql, UnitOfWorkManager uowManger, ContextUserToken userToken) //
|
||||
: base(fSql, uowManger)
|
||||
{
|
||||
UserToken = userToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前上下文关联的用户
|
||||
/// </summary>
|
||||
public ContextUserToken UserToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 递归删除
|
||||
/// </summary>
|
||||
/// <param name="exp">exp</param>
|
||||
/// <param name="disableGlobalFilterNames">禁用全局过滤器名</param>
|
||||
public async Task<bool> DeleteRecursiveAsync( //
|
||||
Expression<Func<TEntity, bool>> exp, params string[] disableGlobalFilterNames)
|
||||
{
|
||||
_ = await Select.Where(exp)
|
||||
.DisableGlobalFilter(disableGlobalFilterNames)
|
||||
.AsTreeCte()
|
||||
.ToDelete()
|
||||
.ExecuteAffrowsAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得Dto
|
||||
/// </summary>
|
||||
/// <param name="id">主键</param>
|
||||
public Task<TDto> GetAsync<TDto>(long id)
|
||||
{
|
||||
return Select.WhereDynamic(id).ToOneAsync<TDto>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据条件获取Dto
|
||||
/// </summary>
|
||||
public Task<TDto> GetAsync<TDto>(Expression<Func<TEntity, bool>> exp)
|
||||
{
|
||||
return Select.Where(exp).ToOneAsync<TDto>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据条件获取实体
|
||||
/// </summary>
|
||||
public Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> exp)
|
||||
{
|
||||
return Select.Where(exp).ToOneAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取分页列表
|
||||
/// </summary>
|
||||
/// <param name="dynamicFilterInfo">动态过滤器</param>
|
||||
/// <param name="page">页码</param>
|
||||
/// <param name="pageSize">页容量</param>
|
||||
/// <returns>分页列表和总条数</returns>
|
||||
public async Task<(IEnumerable<TEntity> List, long Total)> GetPagedListAsync(
|
||||
DynamicFilterInfo dynamicFilterInfo, int page, int pageSize)
|
||||
{
|
||||
var list = await Select.WhereDynamicFilter(dynamicFilterInfo)
|
||||
.Count(out var total)
|
||||
.Page(page, pageSize)
|
||||
.ToListAsync();
|
||||
return (list, total);
|
||||
}
|
||||
}
|
19
src/backend/NetAdmin.Application/Services/IService.cs
Normal file
19
src/backend/NetAdmin.Application/Services/IService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using NetAdmin.Domain.Contexts;
|
||||
|
||||
namespace NetAdmin.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 服务接口
|
||||
/// </summary>
|
||||
public interface IService
|
||||
{
|
||||
/// <summary>
|
||||
/// 服务编号
|
||||
/// </summary>
|
||||
Guid ServiceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上下文用户
|
||||
/// </summary>
|
||||
ContextUserToken UserToken { get; set; }
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using NetAdmin.Application.Repositories;
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 仓储服务基类
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
/// <typeparam name="TLogger">日志类型</typeparam>
|
||||
public abstract class RepositoryService<TEntity, TLogger> : ServiceBase<TLogger>
|
||||
where TEntity : EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RepositoryService{TEntity, TLogger}" /> class.
|
||||
/// </summary>
|
||||
protected RepositoryService(Repository<TEntity> rpo) //
|
||||
{
|
||||
Rpo = rpo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认仓储
|
||||
/// </summary>
|
||||
protected Repository<TEntity> Rpo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 启用级联保存
|
||||
/// </summary>
|
||||
protected bool EnableCascadeSave {
|
||||
get => Rpo.DbContextOptions.EnableCascadeSave;
|
||||
set => Rpo.DbContextOptions.EnableCascadeSave = value;
|
||||
}
|
||||
}
|
45
src/backend/NetAdmin.Application/Services/ServiceBase.cs
Normal file
45
src/backend/NetAdmin.Application/Services/ServiceBase.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using NetAdmin.Domain.Contexts;
|
||||
|
||||
namespace NetAdmin.Application.Services;
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract class ServiceBase<TLogger> : ServiceBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceBase{TLogger}" /> class.
|
||||
/// </summary>
|
||||
protected ServiceBase() //
|
||||
{
|
||||
Logger = App.GetService<ILogger<TLogger>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 日志记录器
|
||||
/// </summary>
|
||||
protected ILogger<TLogger> Logger { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务基类
|
||||
/// </summary>
|
||||
public abstract class ServiceBase : IScoped, IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceBase" /> class.
|
||||
/// </summary>
|
||||
protected ServiceBase()
|
||||
{
|
||||
UserToken = App.GetService<ContextUserToken>();
|
||||
ServiceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务编号
|
||||
/// </summary>
|
||||
public Guid ServiceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上下文用户
|
||||
/// </summary>
|
||||
public ContextUserToken UserToken { get; set; }
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)/CodeQuality.props"/>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.SysComponent.Application/NetAdmin.SysComponent.Application.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)/CodeQuality.props"/>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.SysComponent.Cache/NetAdmin.SysComponent.Cache.csproj"/>
|
||||
<ProjectReference Include="../NetAdmin.BizServer.Application/NetAdmin.BizServer.Application.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,39 @@
|
||||
using NetAdmin.BizServer.Host.Filters;
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
using NetAdmin.Host.Extensions;
|
||||
|
||||
namespace NetAdmin.BizServer.Host.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// ServiceCollection 扩展方法
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册FreeSql
|
||||
/// </summary>
|
||||
public static IServiceCollection AddFreeSql(this IServiceCollection me)
|
||||
{
|
||||
_ = me.AddFreeSql( //
|
||||
FreeSqlInitOptions.SyncStructure | FreeSqlInitOptions.InsertSeedData, freeSql => {
|
||||
// 数据权限过滤器
|
||||
_ = freeSql.GlobalFilter.ApplyOnlyIf<IFieldOwner>( //
|
||||
Chars.FLG_GLOBAL_FILTER_DATA
|
||||
, () => ContextUserInfo.Create()?.Roles.All(x => x.DataScope == DataScopes.Self) ?? false
|
||||
, a => a.OwnerId == ContextUserInfo.Create().Id);
|
||||
});
|
||||
return me;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// jwt授权处理器
|
||||
/// </summary>
|
||||
public static IServiceCollection AddJwt(this IServiceCollection me)
|
||||
{
|
||||
_ = me.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
|
||||
return me;
|
||||
}
|
||||
}
|
48
src/backend/NetAdmin.BizServer.Host/Filters/JwtHandler.cs
Normal file
48
src/backend/NetAdmin.BizServer.Host/Filters/JwtHandler.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using NetAdmin.Domain.Contexts;
|
||||
using NetAdmin.SysComponent.Cache.Sys.Dependency;
|
||||
|
||||
namespace NetAdmin.BizServer.Host.Filters;
|
||||
|
||||
/// <inheritdoc />
|
||||
[SuppressSniffer]
|
||||
public sealed class JwtHandler : AppAuthorizeHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JwtHandler" /> class.
|
||||
/// </summary>
|
||||
public JwtHandler() { }
|
||||
|
||||
/// <summary>
|
||||
/// 验证管道
|
||||
/// </summary>
|
||||
public override async Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
|
||||
{
|
||||
// 无法从token中获取context user,拒绝访问
|
||||
if (App.GetService<ContextUserToken>() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 数据库不存在context user,或用户已被禁用,拒绝访问
|
||||
var userInfo = await App.GetService<IUserCache>().UserInfoAsync();
|
||||
if (userInfo?.Roles == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
httpContext.Items.Add(Chars.FLG_CONTEXT_USER_INFO, userInfo);
|
||||
|
||||
var path = httpContext.Request.Path.Value!.TrimStart('/');
|
||||
foreach (var role in userInfo.Roles) {
|
||||
// 忽略权限控制,直接通过
|
||||
if (role.IgnorePermissionControl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取所属角色接口权限 进行核对
|
||||
if (role.ApiIds?.Contains(path) ?? false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Import Project="$(SolutionDir)/CodeQuality.props"/>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(SolutionDir)/assets/captcha/**" LinkBase="Assets/Captcha"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.SysComponent.Host/NetAdmin.SysComponent.Host.csproj"/>
|
||||
<ProjectReference Include="../NetAdmin.BizServer.Cache/NetAdmin.BizServer.Cache.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="*.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"NetAdmin.BizServer.Host": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:65010",
|
||||
"applicationUrl": "http://[::]:65010",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
src/backend/NetAdmin.BizServer.Host/Startup.cs
Normal file
67
src/backend/NetAdmin.BizServer.Host/Startup.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using NetAdmin.BizServer.Host.Extensions;
|
||||
using NetAdmin.Host.Extensions;
|
||||
using NetAdmin.Host.Middlewares;
|
||||
using Prometheus;
|
||||
|
||||
namespace NetAdmin.BizServer.Host;
|
||||
|
||||
/// <summary>
|
||||
/// 启动类
|
||||
/// </summary>
|
||||
public sealed class Startup : NetAdmin.Host.Startup
|
||||
{
|
||||
/// <summary>
|
||||
/// 程序入口
|
||||
/// </summary>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
ShowBanner();
|
||||
_ = Serve.Run(RunOptions.Default.WithArgs(args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置应用程序中间件
|
||||
/// </summary>
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
_ = app //
|
||||
.UseRealIp() // 获取真实IP
|
||||
.EnableBuffering() // 启用 Body 重读
|
||||
.UseMiddleware<RequestAuditMiddleware>() // 请求审计
|
||||
#if DEBUG
|
||||
.UseOpenApiSkin() // Swagger皮肤
|
||||
#endif
|
||||
.UseInject(string.Empty) // / Furion脚手架
|
||||
.UseUnifyResultStatusCodes() // 状态码拦截
|
||||
.UseCorsAccessor() // 跨域访问
|
||||
.UseRouting() // 路由映射
|
||||
.UseHttpMetrics() // 性能监控
|
||||
.UseAuthentication() // / 认证
|
||||
.UseAuthorization() // 授权
|
||||
.UseMiddleware<RemoveNullNodeMiddleware>() // 删除json空节点
|
||||
.UseEndpoints(); // 执行匹配的端点
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置服务容器
|
||||
/// </summary>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
_ = services.AddConsoleFormatter() // 控制台日志模板
|
||||
.AddAllOptions() // 注册配置项
|
||||
.AddJwt() // Jwt 授权处理器
|
||||
.AddSnowflake() // 雪花编号生成器
|
||||
.AddEventBus() // 事件总线
|
||||
.AddFreeSql() // freeSql
|
||||
.AddRemoteRequest() // 注册远程请求
|
||||
.AddCorsAccessor() // 支持跨域访问
|
||||
.AddContextUser() // 上下文用户
|
||||
.AddRedisCache() // Redis缓存
|
||||
|
||||
// IMvcBuilder
|
||||
.AddControllers() // 注册控制器
|
||||
.AddJsonSerializer(true) // json序列化配置
|
||||
.AddDefaultApiResultHandler() // Api结果处理器
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{}
|
1
src/backend/NetAdmin.BizServer.Host/settings.Test.json
Normal file
1
src/backend/NetAdmin.BizServer.Host/settings.Test.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
47
src/backend/NetAdmin.BizServer.Host/settings.json
Normal file
47
src/backend/NetAdmin.BizServer.Host/settings.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
|
||||
"SpecificationDocumentSettings": {
|
||||
"GroupOpenApiInfos": [
|
||||
{
|
||||
"Group": "Sys",
|
||||
"Title": "系统组件",
|
||||
"Description": "NetAdmin - 系统组件",
|
||||
},
|
||||
{
|
||||
"Group": "Biz",
|
||||
"Title": "业务服务",
|
||||
"Description": "NetAdmin - 业务服务",
|
||||
},
|
||||
{
|
||||
"Group": "Tpl",
|
||||
"Title": "示例服务",
|
||||
"Description": "NetAdmin - 示例服务",
|
||||
"Visible": false
|
||||
},
|
||||
{
|
||||
"Group": "Health",
|
||||
"Visible": false
|
||||
}
|
||||
],
|
||||
"SecurityDefinitions": [
|
||||
{
|
||||
"Id": "Bearer",
|
||||
"Type": "ApiKey",
|
||||
"Name": "Authorization",
|
||||
"Description": "JWT Authorization header using the Bearer scheme.",
|
||||
"BearerFormat": "JWT",
|
||||
"Scheme": "bearer",
|
||||
"In": "Header",
|
||||
"Requirement": {
|
||||
"Scheme": {
|
||||
"Reference": {
|
||||
"Id": "Bearer",
|
||||
"Type": "SecurityScheme"
|
||||
},
|
||||
"Accesses": []
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
||||
<ProjectReference Include="..\NetAdmin.BizServer.Host\NetAdmin.BizServer.Host.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0-preview-23371-04"/>
|
||||
<PackageReference Include="xunit" Version="2.5.1-pre.20"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.1-pre.10">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
18
src/backend/NetAdmin.BizServer.Tests/UsedNumberTests.cs
Normal file
18
src/backend/NetAdmin.BizServer.Tests/UsedNumberTests.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Xunit;
|
||||
|
||||
namespace NetAdmin.BizServer.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// UsedNumberTests
|
||||
/// </summary>
|
||||
public class UsedNumberTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test1
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
// Assert.True("1".Int32() == 2);
|
||||
}
|
||||
}
|
29
src/backend/NetAdmin.Cache/CacheBase.cs
Normal file
29
src/backend/NetAdmin.Cache/CacheBase.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using NetAdmin.Application.Services;
|
||||
|
||||
namespace NetAdmin.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存基类
|
||||
/// </summary>
|
||||
public abstract class CacheBase<TCacheContainer, TService> : ICache<TCacheContainer, TService>
|
||||
where TService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheBase{TCacheLoad, TService}" /> class.
|
||||
/// </summary>
|
||||
protected CacheBase(TCacheContainer cache, TService service)
|
||||
{
|
||||
Cache = cache;
|
||||
Service = service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存对象
|
||||
/// </summary>
|
||||
public TCacheContainer Cache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的服务
|
||||
/// </summary>
|
||||
public TService Service { get; }
|
||||
}
|
95
src/backend/NetAdmin.Cache/DistributedCache.cs
Normal file
95
src/backend/NetAdmin.Cache/DistributedCache.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using NetAdmin.Application.Services;
|
||||
|
||||
namespace NetAdmin.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 分布式缓存
|
||||
/// </summary>
|
||||
public abstract class DistributedCache<TService> : CacheBase<IDistributedCache, TService>
|
||||
where TService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DistributedCache{TService}" /> class.
|
||||
/// </summary>
|
||||
protected DistributedCache(IDistributedCache cache, TService service) //
|
||||
: base(cache, service) { }
|
||||
|
||||
/// <summary>
|
||||
/// 创建缓存
|
||||
/// </summary>
|
||||
/// <param name="key">缓存键</param>
|
||||
/// <param name="createObj">创建对象</param>
|
||||
/// <param name="absLifeTime">绝对过期时间</param>
|
||||
/// <param name="slideLifeTime">滑动过期时间</param>
|
||||
/// <typeparam name="T">缓存对象类型</typeparam>
|
||||
/// <returns>缓存对象</returns>
|
||||
protected Task CreateAsync<T>(string key, T createObj, TimeSpan? absLifeTime = null, TimeSpan? slideLifeTime = null)
|
||||
{
|
||||
var cacheWrite = createObj.ToJson();
|
||||
|
||||
var options = new DistributedCacheEntryOptions();
|
||||
if (absLifeTime != null) {
|
||||
_ = options.SetAbsoluteExpiration(absLifeTime.Value);
|
||||
}
|
||||
|
||||
if (slideLifeTime != null) {
|
||||
_ = options.SetSlidingExpiration(slideLifeTime.Value);
|
||||
}
|
||||
|
||||
return Cache.SetAsync(key, cacheWrite.Hex(), options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存
|
||||
/// </summary>
|
||||
protected async Task<T> GetAsync<T>(string key)
|
||||
{
|
||||
var cacheRead = await Cache.GetStringAsync(key);
|
||||
return cacheRead != null ? cacheRead.ToObject<T>() : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存键
|
||||
/// </summary>
|
||||
protected virtual string GetCacheKey(string id = "0", [CallerMemberName] string memberName = null)
|
||||
{
|
||||
return $"{GetType().FullName}.{memberName}.{id}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建缓存
|
||||
/// </summary>
|
||||
/// <param name="key">缓存键</param>
|
||||
/// <param name="createProc">创建函数</param>
|
||||
/// <param name="absLifeTime">绝对过期时间</param>
|
||||
/// <param name="slideLifeTime">滑动过期时间</param>
|
||||
/// <typeparam name="T">缓存对象类型</typeparam>
|
||||
/// <returns>缓存对象</returns>
|
||||
protected async Task<T> GetOrCreateAsync<T>(string key, Func<Task<T>> createProc, TimeSpan? absLifeTime = null
|
||||
, TimeSpan? slideLifeTime = null)
|
||||
{
|
||||
var cacheRead = await GetAsync<T>(key);
|
||||
if (cacheRead is not null) {
|
||||
return cacheRead;
|
||||
}
|
||||
|
||||
var obj = await createProc.Invoke();
|
||||
|
||||
var cacheWrite = obj?.ToJson();
|
||||
if (cacheWrite == null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
await CreateAsync(key, obj, absLifeTime, slideLifeTime);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除缓存
|
||||
/// </summary>
|
||||
protected Task RemoveAsync(string key)
|
||||
{
|
||||
return Cache.RemoveAsync(key);
|
||||
}
|
||||
}
|
20
src/backend/NetAdmin.Cache/ICache.cs
Normal file
20
src/backend/NetAdmin.Cache/ICache.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using NetAdmin.Application.Services;
|
||||
|
||||
namespace NetAdmin.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存接口
|
||||
/// </summary>
|
||||
public interface ICache<out TCacheLoad, out TService>
|
||||
where TService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存对象
|
||||
/// </summary>
|
||||
TCacheLoad Cache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的服务
|
||||
/// </summary>
|
||||
public TService Service { get; }
|
||||
}
|
16
src/backend/NetAdmin.Cache/MemoryCache.cs
Normal file
16
src/backend/NetAdmin.Cache/MemoryCache.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using NetAdmin.Application.Services;
|
||||
|
||||
namespace NetAdmin.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 内存缓存
|
||||
/// </summary>
|
||||
public abstract class MemoryCache<TService> : CacheBase<IMemoryCache, TService>
|
||||
where TService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MemoryCache{TService}" /> class.
|
||||
/// </summary>
|
||||
protected MemoryCache(IMemoryCache cache, TService service) //
|
||||
: base(cache, service) { }
|
||||
}
|
6
src/backend/NetAdmin.Cache/NetAdmin.Cache.csproj
Normal file
6
src/backend/NetAdmin.Cache/NetAdmin.Cache.csproj
Normal file
@ -0,0 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(SolutionDir)/CodeQuality.props"/>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NetAdmin.Application/NetAdmin.Application.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,23 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 支付宝验证器(手机或邮箱)
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class AlipayAttribute : ValidationAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AlipayAttribute" /> class.
|
||||
/// </summary>
|
||||
public AlipayAttribute()
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.支付宝账号);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object value)
|
||||
{
|
||||
return new MobileAttribute().IsValid(value) || new EmailAddressAttribute().IsValid(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 证件号码
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CertificateAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CertificateAttribute" /> class.
|
||||
/// </summary>
|
||||
public CertificateAttribute() //
|
||||
: base(Chars.RGX_CERTIFICATE)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.无效证件号码);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 中文姓名
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class ChineseNameAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChineseNameAttribute" /> class.
|
||||
/// </summary>
|
||||
public ChineseNameAttribute() //
|
||||
: base(Chars.RGX_CHINESE_NAME)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.中文姓名);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 电话验证器(手机或固话)
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CulturePhoneAttribute : ValidationAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CulturePhoneAttribute" /> class.
|
||||
/// </summary>
|
||||
public CulturePhoneAttribute()
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.手机号码或座机号码);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object value)
|
||||
{
|
||||
return new MobileAttribute().IsValid(value) || new TelephoneAttribute().IsValid(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 区间验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CultureRangeAttribute : RangeAttribute
|
||||
{
|
||||
/// <inheritdoc cref="RangeAttribute" />
|
||||
public CultureRangeAttribute(double minimum, double maximum) //
|
||||
: base(minimum, maximum) { }
|
||||
|
||||
/// <inheritdoc cref="RangeAttribute" />
|
||||
public CultureRangeAttribute(int minimum, int maximum) //
|
||||
: base(minimum, maximum) { }
|
||||
|
||||
/// <inheritdoc cref="RangeAttribute" />
|
||||
public CultureRangeAttribute(Type type, string minimum, string maximum) //
|
||||
: base(type, minimum, maximum) { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string FormatErrorMessage(string name)
|
||||
{
|
||||
return $"{ErrorMessageString} {Ln.必须介于} {Minimum} - {Maximum}";
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 非空验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CultureRequiredAttribute : RequiredAttribute
|
||||
{
|
||||
/// <summary>Applies formatting to an error message, based on the data field where the error occurred.</summary>
|
||||
/// <param name="name">The name to include in the formatted message.</param>
|
||||
/// <exception cref="T:System.InvalidOperationException">The current attribute is malformed.</exception>
|
||||
/// <returns>An instance of the formatted error message.</returns>
|
||||
public override string FormatErrorMessage(string name)
|
||||
{
|
||||
return $"{ErrorMessageString.NullOrEmpty(name)} {Ln.不能为空}";
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// Url验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class CultureUrlAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CultureUrlAttribute" /> class.
|
||||
/// </summary>
|
||||
public CultureUrlAttribute() //
|
||||
: base(Chars.RGX_URL)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.无效网络地址);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class EmailAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EmailAttribute" /> class.
|
||||
/// </summary>
|
||||
public EmailAttribute() //
|
||||
: base(Chars.RGX_EMAIL)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.电子邮箱);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请码验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class InviteCodeAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InviteCodeAttribute" /> class.
|
||||
/// </summary>
|
||||
public InviteCodeAttribute() //
|
||||
: base(Chars.RGX_INVITE_CODE)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.邀请码不正确);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 手机号验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class MobileAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MobileAttribute" /> class.
|
||||
/// </summary>
|
||||
public MobileAttribute() //
|
||||
: base(Chars.RGX_MOBILE)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.手机号码);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 密码验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class PasswordAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PasswordAttribute" /> class.
|
||||
/// </summary>
|
||||
public PasswordAttribute() //
|
||||
: base(Chars.RGX_PASSWORD)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln._8位以上数字字母组合);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 交易密码验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class PayPasswordAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PayPasswordAttribute" /> class.
|
||||
/// </summary>
|
||||
public PayPasswordAttribute() //
|
||||
: base(Chars.RGX_PAY_PASSWORD)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln._6位数字);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 正则表达式验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
#pragma warning disable DesignedForInheritance
|
||||
public class RegexAttribute : RegularExpressionAttribute
|
||||
#pragma warning restore DesignedForInheritance
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RegexAttribute" /> class.
|
||||
/// </summary>
|
||||
protected RegexAttribute(string pattern) //
|
||||
: base(pattern) { }
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using NetAdmin.Domain.Dto.Sys.Role;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 数据范围为特定部门的验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class SpecificDeptAttribute : ValidationAttribute
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
||||
{
|
||||
if (validationContext.ObjectInstance is not CreateRoleReq { DataScope: DataScopes.SpecificDept }) {
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
#pragma warning disable IDE0046
|
||||
|
||||
if ((value as IEnumerable<long>)?.Any() ?? false) {
|
||||
#pragma warning restore IDE0046
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
return new ValidationResult(Ln.未指定部门);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 固定电话验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class TelephoneAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TelephoneAttribute" /> class.
|
||||
/// </summary>
|
||||
public TelephoneAttribute() //
|
||||
: base(Chars.RGX_TELEPHONE)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.区号电话号码分机号);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 用户名验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class UserNameAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserNameAttribute" /> class.
|
||||
/// </summary>
|
||||
public UserNameAttribute() //
|
||||
: base(Chars.RGX_USERNAME)
|
||||
{
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object value)
|
||||
{
|
||||
if (!base.IsValid(value)) {
|
||||
ErrorMessageResourceName = nameof(Ln.用户名长度4位以上);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new MobileAttribute().IsValid(value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 不能是手机号
|
||||
ErrorMessageResourceName = nameof(Ln.用户名不能是手机号);
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
/// <summary>
|
||||
/// 验证码验证器
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||
public sealed class VerifyCodeAttribute : RegexAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="VerifyCodeAttribute" /> class.
|
||||
/// </summary>
|
||||
public VerifyCodeAttribute() //
|
||||
: base(Chars.RGX_VERIFY_CODE)
|
||||
{
|
||||
ErrorMessageResourceName = nameof(Ln.验证码不正确);
|
||||
ErrorMessageResourceType = typeof(Ln);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace NetAdmin.Domain.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 标记一个字段启用服务器时间
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class ServerTimeAttribute : Attribute { }
|
12
src/backend/NetAdmin.Domain/Attributes/SnowflakeAttribute.cs
Normal file
12
src/backend/NetAdmin.Domain/Attributes/SnowflakeAttribute.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
||||
|
||||
namespace NetAdmin.Domain.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// 标记一个字段启用雪花编号生成
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class SnowflakeAttribute : Attribute
|
||||
{
|
||||
//
|
||||
}
|
113
src/backend/NetAdmin.Domain/Contexts/ContextApp.cs
Normal file
113
src/backend/NetAdmin.Domain/Contexts/ContextApp.cs
Normal file
@ -0,0 +1,113 @@
|
||||
namespace NetAdmin.Domain.Contexts;
|
||||
|
||||
/// <summary>
|
||||
/// 上下文应用信息
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 签名算法: $"${appId}{appSecret.ToLowerInvariant()}{timestamp}{reqBody}".Md5(Encoding.UTF8);
|
||||
/// reqBody 需去除\r、\n、whitespace
|
||||
/// </remarks>
|
||||
public sealed record ContextApp : DataAbstraction, IValidatableObject
|
||||
{
|
||||
private const int _TS_OFFSET_SCOPE_SEC = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContextApp" /> class.
|
||||
/// </summary>
|
||||
public ContextApp(long appId, string appSecret, long timestamp)
|
||||
{
|
||||
AppId = appId;
|
||||
AppSecret = appSecret;
|
||||
Timestamp = timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContextApp" /> class.
|
||||
/// </summary>
|
||||
private ContextApp()
|
||||
{
|
||||
AppId = App.HttpContext.Request.Headers[nameof(AppId)].FirstOrDefault().Int64Try(0);
|
||||
AppSecret = App.HttpContext.Request.Headers[nameof(AppSecret)].FirstOrDefault();
|
||||
Sign = App.HttpContext.Request.Headers[nameof(Sign)].FirstOrDefault();
|
||||
Timestamp = App.HttpContext.Request.Headers[nameof(Timestamp)].FirstOrDefault().Int64Try(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AppId
|
||||
/// </summary>
|
||||
[Range(1, long.MaxValue)]
|
||||
public long AppId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// AppSecret
|
||||
/// </summary>
|
||||
public string AppSecret { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 签名
|
||||
/// </summary>
|
||||
public string Sign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳
|
||||
/// </summary>
|
||||
public long Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 从HttpContext 创建上下文应用
|
||||
/// </summary>
|
||||
public static async Task<ContextApp> CreateAsync()
|
||||
{
|
||||
var ret = new ContextApp();
|
||||
if (!ret.TryValidate().IsValid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 具有secret的情况下,自动生成时间戳+sign,方便调试
|
||||
if (!ret.AppSecret.NullOrEmpty()) {
|
||||
ret.Timestamp = DateTime.Now.TimeUnixUtc();
|
||||
ret.Sign = await ret.BuildSignFromHttpContextAsync();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建签名
|
||||
/// </summary>
|
||||
public string BuildSign(string reqBody)
|
||||
{
|
||||
// 去除\r\n和空格再计算签名,规避风格样式问题
|
||||
reqBody = reqBody.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace(" ", string.Empty);
|
||||
return $"{AppId}{AppSecret.ToLowerInvariant()}{Timestamp}{reqBody}".Md5(Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建签名(从http上下文)
|
||||
/// </summary>
|
||||
public async Task<string> BuildSignFromHttpContextAsync()
|
||||
{
|
||||
var sr = new StreamReader(App.HttpContext.Request.Body);
|
||||
var reqBody = await sr.ReadToEndAsync();
|
||||
|
||||
_ = App.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
|
||||
return BuildSign(reqBody);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!AppSecret.NullOrEmpty()) {
|
||||
yield break;
|
||||
}
|
||||
|
||||
// 没有密码, 就要签名+时间戳
|
||||
if (Sign.NullOrEmpty()) {
|
||||
yield return new ValidationResult(Ln.签名缺失, new[] { nameof(Sign) });
|
||||
}
|
||||
|
||||
if (Math.Abs(DateTime.Now.TimeUnixUtc() - Timestamp) > _TS_OFFSET_SCOPE_SEC) {
|
||||
yield return new ValidationResult(Ln.时间戳缺失或误差过大, new[] { nameof(Timestamp) });
|
||||
}
|
||||
}
|
||||
}
|
26
src/backend/NetAdmin.Domain/Contexts/ContextUserInfo.cs
Normal file
26
src/backend/NetAdmin.Domain/Contexts/ContextUserInfo.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.Contexts;
|
||||
|
||||
/// <summary>
|
||||
/// 上下文用户信息
|
||||
/// </summary>
|
||||
public sealed record ContextUserInfo : QueryUserRsp
|
||||
{
|
||||
/// <summary>
|
||||
/// 从HttpContext 创建上下文用户信息
|
||||
/// </summary>
|
||||
public static ContextUserInfo Create()
|
||||
{
|
||||
var ret = App.HttpContext?.Items[nameof(Chars.FLG_CONTEXT_USER_INFO)] as QueryUserRsp;
|
||||
return ret?.Adapt<ContextUserInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在于 HttpContext
|
||||
/// </summary>
|
||||
public static bool HasInContext()
|
||||
{
|
||||
return App.HttpContext?.Items.ContainsKey(Chars.FLG_CONTEXT_USER_INFO) ?? false;
|
||||
}
|
||||
}
|
41
src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs
Normal file
41
src/backend/NetAdmin.Domain/Contexts/ContextUserToken.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.Contexts;
|
||||
|
||||
/// <summary>
|
||||
/// 上下文用户凭据
|
||||
/// </summary>
|
||||
public sealed record ContextUserToken : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户编号
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 做授权验证的Token,全局唯一,可以随时重置(强制下线)
|
||||
/// </summary>
|
||||
public Guid Token { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
public string UserName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 从HttpContext 创建上下文用户
|
||||
/// </summary>
|
||||
public static ContextUserToken Create()
|
||||
{
|
||||
var claim = App.User?.FindFirst(nameof(ContextUserToken));
|
||||
return claim?.Value.ToObject<ContextUserToken>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 QueryUserRsp 创建上下文用户
|
||||
/// </summary>
|
||||
public static ContextUserToken Create(QueryUserRsp user)
|
||||
{
|
||||
return new ContextUserToken { Id = user.Id, Token = user.Token, UserName = user.UserName };
|
||||
}
|
||||
}
|
36
src/backend/NetAdmin.Domain/DataAbstraction.cs
Normal file
36
src/backend/NetAdmin.Domain/DataAbstraction.cs
Normal file
@ -0,0 +1,36 @@
|
||||
namespace NetAdmin.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// 数据基类
|
||||
/// </summary>
|
||||
public abstract record DataAbstraction
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return this.ToJson();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 截断所有字符串属性 以符合[MaxLength(x)]特性
|
||||
/// </summary>
|
||||
public void TruncateStrings()
|
||||
{
|
||||
foreach (var property in GetType()
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(x => x.PropertyType == typeof(string))) {
|
||||
var maxLen = property.GetCustomAttribute<MaxLengthAttribute>(true)?.Length;
|
||||
if (maxLen is null or 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var value = property.GetValue(this);
|
||||
if (value is not string s || s.Length < maxLen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
s = s.Sub(0, maxLen.Value);
|
||||
property.SetValue(this, s);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 数据库实体基类
|
||||
/// </summary>
|
||||
public abstract record EntityBase : DataAbstraction;
|
@ -0,0 +1,22 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端字段接口
|
||||
/// </summary>
|
||||
public interface IFieldCreatedClient
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建者客户端IP
|
||||
/// </summary>
|
||||
int? CreatedClientIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者来源地址
|
||||
/// </summary>
|
||||
string CreatedReferer { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端用户代理
|
||||
/// </summary>
|
||||
string CreatedUserAgent { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间字段接口
|
||||
/// </summary>
|
||||
public interface IFieldCreatedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
DateTime CreatedTime { get; init; }
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 创建用户字段接口
|
||||
/// </summary>
|
||||
public interface IFieldCreatedUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建者编号
|
||||
/// </summary>
|
||||
long? CreatedUserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者用户名
|
||||
/// </summary>
|
||||
string CreatedUserName { get; set; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 启用字段接口
|
||||
/// </summary>
|
||||
public interface IFieldEnabled
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
bool Enabled { get; init; }
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 修改客户端字段接口
|
||||
/// </summary>
|
||||
public interface IFieldModifiedClient
|
||||
{
|
||||
/// <summary>
|
||||
/// 客户端IP
|
||||
/// </summary>
|
||||
int ModifiedClientIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 客户端用户代理
|
||||
/// </summary>
|
||||
string ModifiedUserAgent { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 修改时间字段接口
|
||||
/// </summary>
|
||||
public interface IFieldModifiedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 修改时间
|
||||
/// </summary>
|
||||
DateTime? ModifiedTime { get; init; }
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户字段接口
|
||||
/// </summary>
|
||||
public interface IFieldModifiedUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 修改者编号
|
||||
/// </summary>
|
||||
long? ModifiedUserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改者用户名
|
||||
/// </summary>
|
||||
string ModifiedUserName { get; init; }
|
||||
}
|
@ -0,0 +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; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 主键字段接口
|
||||
/// </summary>
|
||||
public interface IFieldPrimary<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
T Id { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 排序字段接口
|
||||
/// </summary>
|
||||
public interface IFieldSort
|
||||
{
|
||||
/// <summary>
|
||||
/// 排序值,越大越前
|
||||
/// </summary>
|
||||
long Sort { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 描述字段接口
|
||||
/// </summary>
|
||||
public interface IFieldSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
string Summary { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
/// <summary>
|
||||
/// 版本字段接口
|
||||
/// </summary>
|
||||
public interface IFieldVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据版本
|
||||
/// </summary>
|
||||
long Version { get; init; }
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 不可变实体
|
||||
/// </summary>
|
||||
public abstract record ImmutableEntity : ImmutableEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 不可变实体
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract record ImmutableEntity<T> : LiteImmutableEntity<T>, IFieldCreatedUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建者编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(CanUpdate = false, Position = -1)]
|
||||
public long? CreatedUserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者用户名
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanUpdate = false, Position = -1)]
|
||||
public virtual string CreatedUserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override T Id { get; init; }
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 轻型不可变实体
|
||||
/// </summary>
|
||||
public abstract record LiteImmutableEntity : LiteImmutableEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轻型不可变实体
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract record LiteImmutableEntity<T> : EntityBase, IFieldPrimary<T>, IFieldCreatedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(ServerTime = DateTimeKind.Utc, CanUpdate = false, Position = -1)]
|
||||
public virtual DateTime CreatedTime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public virtual T Id { get; init; }
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 轻型可变实体
|
||||
/// </summary>
|
||||
public abstract record LiteMutableEntity : LiteMutableEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轻型可变实体
|
||||
/// </summary>
|
||||
public abstract record LiteMutableEntity<T> : LiteImmutableEntity<T>, IFieldModifiedTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override T Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改时间
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(ServerTime = DateTimeKind.Utc, CanInsert = false, Position = -1)]
|
||||
public virtual DateTime? ModifiedTime { get; init; }
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 乐观锁轻型可变实体
|
||||
/// </summary>
|
||||
public abstract record LiteVersionEntity : LiteVersionEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 乐观锁轻型可变实体
|
||||
/// </summary>
|
||||
public abstract record LiteVersionEntity<T> : LiteMutableEntity<T>, IFieldVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override T Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据版本
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(IsVersion = true, Position = -1)]
|
||||
public virtual long Version { get; init; }
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 可变实体
|
||||
/// </summary>
|
||||
public abstract record MutableEntity : MutableEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可变实体
|
||||
/// </summary>
|
||||
public abstract record MutableEntity<T> : LiteMutableEntity<T>, IFieldModifiedUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override T Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改者编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(CanInsert = false, Position = -1)]
|
||||
public long? ModifiedUserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改者用户名
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
||||
public string ModifiedUserName { get; init; }
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 简单实体
|
||||
/// </summary>
|
||||
public abstract record SimpleEntity : EntityBase;
|
@ -0,0 +1,43 @@
|
||||
using NetAdmin.Domain.Attributes;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 乐观锁可变实体
|
||||
/// </summary>
|
||||
public abstract record VersionEntity : VersionEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Snowflake]
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override long Id { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 乐观锁可变实体
|
||||
/// </summary>
|
||||
public abstract record VersionEntity<T> : LiteVersionEntity<T>, IFieldModifiedUser
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[Column(IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override T Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改者编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(CanInsert = false, Position = -1)]
|
||||
public long? ModifiedUserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 修改者用户名
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31, CanInsert = false, Position = -1)]
|
||||
public string ModifiedUserName { get; init; }
|
||||
}
|
67
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs
Normal file
67
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Api.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// Api接口表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Api))]
|
||||
public record Sys_Api : ImmutableEntity<string>, IFieldSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ParentId))]
|
||||
public IEnumerable<Sys_Api> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127, IsIdentity = false, IsPrimary = true, Position = 1)]
|
||||
public override string Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求方式
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||
public virtual string Method { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Namespace { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 父编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string ParentId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色集合
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleApi))]
|
||||
public ICollection<Sys_Role> Roles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务描述
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Summary { get; init; }
|
||||
}
|
53
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Config.cs
Normal file
53
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Config.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 配置表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Config))]
|
||||
public record Sys_Config : VersionEntity, IFieldEnabled
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册是否需要人工确认
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool UserRegisterConfirm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册默认部门
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(UserRegisterDeptId))]
|
||||
public Sys_Dept UserRegisterDept { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册默认部门编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long UserRegisterDeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册默认角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(UserRegisterRoleId))]
|
||||
public Sys_Role UserRegisterRole { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册默认角色编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long UserRegisterRoleId { get; init; }
|
||||
}
|
60
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Dept.cs
Normal file
60
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Dept.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 部门表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Dept))]
|
||||
public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ParentId))]
|
||||
public IEnumerable<Sys_Dept> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 父编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long ParentId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色集合
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleDept))]
|
||||
public ICollection<Sys_Role> Roles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序值,越大越前
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long Sort { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门描述
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string Summary { get; init; }
|
||||
}
|
46
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_DicCatalog.cs
Normal file
46
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_DicCatalog.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 字典目录表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_DicCatalog))]
|
||||
[Index($"idx_{{tablename}}_{nameof(Code)}", nameof(Code), true)]
|
||||
public record Sys_DicCatalog : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ParentId))]
|
||||
public IEnumerable<Sys_DicCatalog> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典编码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Code { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典内容集合
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(Sys_DicContent.CatalogId))]
|
||||
public ICollection<Sys_DicContent> Contents { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 父编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long ParentId { get; init; }
|
||||
}
|
40
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_DicContent.cs
Normal file
40
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_DicContent.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 字典内容表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_DicContent))]
|
||||
[Index($"idx_{{tablename}}_{nameof(CatalogId)}_{nameof(Key)}", $"{nameof(CatalogId)},{nameof(Key)}", true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(CatalogId)}_{nameof(Value)}", $"{nameof(CatalogId)},{nameof(Value)}", true)]
|
||||
public record Sys_DicContent : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典目录
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(CatalogId))]
|
||||
public Sys_DicCatalog Catalog { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典目录编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long CatalogId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 键名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Key { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 键值
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string Value { get; init; }
|
||||
}
|
132
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Menu.cs
Normal file
132
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Menu.cs
Normal file
@ -0,0 +1,132 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 菜单表
|
||||
/// </summary>
|
||||
[Table(Name = "Sys_Menu")]
|
||||
[Index($"idx_{{tablename}}_{nameof(Name)}", nameof(Name), true)]
|
||||
public record Sys_Menu : VersionEntity, IFieldSort
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点或详情页需要高亮的上级菜单路由地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string Active { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ParentId))]
|
||||
public IEnumerable<Sys_Menu> Children { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 背景颜色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_7)]
|
||||
public virtual string Color { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Component { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否整页路由
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool FullPageRouting { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否隐藏菜单
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Hidden { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否隐藏面包屑
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool HiddenBreadCrumb { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Icon { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 父编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long ParentId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单路径
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string Path { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 重定向地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string Redirect { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 拥有此菜单的角色集合
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleMenu))]
|
||||
public ICollection<Sys_Role> Roles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序值,越大越前
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long Sort { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 标签
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Tag { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单标题
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单类型
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual MenuTypes Type { get; init; }
|
||||
}
|
151
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs
Normal file
151
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RequestLog.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 请求日志表
|
||||
/// </summary>
|
||||
[Table(Name = "Sys_RequestLog")]
|
||||
public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
||||
{
|
||||
/// <summary>
|
||||
/// 接口
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(ApiId))]
|
||||
public Sys_Api Api { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 接口编号
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
[JsonIgnore]
|
||||
public virtual string ApiId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端IP
|
||||
/// </summary>
|
||||
[Column(Position = -1)]
|
||||
[JsonIgnore]
|
||||
public virtual int? CreatedClientIp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者来源地址
|
||||
/// </summary>
|
||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public string CreatedReferer { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者客户端用户代理
|
||||
/// </summary>
|
||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string CreatedUserAgent { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行耗时(微秒)
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual long Duration { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 程序响应码
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual ErrorCodes ErrorCode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 异常信息
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string Exception { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 附加数据
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ExtraData { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP状态码
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual int HttpStatusCode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求方法
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||
[JsonIgnore]
|
||||
public virtual string Method { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 来源地址
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ReferUrl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求内容
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求content-type
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestContentType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求头信息
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestHeaders { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
[JsonIgnore]
|
||||
public virtual string RequestUrl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应内容
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ResponseBody { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应content-type
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
[JsonIgnore]
|
||||
public virtual string ResponseContentType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应头
|
||||
/// </summary>
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
[JsonIgnore]
|
||||
public virtual string ResponseHeaders { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务器IP
|
||||
/// </summary>
|
||||
[Column]
|
||||
[JsonIgnore]
|
||||
public virtual int? ServerIp { get; init; }
|
||||
}
|
115
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Role.cs
Normal file
115
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_Role.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.Dto.Sys.Role;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 角色表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_Role))]
|
||||
[Index("idx_{tablename}_01", nameof(Name), true)]
|
||||
public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary, IRegister
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色-接口映射
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleApi))]
|
||||
public ICollection<Sys_Api> Apis { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据范围
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual DataScopes DataScope { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色-部门映射
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleDept))]
|
||||
public ICollection<Sys_Dept> Depts { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否显示仪表板
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool DisplayDashboard { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否忽略权限控制
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool IgnorePermissionControl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色-菜单映射
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_RoleMenu))]
|
||||
public ICollection<Sys_Menu> Menus { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色名称
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序值,越大越前
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long Sort { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string Summary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 此角色下的用户集合
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_UserRole))]
|
||||
public ICollection<Sys_User> Users { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
_ = config.ForType<CreateRoleReq, Sys_Role>()
|
||||
.Map( //
|
||||
d => d.Depts
|
||||
, s => s.DeptIds.NullOrEmpty()
|
||||
? Array.Empty<Sys_Dept>()
|
||||
: s.DeptIds.Select(x => new Sys_Dept { Id = x }))
|
||||
.Map( //
|
||||
d => d.Menus
|
||||
, s => s.MenuIds.NullOrEmpty()
|
||||
? Array.Empty<Sys_Menu>()
|
||||
: s.MenuIds.Select(x => new Sys_Menu { Id = x }))
|
||||
.Map( //
|
||||
d => d.Apis
|
||||
, s => s.ApiIds.NullOrEmpty()
|
||||
? Array.Empty<Sys_Api>()
|
||||
: s.ApiIds.Select(x => new Sys_Api { Id = x }))
|
||||
|
||||
//
|
||||
;
|
||||
}
|
||||
}
|
36
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs
Normal file
36
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleApi.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 角色-接口映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleApi))]
|
||||
public sealed record Sys_RoleApi : ImmutableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的接口
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Api Api { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 接口编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public string ApiId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Role Role { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public long RoleId { get; init; }
|
||||
}
|
37
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs
Normal file
37
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleDept.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 角色-部门映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleDept))]
|
||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(DeptId)}", $"{nameof(RoleId)},{nameof(DeptId)}", true)]
|
||||
public sealed record Sys_RoleDept : ImmutableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的部门
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Dept Dept { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 可访问的部门编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public long DeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Role Role { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public long RoleId { get; init; }
|
||||
}
|
37
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleMenu.cs
Normal file
37
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_RoleMenu.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 角色-菜单映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_RoleMenu))]
|
||||
[Index($"idx_{{tablename}}_{nameof(RoleId)}_{nameof(MenuId)}", $"{nameof(RoleId)},{nameof(MenuId)}", true)]
|
||||
public record Sys_RoleMenu : ImmutableEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的菜单
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Menu Menu { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long MenuId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Role Role { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long RoleId { get; init; }
|
||||
}
|
120
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_User.cs
Normal file
120
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_User.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.Dto.Sys.User;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 用户基本信息表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_User))]
|
||||
[Index($"idx_{{tablename}}_{nameof(UserName)}", nameof(UserName), true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(Mobile)}", nameof(Mobile), true)]
|
||||
[Index($"idx_{{tablename}}_{nameof(Email)}", nameof(Email), true)]
|
||||
public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister
|
||||
{
|
||||
/// <summary>
|
||||
/// 头像链接
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string Avatar { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 所属部门
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(nameof(DeptId))]
|
||||
public Sys_Dept Dept { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 部门编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual long DeptId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string Email { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual bool Enabled { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 手机号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||
public virtual string Mobile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public Guid Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户档案
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_UserProfile Profile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 所属角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Navigate(ManyToMany = typeof(Sys_UserRole))]
|
||||
public ICollection<Sys_Role> Roles { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public virtual string Summary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权验证Token,全局唯一,可以随时重置(强制下线)
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public Guid Token { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string UserName { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
_ = config.ForType<CreateUserReq, Sys_User>()
|
||||
.Map(d => d.Password, s => s.PasswordText.Pwd().Guid())
|
||||
.Map(d => d.Token, _ => Guid.NewGuid())
|
||||
.Map( //
|
||||
d => d.Roles
|
||||
, s => s.RoleIds.NullOrEmpty()
|
||||
? Array.Empty<Sys_Role>()
|
||||
: s.RoleIds.Select(x => new Sys_Role { Id = x }));
|
||||
|
||||
_ = config.ForType<UpdateUserReq, Sys_User>()
|
||||
.Map( //
|
||||
d => d.Password, s => s.PasswordText.NullOrEmpty() ? Guid.Empty : s.PasswordText.Pwd().Guid())
|
||||
.Map( //
|
||||
d => d.Roles
|
||||
, s => s.RoleIds.NullOrEmpty()
|
||||
? Array.Empty<Sys_Role>()
|
||||
: s.RoleIds.Select(x => new Sys_Role { Id = x }));
|
||||
}
|
||||
}
|
198
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserProfile.cs
Normal file
198
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserProfile.cs
Normal file
@ -0,0 +1,198 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.Dto.Sys.UserProfile;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 用户档案表
|
||||
/// </summary>
|
||||
[Table(Name = "Sys_UserProfile")]
|
||||
public record Sys_UserProfile : VersionEntity, IRegister
|
||||
{
|
||||
/// <summary>
|
||||
/// 出生日期
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual DateTime? BornDate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 证件号码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string CertificateNumber { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 证件类型
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual CertificateTypes? CertificateType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string CompanyAddress { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作地区
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public int? CompanyArea { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作单位
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string CompanyName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作电话
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string CompanyTelephone { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 文化程度
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual Educations? Education { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 紧急联系地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string EmergencyContactAddress { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 紧急联系地区
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public int? EmergencyContactArea { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 紧急联系人手机号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||
public virtual string EmergencyContactMobile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 紧急联系人
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string EmergencyContactName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 毕业学校
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string GraduateSchool { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 身高
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual int? Height { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 住宅地址
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_127)]
|
||||
public virtual string HomeAddress { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 住宅地区
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public int? HomeArea { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 住宅电话
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string HomeTelephone { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 婚姻状况
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual MarriageStatues? MarriageStatus { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 民族
|
||||
/// </summary>
|
||||
/// 7
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual Nations? Nation { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 籍贯
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public int? NationArea { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 政治面貌
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual PoliticalStatues? PoliticalStatus { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 职业
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string Profession { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 真实姓名
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_31)]
|
||||
public virtual string RealName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual Sexes? Sex { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户基本信息
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_User User { get; init; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
_ = config.ForType<CreateUserProfileReq, Sys_UserProfile>()
|
||||
.Map(d => d.NationArea, s => s.NationArea == null ? null : s.NationArea.Value)
|
||||
.Map(d => d.CompanyArea, s => s.CompanyArea == null ? null : s.CompanyArea.Value)
|
||||
.Map(d => d.HomeArea, s => s.HomeArea == null ? null : s.HomeArea.Value)
|
||||
.Map( //
|
||||
d => d.EmergencyContactArea
|
||||
, s => s.EmergencyContactArea == null ? null : s.EmergencyContactArea.Value);
|
||||
}
|
||||
}
|
36
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs
Normal file
36
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_UserRole.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 用户-角色映射表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_UserRole))]
|
||||
public sealed record Sys_UserRole : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联的角色
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_Role Role { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public long RoleId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的用户
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Sys_User User { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户编号
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public long UserId { get; init; }
|
||||
}
|
53
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_VerifyCode.cs
Normal file
53
src/backend/NetAdmin.Domain/DbMaps/Sys/Sys_VerifyCode.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
using NetAdmin.Domain.Enums.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
/// <summary>
|
||||
/// 验证码表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Sys_VerifyCode))]
|
||||
public record Sys_VerifyCode : VersionEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证码
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_7)]
|
||||
public virtual string Code { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标设备
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_63)]
|
||||
public virtual string DestDevice { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备类型
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual VerifyCodeDeviceTypes DeviceType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送报告
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||
public string Report { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码状态
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual VerifyCodeStatues Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码类型
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[Column]
|
||||
public virtual VerifyCodeTypes Type { get; init; }
|
||||
}
|
9
src/backend/NetAdmin.Domain/DbMaps/Tpl/Tpl_Example.cs
Normal file
9
src/backend/NetAdmin.Domain/DbMaps/Tpl/Tpl_Example.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency;
|
||||
|
||||
namespace NetAdmin.Domain.DbMaps.Tpl;
|
||||
|
||||
/// <summary>
|
||||
/// 示例表
|
||||
/// </summary>
|
||||
[Table(Name = Chars.FLG_TABLE_NAME_PREFIX + nameof(Tpl_Example))]
|
||||
public record Tpl_Example : VersionEntity;
|
18
src/backend/NetAdmin.Domain/Dto/Dependency/BulkReq.cs
Normal file
18
src/backend/NetAdmin.Domain/Dto/Dependency/BulkReq.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 批量请求
|
||||
/// </summary>
|
||||
public sealed record BulkReq<T> : DataAbstraction
|
||||
where T : DataAbstraction, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求对象
|
||||
/// </summary>
|
||||
[CultureRequired(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.请求对象))]
|
||||
[MinLength(1)]
|
||||
[MaxLength(Numbers.BULK_REQ_LIMIT)]
|
||||
public IEnumerable<T> Items { get; init; }
|
||||
}
|
16
src/backend/NetAdmin.Domain/Dto/Dependency/DelReq.cs
Normal file
16
src/backend/NetAdmin.Domain/Dto/Dependency/DelReq.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <inheritdoc cref="DelReq{T}" />
|
||||
public sealed record DelReq : DelReq<long>;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:通过编号删除
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public record DelReq<T> : DataAbstraction, IFieldPrimary<T>
|
||||
{
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
public T Id { get; init; }
|
||||
}
|
17
src/backend/NetAdmin.Domain/Dto/Dependency/IPagedInfo.cs
Normal file
17
src/backend/NetAdmin.Domain/Dto/Dependency/IPagedInfo.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 信息:分页
|
||||
/// </summary>
|
||||
public interface IPagedInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前页码
|
||||
/// </summary>
|
||||
int Page { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页容量
|
||||
/// </summary>
|
||||
int PageSize { get; init; }
|
||||
}
|
6
src/backend/NetAdmin.Domain/Dto/Dependency/NopReq.cs
Normal file
6
src/backend/NetAdmin.Domain/Dto/Dependency/NopReq.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 空请求
|
||||
/// </summary>
|
||||
public sealed record NopReq : DataAbstraction;
|
16
src/backend/NetAdmin.Domain/Dto/Dependency/PagedQueryReq.cs
Normal file
16
src/backend/NetAdmin.Domain/Dto/Dependency/PagedQueryReq.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:分页查询
|
||||
/// </summary>
|
||||
public sealed record PagedQueryReq<T> : QueryReq<T>, IPagedInfo
|
||||
where T : DataAbstraction, new()
|
||||
{
|
||||
/// <inheritdoc cref="IPagedInfo.Page" />
|
||||
[Range(1, Numbers.QUERY_MAX_PAGE_NO)]
|
||||
public int Page { get; init; } = 1;
|
||||
|
||||
/// <inheritdoc cref="IPagedInfo.PageSize" />
|
||||
[Range(1, Numbers.QUERY_MAX_PAGE_SIZE)]
|
||||
public int PageSize { get; init; } = Numbers.QUERY_DEF_PAGE_SIZE;
|
||||
}
|
24
src/backend/NetAdmin.Domain/Dto/Dependency/PagedQueryRsp.cs
Normal file
24
src/backend/NetAdmin.Domain/Dto/Dependency/PagedQueryRsp.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:分页查询
|
||||
/// </summary>
|
||||
public sealed record PagedQueryRsp<T>(int Page, int PageSize, long Total, IEnumerable<T> Rows) : IPagedInfo
|
||||
where T : DataAbstraction
|
||||
{
|
||||
/// <inheritdoc cref="IPagedInfo.Page" />
|
||||
public int Page { get; init; } = Page;
|
||||
|
||||
/// <inheritdoc cref="IPagedInfo.PageSize" />
|
||||
public int PageSize { get; init; } = PageSize;
|
||||
|
||||
/// <summary>
|
||||
/// 数据行
|
||||
/// </summary>
|
||||
public IEnumerable<T> Rows { get; init; } = Rows;
|
||||
|
||||
/// <summary>
|
||||
/// 数据总条
|
||||
/// </summary>
|
||||
public long Total { get; init; } = Total;
|
||||
}
|
39
src/backend/NetAdmin.Domain/Dto/Dependency/QueryReq.cs
Normal file
39
src/backend/NetAdmin.Domain/Dto/Dependency/QueryReq.cs
Normal file
@ -0,0 +1,39 @@
|
||||
namespace NetAdmin.Domain.Dto.Dependency;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询
|
||||
/// </summary>
|
||||
public record QueryReq<T> : DataAbstraction
|
||||
where T : DataAbstraction, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// 取前n条
|
||||
/// </summary>
|
||||
[Range(1, Numbers.QUERY_LIMIT)]
|
||||
public int Count { get; init; } = Numbers.QUERY_LIMIT;
|
||||
|
||||
/// <summary>
|
||||
/// 动态查询条件
|
||||
/// </summary>
|
||||
public DynamicFilterInfo DynamicFilter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询条件
|
||||
/// </summary>
|
||||
public T Filter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询关键字
|
||||
/// </summary>
|
||||
public string Keywords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序方式
|
||||
/// </summary>
|
||||
public Orders? Order { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序字段
|
||||
/// </summary>
|
||||
public string Prop { get; init; }
|
||||
}
|
23
src/backend/NetAdmin.Domain/Dto/RestfulInfo.cs
Normal file
23
src/backend/NetAdmin.Domain/Dto/RestfulInfo.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace NetAdmin.Domain.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 信息:RESTful 风格结果集
|
||||
/// </summary>
|
||||
public record RestfulInfo<T> : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||
public ErrorCodes Code { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public T Data { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public object Msg { get; init; }
|
||||
}
|
8
src/backend/NetAdmin.Domain/Dto/Sys/Api/CreateApiReq.cs
Normal file
8
src/backend/NetAdmin.Domain/Dto/Sys/Api/CreateApiReq.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Api;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:创建接口
|
||||
/// </summary>
|
||||
public sealed record CreateApiReq : Sys_Api;
|
8
src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiReq.cs
Normal file
8
src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiReq.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Api;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:查询接口
|
||||
/// </summary>
|
||||
public sealed record QueryApiReq : Sys_Api;
|
38
src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs
Normal file
38
src/backend/NetAdmin.Domain/Dto/Sys/Api/QueryApiRsp.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||
using NetAdmin.Domain.DbMaps.Sys;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Api;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:查询接口
|
||||
/// </summary>
|
||||
public sealed record QueryApiRsp : Sys_Api
|
||||
{
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public new IEnumerable<QueryApiRsp> Children { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||
public override string Id { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Api.Method" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Method { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Api.Name" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Name { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Api.Namespace" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Namespace { get; init; }
|
||||
|
||||
/// <inheritdoc cref="Sys_Api.ParentId" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string ParentId { get; init; }
|
||||
|
||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public override string Summary { get; init; }
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:缓存统计
|
||||
/// </summary>
|
||||
public sealed record CacheStatisticsRsp : DataAbstraction
|
||||
{
|
||||
private static readonly Regex[] _regexes = {
|
||||
new(@"keyspace_hits:(\d+)", RegexOptions.Compiled)
|
||||
, new(@"keyspace_misses:(\d+)", RegexOptions.Compiled)
|
||||
, new(@"uptime_in_seconds:(\d+)", RegexOptions.Compiled)
|
||||
, new(@"used_cpu_sys:([\d\\.]+)", RegexOptions.Compiled)
|
||||
, new(@"used_cpu_user:([\d\\.]+)", RegexOptions.Compiled)
|
||||
, new(@"used_memory:(\d+)", RegexOptions.Compiled)
|
||||
, new("redis_version:(.+)", RegexOptions.Compiled)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class.
|
||||
/// </summary>
|
||||
public CacheStatisticsRsp() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheStatisticsRsp" /> class.
|
||||
/// </summary>
|
||||
public CacheStatisticsRsp(string redisResult)
|
||||
{
|
||||
KeyspaceHits = _regexes[0].Match(redisResult).Groups[1].Value.Trim().Int64Try(0);
|
||||
KeyspaceMisses = _regexes[1].Match(redisResult).Groups[1].Value.Trim().Int64Try(0);
|
||||
UpTime = _regexes[2].Match(redisResult).Groups[1].Value.Trim().Int64Try(0);
|
||||
UsedCpu = _regexes[3].Match(redisResult).Groups[1].Value.Trim().DecTry(0) +
|
||||
_regexes[4].Match(redisResult).Groups[1].Value.Trim().DecTry(0);
|
||||
UsedMemory = _regexes[5].Match(redisResult).Groups[1].Value.Trim().Int64Try(0);
|
||||
Version = _regexes[6].Match(redisResult).Groups[1].Value.Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 键总数
|
||||
/// </summary>
|
||||
public long DbSize { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 命中键的数量
|
||||
/// </summary>
|
||||
public long KeyspaceHits { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 未命中键的数量
|
||||
/// </summary>
|
||||
public long KeyspaceMisses { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Redis运行时间(秒)
|
||||
/// </summary>
|
||||
public long UpTime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用的CPU时间(秒)
|
||||
/// </summary>
|
||||
public decimal UsedCpu { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用的内存量(字节)
|
||||
/// </summary>
|
||||
public long UsedMemory { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Redis版本号
|
||||
/// </summary>
|
||||
public string Version { get; init; }
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:获取所有缓存项
|
||||
/// </summary>
|
||||
public sealed record GetAllEntriesReq : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库索引号
|
||||
/// </summary>
|
||||
public uint DbIndex { get; init; }
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Cache;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:获取所有缓存项
|
||||
/// </summary>
|
||||
public sealed record GetAllEntriesRsp : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GetAllEntriesRsp" /> class.
|
||||
/// </summary>
|
||||
public GetAllEntriesRsp() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GetAllEntriesRsp" /> class.
|
||||
/// </summary>
|
||||
public GetAllEntriesRsp(long absExp, string key, long sldExp, string data)
|
||||
{
|
||||
AbsExp = absExp;
|
||||
Key = key;
|
||||
SldExp = sldExp;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间
|
||||
/// </summary>
|
||||
public long AbsExp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存值
|
||||
/// </summary>
|
||||
public string Data { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存键
|
||||
/// </summary>
|
||||
public string Key { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 滑动过期时间
|
||||
/// </summary>
|
||||
public long SldExp { get; init; }
|
||||
}
|
28
src/backend/NetAdmin.Domain/Dto/Sys/Captcha/GetCaptchaRsp.cs
Normal file
28
src/backend/NetAdmin.Domain/Dto/Sys/Captcha/GetCaptchaRsp.cs
Normal file
@ -0,0 +1,28 @@
|
||||
namespace NetAdmin.Domain.Dto.Sys.Captcha;
|
||||
|
||||
/// <summary>
|
||||
/// 响应:获取人机校验图
|
||||
/// </summary>
|
||||
public sealed record GetCaptchaRsp : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 背景图(base64)
|
||||
/// </summary>
|
||||
public string BackgroundImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
public string Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 缺口x坐标
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public int SawOffsetX { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 滑块图(base64)
|
||||
/// </summary>
|
||||
public string SliderImage { get; init; }
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
using NetAdmin.Domain.Attributes.DataValidation;
|
||||
|
||||
namespace NetAdmin.Domain.Dto.Sys.Captcha;
|
||||
|
||||
/// <summary>
|
||||
/// 请求:完成人机验证
|
||||
/// </summary>
|
||||
public sealed record VerifyCaptchaReq : DataAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一编码
|
||||
/// </summary>
|
||||
[CultureRequired(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.唯一编码))]
|
||||
public string Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 缺口x坐标
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public int? SawOffsetX { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证数据
|
||||
/// </summary>
|
||||
[CultureRequired(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.验证数据))]
|
||||
public string VerifyData { get; init; }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user