新增设置支付密码
This commit is contained in:
@ -0,0 +1,171 @@
|
||||
<page-header-wrapper [title]="''" [logo]="logo">
|
||||
<ng-template #logo>
|
||||
<button nz-button nz-tooltip nzTooltipTitle="返回上一页" (click)="goBack()">
|
||||
<i nz-icon nzType="left" nzTheme="outline"></i>
|
||||
</button>
|
||||
</ng-template>
|
||||
</page-header-wrapper>
|
||||
<nz-card>
|
||||
<div class="container">
|
||||
<div>
|
||||
<div style="display: flex; align-items: center; min-height: 150px">
|
||||
<nz-steps [nzCurrent]="step" style="display: contents" [nzProgressDot]="progressTemplate">
|
||||
<nz-step nzTitle="安全验证"></nz-step>
|
||||
<nz-step nzTitle="重设密码"></nz-step>
|
||||
<nz-step nzTitle="完成"></nz-step>
|
||||
</nz-steps>
|
||||
<ng-template #progressTemplate let-dot let-status="status" let-index="index">
|
||||
<ng-container *ngIf="status === 'finish'; else finshTemplate">
|
||||
<i nz-icon nzType="check" nzTheme="outline" style="color: #fff"></i>
|
||||
</ng-container>
|
||||
<ng-template #finshTemplate>
|
||||
{{ index + 1 }}
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
<nz-card [nzBordered]="false">
|
||||
<div style="width: 480px; margin: 0 auto" [ngSwitch]="step.toString()">
|
||||
<div *ngSwitchCase="0">
|
||||
<sf #step1sf *ngIf="step1Schema" [schema]="step1Schema" button="none" [layout]="'horizontal'">
|
||||
<ng-template sf-template="smsVerifyCode" let-smsVerifyCode let-ui="ui" let-schema="schema">
|
||||
<nz-input-group [nzSuffix]="suffixTemplateInfo">
|
||||
<input
|
||||
type="text"
|
||||
maxlength="6"
|
||||
nz-input
|
||||
placeholder="请输入验证码"
|
||||
[ngModel]="smsVerifyCode.formProperty.value"
|
||||
(ngModelChange)="smsVerifyCode.setValue($event)"
|
||||
/>
|
||||
</nz-input-group>
|
||||
</ng-template>
|
||||
<div nz-col [nzPush]="5">
|
||||
<button
|
||||
nz-button
|
||||
type="submit"
|
||||
nzType="primary"
|
||||
(click)="nextStep()"
|
||||
[disabled]="!step1sf.valid"
|
||||
[nzLoading]="service.http.loading"
|
||||
>
|
||||
下一步
|
||||
</button>
|
||||
</div>
|
||||
</sf>
|
||||
</div>
|
||||
|
||||
<div *ngSwitchCase="1">
|
||||
<form nz-form [formGroup]="formGroup3" class="myForm">
|
||||
<nz-form-item>
|
||||
<nz-form-label nzSpan="6" nzRequired nzFor="passWord">设置支付密码</nz-form-label>
|
||||
<nz-form-control nzSpan="18" [nzErrorTip]="passwordErrorTpl">
|
||||
<nz-input-group [nzSuffix]="pwdIconEye">
|
||||
<input
|
||||
nz-input
|
||||
[type]="isShowPwd ? 'text' : 'password'"
|
||||
formControlName="passWord"
|
||||
minlength="6"
|
||||
maxlength="6"
|
||||
(ngModelChange)="validateConfirmPassword()"
|
||||
placeholder="请输入支付密码"
|
||||
/>
|
||||
</nz-input-group>
|
||||
<ng-template #pwdIconEye>
|
||||
<span (click)="isShowPwd = !isShowPwd">
|
||||
<ng-container *ngIf="isShowPwd; else showPwdTempalte">
|
||||
<i nz-icon nzType="eye" nzTheme="outline"></i>
|
||||
</ng-container>
|
||||
<ng-template #showPwdTempalte>
|
||||
<i nz-icon nzType="eye-invisible" nzTheme="outline"></i>
|
||||
</ng-template>
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template #passwordErrorTpl let-control>
|
||||
<ng-container *ngIf="control.hasError('required')"> 请输入支付密码! </ng-container>
|
||||
<ng-container *ngIf="control.hasError('minlength') || control.hasError('pattern') || control.hasError('confirm')">
|
||||
6位数字,不能为连续数字或者相同数字(如123456、111111)
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-label nzSpan="6" nzRequired nzFor="passWordTo">重复支付密码</nz-form-label>
|
||||
<nz-form-control nzSpan="18" nzDisableAutoTips [nzErrorTip]="confirmPasswordErrorTpl">
|
||||
<nz-input-group [nzSuffix]="confirmPwdIconEye">
|
||||
<input
|
||||
nz-input
|
||||
[type]="isShowConfirmPwd ? 'text' : 'password'"
|
||||
formControlName="passWordTo"
|
||||
minlength="6"
|
||||
maxlength="6"
|
||||
(ngModelChange)="validateConfirmPassword()"
|
||||
placeholder="请输入支付密码"
|
||||
/>
|
||||
</nz-input-group>
|
||||
<ng-template #confirmPwdIconEye>
|
||||
<span (click)="isShowConfirmPwd = !isShowConfirmPwd">
|
||||
<ng-container *ngIf="isShowConfirmPwd; else showConfirmPwdTempalte">
|
||||
<i nz-icon nzType="eye" nzTheme="outline"></i>
|
||||
</ng-container>
|
||||
<ng-template #showConfirmPwdTempalte>
|
||||
<i nz-icon nzType="eye-invisible" nzTheme="outline"></i>
|
||||
</ng-template>
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template #confirmPasswordErrorTpl let-control>
|
||||
<ng-container *ngIf="control.hasError('required')"> 请输入确认密码! </ng-container>
|
||||
<ng-container *ngIf="control.hasError('passWordTo')"> 两次输入的密码不一致! </ng-container>
|
||||
</ng-template>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<nz-form-control nzSpan="18" nzOffset="6">
|
||||
<button
|
||||
[disabled]="!formGroup3.valid"
|
||||
[nzLoading]="service.http.loading"
|
||||
nz-button
|
||||
nzType="primary"
|
||||
(click)="formSubmit()"
|
||||
style="width: 74px"
|
||||
>
|
||||
确认
|
||||
</button>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngSwitchCase="2" class="success-card">
|
||||
<div class="card-icon">
|
||||
<i nz-icon nzType="check" nzTheme="outline" style="color: #fff; font-size: 20px"></i>
|
||||
</div>
|
||||
<p class="card-title">密码设置成功</p>
|
||||
<p class="card-descr">请牢记您的新支付密码,3秒后自动跳转至个人中心...</p>
|
||||
<!-- <button
|
||||
nz-button
|
||||
type="button"
|
||||
nzType="primary"
|
||||
nzSize="large"
|
||||
class="mt-lg"
|
||||
style="font-size: 14px"
|
||||
[routerLink]="['/passport/login']"
|
||||
>
|
||||
立即登录
|
||||
</button> -->
|
||||
</div>
|
||||
<div *ngSwitchDefault></div>
|
||||
</div>
|
||||
</nz-card>
|
||||
</div>
|
||||
</div>
|
||||
</nz-card>
|
||||
|
||||
<ng-template #suffixTemplateInfo>
|
||||
<ng-container *ngIf="count < 1; else intervalTemplate">
|
||||
<span class="msg-btn" style="color: #3370ff; cursor: pointer" (click)="getMsgCode()">获取验证码</span>
|
||||
</ng-container>
|
||||
<ng-template #intervalTemplate>
|
||||
<!-- {{ count > 0 ? '请等待' + count + 's' : ('app.register.get-verification-code' | translate) }} -->
|
||||
{{ count > 0 ? '请等待' + count + 's' : ('app.register.get-verification-code') }}
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<app-captcha #dun [phone]="phone" (done)="captchaDone($event)"></app-captcha>
|
||||
@ -0,0 +1,93 @@
|
||||
:host {
|
||||
::ng-deep {
|
||||
page-grid {
|
||||
background-color: #f0f3f7;
|
||||
|
||||
div.container {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding: 30px 1rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-steps-item-process .ant-steps-item-icon {
|
||||
background-color: #3370ff;
|
||||
border-color: #3370ff;
|
||||
}
|
||||
|
||||
.ant-steps-item-finish > .ant-steps-item-container > .ant-steps-item-icon {
|
||||
background: #3370ff;
|
||||
}
|
||||
|
||||
.ant-steps-dot .ant-steps-item-icon,
|
||||
.ant-steps-dot.ant-steps-small .ant-steps-item-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-left: 55px;
|
||||
line-height: 32px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
// 文本
|
||||
.ant-steps-item-wait .ant-steps-item-icon > .ant-steps-icon {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
// 连接线
|
||||
.ant-steps-dot .ant-steps-item-tail,
|
||||
.ant-steps-dot.ant-steps-small .ant-steps-item-tail {
|
||||
top: 12px;
|
||||
margin: 0 0 0 90px;
|
||||
}
|
||||
|
||||
.ant-steps-item-wait > .ant-steps-item-container > .ant-steps-item-tail::after {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.ant-steps-dot .ant-steps-item-process .ant-steps-item-icon,
|
||||
.ant-steps-dot.ant-steps-small .ant-steps-item-process .ant-steps-item-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.ant-steps-item-process > .ant-steps-item-container > .ant-steps-item-tail::after {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.ant-steps-dot .ant-steps-item-tail::after,
|
||||
.ant-steps-dot.ant-steps-small .ant-steps-item-tail::after {
|
||||
width: calc(100% - 62px);
|
||||
height: 1.5px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-card {
|
||||
text-align: center;
|
||||
|
||||
.card-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin: auto;
|
||||
background-color: #52c41a;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
margin: 14px 0 0;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card-descr {
|
||||
margin: 8px 0 0;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AccountComponentsEditPayPasswordComponent } from './edit-paypassword.component';
|
||||
|
||||
describe('AccountComponentsEditPayPasswordComponent', () => {
|
||||
let component: AccountComponentsEditPayPasswordComponent;
|
||||
let fixture: ComponentFixture<AccountComponentsEditPayPasswordComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AccountComponentsEditPayPasswordComponent],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AccountComponentsEditPayPasswordComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,237 @@
|
||||
import { AfterViewInit, Component, Inject, OnInit, Optional, ViewChild } from '@angular/core';
|
||||
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ReuseTabService } from '@delon/abc/reuse-tab';
|
||||
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
|
||||
import { SFComponent, SFSchema, SFTextareaWidgetSchema, SFTextWidgetSchema, SFUISchema } from '@delon/form';
|
||||
import { SettingsService } from '@delon/theme';
|
||||
import { CaptchaComponent } from 'src/app/shared/components/captcha';
|
||||
|
||||
import { AccountService } from '../../services/account.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-account-components-edit-password',
|
||||
templateUrl: './edit-paypassword.component.html',
|
||||
styleUrls: ['./edit-paypassword.component.less'],
|
||||
})
|
||||
export class AccountComponentsEditPayPasswordComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('dun', { static: false })
|
||||
private dun!: CaptchaComponent;
|
||||
|
||||
step: 0 | 1 | 2 = 0;
|
||||
|
||||
step1Schema!: SFSchema;
|
||||
ui!: SFUISchema;
|
||||
@ViewChild('step1sf', { static: false })
|
||||
step1sf!: SFComponent;
|
||||
|
||||
phone: string;
|
||||
|
||||
formGroup3!: FormGroup;
|
||||
confirmPasswordValidator!: ValidatorFn;
|
||||
|
||||
isShowPwd = false;
|
||||
isShowConfirmPwd = false;
|
||||
|
||||
count = 0;
|
||||
interval$: any;
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
public service: AccountService,
|
||||
private route: ActivatedRoute,
|
||||
private settingService: SettingsService,
|
||||
private router: Router,
|
||||
@Inject(ReuseTabService)
|
||||
private reuseTabService: ReuseTabService,
|
||||
@Optional()
|
||||
@Inject(DA_SERVICE_TOKEN)
|
||||
private tokenService: ITokenService,
|
||||
) {
|
||||
this.phone = route.snapshot.queryParams.phone;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.dun.init();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.phone) {
|
||||
this.initStep1SF();
|
||||
} else {
|
||||
this.service.http.post(this.service.$api_get_current_user_info).subscribe((res) => {
|
||||
if (res) {
|
||||
this.phone = res.data?.phone;
|
||||
this.initStep1SF();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.confirmPasswordValidator = (control) => {
|
||||
if (!control.value) {
|
||||
return { error: true, required: true };
|
||||
} else if (control.value !== this.formGroup3.controls.passWord.value) {
|
||||
return { passWordTo: true, error: true };
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
this.formGroup3 = this.fb.group({
|
||||
passWord: [
|
||||
null,
|
||||
[
|
||||
Validators.required,
|
||||
Validators.maxLength(6),
|
||||
Validators.minLength(6),
|
||||
Validators.pattern('([\\d]){6,6}'),
|
||||
this.blurTestPw
|
||||
|
||||
],
|
||||
],
|
||||
passWordTo: [null, [this.confirmPasswordValidator, Validators.required, Validators.maxLength(6), Validators.minLength(6)]],
|
||||
voucher: [null, [Validators.required]],
|
||||
});
|
||||
}
|
||||
|
||||
initStep1SF() {
|
||||
this.step1Schema = {
|
||||
properties: {
|
||||
phone: {
|
||||
title: '手机号',
|
||||
type: 'string',
|
||||
ui: {
|
||||
widget: 'text',
|
||||
defaultText: this.phone.toString(),
|
||||
} as SFTextWidgetSchema,
|
||||
},
|
||||
smsVerifyCode: {
|
||||
type: 'string',
|
||||
title: '验证码',
|
||||
ui: {
|
||||
widget: 'custom',
|
||||
errors: {
|
||||
required: '请输入验证码',
|
||||
},
|
||||
} as SFTextareaWidgetSchema,
|
||||
},
|
||||
},
|
||||
required: ['smsVerifyCode'],
|
||||
};
|
||||
|
||||
this.ui = {
|
||||
'*': { spanLabelFixed: 90, grid: { span: 16, gutter: 4 } },
|
||||
};
|
||||
}
|
||||
|
||||
nextStep() {
|
||||
if (this.step1sf.valid) {
|
||||
this.service.request(this.service.$api_get_verifyPhone, this.step1sf.value).subscribe((res) => {
|
||||
if (res) {
|
||||
this.formGroup3.patchValue(res, { onlySelf: true });
|
||||
this.step = 1;
|
||||
this.count = 0;
|
||||
clearInterval(this.interval$);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
formSubmit() {
|
||||
for (const i in this.formGroup3.controls) {
|
||||
if (true) {
|
||||
this.formGroup3.controls[i].markAsDirty();
|
||||
this.formGroup3.controls[i].updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.formGroup3.valid) {
|
||||
const param = Object.assign({}, this.formGroup3.value);
|
||||
this.service.http.post(this.service.$api_voucherUpdatePayPassword, param).subscribe((res) => {
|
||||
if (res.success === true) {
|
||||
this.step++;
|
||||
setTimeout(() => {
|
||||
// this.settingService.setUser({});
|
||||
// // 清空路由复用信息
|
||||
// this.reuseTabService.clear();
|
||||
// // 设置用户Token信息
|
||||
// this.tokenService.clear();
|
||||
this.router.navigate(['/account/center']);
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getMsgCode() {
|
||||
if (this.phone) {
|
||||
this.getCode(`${this.service.$api_get_msg_code}`);
|
||||
} else {
|
||||
this.service.request(this.service.$api_get_current_user_info).subscribe((res) => {
|
||||
this.phone = res.phone;
|
||||
this.getCode(`${this.service.$api_get_msg_code}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
goBack() {
|
||||
window.history.go(-1);
|
||||
}
|
||||
getCode(url: string, params?: any) {
|
||||
this.service.http.post(url, null, params).subscribe((res) => {
|
||||
// code==503046 弹出网易盾
|
||||
if (res.success && res.data.code === '1') {
|
||||
this.service.msgSrv.success('发送成功');
|
||||
this.codeCountDown();
|
||||
} else if (res.data.code === '503046') {
|
||||
this.dun.popUp();
|
||||
} else {
|
||||
this.service.msgSrv.success(res.sendResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
/* code倒计时 */
|
||||
codeCountDown() {
|
||||
this.count = 59;
|
||||
this.interval$ = setInterval(() => {
|
||||
this.count -= 1;
|
||||
if (this.count <= 0) {
|
||||
clearInterval(this.interval$);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
/* 网易盾验证通过 */
|
||||
captchaDone(validate: any) {
|
||||
this.codeCountDown();
|
||||
}
|
||||
|
||||
validateConfirmPassword(): void {
|
||||
|
||||
setTimeout(() => this.formGroup3.controls.passWordTo.updateValueAndValidity());
|
||||
}
|
||||
// blurTestPw(){
|
||||
// const reg = /[^\d]/g
|
||||
// const val: any = this.formGroup3.controls.passWord.value
|
||||
// if(val.length === 6) {
|
||||
// const pattern = /([\d])\1{2,}/g
|
||||
// const pattern2 = /(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){5}|(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){5})\d/g
|
||||
// if(pattern.test(val) || pattern2.test(val)){
|
||||
// return false
|
||||
// } else {
|
||||
// return true
|
||||
// }
|
||||
// } else {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
blurTestPw = (control: FormControl): { [s: string]: boolean } => {
|
||||
if (!control.value) {
|
||||
return { required: true };
|
||||
} else if (control.value.length === 6) {
|
||||
const pattern = /([\d])\1{2,}/g
|
||||
const pattern2 = /(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){5}|(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){5})\d/g
|
||||
if(pattern.test(control.value) || pattern2.test(control.value)){
|
||||
return { confirm: true, error: true };
|
||||
}
|
||||
}
|
||||
return {};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user