1、应用列表新增分类

2、密码修改新增强度说明
3、忘记密码页新增强度说明
4、登录失败无提示的功能修复
This commit is contained in:
shibanglin 2023-03-07 11:32:25 +08:00
parent b34063de10
commit bf413e4014
13 changed files with 671 additions and 141 deletions

View File

@ -1,14 +1,15 @@
<nz-card>
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit()" se-container="1">
<form nz-form [formGroup]="validateForm" (ngSubmit)="onSubmit()">
<div nz-row style="width: 100%">
<div nz-col nzMd="6"></div>
<div nz-col nzMd="12">
<div nz-col nzMd="16">
<nz-form-item style="display: none">
<nz-form-label [nzMd]="6" nzFor="id">id</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.id" [ngModelOptions]="{ standalone: true }" nz-input name="id" id="id" value="id" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="displayName">{{ 'mxk.password.displayName' | i18n }}</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not displayName!">
@ -38,14 +39,14 @@
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired [nzSm]="6" [nzXs]="24" nzFor="oldPassword">{{ 'mxk.password.oldPassword' | i18n }}</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid oldPassword!">
<nz-form-control [nzSm]="14" [nzXs]="24" [nzErrorTip]="'validation.oldPassword.input' | i18n">
<nz-input-group [nzSuffix]="suffixOldPasswordTemplate" style="width: 100%">
<input
[type]="oldPasswordVisible ? 'text' : 'password'"
nz-input
placeholder="old password"
formControlName="oldPassword"
placeholder="{{ 'validation.oldPassword.input' | i18n }}"
[(ngModel)]="form.model.oldPassword"
[ngModelOptions]="{ standalone: true }"
name="oldPassword"
id="oldPassword"
/>
@ -57,36 +58,43 @@
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired [nzSm]="6" [nzXs]="24" nzFor="password">{{ 'mxk.password.password' | i18n }}</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid password!">
<nz-form-control [nzSm]="14" [nzXs]="24" [nzErrorTip]="'validation.password.input' | i18n">
<nz-input-group [nzSuffix]="suffixPasswordTemplate" style="width: 100%">
<input
[type]="passwordVisible ? 'text' : 'password'"
nz-input
placeholder="new password"
formControlName="password"
placeholder="{{ 'validation.password.input' | i18n }}"
(input)="dynamicallyCheckPassword(form.model.password)"
[(ngModel)]="form.model.password"
[ngModelOptions]="{ standalone: true }"
name="password"
id="password"
/>
</nz-input-group>
<ng-template #suffixPasswordTemplate>
<i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" (click)="passwordVisible = !passwordVisible"></i>
</ng-template>
<nz-alert
*ngIf="dynamicallyCheckPasswordErrorMsg !=''"
nzType="warning"
nzMessage="{{dynamicallyCheckPasswordErrorMsg}}"
nzShowIcon
></nz-alert>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired [nzSm]="6" [nzXs]="24" nzFor="confirmPassword">{{
'mxk.password.confirmPassword' | i18n
}}</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid confirmPassword!">
}}</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" [nzErrorTip]="'validation.confirmPassword.input' | i18n">
<input
nz-input
placeholder="confirm password"
type="password"
formControlName="confirmPassword"
placeholder="{{ 'validation.confirmPassword.input' | i18n }}"
[(ngModel)]="form.model.confirmPassword"
[ngModelOptions]="{ standalone: true }"
name="confirmPassword"
id="confirmPassword"
(input)="dynamicallyCheckConfirm(form.model.confirmPassword)"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item style="width: 100%">
@ -95,7 +103,15 @@
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzMd="8">
<h2><span nz-icon nzType="lock" nzTheme="outline"></span>{{'validation.password.conformance-strength'| i18n}}</h2>
<ul style="padding: 0 20px;">
<li *ngFor="let item of policyMessage">{{item}}</li>
</ul>
</div>
</div>
<div nz-col nzMd="6"></div>
</form>
</nz-card>

View File

@ -19,10 +19,11 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { SettingsService, User, ALAIN_I18N_TOKEN } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Router, ActivatedRoute } from '@angular/router';
import { ChangePassword } from '../../../entity/ChangePassword';
import { PasswordService } from '../../../service/password.service';
@Component({
selector: 'app-password',
templateUrl: './password.component.html',
@ -36,27 +37,28 @@ export class PasswordComponent implements OnInit {
submitting: false,
model: new ChangePassword()
};
formGroup: FormGroup = new FormGroup({});
validateForm!: FormGroup;
oldPasswordVisible = false;
policy:any = {};
passwordVisible = false;
policyMessage:any[] =[];
dynamicallyCheckPasswordErrorMsg = "";
constructor(
private router: Router,
private fb: FormBuilder,
private settingsService: SettingsService,
private passwordService: PasswordService,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {}
) { }
ngOnInit(): void {
this.formGroup = this.fb.group({
this.loadPolicy();
this.validateForm = this.fb.group({
oldPassword: [null, [Validators.required]],
confirmPassword: [null, [Validators.required]],
password: [1, [Validators.min(6), Validators.max(20)]]
password: [null, [Validators.required]],
});
let user: any = this.settingsService.user;
@ -64,27 +66,151 @@ export class PasswordComponent implements OnInit {
this.form.model.displayName = user.displayName;
this.form.model.username = user.username;
this.form.model.id = user.userId;
this.cdr.detectChanges();
}
loadPolicy():void {
this.policyMessage=[];
this.passwordService.passwordpolicy().subscribe(res => {
if(res.code == 0) {
let data = res.data;
this.policy = data;
this.policyMessage=res.data.policMessageList;
}
});
}
dynamicallyCheckConfirm(value:any):void {
if (value != this.form.model.password) {
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.twice')
} else {
this.dynamicallyCheckPasswordErrorMsg = '';
}
}
dynamicallyCheckPassword(value:any):void {
if (value == '') {
this.dynamicallyCheckPasswordErrorMsg = '';
return;
}
let data = this.policy;
if (data.minLength != 0 && data.maxLength != 0) {
let inputLength = value.length;
if (inputLength < data.minLength || inputLength > data.maxLength) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码长度为"+data.minLength+"-"+data.maxLength+"位"
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if (data.lowerCase > 0) {
let strArr = Array.from(value)
let abc:any = [];
strArr.forEach(function (value:any, index, array) {
let code = value.charCodeAt()
if (code >= 'a'.charCodeAt(0) && code <= 'z'.charCodeAt(0)) {
abc.push(value)
}
})
if(abc.length < data.lowerCase) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.lowerCase+"位【a-z】小写字母"
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if(data.upperCase > 0) {
let strArr = Array.from(value)
let ABC:any = [];
strArr.forEach(function (value:any, index, array) {
let code = value.charCodeAt()
if (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) {
ABC.push(value)
}
})
if(ABC.length < data.upperCase) {
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.lowerCase+"位【A-Z】大写字母"
return;
}
}
if (data.digits > 0) {
let strArr = Array.from(value)
let number:any = [];
strArr.forEach(function (value:any, index, array) {
var regPos = /^[0-9]+.?[0-9]*/; //判断是否是数字。
if(regPos.test(value) ){
number.push(value)
}
})
if(number.length < data.digits) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.digits+"位【0-9】阿拉伯数字";
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if(data.specialChar > 0) {
var AllNumIsSame = new Array("","”","!","@","#","$","%","^","&","*",".");
let strArr = Array.from(value)
let number:any = [];
strArr.forEach(function (value:any, index, array) {
if(AllNumIsSame.indexOf(value) != -1){//$.type 是jquery的函数用来判断对象类型
number.push(value)
}
})
if(number.length < data.specialChar) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.specialChar+"位特殊字符";
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
this.dynamicallyCheckPasswordErrorMsg = '';
}
onSubmit(): void {
this.form.submitting = true;
this.form.model.trans();
//if (this.formGroup.valid) {
this.passwordService.changePassword(this.form.model).subscribe(res => {
if (res.code == 0) {
this.form.model.init(res.data);
this.msg.success(this.i18n.fanyi('mxk.alert.operate.success'));
} else {
this.msg.error(this.i18n.fanyi('mxk.alert.operate.error'));
if (this.validateForm.valid) {
if (this.dynamicallyCheckPasswordErrorMsg == '') {
this.form.submitting = true;
this.form.model.trans();
this.passwordService.changePassword(this.form.model).subscribe(res => {
if (res.code == 0) {
this.form.model.init(res.data);
this.msg.success(this.i18n.fanyi('mxk.alert.operate.success'));
this.form.model.password = '';
this.form.model.oldPassword = '';
this.form.model.confirmPassword = '';
//设置密码正常,路由不进行拦截
let user = this.settingsService.user;
user['passwordSetType'] = 0;
this.settingsService.setUser(user)
this.router.navigateByUrl('/');
} else {
if (res.message) {
this.msg.error(res.message);
return
}
this.msg.error(this.i18n.fanyi('mxk.alert.operate.error'));
}
});
this.form.submitting = false;
this.cdr.detectChanges();
}
});
// } else {
// this.formGroup.updateValueAndValidity({ onlySelf: true });
// this.msg.success(`提交失败`);
//}
this.form.submitting = false;
this.cdr.detectChanges();
} else {
Object.values(this.validateForm.controls).forEach(control => {
if (control.invalid) {
control.markAsDirty();
control.updateValueAndValidity({ onlySelf: true });
}
});
}
}
}

View File

@ -1,55 +1,75 @@
<div nz-row>
<div nz-col nzMd="3"></div>
<div nz-col nzMd="18">
<nz-list
[nzLoading]="loading"
[nzDataSource]="appList"
[nzRenderItem]="item"
[nzGrid]="{ gutter: 24, xl: 6, lg: 8, md: 8, sm: 12, xs: 24 }"
>
<ng-template #item let-item>
<nz-list-item>
<nz-card nzHoverable style="">
<!--<nz-card nzHoverable [nzActions]="[op1, op2, op3, op4]">
<ng-template #op1>
<i nz-tooltip nzTooltipTitle="下载" nz-icon nzType="download"></i>
</ng-template>
<ng-template #op2>
<i nz-tooltip nzTooltipTitle="编辑" nz-icon nzType="edit"></i>
</ng-template>
<ng-template #op3>
<i nz-tooltip nzTooltipTitle="分享" nz-icon nzType="share-alt"></i>
</ng-template>
<ng-template #op4>
<i nz-dropdown [nzDropdownMenu]="op4Menu" nzPlacement="bottomLeft" nz-icon nzType="ellipsis"></i>
<nz-dropdown-menu #op4Menu="nzDropdownMenu">
<i nz-dropdown nz-icon nzType="ellipsis"></i>
<ul nz-menu>
<li nz-menu-item>1st menu item</li>
<li nz-menu-item>2st menu item</li>
<li nz-menu-item>3st menu item</li>
</ul>
</nz-dropdown-menu>
</ng-template>-->
<nz-card-meta [nzTitle]="item.title" [nzAvatar]="nzAvatar" *ngIf="item.protocol == 'Form_Based'">
<ng-template #nzAvatar>
<i nz-icon nzType="user-add" nzTheme="outline" (click)="setAccount(item.id)"> </i>
<!--<nz-avatar nzSize="small" [nzSrc]="item.iconBase64"></nz-avatar>-->
</ng-template>
</nz-card-meta>
<div class="card-info d-flex" style="justify-content: center">
<div class="appCard">
<p style="text-align: center" (click)="onAuthz($event, item.id)">
<img class="appListimage" src="{{ item.iconBase64 }}" />
</p>
<p>{{ item.appName }}</p>
</div>
</div>
</nz-card>
</nz-list-item>
<nz-card [nzExtra]="extraWorkTemplate" [nzTitle]="title">
<ng-template #title>
<div class="el_content">
<div class="el-img">
<img
src="data:image/png;base64,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"
class="el-image__inner"
/>
</div>
<div class="el-title">{{ 'mxk.menu.applist' | i18n }}</div>
</div>
</ng-template>
</nz-list>
<ng-template #extraWorkTemplate>
<nz-select nzShowSearch nzAllowClear nzPlaceHolder="Please select Category" style="min-width: 180px" [(ngModel)]="appsCategory" (ngModelChange)="changeCategory()">
<nz-option nzLabel="All" nzValue=""></nz-option>
<nz-option *ngFor="let item of appCategoryList; let i = index" [nzLabel]="item.name" [nzValue]="item.id" ></nz-option>
</nz-select>
</ng-template>
<nz-list
[nzLoading]="loading"
[nzDataSource]="appList"
[nzRenderItem]="item"
[nzGrid]="{ gutter: 24, xl: 6, lg: 8, md: 8, sm: 12, xs: 24 }"
>
<ng-template #item let-item>
<nz-list-item>
<nz-card nzHoverable style="">
<!--<nz-card nzHoverable [nzActions]="[op1, op2, op3, op4]">
<ng-template #op1>
<i nz-tooltip nzTooltipTitle="下载" nz-icon nzType="download"></i>
</ng-template>
<ng-template #op2>
<i nz-tooltip nzTooltipTitle="编辑" nz-icon nzType="edit"></i>
</ng-template>
<ng-template #op3>
<i nz-tooltip nzTooltipTitle="分享" nz-icon nzType="share-alt"></i>
</ng-template>
<ng-template #op4>
<i nz-dropdown [nzDropdownMenu]="op4Menu" nzPlacement="bottomLeft" nz-icon nzType="ellipsis"></i>
<nz-dropdown-menu #op4Menu="nzDropdownMenu">
<i nz-dropdown nz-icon nzType="ellipsis"></i>
<ul nz-menu>
<li nz-menu-item>1st menu item</li>
<li nz-menu-item>2st menu item</li>
<li nz-menu-item>3st menu item</li>
</ul>
</nz-dropdown-menu>
</ng-template>-->
<nz-card-meta [nzTitle]="item.title" [nzAvatar]="nzAvatar" *ngIf="item.protocol == 'Form_Based'">
<ng-template #nzAvatar>
<i nz-icon nzType="user-add" nzTheme="outline" (click)="setAccount(item.id)"> </i>
<!--<nz-avatar nzSize="small" [nzSrc]="item.iconBase64"></nz-avatar>-->
</ng-template>
</nz-card-meta>
<div class="card-info d-flex" style="justify-content: center">
<div class="appCard">
<p style="text-align: center" (click)="onAuthz($event, item.id)">
<img class="appListimage" src="{{ item.iconBase64 }}" />
</p>
<p>{{ item.appName }}</p>
</div>
</div>
</nz-card>
</nz-list-item>
</ng-template>
</nz-list>
</nz-card>
</div>
<div nz-col nzMd="3"></div>
</div>

View File

@ -0,0 +1,11 @@
.el_content {
display: flex;
}
.el-img img{
width: 22px;
}
.el-title{
font-size: 18px;
margin-left: 5px;
}

View File

@ -31,6 +31,8 @@ import { AuthnService } from '../../../service/authn.service';
import { AccoutsComponent } from '../../config/accouts/accouts.component';
import { Console } from 'console';
import {ALAIN_I18N_TOKEN} from "@delon/theme";
import {I18NService} from "@core";
@Component({
selector: 'app-home',
@ -51,7 +53,9 @@ export class HomeComponent implements OnInit {
loading: boolean = false;
appList: any[] = [];
baseUrl: String = '';
staticAppList: any[] = [];
appCategoryList: any[] = [];
appsCategory: String = '';
constructor(
private modal: NzModalService,
private viewContainerRef: ViewContainerRef,
@ -59,6 +63,7 @@ export class HomeComponent implements OnInit {
private cdr: ChangeDetectorRef,
private obSrv: OnboardingService,
private platform: Platform,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
@Inject(DOCUMENT) private doc: NzSafeAny
) {
// TODO: Wait for the page to load
@ -106,7 +111,136 @@ export class HomeComponent implements OnInit {
this.appListService.appList().subscribe(res => {
//console.log(res.data);
this.appList = res.data;
this.staticAppList = this.appList;
this.cdr.detectChanges();
});
this.appCategoryList = [{
id:'none',
name:this.i18n.fanyi('mxk.apps.category.none')
},{
id:'1011',
name:this.i18n.fanyi('mxk.apps.category.1011')
},
{
id:'1012',
name:this.i18n.fanyi('mxk.apps.category.1012')
},
{
id:'1013',
name:this.i18n.fanyi('mxk.apps.category.1013')
},
{
id:'1014',
name:this.i18n.fanyi('mxk.apps.category.1014')
},
{
id:'1015',
name:this.i18n.fanyi('mxk.apps.category.1015')
},
{
id:'1016',
name:this.i18n.fanyi('mxk.apps.category.1016')
},
{
id:'1017',
name:this.i18n.fanyi('mxk.apps.category.1017')
},
{
id:'1111',
name:this.i18n.fanyi('mxk.apps.category.1111')
},
{
id:'1112',
name:this.i18n.fanyi('mxk.apps.category.1112')
},
{
id:'1113',
name:this.i18n.fanyi('mxk.apps.category.1113')
},
{
id:'1114',
name:this.i18n.fanyi('mxk.apps.category.1114')
},
{
id:'1211',
name:this.i18n.fanyi('mxk.apps.category.1211')
},
{
id:'1212',
name:this.i18n.fanyi('mxk.apps.category.1212')
},
{
id:'1213',
name:this.i18n.fanyi('mxk.apps.category.1213')
},
{
id:'1214',
name:this.i18n.fanyi('mxk.apps.category.1214')
},
{
id:'1215',
name:this.i18n.fanyi('mxk.apps.category.1215')
},
{
id:'1215',
name:this.i18n.fanyi('mxk.apps.category.1215')
},
{
id:'1311',
name:this.i18n.fanyi('mxk.apps.category.1311')
},
{
id:'1411',
name:this.i18n.fanyi('mxk.apps.category.1411')
},
{
id:'1511',
name:this.i18n.fanyi('mxk.apps.category.1511')
},
{
id:'1512',
name:this.i18n.fanyi('mxk.apps.category.1512')
},
{
id:'1611',
name:this.i18n.fanyi('mxk.apps.category.1611')
},
{
id:'1711',
name:this.i18n.fanyi('mxk.apps.category.1711')
},
{
id:'1712',
name:this.i18n.fanyi('mxk.apps.category.1712')
},
{
id:'1811',
name:this.i18n.fanyi('mxk.apps.category.1811')
},
{
id:'1812',
name:this.i18n.fanyi('mxk.apps.category.1812')
},{
id:'1911',
name:this.i18n.fanyi('mxk.apps.category.1911')
},
{
id:'1912',
name:this.i18n.fanyi('mxk.apps.category.1912')
}
]
}
changeCategory (): void {
this.appList = [];
if (this.appsCategory === null || this.appsCategory === '') {
this.appList = this.staticAppList;
} else {
for(let i = 0;i<this.staticAppList.length;i++){
if(this.staticAppList[i].category === this.appsCategory) {
this.appList.push(this.staticAppList[i]);
}
}
}
this.cdr.detectChanges();
}
}

View File

@ -71,18 +71,27 @@
<a class="login" routerLink="/passport/login">{{ 'mxk.forgot.login' | i18n }}</a>
</nz-form-item>
</nz-form-item>
<nz-form-item style="width: 400px;
position: absolute;
right: 50px;" *ngIf="step === 1">
<h2 style="width: 100%;"><span nz-icon nzType="lock" nzTheme="outline"></span>{{'validation.password.conformance-strength'| i18n}}</h2>
<ul style="padding: 0 20px;">
<li *ngFor="let item of policyMessage">{{item}}</li>
</ul>
</nz-form-item>
<nz-form-item style="width: 100%" *ngIf="step === 1">
<nz-form-item style="width: 100%">
<nz-form-label nzRequired nzFor="password">{{ 'mxk.password.password' | i18n }}</nz-form-label>
</nz-form-item>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="The input is not valid password!">
<nz-form-control [nzErrorTip]="'validation.password.input' | i18n">
<nz-input-group nzSize="large" [nzSuffix]="suffixPasswordTemplate" style="width: 100%">
<input
[type]="passwordVisible ? 'text' : 'password'"
nz-input
placeholder="new password"
placeholder="{{ 'validation.password.input' | i18n }}"
[(ngModel)]="form.model.password"
(input)="dynamicallyCheckPassword(form.model.password)"
formControlName="password"
id="password"
/>
@ -90,6 +99,12 @@
<ng-template #suffixPasswordTemplate>
<i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" (click)="passwordVisible = !passwordVisible"></i>
</ng-template>
<nz-alert
*ngIf="dynamicallyCheckPasswordErrorMsg !=''"
nzType="warning"
nzMessage="{{dynamicallyCheckPasswordErrorMsg}}"
nzShowIcon
></nz-alert>
</nz-form-control>
</nz-form-item>
@ -97,13 +112,14 @@
<nz-form-label nzRequired nzFor="confirmPassword">{{ 'mxk.password.confirmPassword' | i18n }}</nz-form-label>
</nz-form-item>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="The input is not valid confirmPassword!">
<nz-form-control [nzErrorTip]="'validation.confirmPassword.input' | i18n">
<input
nz-input
type="password"
nzSize="large"
placeholder="confirm password"
placeholder="{{ 'validation.confirmPassword.input' | i18n }}"
[(ngModel)]="form.model.confirmPassword"
(input)="dynamicallyCheckConfirm(form.model.confirmPassword)"
formControlName="confirmPassword"
name="confirmPassword"
id="confirmPassword"
@ -117,4 +133,5 @@
<a class="login" routerLink="/passport/login">{{ 'mxk.forgot.login' | i18n }}</a>
</nz-form-item>
</nz-form-item>
</form>

View File

@ -14,15 +14,18 @@
* limitations under the License.
*/
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { Component, OnInit, ChangeDetectorRef, Inject } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzStepsModule } from 'ng-zorro-antd/steps';
import { ChangePassword } from '../../../entity/ChangePassword';
import { ForgotPasswordService } from '../../../service/forgot-password.service';
import { ImageCaptchaService } from '../../../service/image-captcha.service';
import {PasswordService} from "../../../service/password.service";
@Component({
selector: 'app-forgot',
@ -49,12 +52,16 @@ export class ForgotComponent implements OnInit {
interval$: any;
userId = '';
username = '';
policyMessage:any[] =[];
policy:any = {};
dynamicallyCheckPasswordErrorMsg:string = '';
constructor(
fb: FormBuilder,
private router: Router,
private forgotPasswordService: ForgotPasswordService,
private imageCaptchaService: ImageCaptchaService,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {
this.formGroup = fb.group({
@ -89,6 +96,14 @@ export class ForgotComponent implements OnInit {
ngOnInit(): void {
this.getImageCaptcha();
this.policyMessage=[];
this.forgotPasswordService.passwordpolicy().subscribe(res => {
if(res.code == 0) {
let data = res.data;
this.policy = data;
this.policyMessage=res.data.policMessageList;
}
});
}
getImageCaptcha(): void {
@ -116,68 +131,136 @@ export class ForgotComponent implements OnInit {
this.forgotPasswordService
.produceOtp({ mobile: this.mobile.value, state: this.state, captcha: this.captcha.value })
.subscribe(res => {
if (res.code !== 0) {
this.msg.success(`发送失败`);
if (res.code == 103) {
this.msg.error(this.i18n.fanyi('validation.forgot.captcha.error'));
this.getImageCaptcha();
this.cdr.detectChanges();
return;
}
if (res.code != 0) {
this.msg.error(this.i18n.fanyi('mxk.alert.operate.error'));
this.getImageCaptcha();
this.cdr.detectChanges();
return;
}
this.userId = res.data.userId;
this.username = res.data.username;
//console.log(res.data);
this.count = 59;
this.interval$ = setInterval(() => {
this.count -= 1;
if (this.count <= 0) {
clearInterval(this.interval$);
}
this.cdr.detectChanges();
}, 1000);
});
} else if (this.forgotType == 'email') {
this.forgotPasswordService
.produceEmailOtp({ email: this.email.value, state: this.state, captcha: this.captcha.value })
.subscribe(res => {
if (res.code !== 0) {
this.msg.success(`发送失败`);
if (res.code == 103) {
this.msg.error(this.i18n.fanyi('validation.forgot.captcha.error'));
this.getImageCaptcha();
this.cdr.detectChanges();
return;
}
if (res.code != 0) {
this.msg.error(this.i18n.fanyi('mxk.alert.operate.error'));
this.getImageCaptcha();
this.cdr.detectChanges();
return;
}
this.userId = res.data.userId;
this.username = res.data.username;
this.count = 59;
this.interval$ = setInterval(() => {
this.count -= 1;
if (this.count <= 0) {
clearInterval(this.interval$);
}
this.cdr.detectChanges();
}, 1000);
//console.log(res.data);
});
}
this.count = 59;
this.interval$ = setInterval(() => {
this.count -= 1;
if (this.count <= 0) {
clearInterval(this.interval$);
}
this.cdr.detectChanges();
}, 1000);
}
onNextReset(e: MouseEvent) {
if (this.forgotType == 'mobile' && this.mobile.invalid) {
this.mobile.markAsDirty({ onlySelf: true });
this.mobile.updateValueAndValidity({ onlySelf: true });
return;
}
if (this.forgotType == 'email' && this.email.invalid) {
this.email.markAsDirty({ onlySelf: true });
this.email.updateValueAndValidity({ onlySelf: true });
return;
}
if (this.captcha.invalid) {
this.captcha.markAsDirty({ onlySelf: true });
this.captcha.updateValueAndValidity({ onlySelf: true });
return;
}
if (this.otpCaptcha.invalid) {
this.otpCaptcha.markAsDirty({ onlySelf: true });
this.otpCaptcha.updateValueAndValidity({ onlySelf: true });
return;
}
this.step = 1;
//this.step = 1;
//判断验证码
this.forgotPasswordService.validateCaptcha({ userId:this.userId, state: this.state, captcha: this.captcha.value, otpCaptcha: this.otpCaptcha.value })
.subscribe(res => {
if (res.code !== 0) {
this.msg.error(this.i18n.fanyi('app.login.message-invalid-verification-code'));
this.cdr.detectChanges();
return;
}
this.step = 1;
});
}
onSubmit(e: MouseEvent) {
this.forgotPasswordService
.setPassWord({
forgotType: this.forgotType,
userId: this.userId,
username: this.username,
password: this.password.value,
confirmPassword: this.confirmPassword.value,
otpCaptcha: this.otpCaptcha.value,
state: this.state
})
.subscribe(res => {
if (res.code !== 0) {
this.msg.success(`密码修改失败`);
this.getImageCaptcha();
this.step = 0;
this.cdr.detectChanges();
}
this.msg.success(`密码修改成功`);
});
if (this.password.invalid) {
this.password.markAsDirty({ onlySelf: true });
this.password.updateValueAndValidity({ onlySelf: true });
return;
}
if (this.confirmPassword.invalid) {
this.confirmPassword.markAsDirty({ onlySelf: true });
this.confirmPassword.updateValueAndValidity({ onlySelf: true });
return;
}
if (this.dynamicallyCheckPasswordErrorMsg == '') {
this.forgotPasswordService
.setPassWord({
forgotType: this.forgotType,
userId: this.userId,
username: this.username,
password: this.password.value,
confirmPassword: this.confirmPassword.value,
otpCaptcha: this.otpCaptcha.value,
state: this.state
})
.subscribe(res => {
if (res.code !== 0) {
this.msg.error(this.i18n.fanyi('mxk.alert.operate.error'));
this.getImageCaptcha();
this.step = 1;
this.cdr.detectChanges();
return;
}
this.msg.success(this.i18n.fanyi('mxk.alert.operate.success'));
setTimeout(() => {
this.router.navigateByUrl('/');
}, 3000);
});
}
}
ngModelChange() {
@ -188,4 +271,98 @@ export class ForgotComponent implements OnInit {
this.email.reset();
}
}
dynamicallyCheckConfirm(value:any):void {
if (value != this.form.model.password) {
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.twice')
} else {
this.dynamicallyCheckPasswordErrorMsg = '';
}
}
dynamicallyCheckPassword(value:any):void {
if (value == '') {
this.dynamicallyCheckPasswordErrorMsg = '';
return;
}
let data = this.policy;
if (data.minLength != 0 && data.maxLength != 0) {
let inputLength = value.length;
if (inputLength < data.minLength || inputLength > data.maxLength) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码长度为"+data.minLength+"-"+data.maxLength+"位"
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if (data.lowerCase > 0) {
let strArr = Array.from(value)
let abc:any = [];
strArr.forEach(function (value:any, index, array) {
let code = value.charCodeAt()
if (code >= 'a'.charCodeAt(0) && code <= 'z'.charCodeAt(0)) {
abc.push(value)
}
})
if(abc.length < data.lowerCase) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.lowerCase+"位【a-z】小写字母"
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if(data.upperCase > 0) {
let strArr = Array.from(value)
let ABC:any = [];
strArr.forEach(function (value:any, index, array) {
let code = value.charCodeAt()
if (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) {
ABC.push(value)
}
})
if(ABC.length < data.upperCase) {
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.lowerCase+"位【A-Z】大写字母"
return;
}
}
if (data.digits > 0) {
let strArr = Array.from(value)
let number:any = [];
strArr.forEach(function (value:any, index, array) {
var regPos = /^[0-9]+.?[0-9]*/; //判断是否是数字。
if(regPos.test(value) ){
number.push(value)
}
})
if(number.length < data.digits) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.digits+"位【0-9】阿拉伯数字";
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
if(data.specialChar > 0) {
var AllNumIsSame = new Array("","”","!","@","#","$","%","^","&","*",".");
let strArr = Array.from(value)
let number:any = [];
strArr.forEach(function (value:any, index, array) {
if(AllNumIsSame.indexOf(value) != -1){//$.type 是jquery的函数用来判断对象类型
number.push(value)
}
})
if(number.length < data.specialChar) {
//this.dynamicallyCheckPasswordErrorMsg = "限定新密码至少需要包含"+data.specialChar+"位特殊字符";
this.dynamicallyCheckPasswordErrorMsg = this.i18n.fanyi('validation.password.non-conformance-strength')
return;
}
}
this.dynamicallyCheckPasswordErrorMsg = '';
}
}

View File

@ -263,8 +263,8 @@ export class UserLoginComponent implements OnInit, OnDestroy {
.subscribe(res => {
this.loading = true;
if (res.code !== 0) {
this.error = res.msg;
//this.msg.success(`登录失败,请重新登录!`);
this.error = res.message;
//this.msg.error(this.error);
if (this.loginType === 'normal') {
this.getImageCaptcha();
}

View File

@ -33,4 +33,12 @@ export class ForgotPasswordService {
setPassWord(param: any) {
return this.http.get('/forgotpassword/setpassword?_allow_anonymous=true', param);
}
validateCaptcha(param: any) {
return this.http.get(`/forgotpassword/validateCaptcha?_allow_anonymous=true`, param);
}
passwordpolicy() {
return this.http.get('/forgotpassword/passwordpolicy?_allow_anonymous=true',null);
}
}

View File

@ -34,4 +34,7 @@ export class PasswordService extends BaseService<ChangePassword> {
public changePassword(body: NzSafeAny): Observable<Message<ChangePassword>> {
return this.http.put<Message<ChangePassword>>('/config/changePassword', body);
}
public passwordpolicy(): Observable<Message<ChangePassword>> {
return this.http.put<Message<ChangePassword>>('/config/passwordpolicy',null);
}
}

View File

@ -663,7 +663,7 @@
"success":"Operate Success!",
"error":"Operate Error!"
}
},
"text": {
"action": "Action",
@ -870,5 +870,11 @@
"validation.title.required": "Please enter a title",
"validation.date.required": "Please select the start and end date",
"validation.goal.required": "Please enter a description of the goal",
"validation.standard.required": "Please enter a metric"
}
"validation.standard.required": "Please enter a metric",
"validation.password.conformance-strength": "Password Strength",
"validation.password.non-conformance-strength": "The password does not meet the strength",
"validation.oldPassword.input": "Please enter old password!",
"validation.password.input": "Please enter new password!",
"validation.confirmPassword.input": "Please enter confirm password!",
"validation.forgot.captcha.error": "Picture Captcha Fail"
}

View File

@ -867,5 +867,11 @@
"validation.title.required": "请输入标题",
"validation.date.required": "请选择起止日期",
"validation.goal.required": "请输入目标描述",
"validation.standard.required": "请输入衡量标准"
}
"validation.standard.required": "请输入衡量标准",
"validation.password.conformance-strength": "密码强度",
"validation.password.non-conformance-strength": "密码不符合强度!",
"validation.oldPassword.input": "请输入当前密码!",
"validation.password.input": "请输入新密码!",
"validation.confirmPassword.input": "请输入确认密码!",
"validation.forgot.captcha.error": "图形验证码错误"
}

View File

@ -867,5 +867,11 @@
"validation.title.required": "請輸入標題",
"validation.date.required": "請選擇起止日期",
"validation.goal.required": "請輸入目標描述",
"validation.standard.required": "請輸入衡量標準"
}
"validation.standard.required": "請輸入衡量標準",
"validation.password.conformance-strength": "密碼强度",
"validation.password.non-conformance-strength": "密碼不符合强度!",
"validation.oldPassword.input": "請輸入當前密碼!",
"validation.password.input": "請輸入新密碼!",
"validation.confirmPassword.input": "請輸入確認密碼!",
"validation.forgot.captcha.error": "圖形驗證碼錯誤"
}