基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

时间:2022-08-31 14:54:54

上一篇介绍了集成ng-zorro的过程,本篇我们来看下如何用abp官方的生成器来生成前端代码。

Abp官方提供了一个强大的代码生成器 ASP.NET Zero Power Tools,它的Visual Studio 插件在这里。当然你也可以不用插件,但你得自己创建json文件。相关官方文档见这里
基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

工作原理

生成器(vs插件)首先根据用户填写的Entity相关的内容创建一个json描述文件,然后开始将真正的代码生成核心程序释放到aspnet-core\AspNetZeroRadTool这个目录下,然后开始执行生成,命令行:dotnet AspNetZeroRadTool.dll YourEntity.Json。执行过程中会扫描FileTemplatesn内的文件进行实际的文件替换等操作生成最终代码文件。

AspNetZeroRadTool文件夹

基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

除了config.json其余内容均可以从生成器(vs插件)自动释放出来。所以你如果用git其实可以把除config.json外的文件ignore。

FileTemplates 文件夹

FileTemplates文件夹顾名思义是放了一些模板文件。本次我们只关注Angular模板,目录结构如下:
基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

  • ComponentHtmlTemplate:用于生成 Asp.net Zero 5.4之前的component html
  • ComponentTemplate:用于生成component ts
  • ComponentTurboTableHtmlTemplate:用于生成 Asp.net Zero 5.4之后的componnet html (由于5.4之后Table更换成了TurboTable组件)
  • CreateOrEditComponentHtmlTemplate:用于生成创建或修改对话框的html
  • CreateOrEditComponentTemplate:用于生成创建或修改对话框的ts
  • LookupTables:用于生成选择关联实体对话框的html/ts (如果你定义的实体有外键关联,在编辑或创建时会通过该对话框进行选择)
  • ViewEntityComponentHtmlTemplate:用于生成view only对话框html (插件界面中有可选项)
  • ViewEntityComponentTemplate:用于生成view only对话框ts (插件界面中有可选项)

每一个模板文件夹都包含以下三个文件,我们来看一下:
基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

  • MainTemplate.txt:根据所在文件夹的不同有不同内容(html/ts),其中会有一些占位的字符串,它们以大括号{{...}}包裹。在生成阶段会被替换。有几个比较通用的占位字符串:
    {{Entity_Name_Here}}表示首字母大写的实体名称,如Book;
    {{entity_Name_Here}}表示首字母小写的实体名称,如book。
  • PartialTemplates.txt:MainTemplate.txt中会有一些占位字符串的内容会根据条件从这个文件中获取。比如生成器在处理MainTemplate.txt时遇到{{Get_Excel_Method_Here}}这个占位符时会去PartialTemplates.txt文件里找到对应的内容,然后根据PartialTemplates的内容(有条件的)去填充MainTemplate.txt的内容。
  • TemplateInfo.txt:这个文件很简单,里面只有path和condition。path代表最终生成之后文件的位置;condition代表是否需要按照本目录的模板生成代码。

创建我们自己的模板

了解了以上结构之后,我们来创建我们的模板文件。

首先我们来禁用一些我们用不到的模板目录,禁用方式很简单,在目录中我们只要复制相应的TemplateInfo.txt文件并重命名为TemplateInfo.custom.txt,然后修改里面的condition为"condition":"false"即可。我们需要禁用ComponentTurboTableHtmlTemplateLookupTables\LookupTableComponentTurboTableHtmlTemplateLookupTables\LookupTableCssTemplate这几个文件夹。

以下我们创建一个列表显示页的html模板页:

  1. 创建模板目录ComponentNgZorroTableHtmlTemplate
  2. 创建模板三个文件MainTemplate.txt、PartialTemplates.txt、TemplateInfo.txt

MainTemplate.txt的内容:

<page-header [title]="title">
    <ng-template #title>
        {{l("{{Entity_Name_Plural_Here}}")}}
        <span class="text-sm text-grey-dark">
            <nz-divider nzType="vertical"></nz-divider>
            {{l("{{Entity_Name_Plural_Here}}HeaderInfo")}}
        </span>
    </ng-template>
</page-header>
<nz-card [nzBordered]="false">
    <form nz-form [nzLayout]="'inline'" class="search__form">
        <nz-row nzGutter="8">
            <nz-col nzSm="24">
                <nz-form-item>
                    <nz-form-control>
                        <nz-input-group nzSearch [nzSuffix]="suffixSearchButton">
                            <input type="text" nz-input [(ngModel)]="filterText" name="filterText" [placeholder]="l('SearchWithThreeDot')">
                            <ng-template #suffixSearchButton>
                                <button nz-button nzType="primary" nzSearch (click)="refresh($event)">
                                    <i class="anticon anticon-search"></i>
                                </button>
                            </ng-template>
                        </nz-input-group>
                    </nz-form-control>
                </nz-form-item>
            </nz-col>
        </nz-row>
        <nz-row nzGutter="8" *ngIf="advancedFiltersVisible">
            {{Property_Filter_Template_Here}}{{NP_Filter_Template_Here}}
        </nz-row>
    </form>
    <nz-row nzGutter="8">
        <nz-col nzMd="20" nzSm="12">
            <button nz-button [nzType]="'primary'" *ngIf="isGranted('{{Permission_Value_Here}}.Create')" (click)="createOrEdit()">
                <i class="anticon anticon-plus"></i>
                <span>
                    {{l("CreateNew{{Entity_Name_Here}}")}}
                </span>
            </button>
            <ng-container *ngIf="selectedDataItems.length > 0">
                <button nz-button [nzType]="'danger'" *ngIf="isGranted('{{Permission_Value_Here}}.Delete')" (click)="batchDelete()">
                    <i class="anticon anticon-delete"></i>
                    <span>
                        Delete Selected
                    </span>
                </button>
            </ng-container>
            {{Get_Excel_Button_Here}}            
        </nz-col>
        <nz-col nzMd="4" nzSm="12" class="text-right">
            <a (click)="advancedFiltersVisible=!advancedFiltersVisible">
                {{advancedFiltersVisible ? l('HideAdvancedFilters') : l('ShowAdvancedFilters')}}
                <i class="anticon" [class.anticon-down]="!advancedFiltersVisible" [class.anticon-up]="advancedFiltersVisible"></i>
            </a>
        </nz-col>
    </nz-row>
    <div class="my-md">
        <nz-alert [nzType]="'info'" [nzShowIcon]="true" [nzMessage]="message">
            <ng-template #message>
                <span>
                    <strong class="text-primary">{{selectedDataItems.length}}</strong> items selected
                </span>
                <a (click)="restCheckStatus(dataList)" class="ml-md" *ngIf="selectedDataItems.length>0">
                    {{l('Clear')}}
                </a>
                <nz-divider nzType="vertical"></nz-divider>
                <a (click)="refresh()">
                    {{l('Refresh')}}
                </a>
            </ng-template>
        </nz-alert>
    </div>
    <nz-row class="my-md">
        <nz-table #ajaxTable [nzData]="dataList" [nzTotal]="totalItems" [(nzPageIndex)]="pageNumber" [(nzPageSize)]="pageSize"
            [nzLoading]="isTableLoading" (nzPageIndexChange)="pageNumberChange()" (nzPageSizeChange)="refresh()"
            [nzShowSizeChanger]="true" [nzShowQuickJumper]="true" [nzNoResult]="noDataTemplate" [nzShowTotal]="totalTemplate"
            [nzFrontPagination]="false" [nzScroll]="{x: 'auto'}">
            <ng-template #noDataTemplate>
                <no-data></no-data>
            </ng-template>
            <ng-template #totalTemplate let-total>
                {{l('TotalRecordsCount', total)}}
            </ng-template>
            <thead (nzSortChange)="gridSort($event)">
                <tr>
                    <th nzShowCheckbox [(nzChecked)]="allChecked" [nzDisabled]="allCheckboxDisabled" [nzIndeterminate]="checkboxIndeterminate"
                        (nzCheckedChange)="checkAll($event)" nzWidth="60px"></th>
                    {{NP_Looped_Header_Template_Here}}{{Property_Looped_Header_Template_Here}}
                    <th class="text-center" [hidden]="!isGrantedAny('{{Permission_Value_Here}}.Edit', '{{Permission_Value_Here}}.Delete')">
                        <span>{{l('Actions')}}</span>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let item of ajaxTable.data">
                    <td nzShowCheckbox [(nzChecked)]="item.checked" (nzCheckedChange)="refreshCheckStatus(dataList)"></td>
                    {{NP_Looped_Template_Here}}{{Property_Looped_Template_Here}}                    
                    <td>
                        {{View_Button_Here}}
                        <ng-container *ngIf="isGranted('{{Permission_Value_Here}}.Edit')">
                            <a (click)="createOrEdit(item.{{entity_Name_Here}}.id)">
                                <i nz-icon type="edit"></i>
                                {{l('Edit')}}
                            </a>
                            <nz-divider nzType="vertical"></nz-divider>
                        </ng-container>
                        <ng-container *ngIf="isGranted('{{Permission_Value_Here}}.Delete')">
                            <nz-popconfirm [nzTitle]="l('{{Entity_Name_Here}}DeleteWarningMessage', '')" (nzOnConfirm)="delete{{Entity_Name_Here}}(item.{{entity_Name_Here}})"
                                [nzOkText]="l('Ok')" [nzCancelText]="l('Cancel')">
                                <a nz-popconfirm>
                                    <i nz-icon type="delete"></i>
                                    {{l('Delete')}}
                                </a>
                            </nz-popconfirm>
                        </ng-container>
                    </td>
                </tr>
            </tbody>
        </nz-table>
    </nz-row>
</nz-card>

PartialTemplates.txt的内容:

{
"propertyTemplates":[
        {
            "placeholder" : "{{Property_Looped_Header_Template_Here}}",
            "condition" : "{{Property_Listed_Here}} == true",
            "templates" : [
                    {
                    "type" : "default",
                    "content" : "
                            <th nzShowSort nzSortKey=\"{{entity_Name_Here}}.{{property_Name_Here}}\">
                                {{l('{{Property_Name_Here}}')}}
                            </th>
                        "
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Looped_Template_Here}}",
            "condition" : "{{Property_Listed_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "
                    <td>
                        {{l('Enum_{{Property_Type_Here}}' + {{property_Type_Here}}[item.{{entity_Name_Here}}.{{property_Name_Here}}])}}
                    </td>"
                    },
                    {
                    "type" : "bool",
                    "content" : "
                        <td class=\"text-center\">
                            <span class=\"badge badge-success\" *ngIf=\"item.{{entity_Name_Here}}.{{property_Name_Here}}\">{{l('Yes')}}</span>
                            <span class=\"badge badge-error\" *ngIf=\"!item.{{entity_Name_Here}}.{{property_Name_Here}}\">{{l('No')}}</span>
                        </td>"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
                        <td class=\"text-center\">
                            {{item.{{entity_Name_Here}}.{{property_Name_Here}} | momentFormat:\'L\'}}
                        </td>"
                    },
                    {
                    "type" : "default",
                    "content" : "
                        <td>
                            {{item.{{entity_Name_Here}}.{{property_Name_Here}}}}
                        </td>"
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Filter_Template_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label for=\"{{Property_Name_Here}}FilterSelect\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-select [(ngModel)]=\"{{property_Name_Here}}Filter\" name=\"{{Property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}FilterSelect\" nzAllowClear>
                                        <nz-option [nzLabel]=\"l('All')\" nzValue=\"-1\"></nz-option>
                                        {{Enum_Option_Looped_Template_Here}}
                                    </nz-select>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "bool",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label for=\"{{Property_Name_Here}}FilterSelect\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-select [(ngModel)]=\"{{property_Name_Here}}Filter\" name=\"{{Property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}FilterSelect\" nzAllowClear>
                                        <nz-option [nzLabel]=\"l('All')\" nzValue=\"-1\"></nz-option>
                                        <nz-option [nzLabel]=\"l('False')\" nzValue=\"0\"></nz-option>
                                        <nz-option [nzLabel]=\"l('True')\" nzValue=\"1\"></nz-option>
                                    </nz-select>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <range-picker name=\"{{property_Name_Here}}Filter\" id=\"{{Property_Name_Here}}Filter\" [(ngModel)]=\"min{{Property_Name_Here}}Filter\" [(ngModelEnd)]=\"max{{Property_Name_Here}}Filter\"
                                            [nzPlaceHolder]=\"[l('StartDateTime'),l('EndDateTime')]\"></range-picker>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "numeric",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"Min{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <nz-input-number id=\"Min{{Property_Name_Here}}Filter\" name=\"min{{Property_Name_Here}}Filter\" [(ngModel)]=\"min{{Property_Name_Here}}Filter\" [nzPlaceHolder]=\"{{l('MinValue')}}\"></nz-input-number>
                                        <nz-input-number id=\"Max{{Property_Name_Here}}Filter\" name=\"max{{Property_Name_Here}}Filter\" [(ngModel)]=\"max{{Property_Name_Here}}Filter\" [nzPlaceHolder]=\"{{l('MaxValue')}}\"></nz-input-number>
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    },
                    {
                    "type" : "default",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{Property_Name_Here}}Filter\">
                                        {{l(\"{{Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <input nz-input id=\"{{Property_Name_Here}}Filter\" name=\"{{property_Name_Here}}Filter\" [(ngModel)]=\"{{property_Name_Here}}Filter\">
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    }
                ]
        }
    ],
"navigationPropertyTemplates":[
    {
            "placeholder" : "{{NP_Looped_Header_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                                <th nzShowSort nzSortKey=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}\">
                                    {{l('{{NP_Display_Property_Name_Here}}')}}
                                </th>
                            "
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Looped_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                    <td>
                        {{item.{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}}}
                    </td>"
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Filter_Template_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
                            <nz-col nzSm=\"6\">
                                <nz-form-item>
                                    <nz-form-label nzFor=\"{{NP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\">
                                        ({{l(\"{{NP_Foreign_Entity_Name_Here}}{{NP_Duplication_Number_Here}}\")}}) {{l(\"{{NP_Display_Property_Name_Here}}\")}}
                                    </nz-form-label>
                                    <nz-form-control>
                                        <input nz-input id=\"{{NP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\" name=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\" [(ngModel)]=\"{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter\">
                                    </nz-form-control>
                                </nz-form-item>
                            </nz-col>"
                    }
                ]
        }
    ],
"enumTemplates":[
        {
            "placeholder" : "{{Enum_Option_Looped_Template_Here}}",
            "content" : "
            <nz-option [nzLabel]=\"l('Enum_{{Enum_Name_Here}}_{{Enum_Property_Value_Here}}')\" nzValue=\"{{Enum_Property_Value_Here}}\"></nz-option>"
        }
    ],
"conditionalTemplates":[
        {
            "placeholder": "{{View_Button_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "
                    <ng-container>
                            <a (click)=\"view{{Entity_Name_Here}}(item.id)\">
                                <i nz-icon type=\"search\"></i>
                                {{l('View')}}
                            </a>
                            <nz-divider nzType=\"vertical\"></nz-divider>
                        </ng-container>"
        },
        {
            "placeholder": "{{Get_Excel_Button_Here}}",
            "condition": "{{Create_Excel_Export_Here}} == true",
            "content": "<button nz-button nzType=\"default\" (click)=\"exportToExcel()\"><i nz-icon type=\"file-excel\"></i><span>{{l('ExportToExcel')}}</span></button>"
        }
    ]
}

TemplateInfo.txt的内容:

{
    "path" : "app\\{{menu_Position_Here}}\\{{namespace_Relative_Here}}\\{{entity_Name_Plural_Here}}\\{{entity_Name_Plural_Here}}.component.html",
    "condition": "true"
}

创建列表显示的typescript文件:
ts模板目录我们直接使用已有的模板目录ComponentTemplate, 这里需要注意如需要修改默认的模板文件内容,必须复制该文件并重命名成.custom.txt。比如复制MainTemplate.txt为MainTemplate.custom.txt,之后在MainTemplate.custom.txt添加你自己的模板内容。
修改后的MainTemplate.custom.txt内容:

import { Component, Injector } from '@angular/core';
import { {{Entity_Name_Plural_Here}}ServiceProxy, {{Entity_Name_Here}}Dto {{Enum_Import_Here}}, Get{{Entity_Name_Here}}ForView } from '@shared/service-proxies/service-proxies';
import { PagedListingComponentBase, PagedRequestDto } from '@shared/common/paged-listing-component-base';
import { CreateOrEdit{{Entity_Name_Here}}ModalComponent } from './create-or-edit-{{entity_Name_Here}}-modal.component';{{View_Component_Import_Here}}
{{View_Component_Import_Here}}
import { FileDownloadService } from '@shared/utils/file-download.service';

import { finalize } from 'rxjs/operators';
import * as moment from 'moment';
import * as _ from 'lodash';

@Component({
    templateUrl: './{{entity_Name_Plural_Here}}.component.html'
})
export class {{Entity_Name_Plural_Here}}Component extends PagedListingComponentBase<Get{{Entity_Name_Here}}ForView> {

    advancedFiltersAreShown = false;
    filterText = '';
{{Property_Filter_Def_Here}}{{NP_Filter_Def_Here}}
    {{enum_Def_Here}}

    constructor(
        injector: Injector,
        private _{{entity_Name_Plural_Here}}ServiceProxy: {{Entity_Name_Plural_Here}}ServiceProxy,
        private _fileDownloadService: FileDownloadService
    ) {
        super(injector);
    }

    protected fetchDataList(request: PagedRequestDto, pageNumber: number, finishedCallback: () => void): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy
            .getAll(
                this.filterText,{{Property_Filter_Param_Here}}{{NP_Filter_Param_Here}}
                request.sorting,
                request.skipCount,                
                request.maxResultCount
            )
            .pipe(finalize(finishedCallback))
            .subscribe(result => {
                this.dataList = result.items;
                this.showPaging(result);
            });
    }

    createOrEdit(id?: number): void {
        this.modalHelper
            .createStatic(CreateOrEdit{{Entity_Name_Here}}ModalComponent, { {{entity_Name_Here}}Id: id }, { size: 'md' })
            .subscribe(res => {
                if (res) {
                    this.refresh();
                }
            });
    }

    delete{{Entity_Name_Here}}({{entity_Name_Here}}: {{Entity_Name_Here}}Dto): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy.delete({{entity_Name_Here}}.id)
            .subscribe(() => {
                this.refresh();
                this.notify.success(this.l('SuccessfullyDeleted'));
            });
    }

    {{Get_View_Component_Method_Here}}
    {{Get_Excel_Method_Here}}
}

PartialTemplates.custom.txt内容:

{
"propertyTemplates":[
        {
            "placeholder" : "{{Property_Filter_Def_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "enum",
                    "content" : "       {{property_Name_Here}}Filter = -1;
"
                    },
                    {
                    "type" : "byte",
                    "content" : "       max{{Property_Name_Here}}Filter : string = '';
        min{{Property_Name_Here}}Filter : string = '';
"
                    },
                    {
                    "type" : "numeric",
                    "content" : "       max{{Property_Name_Here}}Filter : number;
        max{{Property_Name_Here}}FilterEmpty : number;
        min{{Property_Name_Here}}Filter : number;
        min{{Property_Name_Here}}FilterEmpty : number;
"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "       max{{Property_Name_Here}}Filter : moment.Moment;
        min{{Property_Name_Here}}Filter : moment.Moment;
"
                    },
                    {
                    "type" : "bool",
                    "content" : "       {{property_Name_Here}}Filter = -1;
"
                    },
                    {
                    "type" : "default",
                    "content" : "       {{property_Name_Here}}Filter = '';
"
                    }
                ]
        },
        {
            "placeholder" : "{{Property_Filter_Param_Here}}",
            "condition" : "{{Property_Advanced_Filter_Here}} == true",
            "templates" : [
                    {
                    "type" : "byte",
                    "content" : "
            this.max{{Property_Name_Here}}Filter == null ? '' : this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter == null ? '' : this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "numeric",
                    "content" : "
            this.max{{Property_Name_Here}}Filter == null ? this.max{{Property_Name_Here}}FilterEmpty: this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter == null ? this.min{{Property_Name_Here}}FilterEmpty: this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "DateTime",
                    "content" : "
            this.max{{Property_Name_Here}}Filter,
            this.min{{Property_Name_Here}}Filter,"
                    },
                    {
                    "type" : "default",
                    "content" : "
            this.{{property_Name_Here}}Filter,"
                    }
                ]
        }
    ],
"navigationPropertyTemplates":[
        {
            "placeholder" : "{{NP_Filter_Def_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "       {{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter = '';
"
                    }
                ]
        },
        {
            "placeholder" : "{{NP_Filter_Param_Here}}",
            "templates" : [
                    {
                    "relation" : "single",
                    "content" : "
            this.{{nP_Foreign_Entity_Name_Here}}{{NP_Display_Property_Name_Here}}{{NP_Duplication_Number_Here}}Filter,"
                    }
                ]
        }
    ],
"enumTemplates":[
        {
            "placeholder" : "{{Enum_Import_Here}}",
            "content" : ", {{Entity_Name_Here}}Dto{{Enum_Used_For_Property_Name_Here}}"
        },
        {
            "placeholder" : "{{enum_Def_Here}}",
            "content" : "{{enum_Name_Here}} = {{Entity_Name_Here}}Dto{{Enum_Used_For_Property_Name_Here}};
        "
        }
    ],
"conditionalTemplates":[
        {
            "placeholder": "{{View_Component_Import_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "
import { View{{Entity_Name_Here}}ModalComponent } from './view-{{entity_Name_Here}}-modal.component';"
        },  
        {
            "placeholder": "{{Get_Excel_Method_Here}}",
            "condition": "{{Create_Excel_Export_Here}} == true",
            "content": "exportToExcel(): void {
        this._{{entity_Name_Plural_Here}}ServiceProxy.get{{Entity_Name_Plural_Here}}ToExcel(
        this.filterText,{{Property_Filter_Param_Here}}{{NP_Filter_Param_Here}}
        )
        .subscribe(result => {
            this._fileDownloadService.downloadTempFile(result);
         });
    }"
        },
        {
            "placeholder": "{{Get_View_Component_Method_Here}}",
            "condition": "{{Create_View_Only_Here}} == true",
            "content": "view{{Entity_Name_Here}}(id): void {
                this.modalHelper
                    .create(View{{Entity_Name_Here}}ModalComponent, {
                        {{entity_Name_Here}}Id: id
                    }, { size: 'md' })
                    .subscribe(() => { });
            }"
        }
    ]
}

按照上述过程修改其他模板目录中的内容即可使用代码生成器按照你的模板进行代码生成。

在我的项目里已经包含了修改好的模板文件,请自行查看。

项目地址:https://github.com/rqx110/abp-ng-zorro

觉得还可以,请不要吝啬你的Star

使用

我们来简单测试下生成:
基于ng-zorro的ASP.NET ZERO前端实现之代码生成器
这里注意到几个带“Customized”的就是我们将默认模板自定义后的结果。

再来看一个生成后的ts文件,可以和上面的模板文件进行对比:

import { Component, Injector } from '@angular/core';
import { BooksServiceProxy, BookDto , GetBookForView } from '@shared/service-proxies/service-proxies';
import { PagedListingComponentBase, PagedRequestDto } from '@shared/common/paged-listing-component-base';
import { CreateOrEditBookModalComponent } from './create-or-edit-book-modal.component';
import { ViewBookModalComponent } from './view-book-modal.component';

import { ViewBookModalComponent } from './view-book-modal.component';
import { FileDownloadService } from '@shared/utils/file-download.service';

import { finalize } from 'rxjs/operators';
import * as moment from 'moment';
import * as _ from 'lodash';

@Component({
    templateUrl: './books.component.html'
})
export class BooksComponent extends PagedListingComponentBase<GetBookForView> {

    advancedFiltersAreShown = false;
    filterText = '';
        nameFilter = '';
        authorFilter = '';

    

    constructor(
        injector: Injector,
        private _booksServiceProxy: BooksServiceProxy,
        private _fileDownloadService: FileDownloadService
    ) {
        super(injector);
    }

    protected fetchDataList(request: PagedRequestDto, pageNumber: number, finishedCallback: () => void): void {
        this._booksServiceProxy
            .getAll(
                this.filterText,
            this.nameFilter,
            this.authorFilter,
                request.sorting,
                request.skipCount,                
                request.maxResultCount
            )
            .pipe(finalize(finishedCallback))
            .subscribe(result => {
                this.dataList = result.items;
                this.showPaging(result);
            });
    }

    createOrEdit(id?: number): void {
        this.modalHelper
            .createStatic(CreateOrEditBookModalComponent, { bookId: id }, { size: 'md' })
            .subscribe(res => {
                if (res) {
                    this.refresh();
                }
            });
    }

    deleteBook(book: BookDto): void {
        this._booksServiceProxy.delete(book.id)
            .subscribe(() => {
                this.refresh();
                this.notify.success(this.l('SuccessfullyDeleted'));
            });
    }

    viewBook(id): void {
                this.modalHelper
                    .create(ViewBookModalComponent, {
                        bookId: id
                    }, { size: 'md' })
                    .subscribe(() => { });
            }
    exportToExcel(): void {
        this._booksServiceProxy.getBooksToExcel(
        this.filterText,
            this.nameFilter,
            this.authorFilter,
        )
        .subscribe(result => {
            this._fileDownloadService.downloadTempFile(result);
         });
    }
}

结束

ASP.NET Zero Power Tools是一个商业产品,你必须购买才能使用。