ABP 框架代码批量生成器
需要最新源码,或技术提问,请加QQ群:538327407
我的各种github 开源项目和代码:https://github.com/linbin524
简介
用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 类型做了不同代码输出
<%@ 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="HashBlockChain" Optional="False" Category="1.名称空间" Description="系统名称空间的根名称." %>
<%@ Property Name="Namespace" Type="String" Default="ZLDB_Domain" Optional="False" Category="1.名称空间" Description="系统当前所属文件夹的名称(命名空间相关)." %>
<%@ Property Name="FolderNamespace" Type="String" Default="" Optional="true" Category="1.名称空间" Description="系统名称空间的Model名称." %>
<%@ Property Name="PrefixLength" Type="Int32" Default="" 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, "", ); %>
<% FolderNamespace=SourceTable.Name.ToString();%>
<%string tableName=SourceTable.Name.ToString(); %>
<%string paramName=GetParamName(tableName); %> using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Dynamic;
using Abp.Linq.Extensions;
using <%= RootNamespace %>.<%=Namespace%>.Dtos;
using <%= RootNamespace %>.Dto;
using <%= RootNamespace %>.Authorization.<%=tableName%>.Exporting;
namespace <%= RootNamespace %>.<%=Namespace%>
{ <% foreach (ColumnSchema column in SourceTable.Columns) { %>
<% if (column.IsPrimaryKeyMember) { %> <%string tempType = GetCSharpVariableType(column); %> <% if (tempType=="Guid") { %>
/// <summary>
/// <%=SourceTable.Description%> 业务实现接口
/// </summary>
public class <%=tableName%>AppService : AbpZeroTemplateAppServiceBase, I<%=tableName%>AppService
{
private readonly IRepository<<%=tableName%>, Guid> _<%=paramName%>Repository;
private readonly I<%=tableName%>ListExcelExporter _i<%=tableName%>ListExcelExporter; /// <summary>
/// 构造函数自动注入我们所需要的类或接口
/// </summary>
public <%=tableName%>AppService(IRepository<<%=tableName%>, Guid> <%=paramName%>Repository,I<%=tableName%>ListExcelExporter i<%=tableName%>ListExcelExporter)
{
_<%=paramName%>Repository = <%=paramName%>Repository;
_i<%=tableName%>ListExcelExporter = i<%=tableName%>ListExcelExporter; } /// <summary>
/// 获取所有数据列表
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<List<<%=tableName%>Dto>> GetAllList()
{
//调用Task仓储的特定方法GetAllWithPeople
var resultList = await _<%=paramName%>Repository.GetAllListAsync();
return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
} /// <summary>
/// 获取分页数据列表 分页具体代码需要适当修改,如orderby 需要匹配 创建时间 或者其他数据Id(int)
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<PagedResultDto<<%=tableName%>Dto>> GetPagedListAsync(PagedAndFilteredInputDto input)
{
var query = _<%=paramName%>Repository.GetAll();
//TODO:根据传入的参数添加过滤条件 var resultCount = await query.CountAsync();
var result<%=paramName%> = await query
.OrderBy(x=>x.Id)
.PageBy(input)
.ToListAsync(); var resultListDtos = result<%=paramName%>.MapTo<List<<%=tableName%>Dto>>(); if (!string.IsNullOrEmpty(input.Sorting)) {
resultListDtos = resultListDtos.OrderBy(input.Sorting).ToList();
} return new PagedResultDto<<%=tableName%>Dto>(
resultCount,
resultListDtos
);
} /// <summary>
/// 获取指定条件的数据列表 webapi 无法使用
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<List<<%=tableName%>Dto>> GetListByCodition(Expression<Func<<%=tableName%>, bool>> predicate)
{ var resultList = await _<%=paramName%>Repository.GetAllListAsync(predicate);
return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
} /// <summary>
/// 导出excel 具体方法
/// </summary>
/// <returns>excel文件</returns>
/// public async Task<FileDto> Get<%=tableName%>ToExcel()
///{
/// var resultList = await _<%=paramName%>Repository.GetAllListAsync();
/// var <%=paramName%>Dtos= Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
/// return _i<%=tableName%>ListExcelExporter.ExportToFile(<%=paramName%>Dtos);
/// } /// <summary>
/// 根据指定id 获取数据实体
/// </summary>
/// <param name="input">当前id</param>
/// <returns></returns>
public async Task<<%=tableName%>Dto> Get<%=tableName%>ForEditAsync(NullableIdDto<System.Guid> input)
{
var output = new <%=tableName%>Dto(); <%=tableName%>Dto <%=paramName%>EditDto; if (input.Id.HasValue)
{
var entity = await _<%=paramName%>Repository.GetAsync(input.Id.Value);
<%=paramName%>EditDto = entity.MapTo<<%=tableName%>Dto>();
}
else
{
<%=paramName%>EditDto = new <%=tableName%>Dto();
} output = <%=paramName%>EditDto;
return output;
} /// <summary>
/// 根据Id创建或编辑操作
/// </summary>
/// <param name="input">实体</param>
/// <returns></returns>
public async Task CreateOrUpdate<%=tableName%>Async(<%=tableName%>Dto input)
{
if (!string.IsNullOrWhiteSpace(input.Id))
{
await Update(input);
}
else
{
await Create(input);
}
} /// <summary>
/// 新增
/// </summary>
/// <param name="input">新增参数</param>
/// <returns>新增实体</returns>
public async Task<Guid> Create(<%=tableName%>Dto input)
{
input.Id = new <%=tableName%>().Id.ToString();
var resultObj = input.MapTo<<%=tableName%>>();
var result = await _<%=paramName%>Repository.InsertAsync(resultObj); return result.Id;
} /// <summary>
/// 修改
/// </summary>
/// <param name="input">修改参数</param>
/// <returns>修改实体</returns>
public async Task<<%=tableName%>Dto> Update(<%=tableName%>Dto input)
{
<%=tableName%> obj = await _<%=paramName%>Repository.GetAsync(new Guid(input.Id));
input.MapTo(obj);
var result = await _<%=paramName%>Repository.UpdateAsync(obj);
return obj.MapTo<<%=tableName%>Dto>();
} /// <summary>
/// 删除
/// </summary>
/// <param name="input">删除Dto</param>
/// <returns>无返回值</returns>
public async System.Threading.Tasks.Task Delete(EntityDto<string> input)
{
await _<%=paramName%>Repository.DeleteAsync(new Guid(input.Id));
} /// <summary>
/// 删除 webapi 无法使用
/// </summary>
/// <param name="predicate">删除条件</param>
/// <returns>无返回值</returns>
public async System.Threading.Tasks.Task DeleteByCondition(Expression<Func<<%=tableName%>, bool>> predicate)
{
await _<%=paramName%>Repository.DeleteAsync(predicate); }
} <% } else {%>
/// <summary>
/// <%=SourceTable.Description%> 业务实现接口
/// </summary>
public class <%=tableName%>AppService : AbpZeroTemplateAppServiceBase, I<%=tableName%>AppService
{
private readonly IRepository<<%=tableName%>, <%=tempType%>> _<%=paramName%>Repository;
private readonly I<%=tableName%>ListExcelExporter _i<%=tableName%>ListExcelExporter; /// <summary>
/// 构造函数自动注入我们所需要的类或接口
/// </summary>
public <%=tableName%>AppService(IRepository<<%=tableName%>, <%=tempType%>> <%=paramName%>Repository,I<%=tableName%>ListExcelExporter i<%=tableName%>ListExcelExporter)
{
_<%=paramName%>Repository = <%=paramName%>Repository;
_i<%=tableName%>ListExcelExporter = i<%=tableName%>ListExcelExporter; } /// <summary>
/// 获取所有数据列表
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<List<<%=tableName%>Dto>> GetAllList()
{
//调用Task仓储的特定方法GetAllWithPeople
var resultList = await _<%=paramName%>Repository.GetAllListAsync();
return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
} /// <summary>
/// 获取分页数据列表 分页具体代码需要适当修改,如orderby 需要匹配 创建时间 或者其他数据Id(int)
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<PagedResultDto<<%=tableName%>Dto>> GetPagedListAsync(PagedAndFilteredInputDto input)
{
var query = _<%=paramName%>Repository.GetAll();
//TODO:根据传入的参数添加过滤条件 var resultCount = await query.CountAsync();
var result<%=paramName%> = await query
.OrderBy(x=>x.Id)
.PageBy(input)
.ToListAsync(); var resultListDtos = result<%=paramName%>.MapTo<List<<%=tableName%>Dto>>();
return new PagedResultDto<<%=tableName%>Dto>(
resultCount,
resultListDtos
);
} /// <summary>
/// 获取指定条件的数据列表 webapi 无法使用
/// </summary>
/// <returns>返回数据集合</returns>
public async Task<List<<%=tableName%>Dto>> GetListByCodition(Expression<Func<<%=tableName%>, bool>> predicate)
{ var resultList = await _<%=paramName%>Repository.GetAllListAsync(predicate);
return Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
} /// <summary>
/// 导出excel 具体方法
/// </summary>
/// <returns>excel文件</returns>
/// public async Task<FileDto> Get<%=tableName%>ToExcel()
///{
/// var resultList = await _<%=paramName%>Repository.GetAllListAsync();
/// var <%=paramName%>Dtos= Mapper.Map<List<<%=tableName%>Dto>>(resultList).ToList();
/// return _i<%=tableName%>ListExcelExporter.ExportToFile(<%=paramName%>Dtos);
/// } /// <summary>
/// 根据指定id 获取数据实体
/// </summary>
/// <param name="input">当前id</param>
/// <returns></returns>
public async Task<<%=tableName%>Dto> Get<%=tableName%>ForEditAsync(NullableIdDto<<%=tempType%>> input)
{
var output = new <%=tableName%>Dto(); <%=tableName%>Dto <%=paramName%>EditDto; if (Convert.ToInt32(input.Id)>)
{
var entity = await _<%=paramName%>Repository.GetAsync(Convert.ToInt32(input.Id));
<%=paramName%>EditDto = entity.MapTo<<%=tableName%>Dto>();
}
else
{
<%=paramName%>EditDto = new <%=tableName%>Dto();
} output = <%=paramName%>EditDto;
return output;
} /// <summary>
/// 根据Id创建或编辑操作
/// </summary>
/// <param name="input">实体</param>
/// <returns></returns>
public async Task CreateOrUpdate<%=tableName%>Async(<%=tableName%>Dto input)
{
if (Convert.ToInt32(input.Id)>)
{
await Update(input);
}
else
{
await Create(input);
}
} /// <summary>
/// 新增
/// </summary>
/// <param name="input">新增参数</param>
/// <returns>新增实体</returns>
public async Task<<%=tempType%>> Create(<%=tableName%>Dto input)
{
input.Id = new <%=tableName%>().Id.ToString();
var resultObj = input.MapTo<<%=tableName%>>();
var result = await _<%=paramName%>Repository.InsertAsync(resultObj); return result.Id;
} /// <summary>
/// 修改
/// </summary>
/// <param name="input">修改参数</param>
/// <returns>修改实体</returns>
public async Task<<%=tableName%>Dto> Update(<%=tableName%>Dto input)
{
<%=tableName%> obj = await _<%=paramName%>Repository.GetAsync(Convert.ToInt32(input.Id));
input.MapTo(obj);
var result = await _<%=paramName%>Repository.UpdateAsync(obj);
return obj.MapTo<<%=tableName%>Dto>();
} /// <summary>
/// 删除
/// </summary>
/// <param name="input">删除Dto</param>
/// <returns>无返回值</returns>
public async System.Threading.Tasks.Task Delete(EntityDto<string> input)
{
await _<%=paramName%>Repository.DeleteAsync(Convert.ToInt32(input.Id));
} /// <summary>
/// 删除 webapi 无法使用
/// </summary>
/// <param name="predicate">删除条件</param>
/// <returns>无返回值</returns>
public async System.Threading.Tasks.Task DeleteByCondition(Expression<Func<<%=tableName%>, bool>> predicate)
{
await _<%=paramName%>Repository.DeleteAsync(predicate); }
} <% }%>
<% }%> <% }%> } <script runat="template">
<!-- #include file="TemplateUtilities.cs" -->
</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="" 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, "", ); %>
<%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>) {%>
<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="" 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="" 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_Domain Entity 数据库对应实体
//
//
//
//auther:
//----------------------------------------------
namespace HashBlockChain.ZLDB_Domain
{ //获取主键Id的命名 ///链信息表
[Table("ChainInfo")]
public partial class ChainInfo : Entity<int>
{
#region Declarations /// <summary>
/// 链名称
/// </summary>
[DisplayName("链名称")]
[StringLength()] public virtual string ChainName { get; set; } /// <summary>
/// 链Id
/// </summary>
[DisplayName("链Id")]
[StringLength()] public virtual string ChainId { get; set; } /// <summary>
/// 链描述
/// </summary>
[DisplayName("链描述")]
[StringLength()] 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
}
}
中英文 中文显示
部分权限生成的代码
读后感觉不错,有收获可以微信请作者喝杯咖啡,读后有疑问请加微信,拉群研讨,注明来意
ABP 框架代码批量生成器的更多相关文章
- 利用代码生成工具生成基于ABP框架的代码
在前面随笔,我介绍了整个ABP优化过框架的分层模型,包括尽量简化整个ABP框架的各个层的关系,以及纳入一些基类的辅助处理,使得我们对应业务分层类或者接口尽可能减少代码,并具有生产环境所需要的基类接口, ...
- 使用代码生成工具快速开发ABP框架项目
在一般系统开发中,我们一般要借助于高度定制化的代码生成工具,用于统一代码风,节省开发时间,提高开发效率.不同的项目,它的项目不同分层的基类定义不同,我们需要在框架基类的基础上扩展我们的业务类代码,尽量 ...
- Mybatis-plus<一> Springboot框架使用MybatisPlus代码自动生成器
Mybatis-plus<一> Springboot框架使用MybatisPlus代码自动生成器 Mybatis-plus官网: https://mp.baomidou.com/ Demo ...
- ABP框架个人开发实战(1)_环境搭建
前言 之前关注ABP框架有一阵子了,一直没有潜下心来实际研究一下.最近想自己建站,以后有自己的功能开发项目,可以在自己的站点上开发,并一步步的完善,所以找个比较好用的框架迫在眉睫,选来选去,决定用AB ...
- 后台工作者HangFire与ABP框架Abp.Hangfire及扩展
HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于大家来说,比较方便. HangFire是什么 Hangfire是一个开源框架(.NET ...
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十四节--后台工作者HangFire与ABP框架Abp.Hangfire及扩展
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于 ...
- 使用ABP框架踩过的坑系列2
ABP中有很多惯例,如果使用得当,可以事半功倍,如果使用不当,也会有很大的麻烦,是否适当其实还是要看Need需求 ASP.NET Boilerplate (ABP) is an open source ...
- ABP开发框架前后端开发系列---(9)ABP框架的权限控制管理
在前面两篇随笔<ABP开发框架前后端开发系列---(7)系统审计日志和登录日志的管理>和<ABP开发框架前后端开发系列---(8)ABP框架之Winform界面的开发过程>开始 ...
- [译]ABP框架v2.3.0已经发布!
在新冠病毒的日子里,我们发布了ABP框架v2.3, 这篇文章将说明本次发布新增内容和过去的两周我们做了什么. 关于新冠病毒和我们的团队 关于冠状病毒的状况我们很难过.在Volosoft的团队,我们有不 ...
随机推荐
- clipboard.js复制文字
A-固定内容: <script type="text/javascript" src="script/clipboard.min.js"></ ...
- SJY摆棋子&&[Violet 3]天使玩偶
SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/Ju ...
- leetcdoe 175. Combine Two Tables
给定两个表,一个是人,一个是地址,要求查询所有人,可以没有地址. select a.FirstName, a.LastName, b.City, b.State from Person as a le ...
- pdf转word在线转换器
昨天大学辅导员联系我让我pdf转word,一番搜索终于找到一款免费好用的在线转换器,亲测好使免费
- 爬楼梯 · Climbing Stairs
[抄题]: 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? [思维问题]: 不知道一步.两步怎么加.还是用iteration迭代.此题公式可被 ...
- Castle ActiveRecord学习(二)配置、引用、程序启动
来源:http://www.cnblogs.com/zxj159/p/4082987.html 配置数据库驱动: Model层引用:Castle.ActiveRecord.dll.NHibernate ...
- sqlserver 日期格式化
Sql Server 中一个非常强大的日期格式化函数Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AMSelect CONVE ...
- binlog怎样参与mysql recover的
转自 Louis Hust's Blog MySQL两阶段提交 29 July 2015 参数介绍 两阶段提交 什么情况下会出现binlog写入了,但是实际这条数据不存在库中? 参数介绍 innod ...
- $.fn.extend 和$.extend函数
区别和详解:jQuery extend()和jQuery.fn.extend() 首先是简单的概述区别:$.extend()是类方法 $.fn.extend()是原型方法 对象方法和原 ...
- "我们分手吧。"女的对男的说。 "为什么呢?亲爱的,你不要我了么?" "因为你幼稚。"女的坚定地语气回答道,然后转身准备走。 男的上前踩住女的影子,然后说...
1."我们分手吧."女的对男的说. "为什么呢?亲爱的,你不要我了么?" "因为你幼稚."女的坚定地语气回答道,然后转身准备走. 男的上前踩 ...