[开源]OSharpNS 步步为营系列 - 5. 添加前端Angular模块

OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架。这个框架使用最新稳定版的.NetCore SDK(当前是.NET Core 2.2),对 AspNetCore 的配置、依赖注入、日志、缓存、实体框架、Mvc(WebApi)、身份认证、权限授权等模块进行更高一级的自动化封装,并规范了一套业务实现的代码结构与操作流程,使 .Net Core 框架更易于应用到实际项目开发中。

开源地址:https://github.com/i66soft/osharp

官方示例:https://www.osharp.org

文档中心:https://docs.osharp.org

VS 插件:https://marketplace.visualstudio.com/items?itemName=LiuliuSoft.osharp

感谢大家关注

首先特别感谢大家对OSharp快速开发框架的关注,这个系列每一篇都收到了比较多园友的关注,也在博客园首页开启了 刷屏模式

[开源]OSharpNS 步步为营系列 - 5. 添加前端Angular模块

同时演示网站的用户注册数量也在持续上涨

[开源]OSharpNS 步步为营系列 - 5. 添加前端Angular模块

项目 Star 数也增长了几百,欢迎没点 Star 的也来关注下 OSharp快速开发框架

再次感谢

概述

前后端分离的系统中,前端和后端只有必要的数据通信交互,前端相当于一个完整的客户端应用程序,需要包含如下几个方面:

各个模块的布局组合

各个页面的路由连接

业务功能的数据展现和操作流程体现

操作界面的菜单/按钮权限控制

OSharp的Angular前端是基于 NG-ALAIN 框架的,这个框架基于阿里的 NG-ZORRO 封装了很多方便实用的组件,让我们很方便的实现自己需要的前端界面布局。

前端业务模块代码布局

在Angular应用程序中,存在着模块module的组织形式,一个后端的模块正好可以对应着前端的一个module。

博客模块涉及的代码文件布局如下:

src 源代码文件夹 └─app APP文件夹 └─routes 路由文件夹 └─blogs 博客模块文件夹 ├─blogs.module.ts 博客模块文件 ├─blogs.routing.ts 博客模块路由文件 ├─blog 博客组件文件夹 │ ├─blog.component.html 博客组件模板文件 │ └─blog.component.ts 博客组件文件 └─post 文章组件文件夹 ├─post.component.html 文章组件模板文件 └─post.component.ts 文章组件文件 业务组件

组件Component是Angular应用程序的最小组织单元,是完成数据展现和业务操作的基本场所。

一个组件通常包含 组件类 和 组件模板 两个部分,如需要,还可包含 组件样式。

STComponentBase

为方便实现各个数据实体的通用管理列表,OSharp定义了一个通用列表组件基类 STComponentBase,基于这个基类,只需要传入几个关键的配置信息,即可很方便的实现一个后台管理的实体列表信息。STComponentBase主要特点如下:

使用了 NG-ALAIN 的 STComponent 实现数据表格

使用 SFComponent + NzModalComponent 实现数据的 添加/编辑 操作

封装了一个通用的高级查询组件AdSearchComponent,可以很方便实现数据的多条件/条件组无级嵌套数据查询功能

对列表组件进行统一的界面布局,使各列表风格一致

提供了对列表数据的 读取/添加/编辑/删除 的默认实现

极易扩展其他表格功能

STComponentBase 代码实现如下:

export abstract class STComponentBase { moduleName: string; // URL readUrl: string; createUrl: string; updateUrl: string; deleteUrl: string; // 表格属性 columns: STColumn[]; request: PageRequest; req: STReq; res: STRes; page: STPage; @ViewChild('st') st: STComponent; // 编辑属性 schema: SFSchema; ui: SFUISchema; editRow: STData; editTitle = '编辑'; @ViewChild('modal') editModal: NzModalComponent; osharp: OsharpService; alain: AlainService; selecteds: STData[] = []; public get http(): _HttpClient { return this.osharp.http; } constructor(injector: Injector) { this.osharp = injector.get(OsharpService); this.alain = injector.get(AlainService); } protected InitBase() { this.readUrl = `api/admin/${this.moduleName}/read`; this.createUrl = `api/admin/${this.moduleName}/create`; this.updateUrl = `api/admin/${this.moduleName}/update`; this.deleteUrl = `api/admin/${this.moduleName}/delete`; this.request = new PageRequest(); this.columns = this.GetSTColumns(); this.req = this.GetSTReq(this.request); this.res = this.GetSTRes(); this.page = this.GetSTPage(); this.schema = this.GetSFSchema(); this.ui = this.GetSFUISchema(); } // #region 表格 /** * 重写以获取表格的列设置Columns */ protected abstract GetSTColumns(): OsharpSTColumn[]; protected GetSTReq(request: PageRequest): STReq { let req: STReq = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: request, allInBody: true, process: opt => this.RequestProcess(opt), }; return req; } protected GetSTRes(): STRes { let res: STRes = { reName: { list: 'Rows', total: 'Total' }, process: data => this.ResponseDataProcess(data), }; return res; } protected GetSTPage(): STPage { let page: STPage = { showSize: true, showQuickJumper: true, toTop: true, toTopOffset: 0, }; return page; } protected RequestProcess(opt: STRequestOptions): STRequestOptions { if (opt.body.PageCondition) { let page: PageCondition = opt.body.PageCondition; page.PageIndex = opt.body.pi; page.PageSize = opt.body.ps; if (opt.body.sort) { page.SortConditions = []; let sorts = opt.body.sort.split('-'); for (const item of sorts) { let sort = new SortCondition(); let num = item.lastIndexOf('.'); let field = item.substr(0, num); field = this.ReplaceFieldName(field); sort.SortField = field; sort.ListSortDirection = item.substr(num + 1) === 'ascend' ? ListSortDirection.Ascending : ListSortDirection.Descending; page.SortConditions.push(sort); } } else { page.SortConditions = []; } } return opt; } protected ResponseDataProcess(data: STData[]): STData[] { return data; } protected ReplaceFieldName(field: string): string { return field; } search(request: PageRequest) { if (!request) { return; } this.req.body = request; this.st.reload(); } change(value: STChange) { if (value.type === 'checkbox') { this.selecteds = value.checkbox; } else if (value.type === 'radio') { this.selecteds = [value.radio]; } } error(value: STError) { console.log(value); } // #endregion // #region 编辑 /** * 默认由列配置 `STColumn[]` 来生成SFSchema,不需要可以重写定义自己的SFSchema */ protected GetSFSchema(): SFSchema { let schema: SFSchema = { properties: this.ColumnsToSchemas(this.columns) }; return schema; } protected ColumnsToSchemas( columns: OsharpSTColumn[], ): { [key: string]: SFSchema } { let properties: { [key: string]: SFSchema } = {}; for (const column of columns) { if (!column.index || !column.editable || column.buttons) { continue; } let schema: SFSchema = this.alain.ToSFSchema(column); properties[column.index as string] = schema; } return properties; } protected GetSFUISchema(): SFUISchema { let ui: SFUISchema = {}; return ui; } protected toEnum(items: { id: number; text: string }[]): SFSchemaEnumType[] { return items.map(item => { let e: SFSchemaEnumType = { value: item.id, label: item.text }; return e; }); } create() { if (!this.editModal) return; this.schema = this.GetSFSchema(); this.ui = this.GetSFUISchema(); this.editRow = {}; this.editTitle = '新增'; this.editModal.open(); } edit(row: STData) { if (!row || !this.editModal) { return; } this.schema = this.GetSFSchema(); this.ui = this.GetSFUISchema(); this.editRow = row; this.editTitle = '编辑'; this.editModal.open(); } close() { if (!this.editModal) return; console.log(this.editModal); this.editModal.destroy(); } save(value: STData) { let url = value.Id ? this.updateUrl : this.createUrl; this.http.post<AjaxResult>(url, [value]).subscribe(result => { this.osharp.ajaxResult(result, () => { this.st.reload(); this.editModal.destroy(); }); }); } delete(value: STData) { if (!value) { return; } this.http.post<AjaxResult>(this.deleteUrl, [value.Id]).subscribe(result => { this.osharp.ajaxResult(result, () => { this.st.reload(); }); }); } // #endregion }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjywx.html