😎1、增加登录配置租户Id参数模式 2、代码优化
This commit is contained in:
parent
bf2752df8c
commit
6f5d4646df
@ -45,11 +45,11 @@
|
||||
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.3" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="3.6.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.9.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.173" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.174" />
|
||||
<PackageReference Include="SSH.NET" Version="2024.2.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.5.1" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1162" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1163" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -48,38 +48,34 @@ public class DictAttribute : ValidationAttribute, ITransient
|
||||
protected override ValidationResult IsValid(object? value, ValidationContext validationContext)
|
||||
{
|
||||
// 判断是否允许空值
|
||||
if (AllowNullValue && value == null)
|
||||
return ValidationResult.Success;
|
||||
if (AllowNullValue && value == null) return ValidationResult.Success;
|
||||
|
||||
var valueAsString = value?.ToString();
|
||||
|
||||
// 是否忽略空字符串
|
||||
if (AllowEmptyStrings && string.IsNullOrEmpty(valueAsString))
|
||||
return ValidationResult.Success;
|
||||
if (AllowEmptyStrings && string.IsNullOrEmpty(valueAsString)) return ValidationResult.Success;
|
||||
|
||||
// 获取属性的类型
|
||||
var property = validationContext.ObjectType.GetProperty(validationContext.MemberName);
|
||||
if (property == null)
|
||||
return new ValidationResult($"未知属性: {validationContext.MemberName}");
|
||||
var property = validationContext.ObjectType.GetProperty(validationContext.MemberName!);
|
||||
if (property == null) return new ValidationResult($"未知属性: {validationContext.MemberName}");
|
||||
|
||||
var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
|
||||
|
||||
// 枚举类型验证
|
||||
if (propertyType.IsEnum)
|
||||
{
|
||||
return !Enum.IsDefined(propertyType, value)
|
||||
? new ValidationResult($"提示:{ErrorMessage}|枚举值【{value}】不是有效的【{propertyType.Name}】枚举类型值!")
|
||||
: ValidationResult.Success;
|
||||
if (!Enum.IsDefined(propertyType, value!)) return new ValidationResult($"提示:{ErrorMessage}|枚举值【{value}】不是有效的【{propertyType.Name}】枚举类型值!");
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
// 先尝试从 ValidationContext 的依赖注入容器中拿服务,拿不到或类型不匹配时,再从全局的 App 容器中获取
|
||||
// 先尝试从 ValidationContext 的依赖注入容器中拿服务,再从全局的 App 容器中获取
|
||||
if (validationContext.GetService(typeof(SysDictDataService)) is not SysDictDataService sysDictDataService)
|
||||
sysDictDataService = App.GetRequiredService<SysDictDataService>();
|
||||
// 获取字典值列表
|
||||
var dictDataList = sysDictDataService.GetDataList(DictTypeCode).GetAwaiter().GetResult();
|
||||
// 使用 HashSet 来提高查找效率
|
||||
var dictHash = new HashSet<string>(dictDataList.Select(u => u.Code));
|
||||
if (!dictHash.Contains(valueAsString))
|
||||
return new ValidationResult($"提示:{ErrorMessage}|字典【{DictTypeCode}】不包含【{valueAsString}】!");
|
||||
if (!dictHash.Contains(valueAsString)) return new ValidationResult($"提示:{ErrorMessage}|字典【{DictTypeCode}】不包含【{valueAsString}】!");
|
||||
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
@ -71,10 +71,10 @@ public class ConfigConst
|
||||
/// </summary>
|
||||
public const string SysDomainLogin = "sys_domain_login";
|
||||
|
||||
/// <summary>
|
||||
/// 租户域名隔离登录验证
|
||||
/// </summary>
|
||||
public const string SysTenantHostLogin = "sys_tenant_host_login";
|
||||
///// <summary>
|
||||
///// 租户域名隔离登录验证
|
||||
///// </summary>
|
||||
//public const string SysTenantHostLogin = "sys_tenant_host_login";
|
||||
|
||||
/// <summary>
|
||||
/// 行政区划同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级
|
||||
|
||||
@ -35,9 +35,4 @@ public class SqlSugarConst
|
||||
/// 默认租户Id
|
||||
/// </summary>
|
||||
public const long DefaultTenantId = 1300000000001;
|
||||
|
||||
/// <summary>
|
||||
/// 默认租户域名
|
||||
/// </summary>
|
||||
public const string DefaultTenantHost = "gitee.com";
|
||||
}
|
||||
@ -70,12 +70,14 @@ public partial class SysCodeGen : EntityBase
|
||||
[SugarColumn(ColumnDescription = "数据库表名", Length = 128)]
|
||||
[MaxLength(128)]
|
||||
public string? TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自身树控件Name
|
||||
/// 树控件名称
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "自身树控件Name", Length = 64)]
|
||||
[SugarColumn(ColumnDescription = "树控件名称", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? TreeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间
|
||||
/// </summary>
|
||||
@ -134,6 +136,7 @@ public partial class SysCodeGen : EntityBase
|
||||
[SugarColumn(ColumnDescription = "打印模版名称", Length = 32)]
|
||||
[MaxLength(32)]
|
||||
public string? PrintName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左边树形结构表
|
||||
/// </summary>
|
||||
@ -147,16 +150,18 @@ public partial class SysCodeGen : EntityBase
|
||||
[SugarColumn(ColumnDescription = "左边关联字段", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? LeftKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左边关联主表字段
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "左边关联主表字段", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? LeftPrimaryKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左边树Name
|
||||
/// 左边树名称
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "左边树Name", Length = 64)]
|
||||
[SugarColumn(ColumnDescription = "左边树名称", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? LeftName { get; set; }
|
||||
|
||||
@ -173,6 +178,7 @@ public partial class SysCodeGen : EntityBase
|
||||
[SugarColumn(ColumnDescription = "右区域下框表关联字段", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? BottomKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下表关联主表字段
|
||||
/// </summary>
|
||||
@ -186,6 +192,7 @@ public partial class SysCodeGen : EntityBase
|
||||
[SugarColumn(ColumnDescription = "模板文件夹", Length = 64)]
|
||||
[MaxLength(64)]
|
||||
public string? Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用 Api Service
|
||||
/// </summary>
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Admin.NET.Core;
|
||||
|
||||
namespace Admin.NET.Core.SeedData;
|
||||
|
||||
/// <summary>
|
||||
@ -227,11 +225,7 @@ public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData<SysCodeGenTemp
|
||||
}
|
||||
]
|
||||
";
|
||||
List<SysCodeGenTemplate> records = Newtonsoft.Json.JsonConvert.DeserializeObject<List<SysCodeGenTemplate>>(recordList);
|
||||
|
||||
// 后处理数据的特殊字段
|
||||
//for (int i = 0; i < records.Count; i++) { }
|
||||
|
||||
var records = JSON.Deserialize<List<SysCodeGenTemplate>>(recordList);
|
||||
return records;
|
||||
}
|
||||
}
|
||||
@ -31,7 +31,6 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
|
||||
new SysConfig{ Id=1300000000191, Name="RefreshToken过期时间", Code=ConfigConst.SysRefreshTokenExpire, Value="20160", SysFlag=YesNoEnum.Y, Remark="刷新Token过期时间(分钟)(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=100, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code=ConfigConst.SysErrorMail, Value="False", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000211, Name="域登录验证", Code=ConfigConst.SysDomainLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000221, Name="租户隔离登录验证", Code=ConfigConst.SysTenantHostLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="租户隔离登录验证", OrderNo=130, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
new SysConfig{ Id=1300000000241, Name="行政区划同步层级", Code=ConfigConst.SysRegionSyncLevel, Value="3", SysFlag=YesNoEnum.Y, Remark="行政区划同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级", OrderNo=150, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
// 新业务系统记得更改密匙,通过接口(http://localhost:5005/api/sysCommon/smKeyPair)获取
|
||||
new SysConfig{ Id=1300000000251, Name="国密SM2密匙", Code=ConfigConst.SysSM2Key, Value="04851D329AA3E38C2E7670AFE70E6E70E92F8769CA27C8766B12209A0FFBA4493B603EF7A0B9B1E16F0E8930C0406EA0B179B68DF28E25334BDEC4AE76D907E9E9;3A61D1D30C6302DABFF36201D936D0143EEF0C850AF28C5CA6D5C045AF8C5C8A", SysFlag=YesNoEnum.Y, Remark="国密SM2密匙", OrderNo=160, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-11-21 00:00:00") },
|
||||
|
||||
@ -21,7 +21,7 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
|
||||
|
||||
return
|
||||
[
|
||||
new SysTenant{ Id=SqlSugarConst.DefaultTenantId, AppId=SqlSugarConst.DefaultTenantId, OrgId=SqlSugarConst.DefaultTenantId, UserId=1300000000111, Host=SqlSugarConst.DefaultTenantHost, 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, AppId=SqlSugarConst.DefaultTenantId, OrgId=SqlSugarConst.DefaultTenantId, UserId=1300000000111, Host="gitee.com", TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -26,10 +26,10 @@ public class LoginInput
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户域名
|
||||
/// 租户Id
|
||||
/// </summary>
|
||||
//[Required(ErrorMessage = "租户域名不能为空")]
|
||||
public string Host { get; set; }
|
||||
//[Required(ErrorMessage = "租户Id不能为空")]
|
||||
public long TenantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码Id
|
||||
@ -65,10 +65,10 @@ public class LoginPhoneInput
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户域名
|
||||
/// 租户Id
|
||||
/// </summary>
|
||||
//[Required(ErrorMessage = "租户域名不能为空")]
|
||||
public string Host { get; set; }
|
||||
//[Required(ErrorMessage = "租户Id不能为空")]
|
||||
public long TenantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登录模式
|
||||
|
||||
@ -46,9 +46,6 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
[AllowAnonymous]
|
||||
public virtual async Task<LoginOutput> Login([Required] LoginInput input)
|
||||
{
|
||||
//// 可以根据域名获取具体租户
|
||||
//var host = _httpContextAccessor.HttpContext.Request.Host;
|
||||
|
||||
// 判断密码错误次数(缓存30分钟)
|
||||
var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
|
||||
var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
|
||||
@ -61,7 +58,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
if (await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysCaptcha) && !_captcha.Validate(input.CodeId.ToString(), input.Code)) throw Oops.Oh(ErrorCodeEnum.D0008);
|
||||
|
||||
// 获取登录租户和用户
|
||||
var (tenant, user) = await GetLoginUserAndTenant(input.Host, account: input.Account);
|
||||
var (tenant, user) = await GetLoginUserAndTenant(input.TenantId, account: input.Account);
|
||||
|
||||
// 账号是否被冻结
|
||||
if (user.Status == StatusEnum.Disable) throw Oops.Oh(ErrorCodeEnum.D1017);
|
||||
@ -92,53 +89,34 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
/// <summary>
|
||||
/// 获取登录租户和用户
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
/// <param name="tenantId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="phone"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<(SysTenant tenant, SysUser user)> GetLoginUserAndTenant(string host, string account = null, string phone = null)
|
||||
public async Task<(SysTenant tenant, SysUser user)> GetLoginUserAndTenant(long tenantId, string account = null, string phone = null)
|
||||
{
|
||||
// 是否租户隔离登录验证
|
||||
var isTenantHostLogin = await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysTenantHostLogin);
|
||||
|
||||
SysUser user;
|
||||
SysTenant tenant;
|
||||
|
||||
// 租户隔离登录
|
||||
if (isTenantHostLogin)
|
||||
// 若没有传值租户Id,则从请求页URL参数中获取租户Id(空则默认租户)
|
||||
if (tenantId < 1)
|
||||
{
|
||||
// 若租户域名为空或为本地域名,则取默认租户域名
|
||||
if (string.IsNullOrWhiteSpace(host) || host.StartsWith("localhost")) host = SqlSugarConst.DefaultTenantHost;
|
||||
|
||||
// 租户是否存在或已禁用
|
||||
tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Host.Equals(host, StringComparison.CurrentCultureIgnoreCase));
|
||||
if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
|
||||
|
||||
// 根据入参类型、租户查询登录用户
|
||||
user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
|
||||
.Where(u => u.TenantId == tenant.Id || u.AccountType == AccountTypeEnum.SuperAdmin)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
|
||||
.FirstAsync();
|
||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||
|
||||
// 若登录的是超级管理员,则引用当前绑定的租户,这样登陆后操作的租户数据会与该租户关联
|
||||
if (user.AccountType == AccountTypeEnum.SuperAdmin) user.TenantId = tenant.Id;
|
||||
var tenantidStr = _httpContextAccessor.HttpContext.Request.Query["tenantid"].ToString();
|
||||
tenantId = string.IsNullOrWhiteSpace(tenantidStr) ? SqlSugarConst.DefaultTenantId : long.Parse(tenantidStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 根据入参类型查询登录用户
|
||||
user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
|
||||
.FirstAsync();
|
||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||
|
||||
// 租户是否存在或已禁用
|
||||
tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Id == user.TenantId);
|
||||
if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
|
||||
}
|
||||
// 判断租户是否存在及状态
|
||||
var tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Id == tenantId);
|
||||
if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
|
||||
|
||||
// 判断账号是否存在
|
||||
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
|
||||
.Where(u => u.AccountType == AccountTypeEnum.SuperAdmin || u.TenantId == tenantId)
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
|
||||
.FirstAsync();
|
||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||
|
||||
// 如果是超级管理员,则引用登录选择的租户进入系统
|
||||
if (user.AccountType == AccountTypeEnum.SuperAdmin) user.TenantId = tenantId;
|
||||
|
||||
return (tenant, user);
|
||||
}
|
||||
@ -223,7 +201,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
App.GetRequiredService<SysSmsService>().VerifyCode(new SmsVerifyCodeInput { Phone = input.Phone, Code = input.Code });
|
||||
|
||||
// 获取登录租户和用户
|
||||
var (tenant, user) = await GetLoginUserAndTenant(input.Host, phone: input.Phone);
|
||||
var (tenant, user) = await GetLoginUserAndTenant(input.TenantId, phone: input.Phone);
|
||||
|
||||
return await CreateToken(user, tenant.AppId, input.LoginMode);
|
||||
}
|
||||
@ -405,7 +383,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
||||
{
|
||||
Account = auth.UserName,
|
||||
Password = CryptogramUtil.SM2Encrypt(auth.Password),
|
||||
Host = SqlSugarConst.DefaultTenantHost
|
||||
TenantId = SqlSugarConst.DefaultTenantId
|
||||
});
|
||||
|
||||
_sysCacheService.Remove($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}");
|
||||
|
||||
@ -44,6 +44,7 @@ public class CustomViewEngine : ViewEngineModel
|
||||
return ClassName[..1].ToLower() + ClassName[1..]; // 首字母小写
|
||||
}
|
||||
}
|
||||
|
||||
public string? TreeName { get; set; }
|
||||
public string? LowerTreeName { get; set; }
|
||||
public string? LeftTab { get; set; }
|
||||
|
||||
@ -55,10 +55,12 @@ public class PageCodeGenInput : BasePageInput
|
||||
/// 数据库表名
|
||||
/// </summary>
|
||||
public virtual string TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自身树控件Name
|
||||
/// 树控件名称
|
||||
/// </summary>
|
||||
public string? TreeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间
|
||||
/// </summary>
|
||||
@ -190,10 +192,12 @@ public class AddCodeGenInput : PageCodeGenInput
|
||||
/// 左边关联字段
|
||||
/// </summary>
|
||||
public string? LeftKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左边关联主表字段
|
||||
/// </summary>
|
||||
public string? LeftPrimaryKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 左边树Name
|
||||
/// </summary>
|
||||
|
||||
@ -15,22 +15,25 @@ namespace Admin.NET.Core.Service;
|
||||
public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarClient _db;
|
||||
private readonly DbConnectionOptions _dbConnectionOptions;
|
||||
private readonly CodeGenOptions _codeGenOptions;
|
||||
private readonly SqlSugarRepository<SysCodeGenTemplate> _codeGetTemplateRep;
|
||||
private readonly SysCodeGenConfigService _codeGenConfigService;
|
||||
private readonly IViewEngine _viewEngine;
|
||||
private readonly CodeGenOptions _codeGenOptions;
|
||||
|
||||
public SysCodeGenService(ISqlSugarClient db,
|
||||
IOptions<DbConnectionOptions> dbConnectionOptions,
|
||||
SqlSugarRepository<SysCodeGenTemplate> codeGetTemplateRep,
|
||||
SysCodeGenConfigService codeGenConfigService,
|
||||
IViewEngine viewEngine,
|
||||
IOptions<CodeGenOptions> codeGenOptions)
|
||||
{
|
||||
_db = db;
|
||||
_dbConnectionOptions = dbConnectionOptions.Value;
|
||||
_codeGenOptions = codeGenOptions.Value;
|
||||
_codeGetTemplateRep = codeGetTemplateRep;
|
||||
_codeGenConfigService = codeGenConfigService;
|
||||
_viewEngine = viewEngine;
|
||||
_codeGenOptions = codeGenOptions.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -163,7 +166,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
[DisplayName("获取数据库库集合")]
|
||||
public async Task<List<DatabaseOutput>> GetDatabaseList()
|
||||
{
|
||||
var dbConfigs = App.GetOptions<DbConnectionOptions>().ConnectionConfigs;
|
||||
var dbConfigs = _dbConnectionOptions.ConnectionConfigs;
|
||||
return await Task.FromResult(dbConfigs.Adapt<List<DatabaseOutput>>());
|
||||
}
|
||||
|
||||
@ -177,7 +180,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
var provider = _db.AsTenant().GetConnectionScope(configId);
|
||||
var dbTableInfos = provider.DbMaintenance.GetTableInfoList(false);
|
||||
|
||||
var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => configId.Equals(u.ConfigId));
|
||||
var config = _dbConnectionOptions.ConnectionConfigs.FirstOrDefault(u => configId.Equals(u.ConfigId));
|
||||
|
||||
IEnumerable<EntityInfo> entityInfos = await GetEntityInfos(false); // 获取所有实体定义
|
||||
entityInfos = entityInfos.OrderBy(u => u.EntityName.StartsWith("Sys") ? 1 : 0).ThenBy(u => u.EntityName);
|
||||
@ -217,7 +220,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
// 切库---多库代码生成用
|
||||
var provider = _db.AsTenant().GetConnectionScope(configId);
|
||||
|
||||
var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
|
||||
var config = _dbConnectionOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == configId);
|
||||
// 获取实体类型属性
|
||||
var entityType = provider.DbMaintenance.GetTableInfoList(false).FirstOrDefault(u => u.Name == tableName);
|
||||
if (entityType == null) return null;
|
||||
@ -276,7 +279,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
var entityType = GetEntityInfos().GetAwaiter().GetResult().FirstOrDefault(u => u.EntityName == input.TableName);
|
||||
if (entityType == null)
|
||||
return null;
|
||||
var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId);
|
||||
var config = _dbConnectionOptions.ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId);
|
||||
var dbTableName = config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(entityType.DbTableName) : entityType.DbTableName;
|
||||
|
||||
int bracketIndex = dbTableName.IndexOf('{');
|
||||
@ -497,11 +500,11 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
string tResult = string.Empty; // 模板生成结果
|
||||
|
||||
var filename = templateList[i].Name;
|
||||
//更改默认首页模板
|
||||
// 更改默认首页模板
|
||||
if (filename == "web_views_index.vue.vm")
|
||||
{
|
||||
filename = string.IsNullOrEmpty(input.LeftTab) ? filename : "web_views_LeftTree.vue.vm";//左树右列表
|
||||
filename = string.IsNullOrEmpty(input.BottomTab) ? filename : "web_views_BottomIndx.vue.vm";//左数右上列表下列表属性
|
||||
filename = string.IsNullOrEmpty(input.LeftTab) ? filename : "web_views_LeftTree.vue.vm"; // 左树右列表
|
||||
filename = string.IsNullOrEmpty(input.BottomTab) ? filename : "web_views_BottomIndx.vue.vm"; // 左数右上列表下列表属性
|
||||
}
|
||||
var templateFilePath = Path.Combine(templatePath, filename);
|
||||
if (!File.Exists(templateFilePath)) continue;
|
||||
@ -630,7 +633,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
PrintType = input.PrintType!, // 支持打印类型
|
||||
PrintName = input.PrintName!, // 打印模板名称
|
||||
IsApiService = input.IsApiService,
|
||||
RemoteVerify = tableFieldList.Any(t => t.RemoteVerify == true) // 远程验证
|
||||
RemoteVerify = tableFieldList.Any(t => t.RemoteVerify == true), // 远程验证
|
||||
TreeName = input.TreeName,
|
||||
LowerTreeName = string.IsNullOrEmpty(input.TreeName) ? "" : input.TreeName[..1].ToLower() + input.TreeName[1..], // 首字母小写
|
||||
LeftTab = input.LeftTab,
|
||||
@ -659,11 +662,11 @@ public class SysCodeGenService : IDynamicApiController, ITransient
|
||||
string tResult = string.Empty; // 模板生成结果
|
||||
|
||||
var filename = templateList[i].Name;
|
||||
//更改默认首页模板
|
||||
// 更改默认首页模板
|
||||
if (filename == "web_views_index.vue.vm")
|
||||
{
|
||||
filename = string.IsNullOrEmpty(input.LeftTab) ? filename : "web_views_LeftTree.vue.vm";//左树右列表
|
||||
filename = string.IsNullOrEmpty(input.BottomTab) ? filename : "web_views_BottomIndx.vue.vm";//左数右上列表下列表属性
|
||||
filename = string.IsNullOrEmpty(input.LeftTab) ? filename : "web_views_LeftTree.vue.vm"; // 左树右列表
|
||||
filename = string.IsNullOrEmpty(input.BottomTab) ? filename : "web_views_BottomIndx.vue.vm"; // 左数右上列表下列表属性
|
||||
}
|
||||
var templateFilePath = Path.Combine(templatePath, filename);
|
||||
if (!File.Exists(templateFilePath)) continue;
|
||||
|
||||
@ -103,9 +103,7 @@ public class SysUserService : IDynamicApiController, ITransient
|
||||
[DisplayName("增加用户")]
|
||||
public virtual async Task<long> AddUser(AddUserInput input)
|
||||
{
|
||||
// 是否租户隔离登录验证
|
||||
var isTenantHostLogin = await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysTenantHostLogin);
|
||||
var query = _sysUserRep.AsQueryable().ClearFilter().WhereIF(isTenantHostLogin, u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
|
||||
var query = _sysUserRep.AsQueryable().ClearFilter();
|
||||
if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
|
||||
if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
|
||||
|
||||
@ -138,10 +136,7 @@ public class SysUserService : IDynamicApiController, ITransient
|
||||
[DisplayName("更新用户")]
|
||||
public virtual async Task UpdateUser(UpdateUserInput input)
|
||||
{
|
||||
// 是否租户隔离登录验证
|
||||
var isTenantHostLogin = await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysTenantHostLogin);
|
||||
var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.Id != input.Id)
|
||||
.WhereIF(isTenantHostLogin, u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
|
||||
var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.Id != input.Id);
|
||||
if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
|
||||
if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "admin.net.pro",
|
||||
"type": "module",
|
||||
"version": "2.4.33",
|
||||
"lastBuildTime": "2025.01.13",
|
||||
"lastBuildTime": "2025.01.14",
|
||||
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
|
||||
"author": "zuohuaijun",
|
||||
"license": "MIT",
|
||||
@ -88,8 +88,8 @@
|
||||
"@types/node": "^20.17.12",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
||||
"@typescript-eslint/parser": "^8.19.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||
"@typescript-eslint/parser": "^8.20.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
@ -100,7 +100,7 @@
|
||||
"less": "^4.2.1",
|
||||
"prettier": "^3.4.2",
|
||||
"rollup-plugin-visualizer": "^5.14.0",
|
||||
"sass": "^1.83.1",
|
||||
"sass": "^1.83.3",
|
||||
"terser": "^5.37.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.0.7",
|
||||
|
||||
@ -130,6 +130,14 @@ export interface AddCodeGenInput {
|
||||
*/
|
||||
connectionString?: string | null;
|
||||
|
||||
/**
|
||||
* 树控件名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
treeName?: string | null;
|
||||
|
||||
/**
|
||||
* 功能名(数据库表名称)
|
||||
*
|
||||
@ -249,4 +257,68 @@ export interface AddCodeGenInput {
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
codeGenTemplateIds?: Array<number> | null;
|
||||
|
||||
/**
|
||||
* 左边树形结构表
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
leftTab?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
leftKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
leftPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边树Name
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
leftName?: string | null;
|
||||
|
||||
/**
|
||||
* 下表名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
bottomTab?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
bottomKey?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
bottomPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 模板
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AddCodeGenInput
|
||||
*/
|
||||
template?: string | null;
|
||||
}
|
||||
|
||||
@ -40,12 +40,12 @@ export interface LoginInput {
|
||||
password: string;
|
||||
|
||||
/**
|
||||
* 租户域名
|
||||
* 租户Id
|
||||
*
|
||||
* @type {string}
|
||||
* @type {number}
|
||||
* @memberof LoginInput
|
||||
*/
|
||||
host?: string | null;
|
||||
tenantId?: number;
|
||||
|
||||
/**
|
||||
* 验证码Id
|
||||
|
||||
@ -40,12 +40,12 @@ export interface LoginPhoneInput {
|
||||
code: string;
|
||||
|
||||
/**
|
||||
* 租户域名
|
||||
* 租户Id
|
||||
*
|
||||
* @type {string}
|
||||
* @type {number}
|
||||
* @memberof LoginPhoneInput
|
||||
*/
|
||||
host?: string | null;
|
||||
tenantId?: number;
|
||||
|
||||
/**
|
||||
* @type {LoginModeEnum}
|
||||
|
||||
@ -154,6 +154,14 @@ export interface PageCodeGenInput {
|
||||
*/
|
||||
tableName?: string | null;
|
||||
|
||||
/**
|
||||
* 树控件名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PageCodeGenInput
|
||||
*/
|
||||
treeName?: string | null;
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*
|
||||
|
||||
@ -150,6 +150,14 @@ export interface SysCodeGen {
|
||||
*/
|
||||
tableName?: string | null;
|
||||
|
||||
/**
|
||||
* 树控件名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
treeName?: string | null;
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*
|
||||
@ -222,6 +230,70 @@ export interface SysCodeGen {
|
||||
*/
|
||||
printName?: string | null;
|
||||
|
||||
/**
|
||||
* 左边树形结构表
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
leftTab?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
leftKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
leftPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边树名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
leftName?: string | null;
|
||||
|
||||
/**
|
||||
* 下表名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
bottomTab?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
bottomKey?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
bottomPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 模板文件夹
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SysCodeGen
|
||||
*/
|
||||
template?: string | null;
|
||||
|
||||
/**
|
||||
* 是否使用 Api Service
|
||||
*
|
||||
|
||||
@ -130,6 +130,14 @@ export interface UpdateCodeGenInput {
|
||||
*/
|
||||
connectionString?: string | null;
|
||||
|
||||
/**
|
||||
* 树控件名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
treeName?: string | null;
|
||||
|
||||
/**
|
||||
* 功能名(数据库表名称)
|
||||
*
|
||||
@ -250,6 +258,70 @@ export interface UpdateCodeGenInput {
|
||||
*/
|
||||
codeGenTemplateIds?: Array<number> | null;
|
||||
|
||||
/**
|
||||
* 左边树形结构表
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
leftTab?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
leftKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
leftPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 左边树Name
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
leftName?: string | null;
|
||||
|
||||
/**
|
||||
* 下表名称
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
bottomTab?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
bottomKey?: string | null;
|
||||
|
||||
/**
|
||||
* 下表关联主表字段
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
bottomPrimaryKey?: string | null;
|
||||
|
||||
/**
|
||||
* 模板
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UpdateCodeGenInput
|
||||
*/
|
||||
template?: string | null;
|
||||
|
||||
/**
|
||||
* 代码生成器Id
|
||||
*
|
||||
|
||||
@ -215,8 +215,8 @@ const onSignIn = async () => {
|
||||
const publicKey = window.__env__.VITE_SM_PUBLIC_KEY;
|
||||
const password = sm2.doEncrypt(state.ruleForm.password, publicKey, 1);
|
||||
|
||||
const host = route.query.host ?? location.host;
|
||||
const [err, res] = await feature(getAPI(SysAuthApi).apiSysAuthLoginPost({ ...state.ruleForm, password: password, host: host.toString() }));
|
||||
const tenantid = route.query.tenantid ?? 0;
|
||||
const [err, res] = await feature(getAPI(SysAuthApi).apiSysAuthLoginPost({ ...state.ruleForm, password: password, tenantId: Number(tenantid) }));
|
||||
if (err) {
|
||||
getCaptcha(); // 重新获取验证码
|
||||
return;
|
||||
|
||||
@ -74,13 +74,9 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="Name字段" prop="treeName"
|
||||
:rules="[{ required: true, message: '请选择树控件Name字段', trigger: 'blur' }]">
|
||||
<el-select v-model="state.ruleForm.treeName" @change="treeNameChanged"
|
||||
value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.columnData" :key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-form-item label="Name字段" prop="treeName" :rules="[{ required: true, message: '请选择树控件Name字段', trigger: 'blur' }]">
|
||||
<el-select v-model="state.ruleForm.treeName" @change="treeNameChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.columnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -222,10 +218,8 @@
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="树库定位器" prop="configId2">
|
||||
<el-select v-model="state.ruleForm.configId2" placeholder="库名"
|
||||
filterable @change="dbChanged2()" class="w100">
|
||||
<el-option v-for="item in state.dbData" :key="item.configId"
|
||||
:label="item.configId" :value="item.configId" />
|
||||
<el-select v-model="state.ruleForm.configId2" placeholder="库名" filterable @change="dbChanged2()" class="w100">
|
||||
<el-option v-for="item in state.dbData" :key="item.configId" :label="item.configId" :value="item.configId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -234,77 +228,51 @@
|
||||
<template v-slot:label>
|
||||
<div>
|
||||
左边树表
|
||||
<el-tooltip raw-content
|
||||
content="若找不到在前端生成的实体/表,同上,如表有下划线_则因实体去掉划线取不到字段。"
|
||||
placement="top">
|
||||
<el-icon size="16"
|
||||
style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
<el-tooltip raw-content content="若找不到在前端生成的实体/表,同上,如表有下划线_则因实体去掉划线取不到字段。" placement="top">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="state.ruleForm.leftTab"
|
||||
@change="leftTableChanged" value-key="value" filterable
|
||||
clearable class="w100">
|
||||
<el-option v-for="item in state.tableData2"
|
||||
:key="item.entityName"
|
||||
:label="item.entityName + ' ( ' + item.tableName + ' ) [' + item.tableComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.leftTab" @change="leftTableChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.tableData2" :key="item.entityName" :label="item.entityName + ' ( ' + item.tableName + ' ) [' + item.tableComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="左边树关联字段" prop="leftKey">
|
||||
<el-select v-model="state.ruleForm.leftKey" @change="leftKeyChanged"
|
||||
value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.lcolumnData"
|
||||
:key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.leftKey" @change="leftKeyChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.lcolumnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
|
||||
<el-form-item label="关联主表字段" prop="bottomKey">
|
||||
<template v-slot:label>
|
||||
<div>
|
||||
关联主表字段
|
||||
<el-tooltip raw-content content="先选择主表才可以选择字段。"
|
||||
placement="top">
|
||||
<el-icon size="16"
|
||||
style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
<el-tooltip raw-content content="先选择主表才可以选择字段。" placement="top">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="state.ruleForm.leftPrimaryKey"
|
||||
@change="leftPrimaryKeyChanged" value-key="value" filterable
|
||||
clearable class="w100">
|
||||
<el-option v-for="item in state.columnData"
|
||||
:key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.leftPrimaryKey" @change="leftPrimaryKeyChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.columnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="左边树Name字段" prop="leftName">
|
||||
<el-select v-model="state.ruleForm.leftName"
|
||||
@change="leftNameChanged" value-key="value" filterable clearable
|
||||
class="w100">
|
||||
<el-option v-for="item in state.lcolumnData"
|
||||
:key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.leftName" @change="leftNameChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.lcolumnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="模板" prop="template">
|
||||
<el-input v-model="state.ruleForm.template" clearable
|
||||
placeholder="请输入" />
|
||||
<el-input v-model="state.ruleForm.template" clearable placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -313,10 +281,8 @@
|
||||
<el-row :gutter="10">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="右区域下框库定位器" prop="configId3">
|
||||
<el-select v-model="state.ruleForm.configId3" placeholder="库名"
|
||||
filterable @change="dbChanged3()" class="w100">
|
||||
<el-option v-for="item in state.dbData" :key="item.configId"
|
||||
:label="item.configId" :value="item.configId" />
|
||||
<el-select v-model="state.ruleForm.configId3" placeholder="库名" filterable @change="dbChanged3()" class="w100">
|
||||
<el-option v-for="item in state.dbData" :key="item.configId" :label="item.configId" :value="item.configId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -325,33 +291,20 @@
|
||||
<template v-slot:label>
|
||||
<div>
|
||||
下框关联表名称
|
||||
<el-tooltip raw-content
|
||||
content="若找不到在前端生成的实体/表,同上,如表有下划线_则因实体去掉划线取不到字段。"
|
||||
placement="top">
|
||||
<el-icon size="16"
|
||||
style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
<el-tooltip raw-content content="若找不到在前端生成的实体/表,同上,如表有下划线_则因实体去掉划线取不到字段。" placement="top">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="state.ruleForm.bottomTab"
|
||||
@change="bottomTableChanged" value-key="value" filterable
|
||||
clearable class="w100">
|
||||
<el-option v-for="item in state.tableData3"
|
||||
:key="item.entityName"
|
||||
:label="item.entityName + ' ( ' + item.tableName + ' ) [' + item.tableComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.bottomTab" @change="bottomTableChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.tableData3" :key="item.entityName" :label="item.entityName + ' ( ' + item.tableName + ' ) [' + item.tableComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="下框表关联字段" prop="bottomKey">
|
||||
<el-select v-model="state.ruleForm.bottomKey"
|
||||
@change="bottomKeyChanged" value-key="value" filterable
|
||||
clearable class="w100">
|
||||
<el-option v-for="item in state.bcolumnData"
|
||||
:key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.bottomKey" @change="bottomKeyChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.bcolumnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -360,20 +313,13 @@
|
||||
<template v-slot:label>
|
||||
<div>
|
||||
关联主表字段
|
||||
<el-tooltip raw-content content="先选择主表才可以选择字段。"
|
||||
placement="top">
|
||||
<el-icon size="16"
|
||||
style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
<el-tooltip raw-content content="先选择主表才可以选择字段。" placement="top">
|
||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="state.ruleForm.bottomPrimaryKey"
|
||||
@change="bottomPrimaryKeyChanged" value-key="value" filterable
|
||||
clearable class="w100">
|
||||
<el-option v-for="item in state.columnData"
|
||||
:key="item.columnName"
|
||||
:label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'"
|
||||
:value="item" />
|
||||
<el-select v-model="state.ruleForm.bottomPrimaryKey" @change="bottomPrimaryKeyChanged" value-key="value" filterable clearable class="w100">
|
||||
<el-option v-for="item in state.columnData" :key="item.columnName" :label="item.columnName + ' ( ' + item.columnName + ' ) [' + item.columnComment + ']'" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user