diff --git a/Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj b/Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj index 70835385..98305a19 100644 --- a/Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj +++ b/Admin.NET/Admin.NET.Application/Admin.NET.Application.csproj @@ -35,8 +35,4 @@ - - - - diff --git a/Admin.NET/Admin.NET.Core/Entity/SysCodeGenConfig.cs b/Admin.NET/Admin.NET.Core/Entity/SysCodeGenConfig.cs index 2d8e7f19..f6cc1a42 100644 --- a/Admin.NET/Admin.NET.Core/Entity/SysCodeGenConfig.cs +++ b/Admin.NET/Admin.NET.Core/Entity/SysCodeGenConfig.cs @@ -204,4 +204,10 @@ public partial class SysCodeGenConfig : EntityBase /// [SugarColumn(ColumnDescription = "排序")] public int OrderNo { get; set; } = 100; + + /// + /// 字段验证规则 + /// + [SugarColumn(ColumnDescription = "字段验证规则", ColumnDataType = StaticConfig.CodeFirst_BigString)] + public string? Rules { get; set; } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplate.cs b/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplate.cs index ff6d53ad..e2ef9ad9 100644 --- a/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplate.cs +++ b/Admin.NET/Admin.NET.Core/SeedData/SysCodeGenTemplate.cs @@ -1,31 +1,31 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -namespace Admin.NET.Core; - -/// -/// 代码生成模板配置表种子数据 -/// -public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData -{ - /// - /// 种子数据 - /// - /// - public IEnumerable HasData() - { - return new[] - { - new SysCodeGenTemplate{ Id=36036980201001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_api.ts.vm", OutputFile="api/{PagePath}/{TableNameLower}.ts", Describe ="(WEB)接口"}, - new SysCodeGenTemplate{ Id=36036980201002, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_index.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/index.vue", Describe ="(WEB)列表页面"}, - new SysCodeGenTemplate{ Id=36036980201003, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_editDialog.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/component/editDialog.vue", Describe ="(WEB)编辑对话框"}, - - new SysCodeGenTemplate{ Id=36036980202001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_Service.cs.vm", OutputFile="Service/{TableName}/{TableName}Service.cs", Describe ="(服务端)业务"}, - new SysCodeGenTemplate{ Id=36036980202002, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_InputDto.cs.vm", OutputFile="Service/{TableName}/Dto/{TableName}Input.cs", Describe ="(服务端)输入参数"}, - new SysCodeGenTemplate{ Id=36036980202003, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_OutputDto.cs.vm", OutputFile="Service/{TableName}/Dto/{TableName}Output.cs", Describe ="(服务端)输出参数"}, - }; - } +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +/// +/// 代码生成模板配置表种子数据 +/// +public class SysCodeGenTemplateSeedData : ISqlSugarEntitySeedData +{ + /// + /// 种子数据 + /// + /// + public IEnumerable HasData() + { + return new[] + { + new SysCodeGenTemplate{ Id=36036980201001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_api.ts.vm", OutputFile="api/{PagePath}/{TableNameLower}.ts", Describe ="(WEB)接口"}, + new SysCodeGenTemplate{ Id=36036980201002, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_index.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/index.vue", Describe ="(WEB)列表页面"}, + new SysCodeGenTemplate{ Id=36036980201003, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Frontend, Name="web_views_editDialog.vue.vm", OutputFile="views/{PagePath}/{TableNameLower}/component/editDialog.vue", Describe ="(WEB)编辑对话框"}, + + new SysCodeGenTemplate{ Id=36036980202001, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_Service.cs.vm", OutputFile="Service/{TableName}/{TableName}Service.cs", Describe ="(服务端)业务"}, + new SysCodeGenTemplate{ Id=36036980202002, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_InputDto.cs.vm", OutputFile="Service/{TableName}/Dto/{TableName}Input.cs", Describe ="(服务端)输入参数"}, + new SysCodeGenTemplate{ Id=36036980202003, SysFlag=YesNoEnum.Y, Type=CodeGenTypeEnum.Backend, Name="service_OutputDto.cs.vm", OutputFile="Service/{TableName}/Dto/{TableName}Output.cs", Describe ="(服务端)输出参数"}, + }; + } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs index a2f2449e..7c472076 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/CustomViewEngine.cs @@ -54,6 +54,11 @@ public class CustomViewEngine : ViewEngineModel public bool IsApiService { get; set; } + /// + /// 远程验证 + /// + public bool RemoteVerify { get; set; } + public List QueryWhetherList { get; set; } public List TableField { get; set; } diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenConfig.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenConfig.cs index 42f88985..6a4a619c 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenConfig.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/CodeGenConfig.cs @@ -192,4 +192,32 @@ public class CodeGenConfig /// 排序 /// public int OrderNo { get; set; } + + /// + /// 字段验证规则 + /// + public string Rules { get; set; } + + #region 不在数据库中的字段 + + /// + /// 字段验证集合 + /// + public List? RuleItems { get; set; } + + /// + /// 是否远程验证 + /// + public bool RemoteVerify { get; set; } = false; + + /// + /// 是否存在验证规则 + /// + public bool AnyRule { get; set; } = false; + + /// + /// 验证触发器 + /// + public string Trigger { get; set; } + #endregion } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/VerifyRuleItem.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/VerifyRuleItem.cs new file mode 100644 index 00000000..339564c4 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/Dto/VerifyRuleItem.cs @@ -0,0 +1,36 @@ +namespace Admin.NET.Core.Service; + +/// +/// 验证规则选项 +/// +public class VerifyRuleItem +{ + /// + /// 编码 + /// + public long Key { get; set; } + /// + /// 验证类型 + /// + public string Type { get; set; } + /// + /// 验证错误消息 + /// + public string Message { get; set; } + /// + /// 最小值 + /// + public string Min { get; set; } + /// + /// 最大值 + /// + public string Max { get; set; } + /// + /// 正则表达式 + /// + public string Pattern { get; set; } + /// + /// 数据类型(搭配正则) + /// + public string DataType { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs index e588e21d..cb9a6532 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenConfigService.cs @@ -119,7 +119,25 @@ public class SysCodeGenConfigService : IDynamicApiController, ITransient codeGenConfig.WhetherRetract = YesNoEnum.N.ToString(); // 生成代码时,主键并不是必要输入项,故一定要排除主键字段 - codeGenConfig.WhetherRequired = (tableColumn.IsNullable || tableColumn.IsPrimarykey) ? YesNoEnum.N.ToString() : YesNoEnum.Y.ToString(); + //codeGenConfig.WhetherRequired = (tableColumn.IsNullable || tableColumn.IsPrimarykey) ? YesNoEnum.N.ToString() : YesNoEnum.Y.ToString(); + #region 添加校验规则 + //添加校验规则 + codeGenConfig.Id = YitIdHelper.NextId(); + //验证规则 + List ruleItems = new List(); + if (!tableColumn.IsNullable && !tableColumn.IsPrimarykey) + { + ruleItems.Add(new VerifyRuleItem() + { + Key = codeGenConfig.Id, + Type = "required", + Message = $"{tableColumn.ColumnComment}不能为空", + }); + } + codeGenConfig.WhetherRequired = ruleItems.Any(t => t.Type == "required") ? YesNoEnum.Y.ToString() : YesNoEnum.N.ToString(); + codeGenConfig.Rules = ruleItems.ToJson(); + #endregion + codeGenConfig.QueryWhether = YesOrNo; codeGenConfig.WhetherAddUpdate = YesOrNo; codeGenConfig.WhetherTable = YesOrNo; diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs index 6cab2204..402fd7fa 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs @@ -157,7 +157,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient { dbTableName = dbTableName.Substring(0, bracketIndex); } - var table = dbTableInfos.FirstOrDefault(x => x.Name.ToLower().StartsWith(config != null && config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(dbTableName) : dbTableName)); + var table = dbTableInfos.FirstOrDefault(x => x.Name.ToLower().StartsWith((config != null && config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(dbTableName) : dbTableName).ToLower())); if (table == null) continue; tableOutputList.Add(new TableOutput { @@ -233,7 +233,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient IsNullable = u.IsNullable, ColumnKey = u.IsPrimarykey.ToString(), NetType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), - DataType = CodeGenUtil.ConvertDataType(u, provider.CurrentConnectionConfig.DbType), + DataType = u.DataType, ColumnComment = string.IsNullOrWhiteSpace(u.ColumnDescription) ? u.DbColumnName : u.ColumnDescription }).ToList(); @@ -345,26 +345,48 @@ public class SysCodeGenService : IDynamicApiController, ITransient Directory.Delete(outputPath, true); var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 + #region 构造前端需要验证的数据 + foreach (var item in tableFieldList) + { + List list = new List(); + if (!string.IsNullOrWhiteSpace(item.Rules)) + { + if (item.Rules != "[]") + { + list = JSON.Deserialize>(item.Rules); + } + } + else + { + item.Rules = "[]"; + } + item.RuleItems = list; + item.WhetherRequired = list.Any(t => t.Type == "required") ? YesNoEnum.Y.ToString() : YesNoEnum.N.ToString(); + item.AnyRule = list.Count > 0; + item.RemoteVerify = list.Any(t => t.Type == "remote"); + } + #endregion var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 var data = new CustomViewEngine(_db) { - ConfigId = input.ConfigId!, - AuthorName = input.AuthorName!, - BusName = input.BusName!, - NameSpace = input.NameSpace!, - ClassName = input.TableName!, - PagePath = input.PagePath!, - ProjectLastName = input.NameSpace!.Split('.').Last(), - QueryWhetherList = queryWhetherList, - TableField = tableFieldList, - IsJoinTable = joinTableList.Count > 0, - IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), - PrintType = input.PrintType!, - PrintName = input.PrintName!, - IsApiService = input.IsApiService + ConfigId = input.ConfigId!,//库定位器名 + AuthorName = input.AuthorName!,//作者 + BusName = input.BusName!,//业务名称 + NameSpace = input.NameSpace!,//命名空间 + ClassName = input.TableName!,//类名称 + PagePath = input.PagePath!,//页面目录 + ProjectLastName = input.NameSpace!.Split('.').Last(),//项目最后个名称,生成的时候赋值 + QueryWhetherList = queryWhetherList,//查询条件 + TableField = tableFieldList,//表字段配置信息 + IsJoinTable = joinTableList.Count > 0,//是否联表 + IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(),//是否上传 + PrintType = input.PrintType!,//支持打印类型 + PrintName = input.PrintName!,//打印模板名称 + IsApiService = input.IsApiService, + RemoteVerify = tableFieldList.Any(t => t.RemoteVerify == true),//远程验证 }; // 模板 @@ -433,26 +455,48 @@ public class SysCodeGenService : IDynamicApiController, ITransient public async Task> Preview(SysCodeGen input) { var tableFieldList = await _codeGenConfigService.GetList(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合 + #region 构造前端需要验证的数据 + foreach (var item in tableFieldList) + { + List list = new List(); + if (!string.IsNullOrWhiteSpace(item.Rules)) + { + if (item.Rules != "[]") + { + list = JSON.Deserialize>(item.Rules); + } + } + else + { + item.Rules = "[]"; + } + item.RuleItems = list; + item.WhetherRequired = list.Any(t => t.Type == "required") ? YesNoEnum.Y.ToString() : YesNoEnum.N.ToString(); + item.AnyRule = list.Count > 0; + item.RemoteVerify = list.Any(t => t.Type == "remote"); + } + #endregion var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesNoEnum.Y.ToString()).ToList(); // 前端查询集合 var joinTableList = tableFieldList.Where(u => u.EffectType == "Upload" || u.EffectType == "fk" || u.EffectType == "ApiTreeSelect").ToList(); // 需要连表查询的字段 (string joinTableNames, string lowerJoinTableNames) = GetJoinTableStr(joinTableList); // 获取连表的实体名和别名 var data = new CustomViewEngine(_db) { - ConfigId = input.ConfigId!, - AuthorName = input.AuthorName!, - BusName = input.BusName!, - NameSpace = input.NameSpace!, - ClassName = input.TableName!, - PagePath = input.PagePath!, - ProjectLastName = input.NameSpace!.Split('.').Last(), - QueryWhetherList = queryWhetherList, - TableField = tableFieldList, - IsJoinTable = joinTableList.Count > 0, - IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(), - PrintType = input.PrintType!, - PrintName = input.PrintName!, - IsApiService = input.IsApiService + ConfigId = input.ConfigId!,//库定位器名 + AuthorName = input.AuthorName!,//作者 + BusName = input.BusName!,//业务名称 + NameSpace = input.NameSpace!,//命名空间 + ClassName = input.TableName!,//类名称 + PagePath = input.PagePath!,//页面目录 + ProjectLastName = input.NameSpace!.Split('.').Last(),//项目最后个名称,生成的时候赋值 + QueryWhetherList = queryWhetherList,//查询条件 + TableField = tableFieldList,//表字段配置信息 + IsJoinTable = joinTableList.Count > 0,//是否联表 + IsUpload = joinTableList.Where(u => u.EffectType == "Upload").Any(),//是否上传 + PrintType = input.PrintType!,//支持打印类型 + PrintName = input.PrintName!,//打印模板名称 + IsApiService = input.IsApiService, + RemoteVerify = tableFieldList.Any(t => t.RemoteVerify == true)//远程验证 }; // 获取模板文件并替换 diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_InputDto.cs.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_InputDto.cs.vm index 02d4d86b..1cae2652 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_InputDto.cs.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_InputDto.cs.vm @@ -6,6 +6,18 @@ using Admin.NET.Core; using System.ComponentModel.DataAnnotations; +@{ + string RemoteField=""; + string PKName=""; + foreach (var column in Model.TableField){ + if(column.RemoteVerify){ + RemoteField=@column.PropertyName; + } + if(column.ColumnKey == "True"){ + PKName=column.PropertyName; + } + } +} namespace @Model.NameSpace; @@ -67,11 +79,26 @@ if (@column.ColumnKey != "True"){ public class Add@(@Model.ClassName)Input : @(@Model.ClassName)BaseInput { @foreach (var column in Model.TableField){ -if (@column.WhetherRequired == "Y"){ +if (@column.WhetherAddUpdate == "Y"){ @:/// @:/// @column.ColumnComment @:/// + @if(@column.WhetherRequired=="Y"){ @:[Required(ErrorMessage = "@(@column.ColumnComment)不能为空")] + } + @if(@column.NetType.StartsWith("string")&&!@column.RuleItems.Any(t=>t.Type=="length")){ + @:[StringLength(@(@column.ColumnLength), ErrorMessage = "@(@column.ColumnComment)不能超过@(@column.ColumnLength)个字符")] + } + @if(@column.AnyRule){ + @foreach(var rule in @column.RuleItems){ + @if(rule.Type=="pattern"){ + @:[RegularExpression(@@"@(@FormatPattern(rule.Pattern))", ErrorMessage = "@(@rule.Message)")] + } + @if(rule.Type=="length"){ + @:[StringLength(@(@rule.Max),MinimumLength = @(@rule.Min), ErrorMessage = "@(@column.ColumnComment)只能是@(@rule.Min)至@(@rule.Max)字符")] + } + } + } @:public override @column.NetType @column.PropertyName { get; set; } @: } @@ -109,6 +136,29 @@ if (@column.ColumnKey == "True"){ @:public @column.NetType @column.PropertyName { get; set; } @: } +if (@column.WhetherAddUpdate == "Y"){ + @:/// + @:/// @column.ColumnComment + @:/// + @if(@column.WhetherRequired=="Y"){ + @:[Required(ErrorMessage = "@(@column.ColumnComment)不能为空")] + } + @if(@column.NetType.StartsWith("string")&&!@column.RuleItems.Any(t=>t.Type=="length")){ + @:[StringLength(@(@column.ColumnLength), ErrorMessage = "@(@column.ColumnComment)不能超过@(@column.ColumnLength)个字符")] + } + @if(@column.AnyRule){ + @foreach(var rule in @column.RuleItems){ + @if(rule.Type=="pattern"){ + @:[RegularExpression(@@"@(@FormatPattern(rule.Pattern))", ErrorMessage = "@(@rule.Message)")] + } + @if(rule.Type=="length"){ + @:[StringLength(@(@rule.Max),MinimumLength = @(@rule.Min), ErrorMessage = "@(@column.ColumnComment)只能是@(@rule.Min)至@(@rule.Max)字符")] + } + } + } + @:public override @column.NetType @column.PropertyName { get; set; } + @: +} } } @@ -119,3 +169,33 @@ if (@column.ColumnKey == "True"){ { } + + +@if(@Model.RemoteVerify){ + @:/// + @:/// 检查@(RemoteField)字段参数 + @:/// + @:public class Exists@(RemoteField)Input + @:{ + @:/// + @:/// 字段名称 + @:/// + @:public string FieldName { get; set; } + @: + @:/// + @:/// 旧字段名 + @:/// + @:public string OldFieldName { get; set; } + @:} +} +@{ +string FormatPattern(string pattern) +{ + if (pattern.EndsWith('g')) + { + pattern = pattern.TrimEnd('g'); + } + pattern = pattern.Trim('/'); + return pattern; +} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm index 1f5b30e1..92304f6b 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/service_Service.cs.vm @@ -10,10 +10,18 @@ using Microsoft.AspNetCore.Http; string joinTableName = "u"; Dictionary definedObjects = new Dictionary(); bool haveLikeCdt = false; + string RemoteField=""; + string PKName=""; foreach (var column in Model.TableField){ if (column.QueryWhether == "Y" && column.QueryType == "like"){ haveLikeCdt = true; } + if(column.RemoteVerify){ + RemoteField=@column.PropertyName; + } + if(column.ColumnKey == "True"){ + PKName=column.PropertyName; + } } } namespace @Model.NameSpace; @@ -121,8 +129,16 @@ if (@column.QueryWhether == "Y"){ public async Task Add(Add@(@Model.ClassName)Input input) { var entity = input.Adapt<@(@Model.ClassName)>(); + @if(Model.RemoteVerify){ + @://验证重复值 + @:if (await _@(@Model.LowerClassName)Rep.IsAnyAsync(t => t.@(RemoteField) == entity.@(RemoteField))) + @:{ + @://已存在 + @:throw Oops.Oh(ErrorCodeEnum.D1006); + @:} + } await _@(@Model.LowerClassName)Rep.InsertAsync(entity); - return entity.Id; + return entity.@(@PKName); } /// @@ -153,7 +169,15 @@ if (@column.ColumnKey == "True"){ public async Task Update(Update@(@Model.ClassName)Input input) { var entity = input.Adapt<@(@Model.ClassName)>(); - await _@(@Model.LowerClassName)Rep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); + @if(Model.RemoteVerify){ + @://验证重复值 + @:if (await _advertsRep.IsAnyAsync(t => t.@(RemoteField) == entity.@(RemoteField) && t.@(@PKName) != entity.@(@PKName))) + @:{ + @://已存在 + @:throw Oops.Oh(ErrorCodeEnum.D1006); + @:} + } + await _@(@Model.LowerClassName)Rep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// @@ -233,4 +257,32 @@ if(@column.EffectType == "ApiTreeSelect" && !definedObjects.ContainsKey("@(@colu @:} } } + +@if(Model.RemoteVerify){ + @:/// + @:/// 检查@(RemoteField)字段是否可用 + @:/// + @:/// 检查字段参数 + @:/// + @:[ApiDescriptionSettings(Name = "exists@(RemoteField)",Description = "检查@(RemoteField)字段是否可用", Order = 940), HttpPost] + @:[DisplayName("检查@(RemoteField)字段是否可用")] + @:public async Task Exists@(RemoteField)Async(Exists@(RemoteField)Input param) + @:{ + @:if (string.IsNullOrWhiteSpace(param.FieldName)) + @:{ + @:return false; + @:} + @:if (!string.IsNullOrWhiteSpace(param.OldFieldName)) + @:{ + @:if (param.FieldName.Trim() == param.OldFieldName.Trim()) + @:{ + @://编辑状态下触发的 + @:return true; + @:} + @:} + + @:return !(await _@(@Model.LowerClassName)Rep.IsAnyAsync(t => t.@(RemoteField).Equals(param.FieldName.Trim()))); + @:} +} + } diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_api.ts.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_api.ts.vm index 50d4ea93..e53cab1a 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_api.ts.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_api.ts.vm @@ -1,4 +1,16 @@ -@{Dictionary definedObjects = new Dictionary();} +@{ + Dictionary definedObjects = new Dictionary(); + string RemoteField=""; + string PKName=""; + foreach (var column in Model.TableField){ + if(column.RemoteVerify){ + RemoteField=@column.PropertyName; + } + if(column.ColumnKey == "True"){ + PKName=column.PropertyName; + } + } +} import request from '/@@/utils/request'; enum Api { Add@(@Model.ClassName) = '/api/@(@Model.LowerClassName)/add', @@ -6,6 +18,9 @@ enum Api { Update@(@Model.ClassName) = '/api/@(@Model.LowerClassName)/update', Page@(@Model.ClassName) = '/api/@(@Model.LowerClassName)/page', Detail@(@Model.ClassName) = '/api/@(@Model.LowerClassName)/detail', + @if(Model.RemoteVerify){ + @:Exists@(RemoteField) = '/api/@(@Model.LowerClassName)/exists@(RemoteField)', + } @foreach (var column in Model.TableField){ if(@column.EffectType == "fk" && (@column.WhetherAddUpdate == "Y" || column.QueryWhether == "Y")){ @:Get@(@column.FkEntityName)@(@column.PropertyName)Dropdown = '/api/@(@Model.LowerClassName)/@(@column.FkEntityName)@(@column.PropertyName)Dropdown', @@ -111,4 +126,14 @@ if(@column.EffectType == "Upload"){ @:}; break; } +} + +@if(Model.RemoteVerify){ +@:// 检查@(RemoteField)是否存在 +@:export const exists@(RemoteField) = (params?: any) => + @:request({ + @:url: Api.Exists@(RemoteField), + @:method: 'post', + @:data: params, + @:}); } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm index 5717e7b3..8221268c 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/template/web_views_editDialog.vue.vm @@ -1,6 +1,18 @@ @{Dictionary definedObjects = new Dictionary();} @{var pkField = Model.TableField.Where(c => c.ColumnKey == "True").FirstOrDefault();} -@{string pkFieldName = LowerFirstLetter(pkField.PropertyName);} +@{ + string pkFieldName = LowerFirstLetter(pkField.PropertyName); + string RemoteField=""; + string PKName=""; + foreach (var column in Model.TableField){ + if(column.RemoteVerify){ + RemoteField=@column.PropertyName; + } + if(column.ColumnKey == "True"){ + PKName=column.PropertyName; + } + } +}