美文网首页
JHipster一知半解- 4.6.10 webapp-acco

JHipster一知半解- 4.6.10 webapp-acco

作者: 沉寂之舟 | 来源:发表于2018-06-13 21:22 被阅读31次

回文集目录:JHipster一知半解

概述与模块说明

经过前面对共享模块,布局部分的剖析可以看出JHipster的页面模块划分了,剩余的机构子模块,都只是根据不同的路由,替换掉主页上<outlet>部分,已完成不同的具体功能。  
account目录包含账户管理的功能,有JHipster实现了一套简单而标准的模型,用户可以实现(注册-激活)、(忘记密码-修改)、密码修改、用户信息修改功能。  
按照前后端分离的策略,后端仅提供API接口的调用响应,用户界面的展现,逻辑都在前端进行。主题上可以分为API服务调用,路由控制,组件逻辑与展现3个部分。
在看具体的子功能前,先查看AccountModule的部分。
@NgModule({
    //引入共享模块,并forChild加载accountState路由
    imports: [
        JhipsterSampleApplicationNg2SharedModule,
        RouterModule.forChild(accountState)
    ],
    //声明内部的组件(相对简单,没有指令)
    declarations: [
        ActivateComponent,
        RegisterComponent,
        PasswordComponent,
        PasswordStrengthBarComponent,
        PasswordResetInitComponent,
        PasswordResetFinishComponent,
        SettingsComponent
    ],
    //声明内部的服务,都是与后端通讯的封装
    providers: [
        Register,
        ActivateService,
        PasswordService,
        PasswordResetInitService,
        PasswordResetFinishService
    ],
    //已分析过,支持‘-‘命名
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class JhipsterSampleApplicationNg2AccountModule {}

路由配置

每个component组件都需占主体部分,因此path各不相同。

activate.route.ts

export const activateRoute: Route = {
    //路径名我active
    path: 'activate',
    component: ActivateComponent,
    data: {
        //无需权限
        authorities: [],
        pageTitle: 'activate.title'
    },
    //路由守卫为UserRouteAccessService,由于authorities是空数组,始终是允许的。但是守卫会调用principal.identity()从后端获取用户信息。
    canActivate: [UserRouteAccessService,]
};

password.route.ts

password-reset-finish.route.ts

password-reset-init.route.ts

settings.route.ts

这几个路由也类似,password和setting增加需要“'ROLE_USER'”权限

register.route.ts

export const registerRoute: Route = {
    path: 'register',
    component: RegisterComponent,
    data: {
        authorities: [],
        pageTitle: 'register.title'
    }
};
可以看到registerRoute并没有声明路由守卫,因为要注册,那么必然没有用户信息,也就无需获取用户信息了。

服务调用

activate.service.ts

@Injectable()
export class ActivateService {
    //注入封装过的http客户端
    constructor(private http: Http) {}
    //设置params,调用通讯API,返回Observable
    get(key: string): Observable<any> {
        const params: URLSearchParams = new URLSearchParams();
        params.set('key', key);

        return this.http.get(SERVER_API_URL + 'api/activate', {
            search: params
        }).map((res: Response) => res);
    }
}

password.service.ts

password-reset-finish.service.ts

password-reset-init.service.ts

register.service.ts.ts

代码也类似,十分简单。值得注意的是setting并没单独的service。用户信息保存是AccountService的一部分,直接调用即可。

功能组件

组件都使用模板表单的构造方式,通过在html中定义ngModel进行数据绑定,通过定义内部状态,控制表单的提示信息。以下仅分析register组件源码

register.component.ts

export class RegisterComponent implements OnInit, AfterViewInit {

    confirmPassword: string;
    doNotMatch: string;
    error: string;
    errorEmailExists: string;
    errorUserExists: string;
    registerAccount: any;
    success: boolean;
    modalRef: NgbModalRef;
    //注入语言服务,登录框,注册服务,以及标签本身,绘制器
    constructor(
        private languageService: JhiLanguageService,
        private loginModalService: LoginModalService,
        private registerService: Register,
        private elementRef: ElementRef,
        private renderer: Renderer
    ) {
    }

    ngOnInit() {
        this.success = false;
        this.registerAccount = {};
    }
    //默认激活login按钮
    ngAfterViewInit() {
        this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#login'), 'focus', []);
    }

    register() {
        //并非实时判断两个input的匹配程度,提交的时候才会判断,如果不匹配,就提示错误
        if (this.registerAccount.password !== this.confirmPassword) {
            this.doNotMatch = 'ERROR';
        } else {
            //两个密码框相符,则进行注册接口调用。
            this.doNotMatch = null;
            this.error = null;
            this.errorUserExists = null;
            this.errorEmailExists = null;
            this.languageService.getCurrent().then((key) => {
                this.registerAccount.langKey = key;
                this.registerService.save(this.registerAccount).subscribe(() => {
                    this.success = true;
                }, (response) => this.processError(response));
            });
        }
    }
    //通用的登录框显示
    openLogin() {
        this.modalRef = this.loginModalService.open();
    }
    //错误的response处理,出错时候返回type表示不同错误
    private processError(response) {
        this.success = null;
        if (response.status === 400 && response.json().type === LOGIN_ALREADY_USED_TYPE) {
            this.errorUserExists = 'ERROR';
        } else if (response.status === 400 && response.json().type === EMAIL_ALREADY_USED_TYPE) {
            this.errorEmailExists = 'ERROR';
        } else {
            this.error = 'ERROR';
        }
    }
}

register.component.html

<div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <h1 jhiTranslate="register.title">Registration</h1>
            <!-- 成功提示,仅当注册成功时显示 -->
            <div class="alert alert-success" *ngIf="success" jhiTranslate="register.messages.success">
                <strong>Registration saved!</strong> Please check your email for confirmation.
            </div>
            <!-- 失败提示,仅当注册失败时显示 -->
            <div class="alert alert-danger" *ngIf="error" jhiTranslate="register.messages.error.fail">
                <strong>Registration failed!</strong> Please try again later.
            </div>
            <!-- 失败提示,仅当注册失败,且服务器返回用户已存在时显示 -->
            <div class="alert alert-danger" *ngIf="errorUserExists" jhiTranslate="register.messages.error.userexists">
                <strong>Login name already registered!</strong> Please choose another one.
            </div>
            <!-- 失败提示,仅当注册失败,且服务器返回注册Email已存在时显示 -->
            <div class="alert alert-danger" *ngIf="errorEmailExists" jhiTranslate="register.messages.error.emailexists">
                <strong>Email is already in use!</strong> Please choose another one.
            </div>
            <!-- 失败提示,仅当两个密码输入框不符时显示 -->
            <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
                The password and its confirmation do not match!
            </div>
        </div>
    </div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <!-- 窗体form定义,提交方法为register,如果注册成功,就不显示了 -->
            <form name="form" role="form" (ngSubmit)="register()" #registerForm="ngForm" *ngIf="!success">
                <div class="form-group">
                    <label class="form-control-label" for="login" jhiTranslate="global.form.username">Username</label>
                    <!-- 标准的模板方式生成窗体方式,使用ngModel绑定值到login,后面定义了一系列angular的验证器 -->
                    <input type="text" class="form-control" [(ngModel)]="registerAccount.login" id="login" name="login" #login="ngModel" placeholder="{{'global.form.username.placeholder' | translate}}" required minlength="1" maxlength="50" pattern="^[_'.@A-Za-z0-9-]*$">
                    <!-- 统一的错误提示div,包含多个small提示,根据不同的错误类型,有不同的提示 -->
                    <div *ngIf="login.dirty && login.invalid">
                        <small class="form-text text-danger" *ngIf="login.errors.required" jhiTranslate="register.messages.validate.login.required">
                            Your username is required.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.minlength" jhiTranslate="register.messages.validate.login.minlength">
                            Your username is required to be at least 1 character.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.maxlength" jhiTranslate="register.messages.validate.login.maxlength">
                            Your username cannot be longer than 50 characters.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.pattern" jhiTranslate="register.messages.validate.login.pattern">
                            Your username can only contain lower-case letters and digits.
                        </small>
                    </div>
                </div>
                <!-- 省略email,密码,确认密码框 -->
                
                <!-- 如果窗体不合法,就disable提交按钮 -->
                <button type="submit" [disabled]="registerForm.form.invalid" class="btn btn-primary" jhiTranslate="register.form.button">Register</button>
            </form>
            <p></p>
            <!-- 窗体之外,增加默认用户的说明 -->
            <div class="alert alert-warning">
                <span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span>
                <a class="alert-link" (click)="openLogin()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span>
            </div>
        </div>
    </div>
</div>

相关文章

网友评论

      本文标题:JHipster一知半解- 4.6.10 webapp-acco

      本文链接:https://www.haomeiwen.com/subject/hppseftx.html