更新账号模块

change
panqihua 5 years ago
parent 94ad8edfa2
commit d81f98a820
  1. 7
      src/app/account/account/account.module.ts
  2. 17
      src/app/account/login/login.component.html
  3. 12
      src/app/account/login/login.component.ts
  4. 61
      src/app/account/login/login.service.ts
  5. 42
      src/app/account/register/register.component.html
  6. 102
      src/app/account/register/register.component.ts
  7. 4
      src/app/account/register/register.service.spec.ts
  8. 42
      src/app/account/register/register.service.ts
  9. 113
      src/app/account/resetpwd/resetpwd.component.html
  10. 133
      src/app/account/resetpwd/resetpwd.component.ts
  11. 16
      src/app/account/resetpwd/resetpwd.service.spec.ts
  12. 66
      src/app/account/resetpwd/resetpwd.service.ts
  13. 6
      src/app/app.component.html
  14. 3
      src/app/app.component.scss
  15. 30
      src/app/app.component.ts
  16. 4
      src/app/app.module.ts
  17. 16
      src/app/app.service.spec.ts
  18. 29
      src/app/app.service.ts
  19. 42
      src/app/commons.ts
  20. 6
      src/app/forum/forum.component.ts
  21. 7
      src/app/forum/forum/forum.module.ts
  22. 8
      src/app/html.pipe.spec.ts
  23. 20
      src/app/html.pipe.ts
  24. 14
      src/app/interface/HttpInterface.ts
  25. 5
      src/app/interface/JSONRequest.ts
  26. 38
      src/app/interface/JSONResponse.ts
  27. 9
      src/app/interface/vo/Token.ts
  28. 1
      src/app/message/message.service.ts
  29. 12
      src/assets/i18n/en-US.json
  30. 14
      src/assets/i18n/zh-CN.json
  31. 4
      src/environments/environment.prod.ts
  32. 5
      src/environments/environment.rap2.ts
  33. 4
      src/environments/environment.ts

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
// 登陆组件
import {LoginComponent} from '../login/login.component';
// 注册组件
@ -26,4 +26,5 @@ import {InputComponent} from '../../input/input.component';
ReactiveFormsModule,
]
})
export class AccountModule { }
export class AccountModule {
}

@ -8,7 +8,13 @@
<span class="input-group-text">{{ 'login.manager_name' | translate }}</span>
</div>
<input autocomplete="managerName" type="text" class="form-control text-center"
[placeholder]="'tip.input' | translate:{value:'login.manager_name'|translate}" formControlName="managerName">
[class.is-invalid]="getValue('managerName').invalid"
[placeholder]="'tip.input' | translate:{value:'login.manager_name'|translate}"
formControlName="managerName">
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'login.manager_name'|translate} }}
</div>
</div>
<!-- 管理员密码-->
@ -17,17 +23,24 @@
<span class="input-group-text">{{ 'login.password' | translate }}</span>
</div>
<input autocomplete="new-password" type="password" class="form-control text-center"
[class.is-invalid]="getValue('password').invalid"
[placeholder]="'tip.input' | translate:{value:'login.manager_name'|translate}" formControlName="password">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button"
[routerLink]="['/reset_pwd']">{{ 'button.forget_pwd' | translate }}</button>
</div>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'login.password'|translate} }}
</div>
</div>
<div class="col-5 mx-auto text-center mb-3">
<!-- 登陆按钮-->
<button type="button" (click)="login()" class="btn btn-primary btn-lg">{{ 'button.login' | translate }}</button>
<button type="button" (click)="login()" class="btn btn-primary btn-lg"
[disabled]="form().invalid">{{ 'button.login' | translate }}</button>
<!-- 注册按钮 -->
<button type="button" class="btn btn-info btn-lg ml-3"
[routerLink]="['/register']">{{ 'button.register' | translate }}</button>

@ -1,5 +1,5 @@
import {Component, OnInit} from '@angular/core';
import {FormBuilder} from '@angular/forms';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {Commons} from '../../commons';
import {Router} from '@angular/router';
import {LoginService} from './login.service';
@ -13,8 +13,10 @@ import {LoginService} from './login.service';
export class LoginComponent extends Commons implements OnInit {
// 登陆表单
loginForm = this.fb.group({
managerName: [''],
password: ['']
// 管理员名
managerName: this.fb.control('', Validators.required),
// 密码
password: this.fb.control('', Validators.required)
});
@ -39,4 +41,8 @@ export class LoginComponent extends Commons implements OnInit {
}
form(): FormGroup {
return this.loginForm;
}
}

@ -3,6 +3,13 @@ import {CookieService} from 'ngx-cookie-service';
import {Router} from '@angular/router';
import {MessageService} from '../../message/message.service';
import {JSONRequest} from '../../interface/JSONRequest';
import {environment} from '../../../environments/environment';
import {HttpClient} from '@angular/common/http';
import {HttpInterface} from '../../interface/HttpInterface';
import {JSONResponse} from '../../interface/JSONResponse';
import {catchError} from 'rxjs/operators';
import {Result} from '../../interface/Result';
import {Token} from '../../interface/vo/Token';
@Injectable({
providedIn: 'root'
@ -12,7 +19,8 @@ export class LoginService extends JSONRequest {
constructor(
private cookieService: CookieService,
private router: Router,
private messageService: MessageService
private messageService: MessageService,
private http: HttpClient,
) {
super();
}
@ -21,7 +29,7 @@ export class LoginService extends JSONRequest {
*
*/
checkToken(): boolean {
return false;
return this.cookieService.check(environment.tokenKey);
}
/**
@ -35,22 +43,45 @@ export class LoginService extends JSONRequest {
}
}
/**
*
*/
logout() {
this.http.post<JSONResponse<any>>(HttpInterface.logout, {}, this.httpOptions)
.pipe(
catchError(this.handleError<any>('注销'))
)
.subscribe(r => {
if (r.result === Result.OK) {
this.cookieService.deleteAll();
this.messageService.info('注销成功');
this.router.navigateByUrl('/login');
} else {
alert('注销失败');
}
});
}
/**
*
* @param body
*/
request(body: string) {
// res => {
// this.message = res.message;
// if (res.result === 'OK') {
// this.messageStyle = 'info';
// this.cookieService.set(environment.tokenKey, res.body.token, 3600);
// this.router.navigateByUrl('/forum');
// } else {
// this.messageStyle = 'warning';
// }
// }
this.messageService.danger('登陆失败');
return false;
request(body) {
this.http.post<JSONResponse<Token>>(HttpInterface.login, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('登陆'))
)
.subscribe(r => {
if (r.result === Result.OK) {
this.messageService.info('登陆成功');
const time = new Date();
time.setTime(r.body.useTime);
this.cookieService.set(environment.managerKey, r.body.managerName, time);
this.cookieService.set(environment.tokenKey, r.body.token, time);
this.router.navigateByUrl('/forum');
} else {
this.messageService.danger('登陆失败');
}
});
}
}

@ -7,11 +7,11 @@
<div class="input-group-prepend">
<span class="input-group-text">{{ 'login.manager_name' | translate }}</span>
</div>
<input type="text" class="form-control text-center" [class.is-invalid]="checkValue('managerName')"
<input type="text" class="form-control text-center" [class.is-invalid]="getValue('managerName').invalid"
[placeholder]="'tip.input' | translate:{value:'login.manager_name'|translate}"
formControlName="managerName"/>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value:'login.manager_name'|translate} }}
{{'tip.notnull' | translate:{value: 'login.manager_name'|translate} }}
</div>
</div>
@ -21,11 +21,11 @@
<span class="input-group-text">{{ 'login.password' | translate }}</span>
</div>
<input autocomplete="password" type="password" class="form-control text-center"
[class.is-invalid]="checkValue('password')"
[class.is-invalid]="getValue('password').invalid"
[placeholder]="'tip.input' | translate:{value:'login.password'|translate}" formControlName="password"/>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value:'login.password'|translate} }}
{{'tip.notnull' | translate:{value: 'login.password'|translate} }}
</div>
</div>
@ -36,13 +36,17 @@
<span class="input-group-text">{{ 'register.confirm_pwd' | translate }}</span>
</div>
<input autocomplete="confirmPassword" type="password" class="form-control text-center"
[class.is-invalid]="(checkPwd()|async) !==''"
[class.is-invalid]="getValue('confirmPassword').invalid"
[placeholder]="'tip.input' | translate:{value:'register.confirm_pwd'|translate}"
formControlName="confirmPassword"/>
<div class="invalid-feedback font-weight-bold text-center">
{{ checkPwd()|async }}
<div class="invalid-feedback font-weight-bold text-center" *ngIf="getValue('confirmPassword').errors">
<div *ngIf="getValue('confirmPassword')?.errors?.required">
{{'tip.notnull' | translate:{value: 'register.confirm_pwd'|translate} }}
</div>
<div *ngIf="getValue('confirmPassword')?.errors?.pwd">
{{'tip.password_diff'|translate}}
</div>
</div>
</div>
@ -51,11 +55,16 @@
<div class="input-group-prepend">
<span class="input-group-text">{{ 'register.mobile' | translate }}</span>
</div>
<input type="number" class="form-control text-center" [class.is-invalid]="(checkMobile()|async) !==''"
<input type="number" class="form-control text-center" [class.is-invalid]="getValue('mobile').invalid"
[placeholder]="'tip.input' | translate:{value:'register.mobile'|translate}" formControlName="mobile"/>
<div class="invalid-feedback font-weight-bold text-center">
{{ checkMobile()|async }}
<div class="invalid-feedback font-weight-bold text-center" *ngIf="getValue('mobile').errors">
<div *ngIf="getValue('mobile')?.errors?.required">
{{'tip.notnull' | translate:{value: 'register.mobile'|translate} }}
</div>
<div *ngIf="getValue('mobile')?.errors?.mobile">
{{'tip.mobile_error'|translate}}
</div>
</div>
</div>
@ -65,22 +74,23 @@
<span class="input-group-text">{{ 'register.email' | translate }}</span>
</div>
<input type="text" class="form-control text-center"
[placeholder]="'tip.input' | translate:{value:'register.email'|translate}" formControlName="email" [class.is-invalid]="checkValue('email')" />
[placeholder]="'tip.input' | translate:{value:'register.email'|translate}" formControlName="email"
[class.is-invalid]="getValue('email').invalid"/>
<select class="custom-select" formControlName="emailType">
<option selected value="-1">{{'tip.select'|translate:{value:'register.email_type'|translate} }}</option>
<option value="">{{'tip.select'|translate:{value: 'register.email_type'|translate} }}</option>
<option *ngFor="let item of (emailType$|async)?.body" [value]="item.suffix">{{item.name}}</option>
</select>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value:'register.email'|translate} }}
{{'tip.notnull' | translate:{value: 'register.email'|translate} }}
</div>
</div>
<div class="col-7 mx-auto text-center mb-3">
<!-- 注册按钮-->
<button type="button" (click)="register()" [class.disabled]="checkForm()" [disabled]="checkForm()"
class="btn btn-primary btn-lg disabled">{{ 'button.register' | translate }}</button>
<button type="button" (click)="registerService.register(registerForm.value)" [disabled]="form().invalid"
class="btn btn-primary btn-lg">{{ 'button.register' | translate }}</button>
<!-- 返回登陆按钮-->
<button type="button" [routerLink]="['/login']"
class="btn btn-info btn-lg ml-3">{{ 'button.backLogin' | translate }}</button>

@ -1,9 +1,8 @@
import {Component, OnInit} from '@angular/core';
import {FormBuilder} from '@angular/forms';
import {AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators} from '@angular/forms';
import {Commons} from '../../commons';
import {RegisterService} from './register.service';
import {TranslateService} from '@ngx-translate/core';
import {Observable, of} from 'rxjs';
import {AppService} from '../../app.service';
@Component({
selector: 'app-register',
@ -19,105 +18,58 @@ export class RegisterComponent extends Commons implements OnInit {
// 注册表单
registerForm = this.fb.group({
// 管理员名
managerName: [],
managerName: this.fb.control('', [Validators.required]),
// 密码
password: [],
password: this.fb.control('', [Validators.required]),
// 确认密码
confirmPassword: [],
confirmPassword: this.fb.control('', [this.checkPwd()]),
// 手机号
mobile: [],
mobile: this.fb.control('', [this.checkMobile()]),
// 邮箱
email: [],
email: this.fb.control('', [Validators.required]),
// 邮箱类型
emailType: this.fb.control('-1')
emailType: this.fb.control('', [Validators.required])
});
/**
*
*/
emailType$ = this.registerService.getEmailType();
emailType$ = this.appService.getEmailType();
// 表单验证
validForm = {
confirmPassword: {
flag: false
},
mobile: {
flag: false
}
};
constructor(
private fb: FormBuilder,
private registerService: RegisterService,
private translateService: TranslateService
private appService: AppService
) {
super();
}
/**
*
* @param name formControlName
*/
checkValue(name): boolean {
if (!this.validForm.hasOwnProperty(name)) {
this.validForm[name] = {};
}
this.validForm[name].flag = this.registerForm.value[name];
return !this.validForm[name].flag;
}
/**
*
*/
checkForm(): boolean {
for (const key in this.validForm) {
if (!this.validForm[key].flag) {
return true;
}
}
return this.registerForm.value.emailType === '-1';
}
/**
*
*/
checkPwd(): Observable<string> {
if (!this.registerForm.value.confirmPassword) {
this.validForm.confirmPassword.flag = false;
return this.translateService.get('tip.password_null');
} else if (this.registerForm.value.password !== this.registerForm.value.confirmPassword) {
this.validForm.confirmPassword.flag = false;
return this.translateService.get('tip.password_diff');
} else {
this.validForm.confirmPassword.flag = true;
return of('');
}
}
/**
*
*/
checkMobile(): Observable<string> {
if (!this.registerForm.value.mobile) {
this.validForm.mobile.flag = false;
return this.translateService.get('tip.mobile_null');
} else if (!/^1[3456789]\d{9}$/.test(this.registerForm.value.mobile)) {
this.validForm.mobile.flag = false;
return this.translateService.get('tip.mobile_error');
} else {
this.validForm.mobile.flag = true;
return of('');
}
checkMobile(): ValidatorFn {
return (control: AbstractControl): {} => {
if (/^1[3456789]\d{9}$/.test(control.value)) {
return null;
} else {
return {required: control.value === null || control.value.length === 0, mobile: true};
}
};
}
ngOnInit(): void {
this.validForm = {};
for (const key of Object.keys(this.registerForm.value)) {
this.validForm[key] = {
flag: false
};
}
}
register() {
this.registerService.register(this.registerForm.value);
form(): FormGroup {
return this.registerForm;
}
}

@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import { RegisterService } from './register.service';
import {RegisterService} from './register.service';
describe('RegisterService', () => {
let service: RegisterService;

@ -1,14 +1,14 @@
import {Injectable} from '@angular/core';
import {JSONRequest} from '../../interface/JSONRequest';
import {HttpClient} from '@angular/common/http';
import {catchError, tap} from 'rxjs/operators';
import {catchError} from 'rxjs/operators';
import {JSONResponse} from '../../interface/JSONResponse';
import {HttpInterface} from '../../interface/HttpInterface';
import {Observable} from 'rxjs';
import {Result} from '../../interface/Result';
import {Router} from '@angular/router';
import {MessageService} from '../../message/message.service';
@Injectable({
providedIn: 'root'
})
@ -20,9 +20,6 @@ export class RegisterService extends JSONRequest {
private messageService: MessageService
) {
super();
this.httpError.result = Result.FAIL;
this.httpError.message = '注册失败';
}
/**
@ -32,35 +29,14 @@ export class RegisterService extends JSONRequest {
register(body) {
this.http.post<JSONResponse<any>>(HttpInterface.register, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('注册', this.httpError))
catchError(this.handleError<any>('注册'))
).subscribe(r => {
if (r.result === Result.OK) {
this.messageService.info('注册成功');
this.router.navigateByUrl('/login');
} else {
this.messageService.danger('注册失败');
}
if (r.result === Result.OK) {
this.messageService.info('注册成功');
this.router.navigateByUrl('/login');
} else {
this.messageService.danger('注册失败');
}
});
}
/**
*
*/
getEmailType(): Observable<any> {
return this.http.get<JSONResponse<any>>(HttpInterface.getEmailType)
.pipe(
catchError(this.handleError<any>('获取邮箱类型'))
);
}
/**
*
*/
sendEmail(sender): Observable<any> {
return this.http.post<JSONResponse<any>>(HttpInterface.sendCode, {email: 'sender'})
.pipe(
catchError(this.handleError<any>('发送邮件验证码'))
);
}
}

@ -2,44 +2,127 @@
<div [style]="height" class="d-flex align-items-center justify-content-center">
<form [formGroup]="resetForm" class="col-6">
<!-- 管理员名-->
<div class="input-group mb-3 mx-auto col-7">
<div class="input-group mb-3 mx-auto col-7" [class.d-none]="step===3">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'login.manager_name' | translate }}</span>
</div>
<input type="text" class="form-control text-center"
[placeholder]="('tip.input' | translate)+('login.manager_name' | translate)" formControlName="managerName">
<input type="text" class="form-control text-center disabled" [class.is-invalid]="getValue('managerName').invalid"
[placeholder]="'tip.input' | translate:{value:'login.manager_name'|translate}"
formControlName="managerName"/>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'login.manager_name'|translate} }}
</div>
</div>
<!-- 邮箱 -->
<div class="input-group mb-3 mx-auto col-7">
<div class="input-group mb-3 mx-auto col-8" *ngIf="step!==3">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'register.email' | translate }}</span>
</div>
<input type="text" class="form-control text-center"
[placeholder]="('tip.input' | translate)+('register.email' | translate)" formControlName="email">
<div class="input-group-append">
[placeholder]="'tip.input' | translate:{value:'register.email'|translate}" formControlName="email"
[class.is-invalid]="getValue('email').invalid"/>
<select class="custom-select" formControlName="emailType">
<option value="">{{'tip.select'|translate:{value: 'register.email_type'|translate} }}</option>
<option *ngFor="let item of (emailType$|async)?.body" [value]="item.suffix">{{item.name}}</option>
</select>
<div class="input-group-append" *ngIf="step===2">
<button class="btn btn-outline-secondary" type="button"
[class.is-invalid]="getValue('email').invalid"
(click)="sendCode()">{{ 'button.send_code' | translate }}</button>
</div>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'register.email'|translate} }}
</div>
</div>
<!-- 新密码-->
<div class="input-group mb-3 mx-auto col-7" *ngIf="step===3">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'reset_pwd.new_pwd' | translate }}</span>
</div>
<input type="password" class="form-control text-center disabled" [class.is-invalid]="getValue('password').invalid"
[placeholder]="'tip.input' | translate:{value:'reset_pwd.new_pwd'|translate}"
formControlName="password"/>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'reset_pwd.new_pwd'|translate} }}
</div>
</div>
<!-- 确认新密码-->
<div class="input-group mb-3 mx-auto col-7" *ngIf="step===3">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'reset_pwd.confirm_pwd' | translate }}</span>
</div>
<input type="password" class="form-control text-center disabled"
[class.is-invalid]="getValue('confirmPassword').invalid"
[placeholder]="'tip.input' | translate:{value:'reset_pwd.confirm_pwd'|translate}"
formControlName="confirmPassword"/>
<div class="invalid-feedback font-weight-bold text-center" *ngIf="getValue('confirmPassword').errors">
<div *ngIf="getValue('confirmPassword')?.errors?.required">
{{'tip.notnull' | translate:{value: 'reset_pwd.confirm_pwd'|translate} }}
</div>
<div *ngIf="getValue('confirmPassword')?.errors?.pwd">
{{'tip.password_diff'|translate}}
</div>
</div>
</div>
<!-- 验证码-->
<div class="input-group mb-3 mx-auto col-7">
<div class="input-group mb-3 mx-auto col-7" *ngIf="step===2">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'reset_pwd.code' | translate }}</span>
</div>
<input type="text" class="form-control text-center"
[placeholder]="('tip.input' | translate)+('reset_pwd.code' | translate)"
[placeholder]="'tip.input' | translate:{value:'reset_pwd.code'|translate}"
[class.is-invalid]="getValue('verificationCode').invalid"
formControlName="verificationCode">
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'reset_pwd.code'|translate} }}
</div>
</div>
<div class="col-7 mx-auto text-center">
<!-- 重置密码按钮 -->
<button type="button" (click)="resetPwd()"
class="btn btn-primary btn-lg">{{ 'button.reset_pwd' | translate }}</button>
<!-- 返回登陆按钮-->
<button type="button" [routerLink]="['/login']"
class="btn btn-info btn-lg ml-3">{{ 'button.backLogin' | translate }}</button>
<!-- 操作按钮-->
<div class="col-8 mx-auto text-center mb-3">
<ng-container [ngSwitch]="step">
<ng-container *ngSwitchCase="1">
<!-- 检查邮箱-->
<button type="button" class="btn btn-warning btn-lg mr-3"
[disabled]="allowCheckEmail()"
(click)="checkEmail()">{{'button.next'|translate}}</button>
</ng-container>
<ng-container *ngSwitchCase="2">
<!-- 上一步-->
<button type="button" class="btn btn-warning btn-lg mr-3"
(click)="backFirst()">{{'button.prev'|translate}}</button>
<!-- 检查验证码-->
<button type="button" class="btn btn-primary btn-lg mr-3" [disabled]="getValue('verificationCode').invalid"
(click)="checkCode()"
>{{'button.check_code'|translate}}</button>
</ng-container>
<ng-container *ngSwitchCase="3">
<!-- 重置密码按钮 -->
<button type="button" (click)="resetPwd()" [disabled]="form().invalid"
class="btn btn-primary btn-lg mr-3">{{ 'button.reset_pwd' | translate }}</button>
</ng-container>
<!-- 返回登陆按钮-->
<button type="button" [routerLink]="['/login']"
class="btn btn-info btn-lg">{{ 'button.backLogin' | translate }}</button>
</ng-container>
</div>
<app-message></app-message>
</form>
</div>

@ -1,6 +1,11 @@
import {Component, OnInit} from '@angular/core';
import {FormBuilder} from '@angular/forms';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {Commons} from '../../commons';
import {AppService} from '../../app.service';
import {ResetpwdService} from './resetpwd.service';
import {Result} from '../../interface/Result';
import {MessageService} from '../../message/message.service';
import {Router} from '@angular/router';
@Component({
selector: 'app-resetpwd',
@ -12,27 +17,139 @@ export class ResetpwdComponent extends Commons implements OnInit {
// 重置密码表单
resetForm = this.fb.group({
managerName: [],
email: [],
verificationCode: []
// 管理员名
managerName: this.fb.control('', [Validators.required]),
// 邮箱
email: this.fb.control('', [Validators.required]),
// 验证码
verificationCode: this.fb.control('', [Validators.required]),
// 邮箱类型
emailType: this.fb.control('', [Validators.required]),
// 新密码
password: this.fb.control('', [Validators.required]),
// 确认新密码
confirmPassword: this.fb.control('', [this.checkPwd()]),
});
constructor(private fb: FormBuilder) {
/**
*
*/
emailType$ = this.appService.getEmailType();
// 当前步骤
step = 1;
constructor(
private fb: FormBuilder,
private appService: AppService,
private resetpwdService: ResetpwdService,
private messageService: MessageService,
private router: Router
) {
super();
}
//
ngOnInit(): void {
}
// 检查邮箱
checkEmail() {
this.resetpwdService.checkEmail(this.resetForm.value).subscribe(r => {
if (r.result === Result.OK) {
// this.messageService.info('邮箱正确');
// 进入第二步
this.step = 2;
// 清空提示
this.messageService.message = null;
// 第二步不允许编辑账户和邮箱
this.disabled();
} else {
this.messageService.danger('账号或邮箱错误');
}
});
}
// 第二步不允许编辑账户和邮箱
disabled() {
this.getValue('managerName').disable();
this.getValue('email').disable();
this.getValue('emailType').disable();
}
enabled() {
this.getValue('managerName').enable();
this.getValue('email').enable();
this.getValue('emailType').enable();
}
// 发送验证码
sendCode() {
alert('发送验证码');
this.resetpwdService.sendCode({
managerName: this.getValue('managerName').value
}).subscribe(res => {
this.disabled();
if (res.result === Result.OK) {
this.messageService.info('验证码发送成功,请查收验证码');
} else {
this.messageService.danger('验证码发送失败,请重试或联系管理员');
}
});
}
// 返回第一步
backFirst() {
this.step = 1;
this.enabled();
this.getValue('verificationCode').reset();
}
/**
*
*/
checkCode() {
this.resetpwdService.checkCode({
managerName: this.getValue('managerName').value
}).subscribe(res => {
if (res.result === Result.OK) {
// 进入第三步
this.step = 3;
// 清空提示
this.messageService.message = null;
} else {
this.messageService.danger('验证码不正确,请重新输入');
}
});
}
// 重置密码
/**
*
*/
resetPwd() {
alert('重置密码');
this.resetpwdService.resetPwd({
managerName: this.getValue('managerName').value,
password: this.getValue('password').value
}).subscribe(res => {
if (res.result === Result.OK) {
this.messageService.info('重制密码成功');
this.router.navigateByUrl('/login');
} else {
this.messageService.danger('重置密码失败');
}
});
}
form(): FormGroup {
return this.resetForm;
}
/**
*
*/
allowCheckEmail() {
return this.getValue('managerName').invalid || this.getValue('email').invalid || this.getValue('emailType').invalid;
}
}

@ -0,0 +1,16 @@
import {TestBed} from '@angular/core/testing';
import {ResetpwdService} from './resetpwd.service';
describe('ResetpwdService', () => {
let service: ResetpwdService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ResetpwdService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

@ -0,0 +1,66 @@
import {Injectable} from '@angular/core';
import {JSONRequest} from '../../interface/JSONRequest';
import {Router} from '@angular/router';
import {HttpClient} from '@angular/common/http';
import {HttpInterface} from '../../interface/HttpInterface';
import {catchError} from 'rxjs/operators';
import {JSONResponse} from '../../interface/JSONResponse';
import {Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
/**
*
*/
export class ResetpwdService extends JSONRequest {
constructor(
private http: HttpClient,
private router: Router
) {
super();
}
/**
*
*/
checkEmail(body): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.checkEmail, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('检查邮箱'))
);
}
/**
*
*/
sendCode(body): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.sendCode, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('发送验证码'))
);
}
/**
*
* @param body
*/
checkCode(body): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.checkCode, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('检查验证码'))
);
}
/**
*
*/
resetPwd(body): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.resetPwd, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('重置密码'))
);
}
}

@ -16,12 +16,14 @@
<a class="dropdown-item" (click)="translate.use('en-US')">{{ 'english' | translate }}</a>
</div>
</div>
</nav>
<nav class="navbar navbar-light bg-light justify-content-end">
<span class="navbar-text">
{{ 'tip.HELLO' | translate:{value: 'admin'} }}
<span class="navbar-text mr-3" [innerHTML]="'tip.HELLO'|translate:{value:managerName}|html" *ngIf="isLogin">
</span>
<button class="btn btn-info" (click)="logout()" *ngIf="isLogin">{{'button.logout'|translate}}</button>
</nav>
<router-outlet></router-outlet>

@ -0,0 +1,3 @@
.manager {
color: red;
}

@ -1,4 +1,4 @@
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
// 路由
import {NavigationStart, Router} from '@angular/router';
// 国际化服务
@ -9,17 +9,20 @@ import {filter} from 'rxjs/operators';
// cookie操作
import {CookieService} from 'ngx-cookie-service';
// 环境变量
import {environment} from './../environments/environment';
import {environment} from '../environments/environment';
import {LoginService} from './account/login/login.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
export class AppComponent implements OnInit{
// 登陆状态
isLogin = this.cookieService.check(environment.tokenKey);
isLogin = false;
// 当前登陆账户
managerName = null;
navStart: Observable<NavigationStart>;
@ -28,16 +31,31 @@ export class AppComponent {
* @param translate
* @param router
* @param cookieService cookie管理服务
* @param loginService
*/
constructor(public translate: TranslateService, private router: Router, private cookieService: CookieService) {
constructor(
public translate: TranslateService,
private router: Router,
private cookieService: CookieService,
private loginService: LoginService
) {
this.navStart = router.events.pipe(
filter(evt => evt instanceof NavigationStart)
) as Observable<NavigationStart>;
}
public async ngOnInit() {
/**
*
*/
logout() {
this.loginService.logout();
}
async ngOnInit() {
this.navStart.subscribe(evt => {
this.isLogin = this.cookieService.check(environment.tokenKey);
this.managerName = this.cookieService.get(environment.managerKey);
if (evt.url === '/' && this.isLogin) {
this.router.navigateByUrl('/forum');
} else if (evt.url === '/') {

@ -19,6 +19,7 @@ import {AccountModule} from './account/account/account.module';
import {ForumModule} from './forum/forum/forum.module';
// Http请求模块
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {HtmlPipe} from './html.pipe';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
@ -30,7 +31,8 @@ export function HttpLoaderFactory(http: HttpClient) {
@NgModule({
declarations: [
AppComponent,
ErrorComponent
ErrorComponent,
HtmlPipe
],
imports: [
BrowserModule,

@ -0,0 +1,16 @@
import {TestBed} from '@angular/core/testing';
import {AppService} from './app.service';
describe('AppService', () => {
let service: AppService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AppService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

@ -0,0 +1,29 @@
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {JSONResponse} from './interface/JSONResponse';
import {HttpInterface} from './interface/HttpInterface';
import {catchError} from 'rxjs/operators';
import {JSONRequest} from './interface/JSONRequest';
import {HttpClient} from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class AppService extends JSONRequest {
constructor(
private http: HttpClient,
) {
super();
}
/**
*
*/
getEmailType(): Observable<JSONResponse<any>> {
return this.http.get<JSONResponse<any>>(HttpInterface.getEmailType)
.pipe(
catchError(this.handleError<any>('获取邮箱类型'))
);
}
}

@ -1,5 +1,45 @@
// 组件通用配置
export class Commons {
import {AbstractControl, FormGroup, ValidatorFn} from '@angular/forms';
export abstract class Commons {
// 页面高度=屏幕的高度/2
height = 'height:' + screen.height / 2 + 'px';
validForm;
/**
*
*/
abstract form(): FormGroup;
/**
*
* @param key formControlName
*/
getValue(key) {
return this.form().get(key);
}
/**
*
*/
checkPwd(): ValidatorFn {
return (control: AbstractControl): {} => {
const check = {
required: true,
pwd: true
};
if (this.form()) {
check.required = control.value.length === 0;
check.pwd = !check.required && control.value !== this.getValue('password').value;
}
if (check.required || check.pwd) {
return check;
} else {
return null;
}
};
}
}

@ -1,4 +1,5 @@
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
@Component({
selector: 'app-forum',
@ -7,10 +8,13 @@ import {Component, OnInit} from '@angular/core';
})
export class ForumComponent implements OnInit {
constructor() {
constructor(
private router: Router,
) {
}
ngOnInit(): void {
console.debug(this.router);
}
}

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
// 论坛组件
import {ForumComponent} from '../forum.component';
import {TranslateModule} from '@ngx-translate/core';
@ -18,4 +18,5 @@ import {TranslateModule} from '@ngx-translate/core';
TranslateModule
]
})
export class ForumModule { }
export class ForumModule {
}

@ -0,0 +1,8 @@
import {HtmlPipe} from './html.pipe';
describe('HtmlPipe', () => {
it('create an instance', () => {
const pipe = new HtmlPipe();
expect(pipe).toBeTruthy();
});
});

@ -0,0 +1,20 @@
import {Pipe, PipeTransform} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
@Pipe({
name: 'html'
})
/**
* html管道
*/
export class HtmlPipe implements PipeTransform {
constructor(private sanitizer?: DomSanitizer) {
}
transform(value: string): unknown {
return this.sanitizer.bypassSecurityTrustHtml(value);
}
}

@ -8,13 +8,19 @@ const HttpInterface = {
getEmailType: '/api/manager/emailType',
// 登陆接口
login: '/api/manager/login',
// 注销接口
logout: '/api/manager/logout',
// 发送验证码接口
sendCode: '/api/manager/sendcode'
sendCode: '/api/manager/reset/code',
// 检查验证码接口
checkCode: '/api/manager/reset/checkCode',
// 检查邮箱接口
checkEmail: '/api/manager/reset/checkEmail',
// 重置密码
resetPwd: '/api/manager/reset/resetPwd'
};
// tslint:disable-next-line:forin
for (const key in HttpInterface) {
for (const key of Object.keys(HttpInterface)) {
HttpInterface[key] = environment.apiServer + HttpInterface[key];
}
console.debug(HttpInterface);
export {HttpInterface};

@ -1,15 +1,12 @@
import {HttpInterface} from './HttpInterface';
import {Observable, of} from 'rxjs';
import {HttpHeaders} from '@angular/common/http';
import {JSONResponse} from './JSONResponse';
export abstract class JSONRequest {
protected httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
protected httpError = new JSONResponse<any>();
/**
* Handle Http operation that failed.

@ -1,38 +1,12 @@
import {Result} from './Result';
export class JSONResponse<T> {
export interface JSONResponse<T> {
// 响应结果
// tslint:disable-next-line:variable-name
private _result: Result;
// 响应详细结果
// tslint:disable-next-line:variable-name
private _message: string;
// 自定义其他响应信息
// tslint:disable-next-line:variable-name
private _body: T;
result: Result;
// 响应详细结果
message: string;
// 自定义其他响应信息
body: T;
get result(): Result {
return this._result;
}
set result(value: Result) {
this._result = value;
}
get message(): string {
return this._message;
}
set message(value: string) {
this._message = value;
}
get body(): T {
return this._body;
}
set body(value: T) {
this._body = value;
}
}

@ -0,0 +1,9 @@
// 登陆成功记录的令牌信息
export interface Token {
// 令牌
token: string;
// 创建时间
createTime: number;
// 有效时间
useTime: number;
}

@ -41,6 +41,7 @@ export class MessageService {
this.message = message;
}
constructor() {
}

@ -14,7 +14,9 @@
"emailType": "email type"
},
"reset_pwd": {
"code": "verification code"
"code": "verification code",
"new_pwd": "password",
"confirm_pwd": "confirm password"
},
"forum": {
"name": "forum",
@ -32,9 +34,7 @@
"input": "please input {{value}}",
"HELLO": "Hello {{value}} welcome to you",
"notnull": "The {{value}} cannot be empty",
"password_null": "the password cannot be empty",
"password_diff": "The passwords do not match",
"mobile_null": "The phone number cannot be empty",
"mobile_error": "The phone number is illegal",
"select": "please choose an {{value}}"
},
@ -44,6 +44,10 @@
"forget_pwd": "forget password?",
"backLogin": "back",
"send_code": "send verification code",
"reset_pwd": "reset password"
"reset_pwd": "reset password",
"logout": "logout",
"next": "next",
"prev": "prev",
"check_code": "check_code"
}
}

@ -14,7 +14,9 @@
"email_type": "邮箱类型"
},
"reset_pwd": {
"code": "验证码"
"code": "验证码",
"new_pwd": "新密码",
"confirm_pwd": "确认新密码"
},
"forum": {
"name": "论坛管理",
@ -30,11 +32,9 @@
},
"tip":{
"input": "请输入{{value}}",
"HELLO": "欢迎管理员{{value}}登陆",
"HELLO": "欢迎管理员<span style='color:red'>{{value}}</span>登陆",
"notnull": "{{value}}不能为空",
"password_null": "确认密码不能为空",
"password_diff": "密码和确认密码不一致",
"mobile_null": "手机号不能为空",
"mobile_error": "手机号不合法",
"select": "请选择{{value}}"
},
@ -44,6 +44,10 @@
"forget_pwd": "忘记密码?",
"backLogin": "返回登陆",
"send_code": "发送验证码",
"reset_pwd": "重置密码"
"reset_pwd": "重置密码",
"logout": "注销登录",
"next": "下一步",
"prev": "上一步",
"check_code": "检查验证码"
}
}

@ -3,5 +3,7 @@ export const environment = {
// 服务端地址
apiServer: 'http://localhost',
// token key
tokenKey: 'token'
tokenKey: 'token',
// 账户 key
managerKey: 'manager_name'
};

@ -7,8 +7,9 @@ export const environment = {
// 服务端地址
apiServer: 'http://rap2.taobao.org:38080/app/mock/245830',
// token key
tokenKey: 'token'
tokenKey: 'token',
// 账户 key
managerKey: 'manager_name'
};
/*

@ -7,7 +7,9 @@ export const environment = {
// 服务端地址
apiServer: 'http://localhost:8080',
// token key
tokenKey: 'token'
tokenKey: 'token',
// 账户 key
managerKey: 'manager_name'
};

Loading…
Cancel
Save