[TinyERP:企业应用程序的 SPA]添加新员工





5.00/5 (1投票)
概述。如“管理员工 - 第二部分”中所述,查询员工列表很容易,因为它们已经提前准备好了。所有必要的准备步骤都发生在“添加/更新员工信息”中。让我们先来看“添加员工”。在 staffs 中添加以下行。
概述
如“管理员工 - 第二部分”中所述,查询员工列表很容易,因为它们已经提前准备好了。
所有必要的准备步骤都发生在“添加/更新员工信息”中。
让我们先来看“添加员工”。
将以下行添加到 staffs.html 中,作为 page-header 的子元素(放在 page-header 结束标签之前)。
<page-actions class="pull-right" [actions]=model.actions></page-actions>
这是定义每个页面操作列表的组件。我们也有模型属性的操作。所以,让我们将它添加到 StaffsModel 类中。
public actions:Array<PageAction>=[];
同时添加 addAction 方法。
public addAction(action: PageAction):void{ this.actions.push(action); }
此函数从 Staffs.ts 文件调用,用于添加“创建员工”按钮,将此行添加到创建 StaffsModel 的新实例之后。
self.model.addAction(new PageAction("",()=>{self.onAddNewStaffClicked();}).setText("Add new Staff"));
这段代码的意思是,我们将为当前页面添加一个新的页面操作项,当点击该项时,它将触发 onAddNewStaffClicked 方法。
然后我们导航到 addNewStaff 页面。
private onAddNewStaffClicked():void{ this.navigate(routes.addNewStaff.name); }
不用太担心路由。这是一个预定义的从“<modules>/hrm/_share/config/routes.ts”中获取的对象。在此文件中,我们定义了路由列表和相应的名称。所以我们稍后使用它,而不是使用魔术数字。我始终同意使用“routes.staffs.addNew.path”比使用“/hrm/addNewStaff”字符串更好。
随着新添加的 PageAction,"Staffs" 的 UI 在 "Manage Staffs" 的右侧出现了一个新按钮。
注册路由并将 "AddStaff" 页面添加到 HRMRoute 模块。
import {AddNewStaff} from "./pages/addNewStaff"; let routeConfigs = [ { path: "", redirectTo: routes.staffs.path, pathMatch: "full" }, { path: routes.staffs.path, component: Staffs}, { path: routes.addNewStaff.path, component: AddNewStaff} ]; @NgModule({ imports: [CommonModule, FormsModule, RouterModule.forChild(routeConfigs), AppCommon], exports: [RouterModule, Staffs], declarations: [Staffs, AddNewStaff], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class HrmRoute { }
此代码用作参考。运行它会出错。请改用 GitHub 上的源代码。
并定义 addStaff 页面的 UI。
<page> <page-header>Add new Staff</page-header> <page-content> <horizontal-form> <form-text-input [labelText]="'First Name'" [(model)]=model.firstName></form-text-input> <form-text-input [labelText]="'Last Name'" [(model)]=model.lastName></form-text-input> <form-primary-button [label]="'Save'" (onClick)="onSaveClicked($event)"></form-primary-button> <form-default-button [label]="'Cancel'" (onClick)="onCancelClicked($event)"></form-default-button> </horizontal-form> </page-content> </page>
这很直接,有一个包含 2 个文本输入字段的表单。还有 2 个按钮,一个用于取消“AddStaff”过程,一个用于创建新员工(保存按钮)。
此页面的 ts 文件如下:
import { Component } from "@angular/core"; import { BasePage } from "@app/common"; import { IStaffService } from "../_share/services/istaffService"; import {AddNewStaffModel} from "./addNewStaffModel"; import {LocalIoCNames} from "../_share/enum"; import routes from "../_share/config/routes"; @Component({ templateUrl:"src/modules/hrm/pages/addNewStaff.html" }) export class AddNewStaff extends BasePage<AddNewStaffModel>{ public model: AddNewStaffModel= new AddNewStaffModel(); public onSaveClicked():void{ let service: IStaffService = window.ioc.resolve(LocalIoCNames.IStaffService); let self=this; service.create(self.model).then(()=>{ self.navigate(routes.staffs.name); }); } public onCancelClicked():void{ this.navigate(routes.staffs.name); } }
此页面的 TypeScript 文件很简单。它只是创建一个新员工并导航回“管理员工”页面。
在 StaffService 的 create 函数内部,我们进行 REST 调用到远程 API,并将必要的信息发送到 API。
public create(staff: any):Promise{ let uri="https://:86/api/hrm/staffs"; let iconnector: IConnector = window.ioc.resolve(IoCNames.IConnector); return iconnector.post(uri, staff); }
注意:请在运行时将“localhost:86”替换为您的 API 主机。
查看“添加员工”的 API。
一切都始于 TinyERP.HRM 项目中的 StaffHandler 类。
[Route("")] [HttpPost()] [ResponseWrapper()] public void CreateStaff(CreateStaffRequest request) { this.Execute<CreateStaffRequest, CreateStaffResponse>(request); }
在 TinyERP 中,所有操作(例如:创建员工、删除......)都应转换为适当的请求。每个请求都需要包含处理该请求的必要信息(例如身份验证,......)。这在 RESTful Web 服务的无状态规则中有所规定。
我们需要做的是调用“Execute”方法。该方法将 CreateStaffRequest 请求重定向到 IBaseCommandHandler<CreateStaffRequest> 处理程序,由该处理程序处理该请求。目前,我们在“TinyERP.HRM/Command/Bootstrap.cs”类中为该请求注册了处理程序。
container.RegisterTransient<IBaseCommandHandler<CreateStaffRequest, CreateStaffResponse>, StaffCommandHandler>();
这意味着 StaffCommandHandler 类订阅入站的 CreateStaffRequest 并返回 CreateStaffRespone。
默认情况下,普通 API 控制器没有 Execute 方法,我们需要让 StaffHandler 继承自 CommandHandlerController<AggregateType>,AggregateType 在此情况下是“Staff”类。
public class StaffHandler: CommandHandlerController<TinyERP.HRM.Aggregate.Staff>
在 StaffCommandHandler 内部,我们有一个 Handle 方法,它接收 CreateStaffRequest 作为参数。这就是 CreateStaffRequest 被实际处理的地方。
public CreateStaffResponse Handle(CreateStaffRequest command) { this.Validate(command); using (IUnitOfWork uow = this.CreateUnitOfWork<TinyERP.HRM.Aggregate.Staff>()) { TinyERP.HRM.Aggregate.Staff staff = new Aggregate.Staff(); staff.UpdateBasicInfo(command); IStaffRepository repository = IoC.Container.Resolve<IStaffRepository>(uow); repository.Add(staff); uow.Commit(); staff.PublishEvents(); return ObjectHelper.Cast<CreateStaffResponse>(staff); } }
看看代码,有些地方你可能不理解或感到困惑,例如:验证,......
好的,不用担心,我无意在一篇文章中讲述所有内容。暂时忽略它们,我主要想向您展示创建新员工的基本流程。在后续文章中,我们将详细介绍每个方面,例如:错误处理,......
在这种情况下,我们只需创建一个 Staff 聚合的新实例,并调用相应的方法来更新基本信息并将其保存到 MSSQL 数据库。
为什么我们不直接设置 Staff 实例的属性,我是说不调用 UpdateBasicInfo。
这与 DDD(领域驱动设计)有关。我不会超出本文的范围。请在我的博客(http://www.tranthanhtu.vn)上搜索其他文章以获取更多信息。
所以,Staff 可以被视为一个领域,除了基本员工信息,我们还可以有其他信息(例如:工作历史、薪资、部门、工作状态,......)。这取决于您如何将应用程序分解成更小的领域。
当我们想更改 Staff 领域的信息时,请准备好适当的请求(或 CQRS 中所说的命令),并将该请求发送到系统。Staff 领域聚合(在此情况下是 Staff 类)将处理该请求并更新相应的信息并发出必要的事件。
staff.PublishEvents();
为什么我们需要这些事件以及它们是什么?
在 CQRS 中,我们有分离的写端和读端。写端是我们存储数据以供未来验证的地方,而读端,我们将反规范化的数据以必要的格式存储,这将减少将来读取这些数据所需的时间。请在我的博客上搜索有关 CQRS 的文章(http://www.tranthanhtu.vn),因为我不会超出本文的范围。
那么,这意味着当我们修改写端的数据时,我们也需要将这些更改更新到读端。
看看 Staff 类,我们可以看到,每次更改 Staff 类的属性时,都会添加一个新事件。
public Staff() { this.AddEvent(new OnStaffCreated(this.Id)); }
和
internal void UpdateBasicInfo(CreateStaffRequest command) { //.... this.AddEvent(new OnStaffBasicInforChanged(this.Id, this.FirstName, this.LastName, this.Email)); }
这些事件将在 StaffEventHandler 中处理。我们与 StaddCommandHandler 的处理方式类似,所以请自己阅读代码。
运行“添加员工”功能的最终结果如下:
输入新员工的信息。
该员工的数据存储在 MSSQL(写端)数据库中。
并且也存储在读端(使用 mongodb)。
然后,我们可以在“管理员工”页面上看到员工列表。
本文摘要。
- 应用程序应分解为更小的独立域。
- 每个操作(修改域数据)都需要转换为请求(或 CQRS 中所说的命令)。
- 域聚合将订阅并处理适当的请求,然后发出必要的事件。
- 我们可以监听这些事件并更新读端的数据或执行其他操作(例如:为新注册会员发送激活邮件,......)。
- 数据以反规范化的格式存储,并且可以快速读取。
有关此部分源代码的更多信息,请参阅 https://github.com/tranthanhtu0vn/TinyERP (在 feature/add_staff 分支中)。
感谢阅读,CodeProject