Merge pull request 'main' (#1) from Admin.NET/Admin.NET.Pro:main into main

Reviewed-on: http://101.43.53.74:3000/zhao-fuck-sky/Admin.NET.Pro/pulls/1
This commit is contained in:
zhao-fuck-sky 2024-08-09 17:24:13 +08:00
commit 97043f00fd
57 changed files with 1034 additions and 1092 deletions

View File

@ -17,7 +17,7 @@
<PackageReference Include="AngleSharp" Version="1.1.2" />
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.7" />
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="8.14.8" />
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.4.11" />
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.4.11" />
<PackageReference Include="Furion.Pure" Version="4.9.4.11" />
@ -39,7 +39,7 @@
<PackageReference Include="SqlSugarCore" Version="5.1.4.166" />
<PackageReference Include="SSH.NET" Version="2024.1.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.4" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1059" />
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1064" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup>

View File

@ -33,7 +33,7 @@ public abstract class EntityBase : EntityBaseId, IDeletedFilter
/// <summary>
/// 更新时间
/// </summary>
[SugarColumn(ColumnDescription = "更新时间", IsOnlyIgnoreInsert = true)]
[SugarColumn(ColumnDescription = "更新时间")]
public virtual DateTime? UpdateTime { get; set; }
/// <summary>

View File

@ -60,6 +60,13 @@ public partial class SysCodeGenConfig : EntityBase
[MaxLength(64)]
public string? EffectType { get; set; }
/// <summary>
/// 外键库标识
/// </summary>
[SugarColumn(ColumnDescription = "外键库标识", Length = 20)]
[MaxLength(20)]
public string? FkConfigId { get; set; }
/// <summary>
/// 外键实体名称
/// </summary>

View File

@ -17,7 +17,7 @@ public class RetryEventHandlerExecutor : IEventHandlerExecutor
// 判断是否自定义了重试失败回调服务
var fallbackPolicyService = eventSubscribeAttribute?.FallbackPolicy == null
? null
: App.GetService(eventSubscribeAttribute.FallbackPolicy) as IEventFallbackPolicy;
: App.GetRequiredService(eventSubscribeAttribute.FallbackPolicy) as IEventFallbackPolicy;
await Retry.InvokeAsync(async () =>
{

View File

@ -25,8 +25,8 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
new SysConfig{ Id=1300000000131, Name="日志保留天数", Code=ConfigConst.SysLogRetentionDays, Value="180", SysFlag=YesNoEnum.Y, Remark="日志保留天数(天)", OrderNo=40, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000141, Name="记录操作日志", Code=ConfigConst.SysOpLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否记录操作日志", OrderNo=50, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000151, Name="单设备登录", Code=ConfigConst.SysSingleLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启单设备登录", OrderNo=60, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000161, Name="登录二次验证", Code=ConfigConst.SysSecondVer, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启登录二次验证", OrderNo=70, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000171, Name="图形验证码", Code=ConfigConst.SysCaptcha, Value="True", SysFlag=YesNoEnum.Y, Remark="是否开启图形验证码", OrderNo=80, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000161, Name="登录二次验证", Code=ConfigConst.SysSecondVer, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启登录二次验证", OrderNo=70, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000171, Name="图形验证码", Code=ConfigConst.SysCaptcha, Value="True", SysFlag=YesNoEnum.Y, Remark="是否开启图形验证码", OrderNo=80, GroupCode="WebConfig", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000181, Name="Token过期时间", Code=ConfigConst.SysTokenExpire, Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间分钟", OrderNo=90, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000191, Name="RefreshToken过期时间", Code=ConfigConst.SysRefreshTokenExpire, Value="20160", SysFlag=YesNoEnum.Y, Remark="刷新Token过期时间分钟一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=100, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code=ConfigConst.SysErrorMail, Value="True", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },

View File

@ -195,6 +195,7 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
new SysMenu{ Id=1310000000681, Pid=1310000000601, Title="FastCrud", Path="/develop/fastCrud", Name="sysFastCrud", Component="/system/fastCrud/index", Icon="ele-CoffeeCup", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150},
new SysMenu{ Id=1310000000701, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 },
new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="http://101.43.53.74:5050/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },

View File

@ -20,12 +20,12 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
{
return new[]
{
new SysOrg{ Id=1300000000101, Pid=0, Name="XXX公司", Code="1001", Type="101", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="XXX公司", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000102, Pid=1300000000101, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000103, Pid=1300000000101, Name="研发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="研发部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000104, Pid=1300000000101, Name="财务部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000105, Pid=1300000000104, Name="财务部1", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部1", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000106, Pid=1300000000104, Name="财务部2", Code="10010302", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部2", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId, Pid=0, Name="XXX公司", Code="1001", Type="101", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="XXX公司", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 1, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 2, Pid=SqlSugarConst.DefaultTenantId, Name="研发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="研发部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 3, Pid=SqlSugarConst.DefaultTenantId, Name="财务部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 4, Pid=SqlSugarConst.DefaultTenantId, Name="财务部1", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部1", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 5, Pid=SqlSugarConst.DefaultTenantId, Name="财务部2", Code="10010302", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="财务部2", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000201, Pid=0, Name="分公司1", Code="1002", Type="201", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="分公司1", TenantId=SqlSugarConst.DefaultTenantId },
new SysOrg{ Id=1300000000202, Pid=1300000000201, Name="市场部", Code="100201", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },

View File

@ -21,7 +21,7 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
return new[]
{
new SysTenant{ Id=SqlSugarConst.DefaultTenantId, OrgId=1300000000101, UserId=1300000000111, Host="https://gitee.com", TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
new SysTenant{ Id=SqlSugarConst.DefaultTenantId, OrgId=SqlSugarConst.DefaultTenantId, UserId=1300000000111, Host="https://gitee.com", TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
};
}
}

View File

@ -23,11 +23,11 @@ public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
return new[]
{
new SysUser{ Id=1300000000101, Account="superadmin", Password=encryptPassword, NickName="超级管理员", RealName="超级管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SuperAdmin, Remark="超级管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000111, Account="admin", Password=encryptPassword, NickName="系统管理员", RealName="系统管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SysAdmin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=1300000000101, PosId=1300000000102, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000112, Account="user1", Password=encryptPassword, NickName="部门主管", RealName="部门主管", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门主管", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=1300000000102, PosId=1300000000108, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000113, Account="user2", Password=encryptPassword, NickName="部门职员", RealName="部门职员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=1300000000103, PosId=1300000000110, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000114, Account="user3", Password=encryptPassword, NickName="普通用户", RealName="普通用户", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=1300000000104, PosId=1300000000115, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000115, Account="user4", Password=encryptPassword, NickName="其他", RealName="其他", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.Member, Remark="会员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=1300000000105, PosId=1300000000116, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000111, Account="admin", Password=encryptPassword, NickName="系统管理员", RealName="系统管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SysAdmin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId, PosId=1300000000102, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000112, Account="user1", Password=encryptPassword, NickName="部门主管", RealName="部门主管", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门主管", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 1, PosId=1300000000108, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000113, Account="user2", Password=encryptPassword, NickName="部门职员", RealName="部门职员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 2, PosId=1300000000110, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000114, Account="user3", Password=encryptPassword, NickName="普通用户", RealName="普通用户", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 3, PosId=1300000000115, TenantId=SqlSugarConst.DefaultTenantId },
new SysUser{ Id=1300000000115, Account="user4", Password=encryptPassword, NickName="其他", RealName="其他", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.Member, Remark="会员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 4, PosId=1300000000116, TenantId=SqlSugarConst.DefaultTenantId },
};
}
}

View File

@ -65,8 +65,11 @@ public class SysAuthService : IDynamicApiController, ITransient
// 判断密码错误次数缓存30分钟
var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
var passwdMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysPasswordMaxErrorTimes);
if (passwordErrorTimes >= passwdMaxErrorTimes)
var passwordMaxErrorTimes = await _sysConfigService.GetConfigValue<int>(ConfigConst.SysPasswordMaxErrorTimes);
// 若未配置或误配置为0、负数, 则默认密码错误次数最大为10次
if (passwordMaxErrorTimes < 1)
passwordMaxErrorTimes = 10;
if (passwordErrorTimes > passwordMaxErrorTimes)
throw Oops.Oh(ErrorCodeEnum.D1027);
// 是否开启验证码
@ -324,20 +327,6 @@ public class SysAuthService : IDynamicApiController, ITransient
_httpContextAccessor.HttpContext.SignoutToSwagger();
}
/// <summary>
/// 获取登录配置 🔖
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[SuppressMonitor]
[DisplayName("获取登录配置")]
public async Task<dynamic> GetLoginConfig()
{
var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSecondVer);
var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysCaptcha);
return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled };
}
/// <summary>
/// 获取验证码 🔖
/// </summary>
@ -349,7 +338,8 @@ public class SysAuthService : IDynamicApiController, ITransient
{
var codeId = YitIdHelper.NextId().ToString();
var captcha = _captcha.Generate(codeId);
return new { Id = codeId, Img = captcha.Base64 };
var expirySeconds = App.GetOptions<CaptchaOptions>()?.ExpirySeconds ?? 60;
return new { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds };
}
/// <summary>

View File

@ -56,6 +56,11 @@ public class CodeGenConfig
/// </summary>
public string EffectType { get; set; }
/// <summary>
/// 外键库标识
/// </summary>
public string FkConfigId { get; set; }
/// <summary>
/// 外键实体名称
/// </summary>

View File

@ -55,4 +55,14 @@ public class InfoSaveInput
/// ICP地址
/// </summary>
public string SysIcpUrl { get; set; }
/// <summary>
/// 登录二次验证
/// </summary>
public bool? SysSecondVer { get; set; }
/// <summary>
/// 图形验证码
/// </summary>
public bool? SysCaptcha { get; set; }
}

View File

@ -245,6 +245,8 @@ public class SysConfigService : IDynamicApiController, ITransient
var sysCopyright = await GetConfigValue<string>(ConfigConst.SysWebCopyright);
var sysIcp = await GetConfigValue<string>(ConfigConst.SysWebIcp);
var sysIcpUrl = await GetConfigValue<string>(ConfigConst.SysWebIcpUrl);
var sysSecondVer = await GetConfigValue<bool>(ConfigConst.SysSecondVer);
var sysCaptcha = await GetConfigValue<bool>(ConfigConst.SysCaptcha);
return new
{
@ -255,7 +257,9 @@ public class SysConfigService : IDynamicApiController, ITransient
SysWatermark = sysWatermark,
SysCopyright = sysCopyright,
SysIcp = sysIcp,
SysIcpUrl = sysIcpUrl
SysIcpUrl = sysIcpUrl,
SysSecondVer = sysSecondVer,
SysCaptcha = sysCaptcha
};
}
@ -308,5 +312,7 @@ public class SysConfigService : IDynamicApiController, ITransient
await UpdateConfigValue(ConfigConst.SysWebCopyright, input.SysCopyright);
await UpdateConfigValue(ConfigConst.SysWebIcp, input.SysIcp);
await UpdateConfigValue(ConfigConst.SysWebIcpUrl, input.SysIcpUrl);
await UpdateConfigValue(ConfigConst.SysSecondVer, (input.SysSecondVer ?? false).ToString());
await UpdateConfigValue(ConfigConst.SysCaptcha, (input.SysCaptcha ?? true).ToString());
}
}

View File

@ -279,7 +279,8 @@ public class SysFileService : IDynamicApiController, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private async Task<SysFile> GetFile([FromQuery] FileInput input)
[DisplayName("获取文件")]
public async Task<SysFile> GetFile([FromQuery] FileInput input)
{
var file = await _sysFileRep.CopyNew().GetFirstAsync(u => u.Id == input.Id);
return file ?? throw Oops.Oh(ErrorCodeEnum.D8000);

View File

@ -36,7 +36,8 @@ public static class SqlSugarFilter
public static void SetOrgEntityFilter(SqlSugarScopeProvider db)
{
// 若仅本人数据,则直接返回
if (SetDataScopeFilter(db) == (int)DataScopeEnum.Self) return;
var maxDataScope = SetDataScopeFilter(db);
if (maxDataScope == 0 || maxDataScope == (int)DataScopeEnum.Self) return;
var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
if (string.IsNullOrWhiteSpace(userId)) return;
@ -46,12 +47,15 @@ public static class SqlSugarFilter
var orgFilter = _cache.Get<ConcurrentDictionary<Type, LambdaExpression>>(cacheKey);
if (orgFilter == null)
{
// 获取用户最大数据范围,如果是全部数据,则跳过
if (maxDataScope == (int)DataScopeEnum.All) return;
// 获取用户所属机构,保证同一作用域
var orgIds = new List<long>();
Scoped.Create((factory, scope) =>
{
var services = scope.ServiceProvider;
orgIds = services.GetService<SysOrgService>().GetUserOrgIdList().GetAwaiter().GetResult();
orgIds = services.GetRequiredService<SysOrgService>().GetUserOrgIdList().GetAwaiter().GetResult();
});
if (orgIds == null || orgIds.Count == 0) return;
@ -96,6 +100,17 @@ public static class SqlSugarFilter
// 获取用户最大数据范围---仅本人数据
maxDataScope = App.GetRequiredService<SysCacheService>().Get<int>(CacheConst.KeyRoleMaxDataScope + userId);
// 若为0则获取用户机构组织集合建立缓存
if (maxDataScope == 0)
{
// 获取用户所属机构,保证同一作用域
Scoped.Create((factory, scope) =>
{
var services = scope.ServiceProvider;
services.GetRequiredService<SysOrgService>().GetUserOrgIdList().GetAwaiter().GetResult();
maxDataScope = services.GetRequiredService<SysCacheService>().Get<int>(CacheConst.KeyRoleMaxDataScope + userId);
});
}
if (maxDataScope != (int)DataScopeEnum.Self) return maxDataScope;
// 配置用户数据范围缓存

View File

@ -11,6 +11,9 @@ public static class SqlSugarSetup
// 多租户实例
public static ITenant ITenant { get; set; }
// 是否正在处理种子数据
private static bool _isHandlingSeedData = false;
/// <summary>
/// SqlSugar 上下文初始化
/// </summary>
@ -165,6 +168,9 @@ public static class SqlSugarSetup
// 数据审计
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
// 若正在处理种子数据则直接返回
if (_isHandlingSeedData) return;
// 新增/插入
if (entityInfo.OperationType == DataFilterType.InsertByObject)
{
@ -322,6 +328,8 @@ public static class SqlSugarSetup
// 初始化种子数据
if (config.SeedSettings.EnableInitSeed)
{
_isHandlingSeedData = true;
Log.Information($"初始化种子数据 {config.DbType} - {config.ConfigId}");
var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))))
.WhereIF(config.SeedSettings.EnableIncreSeed, u => u.IsDefined(typeof(IncreSeedAttribute), false))
@ -353,12 +361,12 @@ public static class SqlSugarSetup
if (seedData == null) continue;
var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
Console.WriteLine($"添加数据 {entityInfo.DbTableName} ({config.ConfigId} - {++count}/{sum})");
Console.WriteLine($"添加数据 {entityInfo.DbTableName} ({config.ConfigId} - {++count}/{sum},数据量:{seedData.Count()})");
if (entityType.GetCustomAttribute<SplitTableAttribute>(true) != null)
{
//拆分表的操作需要实体类型,而通过反射很难实现
//所以这里将Init方法写在“种子数据类”内部再传入 db 反射调用
// 拆分表的操作需要实体类型,而通过反射很难实现
// 所以这里将Init方法写在“种子数据类”内部再传入 db 反射调用
var hasInitMethod = seedType.GetMethod("Init");
var parameters = new object[] { db };
hasInitMethod?.Invoke(instance, parameters);
@ -369,9 +377,15 @@ public static class SqlSugarSetup
{
// 按主键进行批量增加和更新
var storage = dbProvider.StorageableByObject(seedData.ToList()).ToStorage();
storage.AsInsertable.ExecuteCommand();
// 先修改再插入,否则会更新修改时间字段
if (seedType.GetCustomAttribute<IgnoreUpdateSeedAttribute>() == null) // 有忽略更新种子特性时则不更新
storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null).Select(u => u.PropertyName).ToArray()).ExecuteCommand();
{
int updateCount = storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u => u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>() != null).Select(u => u.PropertyName).ToArray()).ExecuteCommand();
Console.WriteLine($" 修改 {updateCount}/{seedData.Count()} 条记录");
}
int insertCount = storage.AsInsertable.ExecuteCommand();
Console.WriteLine($" 插入 {insertCount}/{seedData.Count()} 条记录");
}
else
{
@ -381,6 +395,8 @@ public static class SqlSugarSetup
}
}
}
_isHandlingSeedData = false;
}
}

View File

@ -147,10 +147,17 @@ public static class ComputerUtil
/// <returns></returns>
public static string GetIpFromOnline()
{
var url = "https://www.ip.cn/api/index?ip&type=0";
var str = url.GetAsStringAsync().GetAwaiter().GetResult();
var resp = JSON.Deserialize<IpCnResp>(str);
return resp.Ip + " " + resp.Address;
try
{
var url = "https://www.ip.cn/api/index?ip&type=0";
var str = url.GetAsStringAsync().GetAwaiter().GetResult();
var resp = JSON.Deserialize<IpCnResp>(str);
return resp.Ip + " " + resp.Address;
}
catch
{
return "unknow";
}
}
public static bool IsUnix()

View File

@ -42,7 +42,7 @@ public class SysApprovalService : ITransient
var funcName = path[2];
var typeName = path[3];
var list = await App.GetService<ApprovalFlowService>().FormRoutes();
var list = await App.GetRequiredService<ApprovalFlowService>().FormRoutes();
if (list.Any(u => u.Contains(funcName) && u.Contains(typeName)))
{
var approvalFlow = new ApprovalFlowRecord

125
Web/eslint.config.mjs Normal file
View File

@ -0,0 +1,125 @@
import vue from 'eslint-plugin-vue';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import globals from 'globals';
import parser from 'vue-eslint-parser';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import js from '@eslint/js';
import { FlatCompat } from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
{
ignores: [
'**/*.sh',
'**/node_modules',
'**/lib',
'**/*.md',
'**/*.scss',
'**/*.woff',
'**/*.ttf',
'**/.vscode',
'**/.idea',
'**/dist',
'**/mock',
'**/public',
'**/bin',
'**/build',
'**/config',
'**/index.html',
'src/assets',
],
},
...compat.extends('plugin:vue/vue3-essential', 'plugin:vue/essential', 'eslint:recommended'),
{
plugins: {
vue,
'@typescript-eslint': typescriptEslint,
},
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
parser: parser,
ecmaVersion: 12,
sourceType: 'module',
parserOptions: {
parser: '@typescript-eslint/parser',
},
},
rules: {
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-redeclare': 'off',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
'vue/no-unused-vars': 'off',
'vue/no-mutating-props': 'warn',
'vue/custom-event-name-casing': 'off',
'vue/attributes-order': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/valid-v-else': 'warn',
'vue/no-deprecated-filter': 'warn',
'vue/html-self-closing': 'off',
'vue/no-multiple-template-root': 'off',
'vue/require-default-prop': 'off',
'vue/no-v-model-argument': 'off',
'vue/no-arrow-functions-in-watch': 'off',
'vue/no-template-key': 'off',
'vue/no-v-for-template-key': 'warn',
'vue/no-v-html': 'off',
'vue/comment-directive': 'off',
'vue/no-parsing-error': 'off',
'vue/no-deprecated-v-on-native-modifier': 'off',
'vue/multi-word-component-names': 'off',
'no-constant-binary-expression': 'warn',
'no-useless-escape': 'off',
'no-sparse-arrays': 'off',
'no-prototype-builtins': 'off',
'no-constant-condition': 'off',
'no-use-before-define': 'off',
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off',
'generator-star-spacing': 'off',
'no-unreachable': 'off',
'no-multiple-template-root': 'off',
'no-unused-vars': 'off',
'no-v-model-argument': 'off',
'no-case-declarations': 'off',
'no-console': 'off',
'no-redeclare': 'off',
},
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.vue'],
rules: {
'no-undef': 'off',
},
},
];

View File

@ -2,18 +2,24 @@
"name": "admin.net.pro",
"type": "module",
"version": "2.4.33",
"lastBuildTime": "2024.08.01",
"lastBuildTime": "2024.08.08",
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
"author": "zuohuaijun",
"license": "MIT",
"scripts": {
"dev": "vite",
"build": "node --max-old-space-size=8192 ./node_modules/vite/bin/vite build",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
"lint-fix": "eslint --fix src/",
"format": "prettier --write .",
"build-api": "cd api_build/ && build.bat"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@fast-crud/fast-crud": "^1.21.2",
"@fast-crud/fast-extends": "^1.21.2",
"@fast-crud/ui-element": "^1.21.2",
"@fast-crud/ui-interface": "^1.21.2",
"@iconify/vue": "^4.1.2",
"@logicflow/core": "^1.2.28",
"@logicflow/extension": "^1.2.28",
"@microsoft/signalr": "^8.0.7",
@ -25,7 +31,7 @@
"@wangeditor/editor-for-vue": "^5.1.12",
"animate.css": "^4.1.1",
"async-validator": "^4.2.5",
"axios": "^1.7.2",
"axios": "^1.7.3",
"countup.js": "^2.8.0",
"cropperjs": "^1.6.2",
"echarts": "^5.5.1",
@ -40,16 +46,17 @@
"js-table2excel": "^1.1.2",
"jsplumb": "^2.15.6",
"lodash-es": "^4.17.21",
"md-editor-v3": "^4.18.0",
"mitt": "^3.0.1",
"monaco-editor": "^0.50.0",
"mqtt": "^4.3.8",
"nprogress": "^0.2.0",
"ol": "^10.0.0",
"pinia": "^2.2.0",
"pinia": "^2.2.1",
"print-js": "^1.6.0",
"push.js": "^1.0.12",
"qrcodejs2-fixes": "^0.0.2",
"qs": "^6.12.3",
"qs": "^6.13.0",
"relation-graph": "^2.2.3",
"screenfull": "^6.0.2",
"sm-crypto-v2": "^1.9.1",
@ -57,46 +64,47 @@
"splitpanes": "^3.1.5",
"vcrontab-3": "^3.3.22",
"vform3-builds": "^3.0.10",
"vue": "^3.4.35",
"vue": "^3.4.36",
"vue-clipboard3": "^2.0.0",
"vue-demi": "^0.14.10",
"vue-demi": "0.14.6",
"vue-draggable-plus": "^0.5.3",
"vue-grid-layout": "3.0.0-beta1",
"vue-i18n": "^9.13.1",
"vue-json-pretty": "^2.4.0",
"vue-plugin-hiprint": "0.0.57-beta20",
"vue-router": "^4.4.1",
"vue-plugin-hiprint": "0.0.57-beta27",
"vue-router": "^4.4.3",
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vuedraggable": "4.0.3",
"vxe-pc-ui": "^4.0.82",
"vxe-pc-ui": "^4.0.91",
"vxe-table": "^4.7.59",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.5",
"xe-utils": "^3.5.28",
"xe-utils": "^3.5.29",
"xlsx-js-style": "^1.2.0"
},
"devDependencies": {
"@iconify/vue": "^4.1.2",
"@plugin-web-update-notification/vite": "^1.7.1",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.14.13",
"@types/node": "^20.14.14",
"@types/nprogress": "^0.2.3",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-vue": "^5.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.0",
"@vue/compiler-sfc": "^3.4.35",
"@vue/compiler-sfc": "^3.4.36",
"code-inspector-plugin": "^0.15.2",
"eslint": "^9.8.0",
"eslint-plugin-vue": "^9.27.0",
"globals": "^15.8.0",
"less": "^4.2.0",
"prettier": "^3.3.3",
"rollup-plugin-visualizer": "^5.12.0",
"sass": "^1.77.8",
"terser": "^5.31.3",
"terser": "^5.31.4",
"typescript": "^5.5.4",
"vite": "^5.3.5",
"vite": "^5.4.0",
"vite-plugin-cdn-import": "^1.0.1",
"vite-plugin-compression2": "^1.1.3",
"vite-plugin-vue-setup-extend": "^0.4.0",

View File

@ -220,6 +220,9 @@ table.hiprint-printElement-tableTarget {
.hiprint-printElement-tableTarget-border-td-all td:not(:nth-last-child(-n+2)) {
border-right: 1px solid;
}
.hiprint-printElement-tableTarget-border-td-all td:not(last-child) {
border-right: 1px solid;
}
.hiprint-printElement-tableTarget-border-td-all td:last-child {
border-left: 1px solid;
}

View File

@ -133,6 +133,9 @@ const loadSysInfo = () => {
themeConfig.value.watermarkText = data.sysWatermark;
//
themeConfig.value.copyright = data.sysCopyright;
//
themeConfig.value.secondVer = data.sysSecondVer;
themeConfig.value.captcha = data.sysCaptcha;
// favicon
updateFavicon(data.sysLogo);

View File

@ -173,49 +173,6 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysAuthLoginConfigGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysAuth/loginConfig`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary 🔖
@ -556,19 +513,6 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysAuthLoginConfigGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).apiSysAuthLoginConfigGet(options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary 🔖
@ -689,15 +633,6 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
async apiSysAuthCaptchaGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
return SysAuthApiFp(configuration).apiSysAuthCaptchaGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysAuthLoginConfigGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
return SysAuthApiFp(configuration).apiSysAuthLoginConfigGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary 🔖
@ -798,16 +733,6 @@ export class SysAuthApi extends BaseAPI {
public async apiSysAuthCaptchaGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
return SysAuthApiFp(this.configuration).apiSysAuthCaptchaGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysAuthApi
*/
public async apiSysAuthLoginConfigGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
return SysAuthApiFp(this.configuration).apiSysAuthLoginConfigGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary 🔖

View File

@ -38,6 +38,7 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -64,7 +65,7 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysCodeGenConfigDetailGet: async (id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
apiSysCodeGenConfigDetailGet: async (id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysCodeGenConfig/detail`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@ -121,6 +122,10 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
localVarQueryParameter['EffectType'] = effectType;
}
if (fkConfigId !== undefined) {
localVarQueryParameter['FkConfigId'] = fkConfigId;
}
if (fkEntityName !== undefined) {
localVarQueryParameter['FkEntityName'] = fkEntityName;
}
@ -241,6 +246,7 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -267,7 +273,7 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysCodeGenConfigListGet: async (id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
apiSysCodeGenConfigListGet: async (id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysCodeGenConfig/list`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@ -324,6 +330,10 @@ export const SysCodeGenConfigApiAxiosParamCreator = function (configuration?: Co
localVarQueryParameter['EffectType'] = effectType;
}
if (fkConfigId !== undefined) {
localVarQueryParameter['FkConfigId'] = fkConfigId;
}
if (fkEntityName !== undefined) {
localVarQueryParameter['FkEntityName'] = fkEntityName;
}
@ -501,6 +511,7 @@ export const SysCodeGenConfigApiFp = function(configuration?: Configuration) {
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -527,8 +538,8 @@ export const SysCodeGenConfigApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysCodeGenConfig>>> {
const localVarAxiosArgs = await SysCodeGenConfigApiAxiosParamCreator(configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options);
async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysCodeGenConfig>>> {
const localVarAxiosArgs = await SysCodeGenConfigApiAxiosParamCreator(configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
@ -546,6 +557,7 @@ export const SysCodeGenConfigApiFp = function(configuration?: Configuration) {
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -572,8 +584,8 @@ export const SysCodeGenConfigApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListCodeGenConfig>>> {
const localVarAxiosArgs = await SysCodeGenConfigApiAxiosParamCreator(configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options);
async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListCodeGenConfig>>> {
const localVarAxiosArgs = await SysCodeGenConfigApiAxiosParamCreator(configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
@ -614,6 +626,7 @@ export const SysCodeGenConfigApiFactory = function (configuration?: Configuratio
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -640,8 +653,8 @@ export const SysCodeGenConfigApiFactory = function (configuration?: Configuratio
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysCodeGenConfig>> {
return SysCodeGenConfigApiFp(configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(axios, basePath));
async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysCodeGenConfig>> {
return SysCodeGenConfigApiFp(configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(axios, basePath));
},
/**
*
@ -655,6 +668,7 @@ export const SysCodeGenConfigApiFactory = function (configuration?: Configuratio
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -681,8 +695,8 @@ export const SysCodeGenConfigApiFactory = function (configuration?: Configuratio
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListCodeGenConfig>> {
return SysCodeGenConfigApiFp(configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(axios, basePath));
async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListCodeGenConfig>> {
return SysCodeGenConfigApiFp(configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(axios, basePath));
},
/**
*
@ -716,6 +730,7 @@ export class SysCodeGenConfigApi extends BaseAPI {
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -743,8 +758,8 @@ export class SysCodeGenConfigApi extends BaseAPI {
* @throws {RequiredError}
* @memberof SysCodeGenConfigApi
*/
public async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysCodeGenConfig>> {
return SysCodeGenConfigApiFp(this.configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(this.axios, this.basePath));
public async apiSysCodeGenConfigDetailGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysCodeGenConfig>> {
return SysCodeGenConfigApiFp(this.configuration).apiSysCodeGenConfigDetailGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(this.axios, this.basePath));
}
/**
*
@ -758,6 +773,7 @@ export class SysCodeGenConfigApi extends BaseAPI {
* @param {string} [columnComment]
* @param {string} [netType] .NET类型
* @param {string} [effectType]
* @param {string} [fkConfigId]
* @param {string} [fkEntityName]
* @param {string} [fkTableName]
* @param {string} [lowerFkEntityName] ()
@ -785,8 +801,8 @@ export class SysCodeGenConfigApi extends BaseAPI {
* @throws {RequiredError}
* @memberof SysCodeGenConfigApi
*/
public async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListCodeGenConfig>> {
return SysCodeGenConfigApiFp(this.configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(this.axios, this.basePath));
public async apiSysCodeGenConfigListGet(id?: number, codeGenId?: number, columnName?: string, propertyName?: string, columnLength?: number, lowerPropertyName?: string, columnComment?: string, netType?: string, effectType?: string, fkConfigId?: string, fkEntityName?: string, fkTableName?: string, lowerFkEntityName?: string, fkColumnName?: string, fkLinkColumnName?: string, lowerFkColumnName?: string, fkColumnNetType?: string, dictTypeCode?: string, whetherRetract?: string, whetherRequired?: string, whetherSortable?: string, queryWhether?: string, queryType?: string, whetherTable?: string, whetherAddUpdate?: string, columnKey?: string, dataType?: string, whetherCommon?: string, tableNickName?: string, displayColumn?: string, valueColumn?: string, pidColumn?: string, orderNo?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListCodeGenConfig>> {
return SysCodeGenConfigApiFp(this.configuration).apiSysCodeGenConfigListGet(id, codeGenId, columnName, propertyName, columnLength, lowerPropertyName, columnComment, netType, effectType, fkConfigId, fkEntityName, fkTableName, lowerFkEntityName, fkColumnName, fkLinkColumnName, lowerFkColumnName, fkColumnNetType, dictTypeCode, whetherRetract, whetherRequired, whetherSortable, queryWhether, queryType, whetherTable, whetherAddUpdate, columnKey, dataType, whetherCommon, tableNickName, displayColumn, valueColumn, pidColumn, orderNo, options).then((request) => request(this.axios, this.basePath));
}
/**
*

View File

@ -92,6 +92,14 @@ export interface CodeGenConfig {
*/
effectType?: string | null;
/**
*
*
* @type {string}
* @memberof CodeGenConfig
*/
fkConfigId?: string | null;
/**
*
*

View File

@ -91,4 +91,20 @@ export interface InfoSaveInput {
* @memberof InfoSaveInput
*/
sysIcpUrl?: string | null;
/**
*
*
* @type {boolean}
* @memberof InfoSaveInput
*/
sysSecondVer?: boolean | null;
/**
*
*
* @type {boolean}
* @memberof InfoSaveInput
*/
sysCaptcha?: boolean | null;
}

View File

@ -140,6 +140,14 @@ export interface SysCodeGenConfig {
*/
effectType?: string | null;
/**
*
*
* @type {string}
* @memberof SysCodeGenConfig
*/
fkConfigId?: string | null;
/**
*
*

View File

@ -1,12 +1,13 @@
<template>
<div class="notice-bar" :style="{ background, height: `${height}px` }" v-show="!state.isMode">
<div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }">
<div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }" ref="noticeBarWarpRef">
<i v-if="leftIcon" class="notice-bar-warp-left-icon" :class="leftIcon"></i>
<div class="notice-bar-warp-text-box" ref="noticeBarWarpRef">
<div class="notice-bar-warp-text" ref="noticeBarTextRef" v-if="!scrollable">{{ text }}</div>
<div class="notice-bar-warp-slot" v-else><slot /></div>
<div class="notice-bar-warp-text-box">
<div class="notice-bar-warp-text" ref="noticeBarTextRef">
<div v-html="text" data-slate-editor />
</div>
</div>
<SvgIcon :name="rightIcon" v-if="rightIcon" class="notice-bar-warp-right-icon" @click="onRightIconClick" />
<!-- <SvgIcon :name="rightIcon" v-if="rightIcon" class="notice-bar-warp-right-icon" @click="onRightIconClick" /> -->
</div>
</div>
</template>
@ -14,117 +15,65 @@
<script setup lang="ts" name="noticeBar">
import { reactive, ref, onMounted, nextTick } from 'vue';
//
const props = defineProps({
// closeable link
mode: {
type: String,
default: () => '',
},
//
text: {
type: String,
default: () => '',
},
//
color: {
type: String,
default: () => 'var(--el-color-warning)',
},
//
background: {
type: String,
default: () => 'var(--el-color-warning-light-9)',
},
// px
size: {
type: [Number, String],
default: () => 14,
},
// px
height: {
type: Number,
default: () => 40,
},
// (s)
delay: {
type: Number,
default: () => 1,
},
// (px/s)
speed: {
type: Number,
default: () => 100,
},
//
scrollable: {
type: Boolean,
default: () => false,
},
//
leftIcon: {
type: String,
default: () => '',
},
//
rightIcon: {
type: String,
default: () => '',
},
mode: { type: String, default: '' }, // closeable link
text: { type: String, default: '欢迎使用 Admin.NET 通用权限开发框架 <a href="https://gitee.com/zuohuaijun/Admin.NET" target="_blank">https://gitee.com/zuohuaijun/Admin.NET</a>' }, //
color: { type: String, default: 'var(--el-color-warning)' }, //
background: { type: String, default: 'var(--el-color-warning-light-9)' }, //
size: { type: [Number, String], default: 14 }, // px
height: { type: Number, default: 40 }, // px
delay: { type: Number, default: 1 }, // (s)
speed: { type: Number, default: 100 }, // (px/s)
scrollable: { type: Boolean, default: false }, //
leftIcon: { type: String, default: 'iconfont icon-tongzhi2' }, //
rightIcon: { type: String, default: '' }, //
});
// /
const emit = defineEmits(['close', 'link']);
//
const noticeBarWarpRef = ref();
const noticeBarTextRef = ref();
const noticeBarWarpRef = ref<HTMLDivElement | null>(null);
const noticeBarTextRef = ref<HTMLDivElement | null>(null);
const state = reactive({
order: 1,
oneTime: 0,
twoTime: 0,
isMode: false,
warpOWidth: 0,
textOWidth: 0,
isMode: false,
animationDuration: 0,
});
// animation
//
onMounted(() => {
if (!props.scrollable) {
initAnimation();
}
});
//
const initAnimation = () => {
nextTick(() => {
state.warpOWidth = noticeBarWarpRef.value.offsetWidth;
state.textOWidth = noticeBarTextRef.value.offsetWidth;
document.styleSheets[0].insertRule(`@keyframes oneAnimation {0% {left: 0px;} 100% {left: -${state.textOWidth}px;}}`);
document.styleSheets[0].insertRule(`@keyframes twoAnimation {0% {left: ${state.warpOWidth}px;} 100% {left: -${state.textOWidth}px;}}`);
computeAnimationTime();
setTimeout(() => {
changeAnimation();
}, props.delay * 1000);
if (noticeBarWarpRef.value && noticeBarTextRef.value) {
state.warpOWidth = noticeBarWarpRef.value.offsetWidth;
state.textOWidth = noticeBarTextRef.value.scrollWidth;
state.animationDuration = (state.textOWidth + state.warpOWidth) / props.speed;
// Clear existing animation styles
noticeBarTextRef.value.style.animation = 'none';
noticeBarTextRef.value.offsetHeight; // Trigger reflow
noticeBarTextRef.value.style.animation = `marquee ${state.animationDuration}s linear infinite`;
// Define keyframes for marquee animation
const keyframes = `
@keyframes marquee {
0% { transform: translateX(${state.warpOWidth}px); }
100% { transform: translateX(-${state.textOWidth}px); }
}
`;
const styleSheet = document.createElement('style');
styleSheet.innerText = keyframes;
document.head.appendChild(styleSheet);
}
});
};
// animation
const computeAnimationTime = () => {
state.oneTime = state.textOWidth / props.speed;
state.twoTime = (state.textOWidth + state.warpOWidth) / props.speed;
};
// animation
const changeAnimation = () => {
if (state.order === 1) {
noticeBarTextRef.value.style.cssText = `animation: oneAnimation ${state.oneTime}s linear; opactity: 1;}`;
state.order = 2;
} else {
noticeBarTextRef.value.style.cssText = `animation: twoAnimation ${state.twoTime}s linear infinite; opacity: 1;`;
}
};
// animation
const listenerAnimationend = () => {
noticeBarTextRef.value.addEventListener(
'animationend',
() => {
changeAnimation();
},
false
);
};
// icon
const onRightIconClick = () => {
if (!props.mode) return false;
@ -135,12 +84,6 @@ const onRightIconClick = () => {
emit('link');
}
};
//
onMounted(() => {
if (props.scrollable) return false;
initAnimation();
listenerAnimationend();
});
</script>
<style scoped lang="scss">
@ -160,19 +103,12 @@ onMounted(() => {
align-items: center;
overflow: hidden;
position: relative;
.notice-bar-warp-text {
white-space: nowrap;
position: absolute;
left: 0;
}
.notice-bar-warp-slot {
width: 100%;
white-space: nowrap;
:deep(.el-carousel__item) {
display: flex;
align-items: center;
}
}
margin-right: 35px;
// .notice-bar-warp-text {
// white-space: nowrap;
// position: absolute;
// left: 0;
// }
}
.notice-bar-warp-left-icon {
width: 24px;

View File

@ -492,7 +492,7 @@ const cliChineseColor = (e: any) => {
};
//
const getThemeConfig = computed(() => {
const updateThemeConfig = () => {
if (!themeConfig.value.columnsMenuWidth) {
themeConfig.value.columnsMenuWidth = 70;
}
@ -502,6 +502,9 @@ const getThemeConfig = computed(() => {
if (!themeConfig.value.columnsLogoHeight) {
themeConfig.value.columnsLogoHeight = 50;
}
};
const getThemeConfig = computed(() => {
updateThemeConfig();
return themeConfig.value;
});
// 1

View File

@ -7,7 +7,6 @@ import { i18n } from '/@/i18n/index';
import other from '/@/utils/other';
import ElementPlus from 'element-plus';
import '/@/theme/index.scss';
import VueGridLayout from 'vue-grid-layout';
// 动画库
import 'animate.css';
// 栅格布局
@ -31,4 +30,92 @@ const app = createApp(App);
directive(app);
other.elSvg(app);
// #region FastCrud配置
import { FastCrud } from '@fast-crud/fast-crud';
import '@fast-crud/fast-crud/dist/style.css';
import ui from '@fast-crud/ui-element';
import { FsExtendsUploader, FsExtendsEditor } from '@fast-crud/fast-extends';
import '@fast-crud/fast-extends/dist/style.css';
app.use(ui);
app.use(FastCrud, {
i18n,
commonOptions() {
return {
request: {
transformQuery: ({ page, form, sort }) => {
const order = sort == null ? {} : { orderProp: sort.prop, orderAsc: sort.asc };
return { page: page?.currentPage, pageSize: page?.pageSize, ...form, ...order };
},
// page请求结果转换
transformRes: ({ res }) => {
const records = res.data.result.items;
const total = res.data.result.total;
const currentPage = res.data.result.page;
const pageSize = res.data.result.pageSize;
return {
currentPage: currentPage,
pageSize: pageSize,
total: total,
records,
};
},
form: {
display: 'flex', // 表单布局
labelWidth: '120px', // 表单label宽度
},
},
};
},
});
const baseURL = import.meta.env.VITE_API_URL;
import request from '/@/utils/request';
import { getToken } from '/@/utils/axios-utils';
// 文件上传
app.use(FsExtendsUploader, {
defaultType: 'form',
form: {
action: baseURL + '/api/sysFile/uploadFile',
name: 'file',
withCredentials: false,
uploadRequest: async (props) => {
const { action, file, onProgress } = props;
const data = new FormData();
data.append('file', file);
const token = getToken();
const Authorization = token ? `Bearer ${token}` : null;
const result = await request({
url: action,
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data',
Authorization: Authorization,
},
timeout: 60000,
onUploadProgress(progress) {
onProgress({ percent: Math.round((progress.loaded / progress.total!) * 100) });
},
});
if (result) {
return result.data;
} else {
throw new Error(result.message);
}
},
async successHandle(ret: any) {
return {
url: baseURL + '/' + ret.result.filePath + '/' + ret.result.id + ret.result.suffix,
key: ret.result.fileName,
};
},
},
});
// 富文本编辑器
app.use(FsExtendsEditor, {
wangEditor: {},
});
// #endregion
app.use(pinia).use(router).use(ElementPlus).use(setupVXETable).use(i18n).use(VueGridLayout).use(VForm3).use(VueSignaturePad).use(vue3TreeOrg).mount('#app');

View File

@ -29,13 +29,15 @@
overflow: auto;
}
// 在小屏幕中取消表单左边距
.el-form-item__label-wrap{
.el-form-item__label-wrap {
margin-left: 0px !important;
}
// 列表页查询表单内的输入框宽度适配
.el-form--inline .el-form-item .el-select,
.el-form--inline .el-form-item .el-input
{
width: 100% !important;
}
.el-form--inline .el-form-item .el-select,
.el-form--inline .el-form-item .el-input {
width: 100% !important;
}
.el-form--inline .el-form-item:has(.el-form-item__label) {
margin-right: 0;
}
}

View File

@ -45,58 +45,60 @@ declare interface RoutesListState<T = any> {
// 布局配置
declare interface ThemeConfigState {
themeConfig: {
isDrawer: boolean;
primary: string;
topBar: string;
topBarColor: string;
isTopBarColorGradual: boolean;
menuBar: string;
menuBarColor: string;
menuBarActiveColor: string;
isMenuBarColorGradual: boolean;
columnsMenuBar: string;
columnsMenuBarColor: string;
isColumnsMenuBarColorGradual: boolean;
isColumnsMenuHoverPreload: boolean;
columnsLogoHeight: number;
columnsMenuWidth: number;
columnsMenuHeight: number;
isCollapse: boolean;
isUniqueOpened: boolean;
isFixedHeader: boolean;
isFixedHeaderChange: boolean;
isClassicSplitMenu: boolean;
isLockScreen: boolean;
lockScreenTime: number;
isShowLogo: boolean;
isShowLogoChange: boolean;
isBreadcrumb: boolean;
isTagsview: boolean;
isBreadcrumbIcon: boolean;
isTagsviewIcon: boolean;
isCacheTagsView: boolean;
isSortableTagsView: boolean;
isShareTagsView: boolean;
isFooter: boolean;
isGrayscale: boolean;
isInvert: boolean;
isIsDark: boolean;
isWatermark: boolean;
watermarkText: string;
tagsStyle: string;
animation: string;
columnsAsideStyle: string;
columnsAsideLayout: string;
layout: string;
isRequestRoutes: boolean;
globalTitle: string;
globalViceTitle: string;
globalViceTitleMsg: string;
copyright: string;
globalI18n: string;
globalComponentSize: string;
isDrawer: boolean; // 是否开启抽屉配置
primary: string; // 主题颜色
topBar: string; // 顶部栏背景
topBarColor: string; // 顶部栏背景色
isTopBarColorGradual: boolean; // 是否顶部栏背景渐变
menuBar: string; // 侧边栏菜单栏背景
menuBarColor: string; // 侧边栏菜单栏背景色
menuBarActiveColor: string; // 侧边栏激活项背景色
isMenuBarColorGradual: boolean; // 是否侧边栏菜单栏背景渐变
columnsMenuBar: string; // 侧边栏菜单栏背景
columnsMenuBarColor: string; // 侧边栏菜单栏背景
isColumnsMenuBarColorGradual: boolean; // 是否侧边栏菜单栏背景渐变
isColumnsMenuHoverPreload: boolean; // 是否鼠标悬停预加载路由
columnsLogoHeight: number; // 侧边栏logo高度
columnsMenuWidth: number; // 侧边栏宽度
columnsMenuHeight: number; // 侧边栏高度
isCollapse: boolean; // 是否水平折叠收起菜单(支持手机端)
isUniqueOpened: boolean; // 是否只保持一个菜单的展开
isFixedHeader: boolean; // 是否固定头部
isFixedHeaderChange: boolean; // 是否固定头部
isClassicSplitMenu: boolean; // 是否分割菜单
isLockScreen: boolean; // 是否开启锁屏
lockScreenTime: number; // 锁屏时间
isShowLogo: boolean; // 是否显示logo
isShowLogoChange: boolean; // 是否显示logo动画
isBreadcrumb: boolean; // 是否显示面包屑
isTagsview: boolean; // 是否显示多标签页
isBreadcrumbIcon: boolean; // 是否显示面包屑图标
isTagsviewIcon: boolean; // 是否显示多标签页图标
isCacheTagsView: boolean; // 是否缓存 TagsView
isSortableTagsView: boolean; // 是否开启拖拽排序
isShareTagsView: boolean; // 是否开启多标签页缓存
isFooter: boolean; // 是否显示页脚
isGrayscale: boolean; // 是否灰度模式
isInvert: boolean; // 是否色弱模式
isIsDark: boolean; // 是否暗黑模式
isWatermark: boolean; // 是否开启水印
watermarkText: string; // 水印内容
tagsStyle: string; // 标签页主题
animation: string; // 动画
columnsAsideStyle: string; // 侧边栏主题
columnsAsideLayout: string; // 侧边栏布局
layout: string; // 布局模式
isRequestRoutes: boolean; // 是否开启路由懒加载
globalI18n: string; // 是否开启国际化
globalComponentSize: string; // 全局组件大小
globalTitle: string; // 全局标题
globalViceTitle: string; // 全局副标题
globalViceTitleMsg: string; // 全局副标题消息
copyright: string; // 版权信息
logoUrl: string; // 系统 logo 地址
icp: string; // Icp备案号
icpUrl: string; // Icp地址
secondVer: boolean; // 是否开启二级验证
captcha: boolean; // 是否开启验证码
};
}

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,7 @@
<script lang="ts">
export default {
title: '关于项目',
icon: 'ele-Setting',
icon: 'ele-QuestionFilled',
description: '点个星星支持一下',
};
</script>

View File

@ -19,7 +19,7 @@
<script lang="ts">
export default {
title: '更新记录',
icon: 'ele-Message',
icon: 'ele-DocumentCopy',
description: '当前项目更新记录',
};
</script>
@ -69,4 +69,8 @@ onMounted(() => {
font-size: 12px;
margin-top: 10px;
}
.commit {
max-height: 500px;
overflow: auto;
}
</style>

View File

@ -1,5 +1,9 @@
<template>
<el-card shadow="hover" header="快捷入口">
<template #header>
<el-icon style="display: inline; vertical-align: middle"> <ele-Guide /> </el-icon>
<span style=""> 快捷入口 </span>
</template>
<ul class="myMods">
<li v-for="mod in myMods" :key="mod.path!">
<router-link :to="{ path: mod.path! }">
@ -17,25 +21,21 @@
<el-drawer title="添加应用" v-model="modsDrawer" :size="520" destroy-on-close :before-close="beforeClose">
<div class="setMods mt15">
<h4>我的常用 ( {{ myMods.length }} )</h4>
<draggable tag="ul" v-model="myMods" animation="200" item-key="id" group="app" class="draggable-box" force-fallback fallback-on-body>
<template #item="{ element }">
<li>
<SvgIcon :name="element.meta.icon" style="font-size: 18px" />
<p>{{ element.meta.title }}</p>
</li>
</template>
</draggable>
<VueDraggable tag="ul" v-model="myMods" :animation="200" group="app" class="draggable-box">
<li v-for="item in myMods" :key="item.id">
<SvgIcon :name="item.meta?.icon" style="font-size: 18px" />
<p>{{ item.meta?.title }}</p>
</li>
</VueDraggable>
</div>
<div class="setMods">
<h4>全部应用 ( {{ filterMods.length }} )</h4>
<draggable tag="ul" v-model="filterMods" animation="200" item-key="id" group="app" class="draggable-box-all" force-fallback fallback-on-body>
<template #item="{ element }">
<li :style="{ background: element.meta.color || '#909399' }">
<SvgIcon :name="element.meta.icon" style="font-size: 18px" />
<p>{{ element.meta.title }}</p>
</li>
</template>
</draggable>
<VueDraggable tag="ul" v-model="filterMods" :animation="200" group="app" class="draggable-box-all">
<li v-for="item in filterMods" :key="item.id" :style="{ background: '#909399' }">
<SvgIcon :name="item.meta?.icon" style="font-size: 18px" />
<p>{{ item.meta?.title }}</p>
</li>
</VueDraggable>
</div>
<template #footer>
<div style="margin: 0 20px 20px 0">
@ -50,17 +50,17 @@
<script lang="ts">
export default {
title: '快捷入口',
icon: 'ele-Monitor',
icon: 'ele-Guide',
description: '可以配置的快捷入口',
};
</script>
<script setup lang="ts" name="myapp">
import { reactive, onMounted, ref } from 'vue';
import { onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { useRequestOldRoutes } from '/@/stores/requestOldRoutes';
import { storeToRefs } from 'pinia';
import draggable from 'vuedraggable';
import { VueDraggable } from 'vue-draggable-plus';
import { useUserInfo } from '/@/stores/userInfo';
import { getAPI } from '/@/utils/axios-utils';
@ -74,10 +74,6 @@ const filterMods = ref<MenuOutput[]>([]); // 过滤我的常用后的应用
const modsDrawer = ref<boolean>(false);
const { userInfos } = storeToRefs(useUserInfo());
const state = reactive({
navError: '',
navData: [],
});
onMounted(() => {
getMods();

View File

@ -8,16 +8,12 @@
<div class="custome-canlendar">
<el-calendar v-model="state.calendarValue" ref="calendar">
<template #header="{date }">
<span>{{ date }}</span>
<template #header="{ date }">
<span>{{ date }}</span>
<el-button-group>
<el-button size="small" @click="selectDate('prev-month')">
上个月
</el-button>
<el-button size="small" @click="selectDate('prev-month')"> 上个月 </el-button>
<el-button size="small" @click="selectDate('today')">今天</el-button>
<el-button size="small" @click="selectDate('next-month')">
下个月
</el-button>
<el-button size="small" @click="selectDate('next-month')"> 下个月 </el-button>
</el-button-group>
</template>
<template #date-cell="{ data }">
@ -30,7 +26,6 @@
{{ solarDate2lunar(data.day) }}
</div>
</div>
</template>
</el-calendar>
</div>
@ -58,7 +53,7 @@
<script lang="ts">
export default {
title: '日程',
icon: 'ele-Odometer',
icon: 'ele-Calendar',
description: '日程演示',
};
</script>

View File

@ -19,7 +19,7 @@
<script lang="ts">
export default {
title: '版本信息',
icon: 'ele-Monitor',
icon: 'ele-InfoFilled',
description: '版本信息原子组件演示',
};
</script>

View File

@ -45,7 +45,7 @@ const { themeConfig } = storeToRefs(storesThemeConfig);
export default {
title: '欢迎',
icon: 'ele-Present',
icon: 'ele-Promotion',
description: '项目特色以及文档链接',
};
</script>

View File

@ -1,13 +1,21 @@
<template>
<div>
<NoticeBar style="margin: 4px" />
<div style="float: right; margin: -35px 10px 0 0">
<el-button v-if="customizing" type="warning" icon="ele-Check" circle plain @click="save"></el-button>
<el-button v-else type="warning" icon="ele-Edit" circle plain @click="custom"></el-button>
</div>
</div>
<div :class="['widgets-home', customizing ? 'customizing' : '']" ref="main">
<div class="widgets-content">
<div class="widgets-top">
<!-- <div class="widgets-top">
<div class="widgets-top-title">控制台</div>
<div class="widgets-top-actions">
<el-button v-if="customizing" type="primary" icon="ele-Check" round @click="save">完成</el-button>
<el-button v-else type="primary" icon="ele-Edit" round @click="custom">自定义</el-button>
</div>
</div>
</div> -->
<div class="widgets" ref="widgetsRef">
<div class="widgets-wrapper">
<div v-if="nowCompsList.length <= 0" class="no-widgets">
@ -15,29 +23,19 @@
</div>
<el-row :gutter="8">
<el-col v-for="(item, index) in grid.layout" :key="index" :md="item" :xs="24">
<draggable
v-model="grid.copmsList[index]"
animation="200"
handle=".customize-overlay"
group="people"
item-key="com"
drag-class="aaaaa"
force-fallback
fallback-on-body
class="draggable-box"
>
<template #item="{ element }">
<VueDraggable v-model="grid.copmsList[index]" :animation="200" group="grid" handle=".customize-overlay" class="draggable-box">
<div v-for="item in grid.copmsList[index]" :key="item">
<div class="widgets-item mb8">
<component :is="allComps[element]"></component>
<component :is="allComps[item]"></component>
<div v-if="customizing" class="customize-overlay">
<el-button class="close" type="danger" plain icon="ele-Close" @click="remove(element)"></el-button>
<label v-if="allComps[element]">
<el-icon> <component :is="allComps[element].icon" /> </el-icon>{{ allComps[element].title }}
<el-button class="close" type="danger" plain icon="ele-Close" @click="remove(item)"></el-button>
<label v-if="allComps[item]">
<el-icon> <component :is="allComps[item].icon" /> </el-icon>{{ allComps[item].title }}
</label>
</div>
</div>
</template>
</draggable>
</div>
</VueDraggable>
</el-col>
</el-row>
</div>
@ -136,10 +134,11 @@
<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue';
import draggable from 'vuedraggable';
import { VueDraggable } from 'vue-draggable-plus';
import { clone } from '/@/utils/arrayOperation';
import allComps from './components/index';
import { Local } from '/@/utils/storage';
import NoticeBar from '/@/components/noticeBar/index.vue';
interface Grid {
layout: number[];
@ -148,7 +147,7 @@ interface Grid {
const defaultGrid = {
layout: [12, 6, 6],
copmsList: [
['welcome', 'commit'],
['welcome', 'myapp', 'commit'],
['about', 'version'],
['timer', 'schedule'],
],
@ -266,7 +265,7 @@ const close = () => {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
position: relative;
overflow: auto;
padding-top: 20px;
padding-top: 10px;
}
.widgets-aside-title {
margin-top: 10px;

View File

@ -44,8 +44,8 @@
</el-col>
<el-col :span="1"></el-col>
<el-col :span="8">
<div class="login-content-code">
<img class="login-content-code-img" @click="getCaptcha" width="130px" height="38px" :src="state.captchaImage" style="cursor: pointer" />
<div :class="[state.expirySeconds > 0 ? 'login-content-code' : 'login-content-code-expired']" @click="getCaptcha">
<img class="login-content-code-img" width="130px" height="38px" :src="state.captchaImage" style="cursor: pointer" />
</div>
</el-col>
</el-form-item>
@ -131,8 +131,13 @@ const state = reactive({
captchaEnabled: false,
isPassRotate: false,
capsLockVisible: false,
expirySeconds: 60, //
});
//
let timer: any = null;
//
onMounted(async () => {
// URLToken
var accessToken = route.query.token;
@ -141,19 +146,29 @@ onMounted(async () => {
}
//
var res1 = await getAPI(SysAuthApi).apiSysAuthLoginConfigGet();
state.secondVerEnabled = res1.data.result.secondVerEnabled ?? true;
state.captchaEnabled = res1.data.result.captchaEnabled ?? true;
state.secondVerEnabled = themeConfig.value.secondVer ?? false;
state.captchaEnabled = themeConfig.value.captcha ?? true;
//
getCaptcha();
//
if (state.captchaEnabled) {
timer = setInterval(() => {
if (state.expirySeconds > 0) state.expirySeconds -= 1;
}, 1000);
}
// /CapsLK
document.addEventListener('keyup', handleKeyPress);
});
//
//
onUnmounted(() => {
//
clearInterval(timer);
timer = null;
document.removeEventListener('keyup', handleKeyPress);
});
@ -171,6 +186,7 @@ const getCaptcha = async () => {
var res = await getAPI(SysAuthApi).apiSysAuthCaptchaGet();
state.captchaImage = 'data:text/html;base64,' + res.data.result?.img;
state.ruleForm.codeId = res.data.result?.id;
state.expirySeconds = res.data.result?.expirySeconds;
};
//
@ -328,6 +344,7 @@ defineExpose({ saveTokenAndInitRoutes });
display: flex;
align-items: center;
justify-content: space-around;
position: relative;
.login-content-code-img {
width: 100%;
@ -347,6 +364,22 @@ defineExpose({ saveTokenAndInitRoutes });
}
}
.login-content-code-expired {
@extend .login-content-code;
&::before {
content: '验证码已过期';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.5);
color: #ffffff;
text-align: center;
}
}
.login-content-submit {
width: 100%;
letter-spacing: 2px;

View File

@ -131,7 +131,7 @@
<el-input v-model="publish.payload" clearable maxlength="64" show-word-limit>
<!--<template #prepend>
<el-button :icon="Operation" />
</template> -->
</template> -->
<template #append>
<el-select v-model="publish.payload" placeholder="选择指令" style="width: 115px">
<el-option label="状态查询" value="55 AA AA AA AA 91 CF" />

View File

@ -1,13 +1,16 @@
<template>
<div class="sys-cache-container">
<NoticeBar text="系统缓存数据管理,请慎重操作!" leftIcon="iconfont icon-tongzhi2" background="var(--el-color-primary-light-9)" color="var(--el-color-primary)" />
<el-row :gutter="5" class="mt5">
<el-col :span="8" :xs="24">
<el-card shadow="hover" header="缓存列表" style="height: calc(100vh - 156px)" v-loading="state.loading" body-style="height:100%;overflow:auto;padding:5px 5px 50px 5px;">
<div>
<NoticeBar text="系统缓存数据管理,请慎重操作!" style="margin: 4px" />
</div>
<splitpanes class="default-theme">
<pane size="20">
<el-card shadow="hover" header="缓存列表" v-loading="state.loading" style="height: 100%" body-style="height:100%; overflow:auto">
<template #header>
<div class="card-header">
<span>缓存列表</span>
<el-button icon="ele-Refresh" size="small" circle text @click="handleQuery" v-auth="'sysCache/keyList'" />
<el-button icon="ele-Refresh" size="small" circle @click="handleQuery" v-auth="'sysCache/keyList'" />
</div>
</template>
<el-tree
@ -21,11 +24,12 @@
highlight-current
check-strictly
default-expand-all
accordion
/>
</el-card>
</el-col>
<el-col :span="16" :xs="24">
<el-card shadow="hover" header="缓存数据" style="height: calc(100vh - 156px)" v-loading="state.loadingData" body-style="height:calc(100% - 36px);overflow:auto;">
</pane>
<pane size="80">
<el-card shadow="hover" header="缓存数据" v-loading="state.loading1" style="height: 100%" body-style="height:100%; overflow:auto">
<template #header>
<div class="card-header">
<span>{{ `缓存数据${state.cacheKey ? `${state.cacheKey}` : ''}` }}</span>
@ -34,8 +38,8 @@
</template>
<vue-json-pretty :data="state.cacheValue" showLength showIcon showLineNumber showSelectController />
</el-card>
</el-col>
</el-row>
</pane>
</splitpanes>
</div>
</template>
@ -45,6 +49,8 @@ import { ElMessageBox, ElMessage, ElTree } from 'element-plus';
import NoticeBar from '/@/components/noticeBar/index.vue';
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import { getAPI } from '/@/utils/axios-utils';
import { SysCacheApi } from '/@/api-services';
@ -53,15 +59,14 @@ const treeRef = ref<InstanceType<typeof ElTree>>();
const currentNode = ref<any>({});
const state = reactive({
loading: false,
loadingData: false,
loading1: false,
cacheData: [] as any,
cacheValue: undefined as any,
cacheKey: undefined,
});
//
onMounted(async () => {
await handleQuery();
handleQuery();
});
//
@ -109,7 +114,7 @@ const delCache = () => {
})
.then(async () => {
await getAPI(SysCacheApi).apiSysCacheDeleteKeyPost(currentNode.value.id);
await handleQuery();
handleQuery();
state.cacheValue = undefined;
state.cacheKey = undefined;
ElMessage.success('删除成功');
@ -122,7 +127,7 @@ const nodeClick = async (node: any) => {
if (node.id == 0) return;
currentNode.value = node;
state.loadingData = true;
state.loading1 = true;
var res = await getAPI(SysCacheApi).apiSysCacheValueKeyGet(node.id);
// state.cacheValue = JSON.parse(res.data.result);
var result = res.data.result;
@ -142,7 +147,7 @@ const nodeClick = async (node: any) => {
}
state.cacheKey = node.id;
state.loadingData = false;
state.loading1 = false;
};
</script>
@ -152,7 +157,4 @@ const nodeClick = async (node: any) => {
justify-content: space-between;
align-items: center;
}
:deep(.el-card__header) {
padding: 6px !important;
}
</style>

View File

@ -104,27 +104,42 @@ const getColumnInfoList = async () => {
};
//
const openDialog = (row: any) => {
const openDialog = async (row: any) => {
rowdata = row;
if (rowdata.fkConfigId) {
await getDbList();
state.ruleForm.tableName = rowdata.fkTableName;
state.ruleForm.columnName = rowdata.fkColumnName;
state.ruleForm.linkColumnName = rowdata.fkLinkColumnName;
state.ruleForm.configId = rowdata.fkConfigId;
await DbChanged();
await TableChanged();
}
state.isShowDialog = true;
};
//
const closeDialog = () => {
rowdata.fkTableName = state.ruleForm.tableName;
let tableData = state.tableData.filter((x) => x.tableName == state.ruleForm.tableName);
let tableData = state.tableData.filter((x: any) => x.tableName == state.ruleForm.tableName);
rowdata.fkEntityName = tableData.length == 0 ? '' : tableData[0].entityName;
rowdata.fkColumnName = state.ruleForm.columnName;
rowdata.fkLinkColumnName = state.ruleForm.linkColumnName;
let columnData = state.columnData.filter((x) => x.columnName == state.ruleForm.columnName);
rowdata.fkConfigId = state.ruleForm.configId;
let columnData = state.columnData.filter((x: any) => x.columnName == state.ruleForm.columnName);
rowdata.fkColumnNetType = columnData.length == 0 ? '' : columnData[0].netType;
emits('submitRefreshFk', rowdata);
state.isShowDialog = false;
cancel();
};
//
const cancel = () => {
state.isShowDialog = false;
ruleFormRef.value?.resetFields();
state.ruleForm = {};
state.dbData.value = [];
state.tableData.value = [];
state.columnData.value = [];
};
//

View File

@ -16,11 +16,21 @@
</template>
</el-table-column>
<el-table-column prop="netType" label="数据类型" min-width="90" show-overflow-tooltip />
<el-table-column prop="effectType" label="作用类型" width="120" show-overflow-tooltip>
<el-table-column prop="effectType" label="作用类型" width="140" show-overflow-tooltip>
<template #default="scope">
<el-select v-model="scope.row.effectType" class="m-2" placeholder="Select" :disabled="judgeColumns(scope.row)" @change="effectTypeChange(scope.row, scope.$index)">
<el-option v-for="item in state.effectTypeList" :key="item.code" :label="item.value" :value="item.code" />
</el-select>
<div class="effect-type-container">
<el-select v-model="scope.row.effectType" class="m-2" placeholder="Select" :disabled="judgeColumns(scope.row)" @change="effectTypeChange(scope.row, scope.$index)">
<el-option v-for="item in state.effectTypeList" :key="item.code" :label="item.value" :value="item.code" />
</el-select>
<el-button
v-if="scope.row.effectType === 'ApiTreeSelect' || scope.row.effectType === 'fk'"
:icon="Edit"
type="dashed"
title="修改"
link
@click="effectTypeChange(scope.row, scope.$index)"
/>
</div>
</template>
</el-table-column>
<el-table-column prop="dictTypeCode" label="字典" width="180" show-overflow-tooltip>
@ -85,6 +95,7 @@
<script lang="ts" setup name="sysCodeGenConfig">
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import mittBus from '/@/utils/mitt';
import { Edit } from '@element-plus/icons-vue';
import fkDialog from '/@/views/system/codeGen/component/fkDialog.vue';
import treeDialog from '/@/views/system/codeGen/component/treeDialog.vue';

View File

@ -110,10 +110,20 @@ const getColumnInfoList = async () => {
};
//
const openDialog = (row: any) => {
const openDialog = async (row: any) => {
rowdata = row;
state.isShowDialog = true;
ruleFormRef.value?.resetFields();
if (rowdata.fkConfigId) {
await getDbList();
state.ruleForm.tableName = rowdata.fkTableName;
state.ruleForm.displayColumn = rowdata.displayColumn;
state.ruleForm.valueColumn = rowdata.valueColumn;
state.ruleForm.pidColumn = rowdata.pidColumn;
state.ruleForm.configId = rowdata.fkConfigId;
await DbChanged();
await TableChanged();
}
};
//
@ -121,20 +131,26 @@ const closeDialog = () => {
rowdata.fkTableName = state.ruleForm.tableName;
// rowdata.fkEntityName = state.ruleForm.entityName;
// fkEntityName,
let tableData = state.tableData.filter((x) => x.tableName == state.ruleForm.tableName);
let tableData = state.tableData.filter((x: any) => x.tableName == state.ruleForm.tableName);
rowdata.fkEntityName = tableData.length == 0 ? '' : tableData[0].entityName;
// rowdata.fkColumnName = state.ruleForm.columnName;
// rowdata.fkColumnNetType = state.ruleForm.columnNetType;
rowdata.displayColumn = state.ruleForm.displayColumn;
rowdata.valueColumn = state.ruleForm.valueColumn;
rowdata.pidColumn = state.ruleForm.pidColumn;
rowdata.fkConfigId = state.ruleForm.configId;
emits('submitRefreshFk', rowdata);
state.isShowDialog = false;
cancel();
};
//
const cancel = () => {
state.isShowDialog = false;
ruleFormRef.value?.resetFields();
state.ruleForm = {};
state.dbData.value = [];
state.tableData.value = [];
state.columnData.value = [];
};
//

View File

@ -0,0 +1,180 @@
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { dict, compute, EditReq, DelReq, AddReq } from '@fast-crud/fast-crud';
import { getAPI } from '/@/utils/axios-utils';
import { SysNoticeApi } from '/@/api-services/api';
import { PageFileInput } from '/@/api-services/models';
export default function ({ expose }) {
// 分页查询
const pageRequest = async (query: any) => {
const params = {
page: query.currentPage,
pageSize: query.pageSize,
field: query.field,
order: query.order,
descStr: 'desc',
} as PageFileInput;
const result = await getAPI(SysNoticeApi).apiSysNoticePagePost(params);
return result;
};
// 编辑
const editRequest = async ({ form, row }: EditReq) => {
if (form.id == null) {
form.id = row.id;
}
return await getAPI(SysNoticeApi)
.apiSysNoticeUpdatePost(form)
.then((rsp: any) => {
if (rsp.data.code == 200) {
ElMessage.success('修改成功!');
} else {
ElMessage.error('修改失败:' + rsp.data.message);
}
});
};
// 删除
const delRequest = async ({ row }: DelReq) => {
return await getAPI(SysNoticeApi).apiSysNoticeDeletePost(row);
};
// 增加
const addRequest = async ({ form }: AddReq) => {
return await getAPI(SysNoticeApi).apiSysNoticeAddPost(form);
};
// 选择
const selectedIds = ref([]);
const onSelectionChange = (changed: any) => {
selectedIds.value = changed;
};
return {
selectedIds,
crudOptions: {
container: {
is: 'fs-layout-card',
},
form: {
wrapper: {
// is: 'el-drawer',
// width: '80%',
draggable: false,
closeOnEsc: false,
maskClosable: false,
},
},
search: {
show: true,
},
actionbar: {},
toolbar: {
show: true,
buttons: {
search: { show: true },
refresh: { show: true },
compact: { show: true },
export: { show: true },
columns: { show: true },
},
},
table: {
scrollX: 725,
bordered: false,
rowKey: (row: any) => row.id,
checkedRowKeys: selectedIds,
'onUpdate:checkedRowKeys': onSelectionChange,
},
pagination: {
show: true,
},
request: {
pageRequest,
addRequest,
editRequest,
delRequest,
},
rowHandle: {
fixed: 'right',
align: 'center',
width: 200,
buttons: {
view: { show: true },
edit: { show: true },
},
},
columns: {
_checked: {
title: '选择',
form: { show: false },
column: {
type: 'selection',
align: 'center',
width: '55px',
columnSetDisabled: true,
disabled(row: any) {
return row.account === 'gvanet';
},
},
},
type: {
title: '类型',
type: 'dict-select',
search: { show: true, col: { span: 6 } },
column: {
align: 'center',
width: '120px',
},
dict: dict({
value: 'id',
label: 'text',
data: [
{ id: '1', text: '通知' },
{ id: '2', text: '公告' },
],
}),
form: {
col: { span: 24 },
rule: [{ required: true, message: '请输入类型' }],
},
},
title: {
title: '标题',
type: 'text',
search: { show: true, col: { span: 6 } },
column: {
align: 'center',
width: 'auto',
},
form: {
col: { span: 24 },
rule: [{ required: true, message: '请输入标题' }],
},
},
content: {
title: '内容',
type: 'editor-wang5',
search: { show: false, col: { span: 6 } },
column: {
show: false,
},
form: {
col: { span: 24 },
rule: [{ required: true, message: '请输入内容' }],
component: {
disabled: compute(({ form }) => {
return form.disabled;
}),
id: '1', // 当同一个页面有多个editor时需要配置不同的id
config: {},
uploader: {
type: 'form',
buildUrl(res: any) {
return res.url;
},
},
},
},
},
},
},
};
}

View File

@ -0,0 +1,66 @@
<template>
<div class="h-full">
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #pagination-left>
<fs-button icon="ion:trash-outline" @click="handleBatchDelete" />
</template>
<template #cell_url="scope">
<n-tooltip trigger="hover">
<template #trigger>
<n-button> 预览 </n-button>
</template>
<n-image width="120px" height="120px" :src="baseURL + '/' + scope.row.url"></n-image>
</n-tooltip>
</template>
</fs-crud>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import { useExpose, useCrud } from '@fast-crud/fast-crud';
import createCrudOptions from './crud';
const baseURL = import.meta.env.VITE_API_URL;
export default defineComponent({
name: 'FastCrud',
setup() {
const crudRef = ref();
const crudBinding = ref();
const { expose } = useExpose({ crudRef, crudBinding });
const { crudOptions, selectedIds } = createCrudOptions({ expose });
const { resetCrudOptions } = useCrud({ expose, crudOptions });
//
onMounted(() => {
expose.doRefresh();
});
//
const handleBatchDelete = async () => {
if (selectedIds.value?.length > 0) {
// ElMessageBox.confirm(`${selectedIds.value.length}`, '', {
// confirmButtonText: '',
// cancelButtonText: '',
// type: 'info',
// }).then(async () => {
// await delBatchSysFile(selectedIds.value);
// message.success('');
// selectedIds.value = [];
// await expose.doRefresh();
// ElMessage.success('');
// })
// .catch(() => { });
} else {
// ElMessage.success('');
}
};
return {
crudBinding,
crudRef,
handleBatchDelete,
baseURL,
};
},
});
</script>

View File

@ -37,6 +37,19 @@
<el-descriptions-item label="ICP地址">
<el-input v-model="state.formData.sysIcpUrl" />
</el-descriptions-item>
<el-descriptions-item label="图形验证码">
<el-radio-group v-model="state.formData.sysCaptcha">
<el-radio :value="true">启用</el-radio>
<el-radio :value="false">禁用</el-radio>
</el-radio-group>
</el-descriptions-item>
<el-descriptions-item label="登录二次验证">
<el-radio-group v-model="state.formData.sysSecondVer">
<el-radio :value="true">启用</el-radio>
<el-radio :value="false">禁用</el-radio>
</el-radio-group>
</el-descriptions-item>
<template #extra>
<el-button type="primary" icon="ele-SuccessFilled" @click="onSave">保存</el-button>
</template>
@ -68,6 +81,8 @@ const state = reactive({
sysCopyright: '',
sysIcp: '',
sysIcpUrl: '',
sysSecondVer: false,
sysCaptcha: true,
},
});
@ -101,13 +116,18 @@ const onSave = async () => {
sysCopyright: state.formData.sysCopyright,
sysIcp: state.formData.sysIcp,
sysIcpUrl: state.formData.sysIcpUrl,
sysSecondVer: state.formData.sysSecondVer,
sysCaptcha: state.formData.sysCaptcha,
});
if (res.data!.type !== 'success') return;
// file
state.file = undefined;
await loadData();
// await loadData();
ElMessage.success('保存成功');
//
window.location.reload();
} finally {
nextTick(() => {
state.isLoading = false;
@ -134,6 +154,8 @@ const loadData = async () => {
sysCopyright: result.sysCopyright,
sysIcp: result.sysIcp,
sysIcpUrl: result.sysIcpUrl,
sysSecondVer: result.sysSecondVer,
sysCaptcha: result.sysCaptcha,
};
} finally {
nextTick(() => {

View File

@ -5,12 +5,12 @@
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="开始时间" prop="name">
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" :shortcuts="shortcuts" />
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" :shortcuts="shortcuts" class="w100" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="结束时间" prop="code">
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" :shortcuts="shortcuts" />
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" :shortcuts="shortcuts" class="w100" />
</el-form-item>
</el-col>
</el-row>
@ -79,7 +79,7 @@
</el-scrollbar>
</el-tab-pane>
</el-tabs>
</el-dialog>
</el-dialog>
</div>
</template>

View File

@ -5,17 +5,17 @@
<el-row :gutter="10">
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="开始时间" prop="name">
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" :shortcuts="shortcuts" />
<el-date-picker v-model="state.queryParams.startTime" type="datetime" placeholder="开始时间" :shortcuts="shortcuts" class="w100" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="结束时间" prop="code">
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" :shortcuts="shortcuts" />
<el-date-picker v-model="state.queryParams.endTime" type="datetime" placeholder="结束时间" :shortcuts="shortcuts" class="w100" />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="模块名称">
<el-input v-model="state.queryParams.controllerName" placeholder="方法名称" clearable />
<el-input v-model="state.queryParams.controllerName" placeholder="模块名称" clearable />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
@ -64,6 +64,7 @@
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents" @cell-dblclick="handleView">
<template #toolbar_buttons>
<el-button icon="ele-FolderOpened" type="primary" @click="exportLog" v-auth="'sysLogEx/export'"> 导出 </el-button>
<el-button icon="ele-DeleteFilled" type="danger" @click="handleClear" v-auth="'sysLogEx/clear'"> 清空 </el-button>
</template>
<template #toolbar_tools> </template>
@ -123,6 +124,7 @@ import { auth } from '/@/utils/authFunction';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { downloadByData, getFileName } from '/@/utils/download';
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';
import { StringToObj } from '/@/utils/json-utils';
@ -268,6 +270,16 @@ const handleView = async ({ row }: any) => {
state.detail.returnResult = StringToObj(data?.result?.returnResult);
state.visible = true;
};
//
const exportLog = async () => {
options.loading = true;
var res = await getAPI(SysLogExApi).apiSysLogExExportPost(state.queryParams, { responseType: 'blob' });
options.loading = false;
var fileName = getFileName(res.headers);
downloadByData(res.data as any, fileName);
};
</script>
<style lang="scss" scoped>

View File

@ -15,7 +15,7 @@
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="模块名称">
<el-input v-model="state.queryParams.controllerName" placeholder="方法名称" clearable />
<el-input v-model="state.queryParams.controllerName" placeholder="模块名称" clearable />
</el-form-item>
</el-col>
<el-col class="mb5" :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
@ -56,6 +56,7 @@
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents" @cell-dblclick="handleView">
<template #toolbar_buttons>
<el-button icon="ele-FolderOpened" type="primary" @click="exportLog" v-auth="'sysLogOp/export'"> 导出 </el-button>
<el-button icon="ele-DeleteFilled" type="danger" @click="handleClear" v-auth="'sysLogOp/clear'"> 清空 </el-button>
</template>
<template #toolbar_tools> </template>
@ -115,6 +116,7 @@ import { auth } from '/@/utils/authFunction';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { downloadByData, getFileName } from '/@/utils/download';
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';
import { StringToObj } from '/@/utils/json-utils';
@ -261,6 +263,16 @@ const handleView = async ({ row }: any) => {
state.detail.returnResult = StringToObj(data?.result?.returnResult);
state.visible = true;
};
//
const exportLog = async () => {
options.loading = true;
var res = await getAPI(SysLogOpApi).apiSysLogOpExportPost(state.queryParams, { responseType: 'blob' });
options.loading = false;
var fileName = getFileName(res.headers);
downloadByData(res.data as any, fileName);
};
</script>
<style lang="scss" scoped>

View File

@ -59,8 +59,8 @@
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #toolbar_buttons>
<el-button icon="ele-DeleteFilled" type="danger" @click="handleClear" v-auth="'sysLogVis/clear'"> 清空 </el-button>
<el-button icon="ele-MapLocation" type="primary" @click="handleMap" v-auth="'sysLogVis/list'"> 热力图 </el-button>
<el-button icon="ele-DeleteFilled" type="danger" @click="handleClear" v-auth="'sysLogVis/clear'"> 清空 </el-button>
</template>
<template #toolbar_tools> </template>
<template #empty>

View File

@ -109,7 +109,7 @@ const options = useVxeTable<SysMenu>(
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'title', title: '菜单名称', minWidth: 180, showOverflow: 'tooltip', treeNode: true, slots: { default: 'row_title' } },
{ field: 'title', title: '菜单名称', minWidth: 180, showOverflow: 'tooltip', treeNode: true, align: 'left', headerAlign: 'center', slots: { default: 'row_title' } },
{ field: 'type', title: '菜单类型', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_type' } },
{ field: 'path', title: '路由路径', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'component', title: '组件路径', minWidth: 150, showOverflow: 'tooltip' },

View File

@ -1,11 +1,10 @@
<template>
<div class="sys-org-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="4" :xs="24" style="display: flex; height: 100%">
<splitpanes class="default-theme">
<pane size="15" style="display: flex">
<OrgTree ref="orgTreeRef" @node-click="handleNodeChange" />
</el-col>
<el-col :span="20" :xs="24" style="display: flex; flex-direction: column; height: 100%">
</pane>
<pane size="85" style="display: flex; flex-direction: column">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
@ -71,8 +70,8 @@
</template>
</vxe-grid>
</el-card>
</el-col>
</el-row>
</pane>
</splitpanes>
<EditOrg ref="editOrgRef" :title="state.title" :orgData="state.treeData" @reload="handleQuery" />
</div>
@ -83,6 +82,8 @@ import { onMounted, reactive, ref, nextTick } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { VxeGridInstance, VxeGridListeners } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import OrgTree from '/@/views/system/org/component/orgTree.vue';
import EditOrg from '/@/views/system/org/component/editOrg.vue';
@ -115,7 +116,7 @@ const options = useVxeTable<SysOrg>(
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
{ type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'name', title: '机构名称', minWidth: 200, showOverflow: 'tooltip', treeNode: true },
{ field: 'name', title: '机构名称', minWidth: 200, showOverflow: 'tooltip', treeNode: true, align: 'left', headerAlign: 'center' },
{ field: 'code', title: '机构编码', minWidth: 200, showOverflow: 'tooltip' },
{ field: 'level', title: '级别', minWidth: 70, showOverflow: 'tooltip' },
{ field: 'type', title: '机构类型', minWidth: 80, formatter: ({ cellValue }: any) => state.orgTypeList.find((u: any) => u.code == cellValue)?.value, showOverflow: 'tooltip' },

View File

@ -1,11 +1,10 @@
<template>
<div class="sys-region-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="6" :xs="24" style="display: flex; height: 100%">
<splitpanes class="default-theme">
<pane size="20" style="display: flex">
<RegionTree ref="regionTreeRef" @node-click="handleNodeChange" />
</el-col>
<el-col :span="18" :xs="24" style="display: flex; flex-direction: column; height: 100%">
</pane>
<pane size="80" style="display: flex; flex-direction: column">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
@ -58,8 +57,8 @@
</template>
</vxe-grid>
</el-card>
</el-col>
</el-row>
</pane>
</splitpanes>
<EditRegion ref="editRegionRef" :title="state.title" @handleQuery="handleQuery" />
</div>
@ -72,6 +71,8 @@ import { auth } from '/@/utils/authFunction';
import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import RegionTree from '/@/views/system/region/component/regionTree.vue';
import EditRegion from '/@/views/system/region/component/editRegion.vue';

View File

@ -1,11 +1,10 @@
<template>
<div class="sys-user-container">
<el-row :gutter="5" style="width: 100%; height: 100%">
<el-col :span="4" :xs="24" style="display: flex; height: 100%">
<OrgTree ref="treeRef" @node-click="handleNodeChange" />
</el-col>
<el-col :span="20" :xs="24" style="display: flex; flex-direction: column; height: 100%">
<splitpanes class="default-theme">
<pane size="15" style="display: flex">
<OrgTree ref="orgTreeRef" @node-click="handleNodeChange" />
</pane>
<pane size="85" style="display: flex; flex-direction: column">
<el-card shadow="hover" :body-style="{ padding: '5px 5px 0 5px', display: 'flex', width: '100%', height: '100%', alignItems: 'start' }">
<el-form :model="state.queryParams" ref="queryForm" :show-message="false" :inlineMessage="true" label-width="auto" style="flex: 1 1 0%">
<el-row :gutter="10">
@ -44,7 +43,7 @@
</el-row>
</el-card>
<el-card class="full-table" shadow="hover" style="margin-top: 5px">
<el-card class="full-table" shadow="hover" style="margin-top: 5px; flex: 1">
<vxe-grid ref="xGrid" class="xGrid-style" v-bind="options" v-on="gridEvents">
<template #toolbar_buttons>
<el-button type="primary" icon="ele-Plus" @click="handleAdd" v-auth="'sysUser/add'"> 新增 </el-button>
@ -86,8 +85,8 @@
</template>
</vxe-grid>
</el-card>
</el-col>
</el-row>
</pane>
</splitpanes>
<EditUser ref="editUserRef" :title="state.title" :orgData="state.treeData" @handleQuery="handleQuery" />
</div>
@ -100,6 +99,8 @@ import { VxeGridInstance, VxeGridListeners, VxeGridPropTypes } from 'vxe-table';
import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
import { Local } from '/@/utils/storage';
import XEUtils from 'xe-utils';
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import OrgTree from '/@/views/system/org/component/orgTree.vue';
import EditUser from '/@/views/system/user/component/editUser.vue';