ABP 框架程式碼批量生成器
需要最新原始碼,或技術提問,請加QQ群:538327407,由於原始碼在不斷完善,會在之後同步到開源專案中
簡介
用abp 框架快兩年了,用它完成了多個專案,作為CTO同時也作為架構師,在應對中小型專案時候,我們通常選擇ABP(內部大型的物聯網架構採用自己的框架),感覺這款框架真心不錯。雖然開源社群有也有很多寫了幾套程式碼生成器,但是我用完之後,總是感覺不能達到我自己想要的效果,我個人還是比較喜歡一步到位,批量生成,所以就寫了這套基於codesmith的程式碼生成器,這一套在專案中還算穩定。
模板介紹
先看一下程式碼結構
我們的專案中我規劃使用的是spa的,所以一般會生成常規 四個目錄,分別是如下
其餘的中英文,還有許可權、以及DbContext 部分相對數量比較少,統一改造,生成單個檔案進行copy。
最後使用TemplateBuid 自動生成上面的批量檔案。
程式碼解析和使用
每個程式碼生成器部分需要先配置對應的專案名稱,和model等,細節需要自己去了解
常規簡單操作
一般需要我們用powerdesign等設計工具,設計好對應的表,標註要註釋,先臨時生成一個資料庫,通過codesmith 生成程式碼後,在通過code first 形式,真正在abp 對應的資料庫中生成資料庫表。
以下檔案是TemplateBuid.Cst 檔案,配置完成後,
生成程式碼操作,先編譯,後生成。
詳細程式碼舉例說明
由於篇幅有限,我就簡單說明一下Repository、AppAuthorizationProvider、view中的createOrEditModal 進行簡單說明
1、repository
常規封裝增刪改查等操作,我在專案中重寫了基類方法,封裝了批量等操作,但沒有和程式碼生成器組合起來,常規的業務裡面不需要批量操作
其中 預設主鍵都是位ID,如果實際專案中有需求,主鍵要為其他欄位,需要手動修改。目前我封裝的主要針對ID 是int 型別、GUid 型別做了不同程式碼輸出
1 <%@ CodeTemplate Language="C#" TargetLanguage="C#" ResponseEncoding="UTF-8" Description="Generates a single entity business class." Debug="True" %> 2 <%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="2.資料庫" Description="Database table that this entity should be based on." %> 3 <%@ Property Name="TablePrefixes" Type="String" Default="" Optional="True" Category="2.資料庫" Description="The table prefix to be cut from the class name" %> 4 <%@ Property Name="RootNamespace" Type="String" Default="HashBlockChain" Optional="False" Category="1.名稱空間" Description="系統名稱空間的根名稱." %> 5 <%@ Property Name="Namespace" Type="String" Default="ZLDB_Domain" Optional="False" Category="1.名稱空間" Description="系統當前所屬資料夾的名稱(名稱空間相關)." %> 6 <%@ Property Name="FolderNamespace" Type="String" Default="" Optional="true" Category="1.名稱空間" Description="系統名稱空間的Model名稱." %> 7 <%@ Property Name="PrefixLength" Type="Int32" Default="0" Optional="False" Category="2.資料庫" Description="資料表字首擷取長度." %> 8 <%@ Assembly Name="SchemaExplorer" %> 9 <%@ Assembly Name="CodeSmith.BaseTemplates" %> 10 <%@ Assembly Name="System.Data" %> 11 <%@ Import Namespace="SchemaExplorer" %> 12 <%@ Import Namespace="System.Data" %> 13 <%string tableClass=GetClassName(SourceTable, "", 0); %> 14 <% FolderNamespace=SourceTable.Name.ToString();%> 15 <%string tableName=SourceTable.Name.ToString(); %> 16 <%string paramName=GetParamName(tableName); %> 17 18 using Abp.Application.Services; 19 using Abp.Application.Services.Dto; 20 using Abp.AutoMapper; 21 using Abp.Domain.Repositories; 22 using Abp.Domain.Uow; 23 using AutoMapper; 24 using System; 25 using System.Collections.Generic; 26 using System.Data.Entity; 27 using System.Linq; 28 using System.Linq.Expressions; 29 using System.Text; 30 using System.Threading.Tasks; 31 using System.Linq.Dynamic; 32 using Abp.Linq.Extensions; 33 using <%= RootNamespace %>.<%=Namespace%>.Dtos; 34 using <%= RootNamespace %>.Dto; 35 using <%= RootNamespace %>.Authorization.<%=tableName%>.Exporting; 36 namespace <%= RootNamespace %>.<%=Namespace%> 37 { 38 39<% foreach (ColumnSchema column in SourceTable.Columns) { %> 40<% if (column.IsPrimaryKeyMember) {%> 41 42<%string tempType = GetCSharpVariableType(column); %> 43 44<% if (tempType=="Guid") {%> 45/// <summary> 46/// <%=SourceTable.Description%> 業務實現介面 47/// </summary> 48public class <%=tableName%>AppService : AbpZeroTemplateAppServiceBase, I<%=tableName%>AppService 49{ 50private readonly IRepository<<%=tableName%>, Guid> _<%=paramName%>Repository; 51private readonly I<%=tableName%>ListExcelExporter _i<%=tableName%>ListExcelExporter; 52 53/// <summary> 54/// 建構函式自動注入我們所需要的類或介面 55/// </summary> 56public <%=tableName%>AppService(IRepository<<%=tableName%>, Guid> <%=paramName%>Repository,I<%=tableName%>ListExcelExporter i<%=tableName%>ListExcelExporter) 57{ 58_<%=paramName%>Repository = <%=paramName%>Repository; 59_i<%=tableName%>ListExcelExporter = i<%=tableName%>ListExcelExporter; 60 61} 62 63/// <summary> 64/// 獲取所有資料列表 65/// </summary> 66/// <returns>返回資料集合</returns> 67public async Task<List<<%=tableName%>Dto>> GetAllList() 68{ 69//呼叫Task倉儲的特定方法GetAllWithPeople 70var resultList = await _<%=paramName%>Repository.GetAllListAsync(); 71return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 72} 73 74/// <summary> 75/// 獲取分頁資料列表 分頁具體程式碼需要適當修改,如orderby 需要匹配 建立時間 或者其他資料Id(int) 76/// </summary> 77/// <returns>返回資料集合</returns> 78public async Task<PagedResultDto<<%=tableName%>Dto>> GetPagedListAsync(PagedAndFilteredInputDto input) 79{ 80var query = _<%=paramName%>Repository.GetAll(); 81//TODO:根據傳入的引數新增過濾條件 82 83var resultCount = await query.CountAsync(); 84var result<%=paramName%> = await query 85.OrderBy(x=>x.Id) 86.PageBy(input) 87.ToListAsync(); 88 89var resultListDtos = result<%=paramName%>.MapTo<List<<%=tableName%>Dto>>(); 90 91if (!string.IsNullOrEmpty(input.Sorting)) { 92resultListDtos = resultListDtos.OrderBy(input.Sorting).ToList(); 93} 94 95return new PagedResultDto<<%=tableName%>Dto>( 96resultCount, 97resultListDtos 98); 99} 100 101/// <summary> 102/// 獲取指定條件的資料列表webapi 無法使用 103/// </summary> 104/// <returns>返回資料集合</returns> 105public async Task<List<<%=tableName%>Dto>> GetListByCodition(Expression<Func<<%=tableName%>, bool>> predicate) 106{ 107 108var resultList = await _<%=paramName%>Repository.GetAllListAsync(predicate); 109return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 110} 111 112 113/// <summary> 114/// 匯出excel 具體方法 115/// </summary> 116/// <returns>excel檔案</returns> 117/// public async Task<FileDto> Get<%=tableName%>ToExcel() 118///{ 119///var resultList = await _<%=paramName%>Repository.GetAllListAsync(); 120///var <%=paramName%>Dtos= Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 121///return _i<%=tableName%>ListExcelExporter.ExportToFile(<%=paramName%>Dtos); 122/// } 123 124/// <summary> 125/// 根據指定id 獲取資料實體 126/// </summary> 127/// <param name="input">當前id</param> 128/// <returns></returns> 129public async Task<<%=tableName%>Dto> Get<%=tableName%>ForEditAsync(NullableIdDto<System.Guid> input) 130{ 131var output = new <%=tableName%>Dto(); 132 133<%=tableName%>Dto <%=paramName%>EditDto; 134 135if (input.Id.HasValue) 136{ 137var entity = await _<%=paramName%>Repository.GetAsync(input.Id.Value); 138<%=paramName%>EditDto = entity.MapTo<<%=tableName%>Dto>(); 139} 140else 141{ 142<%=paramName%>EditDto = new <%=tableName%>Dto(); 143} 144 145output = <%=paramName%>EditDto; 146return output; 147} 148 149/// <summary> 150/// 根據Id建立或編輯操作 151/// </summary> 152/// <param name="input">實體</param> 153/// <returns></returns> 154public async Task CreateOrUpdate<%=tableName%>Async(<%=tableName%>Dto input) 155{ 156if (!string.IsNullOrWhiteSpace(input.Id)) 157{ 158await Update(input); 159} 160else 161{ 162await Create(input); 163} 164} 165 166/// <summary> 167/// 新增 168/// </summary> 169/// <param name="input">新增引數</param> 170/// <returns>新增實體</returns> 171public async Task<Guid> Create(<%=tableName%>Dto input) 172{ 173input.Id = new <%=tableName%>().Id.ToString(); 174var resultObj = input.MapTo<<%=tableName%>>(); 175var result = await _<%=paramName%>Repository.InsertAsync(resultObj); 176 177return result.Id; 178} 179 180/// <summary> 181/// 修改 182/// </summary> 183/// <param name="input">修改引數</param> 184/// <returns>修改實體</returns> 185public async Task<<%=tableName%>Dto> Update(<%=tableName%>Dto input) 186{ 187<%=tableName%> obj = await _<%=paramName%>Repository.GetAsync(new Guid(input.Id)); 188input.MapTo(obj); 189var result = await _<%=paramName%>Repository.UpdateAsync(obj); 190return obj.MapTo<<%=tableName%>Dto>(); 191} 192 193/// <summary> 194/// 刪除 195/// </summary> 196/// <param name="input">刪除Dto</param> 197/// <returns>無返回值</returns> 198public async System.Threading.Tasks.Task Delete(EntityDto<string> input) 199{ 200await _<%=paramName%>Repository.DeleteAsync(new Guid(input.Id)); 201} 202 203/// <summary> 204/// 刪除 webapi 無法使用 205/// </summary> 206/// <param name="predicate">刪除條件</param> 207/// <returns>無返回值</returns> 208public async System.Threading.Tasks.Task DeleteByCondition(Expression<Func<<%=tableName%>, bool>> predicate) 209{ 210await _<%=paramName%>Repository.DeleteAsync(predicate); 211 212} 213} 214 215 216<%} else {%> 217/// <summary> 218/// <%=SourceTable.Description%> 業務實現介面 219/// </summary> 220public class <%=tableName%>AppService : AbpZeroTemplateAppServiceBase, I<%=tableName%>AppService 221{ 222private readonly IRepository<<%=tableName%>, <%=tempType%>> _<%=paramName%>Repository; 223private readonly I<%=tableName%>ListExcelExporter _i<%=tableName%>ListExcelExporter; 224 225/// <summary> 226/// 建構函式自動注入我們所需要的類或介面 227/// </summary> 228public <%=tableName%>AppService(IRepository<<%=tableName%>,<%=tempType%>> <%=paramName%>Repository,I<%=tableName%>ListExcelExporter i<%=tableName%>ListExcelExporter) 229{ 230_<%=paramName%>Repository = <%=paramName%>Repository; 231_i<%=tableName%>ListExcelExporter = i<%=tableName%>ListExcelExporter; 232 233} 234 235/// <summary> 236/// 獲取所有資料列表 237/// </summary> 238/// <returns>返回資料集合</returns> 239public async Task<List<<%=tableName%>Dto>> GetAllList() 240{ 241//呼叫Task倉儲的特定方法GetAllWithPeople 242var resultList = await _<%=paramName%>Repository.GetAllListAsync(); 243return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 244} 245 246/// <summary> 247/// 獲取分頁資料列表 分頁具體程式碼需要適當修改,如orderby 需要匹配 建立時間 或者其他資料Id(int) 248/// </summary> 249/// <returns>返回資料集合</returns> 250public async Task<PagedResultDto<<%=tableName%>Dto>> GetPagedListAsync(PagedAndFilteredInputDto input) 251{ 252var query = _<%=paramName%>Repository.GetAll(); 253//TODO:根據傳入的引數新增過濾條件 254 255var resultCount = await query.CountAsync(); 256var result<%=paramName%> = await query 257.OrderBy(x=>x.Id) 258.PageBy(input) 259.ToListAsync(); 260 261var resultListDtos = result<%=paramName%>.MapTo<List<<%=tableName%>Dto>>(); 262return new PagedResultDto<<%=tableName%>Dto>( 263resultCount, 264resultListDtos 265); 266} 267 268/// <summary> 269/// 獲取指定條件的資料列表webapi 無法使用 270/// </summary> 271/// <returns>返回資料集合</returns> 272public async Task<List<<%=tableName%>Dto>> GetListByCodition(Expression<Func<<%=tableName%>, bool>> predicate) 273{ 274 275var resultList = await _<%=paramName%>Repository.GetAllListAsync(predicate); 276return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 277} 278 279 280/// <summary> 281/// 匯出excel 具體方法 282/// </summary> 283/// <returns>excel檔案</returns> 284/// public async Task<FileDto> Get<%=tableName%>ToExcel() 285///{ 286///var resultList = await _<%=paramName%>Repository.GetAllListAsync(); 287///var <%=paramName%>Dtos= Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList(); 288///return _i<%=tableName%>ListExcelExporter.ExportToFile(<%=paramName%>Dtos); 289/// } 290 291/// <summary> 292/// 根據指定id 獲取資料實體 293/// </summary> 294/// <param name="input">當前id</param> 295/// <returns></returns> 296public async Task<<%=tableName%>Dto> Get<%=tableName%>ForEditAsync(NullableIdDto<<%=tempType%>> input) 297{ 298var output = new <%=tableName%>Dto(); 299 300<%=tableName%>Dto <%=paramName%>EditDto; 301 302if (Convert.ToInt32(input.Id)>0) 303{ 304var entity = await _<%=paramName%>Repository.GetAsync(Convert.ToInt32(input.Id)); 305<%=paramName%>EditDto = entity.MapTo<<%=tableName%>Dto>(); 306} 307else 308{ 309<%=paramName%>EditDto = new <%=tableName%>Dto(); 310} 311 312output = <%=paramName%>EditDto; 313return output; 314} 315 316/// <summary> 317/// 根據Id建立或編輯操作 318/// </summary> 319/// <param name="input">實體</param> 320/// <returns></returns> 321public async Task CreateOrUpdate<%=tableName%>Async(<%=tableName%>Dto input) 322{ 323if (Convert.ToInt32(input.Id)>0) 324{ 325await Update(input); 326} 327else 328{ 329await Create(input); 330} 331} 332 333/// <summary> 334/// 新增 335/// </summary> 336/// <param name="input">新增引數</param> 337/// <returns>新增實體</returns> 338public async Task<<%=tempType%>> Create(<%=tableName%>Dto input) 339{ 340input.Id = new <%=tableName%>().Id.ToString(); 341var resultObj = input.MapTo<<%=tableName%>>(); 342var result = await _<%=paramName%>Repository.InsertAsync(resultObj); 343 344return result.Id; 345} 346 347/// <summary> 348/// 修改 349/// </summary> 350/// <param name="input">修改引數</param> 351/// <returns>修改實體</returns> 352public async Task<<%=tableName%>Dto> Update(<%=tableName%>Dto input) 353{ 354<%=tableName%> obj = await _<%=paramName%>Repository.GetAsync(Convert.ToInt32(input.Id)); 355input.MapTo(obj); 356var result = await _<%=paramName%>Repository.UpdateAsync(obj); 357return obj.MapTo<<%=tableName%>Dto>(); 358} 359 360/// <summary> 361/// 刪除 362/// </summary> 363/// <param name="input">刪除Dto</param> 364/// <returns>無返回值</returns> 365public async System.Threading.Tasks.Task Delete(EntityDto<string> input) 366{ 367await _<%=paramName%>Repository.DeleteAsync(Convert.ToInt32(input.Id)); 368} 369 370/// <summary> 371/// 刪除 webapi 無法使用 372/// </summary> 373/// <param name="predicate">刪除條件</param> 374/// <returns>無返回值</returns> 375public async System.Threading.Tasks.Task DeleteByCondition(Expression<Func<<%=tableName%>, bool>> predicate) 376{ 377await _<%=paramName%>Repository.DeleteAsync(predicate); 378 379} 380} 381 382 383<%}%> 384<%}%> <%}%> 385 386 387 } 388 389 390 391 392 <script runat="template"> 393 <!-- #include file="TemplateUtilities.cs" --> 394 </script>
2、AppAuthorizationProvider.cst 是要和AppPermissions.cst 一起使用的,我在實際專案中拆分了原有abp程式碼,實現了自己的整合的版本,儘量減少對abp 原有程式碼的耦合
AbpZeroTemplateApplicationModule 中的Configuration.Authorization.Providers.Add<CustomsAppAuthorizationProvider>(); 確保注入
<%-- Name: Author: Description: --%> <%@ Template Language="C#" TargetLanguage="Text" Src="" Inherits=""Debug="False" CompilerVersion="v4.0" %> <%@ Assembly Name="SchemaExplorer" %> <%@ Import Namespace="SchemaExplorer" %> <%@ Property Name="SourceDatabase" DeepLoad="True" Type="SchemaExplorer.DatabaseSchema" %> <%@ Property Name="Tables" Type="TableSchemaCollection" Optional="True" Category="2.資料庫" Description="Tables to Inclue" %> <%@ Template Language="C#" TargetLanguage="Text" %> <%@ Property Name="SampleStringProperty" Default="SomeValue" Type="System.String" %> <%@ Property Name="SampleBooleanProperty" Default="True" Type="System.Boolean" %> <%@ Property Name="RootNamespace" Type="String" Default="HashBlockChain" Optional="False" Category="1.名稱空間" Description="系統名稱空間的根名稱." %> <%@ Property Name="Namespace" Type="String" Default="ZLDB_Domain" Optional="False" Category="1.名稱空間" Description="系統當前所屬資料夾的名稱(名稱空間相關)." %> My static content here. My dynamic content here: "<%= SampleStringProperty %>" Call a script method: <%= SampleMethod() %> <% if (SampleBooleanProperty) { %> My conditional content here. <% } %> <script runat="template"> // My methods here. public string SampleMethod() { return "Method output."; } </script> using System.Linq; using Abp.Authorization; using Abp.Localization; using <%=RootNamespace%>.Authorization; //-------------------------------------------------------------------------------------------------------------------------------------------------------------- //簡介:Abp 許可權配置,生成後要在 AbpZeroTemplateApplicationModule 中的Configuration.Authorization.Providers.Add<CustomsAppAuthorizationProvider>(); 確保注入 // // // // //作者: //-------------------------------------------------------------------------------------------------------------------------------------------------------------- namespace <%= RootNamespace %>.<%=Namespace%>.Authorization { /// <summary> /// 許可權配置都在這裡。 /// 給許可權預設設定服務 /// See <see cref="CustomsAppPermissions"/> for all permission names. /// </summary> public class CustomsAppAuthorizationProvider : AuthorizationProvider { public override void SetPermissions(IPermissionDefinitionContext context) { //在這裡配置了自定義 的許可權。 var pages = context.GetPermissionOrNull(AppPermissions.Pages) ?? context.CreatePermission(AppPermissions.Pages, L("Pages")); var entityNameModel = pages.Children.FirstOrDefault(p => p.Name == AppPermissions.Pages_Administration) ?? pages.CreateChildPermission(AppPermissions.Pages_Administration, L("Administration")); <% foreach(TableSchema t in Tables){ %> <%string tableName=t.Name.ToString(); %> <%string paramName=GetParamName(tableName); %> //<%=t.Description%> 許可權 var <%=paramName%> = entityNameModel.CreateChildPermission(CustomsAppPermissions.<%=t.Name %>, L("<%=t.Name %>")); <%=paramName%>.CreateChildPermission(CustomsAppPermissions.<%=t.Name %>_Create<%=t.Name %>, L("Create<%=t.Name %>")); <%=paramName%>.CreateChildPermission(CustomsAppPermissions.<%=t.Name %>_Edit<%=t.Name %>, L("Edit<%=t.Name %>")); <%=paramName%>.CreateChildPermission(CustomsAppPermissions.<%=t.Name %>_Delete<%=t.Name %>, L("Delete<%=t.Name %>")); <% }%> } private static ILocalizableString L(string name) { return new LocalizableString(name, AbpZeroTemplateConsts.LocalizationSourceName); } } } <script runat="template"> <!-- #include file="TemplateUtilities.cs" --> </script>
3、view 資料夾中的createOrEditModal.cst
這個是view 檢視中基於angular.js,我在這上面封裝資料驗證,如果不需要的可以自己手動調整,並且 主動拆分為單列和兩列的模板,需要自動手動改動
<%@ CodeTemplate Language="C#" TargetLanguage="C#" ResponseEncoding="UTF-8" Description="Generates a single entity business class." Debug="True" %> <%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="2.資料庫" Description="Database table that this entity should be based on." %> <%@ Property Name="TablePrefixes" Type="String" Default="" Optional="True" Category="2.資料庫" Description="The table prefix to be cut from the class name" %> <%@ Property Name="RootNamespace" Type="String" Default="ManagementSystem" Optional="False" Category="1.名稱空間" Description="系統名稱空間的根名稱." %> <%@ Property Name="Title" Type="String" Default="createOrEditModal" Optional="False" Category="1.名稱空間" Description="系統名稱空間的Model名稱." %> <%@ Property Name="PrefixLength" Type="Int32" Default="0" Optional="False" Category="2.資料庫" Description="資料表字首擷取長度." %> <%@ Assembly Name="SchemaExplorer" %> <%@ Assembly Name="CodeSmith.BaseTemplates" %> <%@ Assembly Name="System.Data" %> <%@ Import Namespace="SchemaExplorer" %> <%@ Import Namespace="System.Data" %> <%string tableClass=GetClassName(SourceTable, "", 0); %> <%string tableName=SourceTable.Name.ToString(); %> <%string paramName=GetParamName(tableName); %> <%string tableDescString=GetTableDescriptionName(SourceTable.Description);%> @using Abp.Web.Mvc.Extensions @using <%=RootNamespace%>.Web.Bundling @using <%=RootNamespace%>.AbpZeroTemplate @{ LocalizationSourceName = AbpZeroTemplateConsts.LocalizationSourceName; } @section Styles { @*@Html.IncludeStyle("~/libs/bootstrap-daterangepicker/daterangepicker.css")*@ } @section Scripts { @*@Html.IncludeScript(ScriptPaths.Angular_DateRangePicker)*@ } <div> @*//mark 1*@ <form name="<%=paramName%>CreateOrEditForm" role="form" novalidate class="form-validation"> <div class="modal-header"> <h4 class="modal-title"> <span ng-if="vm.<%=paramName%>.id">編輯資訊:{{vm.<%=paramName%>.name}}</span> <span ng-if="!vm.<%=paramName%>.id">新增資訊</span> </h4> </div> <div class="modal-body"> /* 兩列模板 <div class="row"> <div class="col-sm-6"> //單列的具體程式碼1 </div> <div class="col-sm-6"> //單列的具體程式碼2 </div> </div> */ <% foreach (ColumnSchema column in SourceTable.Columns) { %> <% if(column.Size>100) {%> <div class="form-group form-md-line-input form-md-floating-label no-hint"> <textarea auto-focus class="form-control" name="<%=GetParamName(column.Name)%>" style="resize: none;" ng-class="{'edited':vm.<%=paramName%>.<%=GetParamName(column.Name)%>}" ng-model="vm.<%=paramName%>.<%=GetParamName(column.Name)%>" required ng-pattern="{填寫具體正則表示式}" ng-minlength="10" ng-maxlength="<%=column.Size%>"></textarea> <label><%=column.Description%></label> </div> <div ng-messages="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error" ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error"> <ul class="help-block text-danger"> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.pattern" ng-message="pattern"><%=column.Description%>格式不正確{具體自己再次更改}!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.required" ng-message="required"><%=column.Description%>不能為空!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.minlength" ng-message="minlength"><%=column.Description%>最小長度為10!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.maxlength" ng-message="maxlength"><%=column.Description%>最大長度為<%=column.Size%>!</li> </ul> </div> <%}else {%> <div class="form-group form-md-line-input form-md-floating-label no-hint"> <input type="text" class="form-control" name="<%=GetParamName(column.Name)%>" ng-class="{'edited':vm.<%=paramName%>.<%=GetParamName(column.Name)%>}" ng-pattern="{填寫具體正則表示式}" ng-model="vm.<%=paramName%>.<%=GetParamName(column.Name)%>" required ng-minlength="10" ng-maxlength="<%=column.Size%>" /> <label><%=column.Description%></label> </div> <div ng-messages="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error" ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error"> <ul class="help-block text-danger"> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.pattern" ng-message="pattern"><%=column.Description%>格式不正確{具體自己再次更改}!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.required" ng-message="required"><%=column.Description%>不能為空!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.minlength" ng-message="minlength"><%=column.Description%>最小長度為10!</li> <li ng-show="<%=paramName%>CreateOrEditForm.<%=GetParamName(column.Name)%>.$error.maxlength" ng-message="maxlength"><%=column.Description%>最大長度為<%=column.Size%>!</li> </ul> </div> <% }%> <% } %> </div> <div class="modal-footer"> <button ng-disabled="vm.saving" type="button" class="btn btn-default" ng-click="vm.cancel()">@L("Cancel")</button> <button type="submit" button-busy="vm.saving" busy-text="@L("SavingWithThreeDot")" class="btn btn-primary blue" ng-click="vm.save()" ng-disabled="<%=paramName%>CreateOrEditForm.$invalid"><i class="fa fa-save"></i> <span>@L("Save")</span></button> </div> </form> </div> <script runat="template"> <!-- #include file="../TemplateUtilities.cs" --> </script>
結果區域性展示
model 實體
using System; using Abp.Authorization.Users; using Abp.Extensions; using Microsoft.AspNet.Identity; using System.ComponentModel.DataAnnotations.Schema; using Abp.Domain.Entities; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; using System.ComponentModel; using Abp; //---------------------------------------------- //簡介:HashBlockChain.ZLDB_DomainEntity 資料庫對應實體 // // // //auther: //---------------------------------------------- namespace HashBlockChain.ZLDB_Domain { //獲取主鍵Id的命名 ///鏈資訊表 [Table("ChainInfo")] public partial class ChainInfo : Entity<int> { #region Declarations /// <summary> /// 鏈名稱 /// </summary> [DisplayName("鏈名稱")] [StringLength(30)] public virtual string ChainName { get; set; } /// <summary> /// 鏈Id /// </summary> [DisplayName("鏈Id")] [StringLength(30)] public virtual string ChainId { get; set; } /// <summary> /// 鏈描述 /// </summary> [DisplayName("鏈描述")] [StringLength(200)] public virtual string ChainDescription { get; set; } /// <summary> /// 鏈狀態 /// </summary> public virtual int? ChainStatus { get; set; } /// <summary> /// 排序 /// </summary> public virtual int? Sort { get; set; } /// <summary> /// 是否可見 /// </summary> public virtual bool? IsEnabled { get; set; } /// <summary> /// 建立人 /// </summary> public virtual int? CreateUserId { get; set; } /// <summary> /// 建立時間 /// </summary> public virtual DateTime? CreateDateTime { get; set; } /// <summary> /// 最後一次修改人 /// </summary> public virtual int? LastEditUserId { get; set; } /// <summary> /// 最後一次修改時間 /// </summary> public virtual DateTime? LastEditDateTime { get; set; } /// <summary> /// 節點個數 /// </summary> public virtual int? PeerCount { get; set; } /// <summary> /// 區塊鏈高度 /// </summary> public virtual long? BlockHeight { get; set; } #endregion } }
中英文 中文顯示
部分許可權生成的程式碼