import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnDestroy, Optional } from '@angular/core'; import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { StartupService } from '@core'; import { ReuseTabService } from '@delon/abc/reuse-tab'; import { DA_SERVICE_TOKEN, ITokenService, SocialOpenType, SocialService } from '@delon/auth'; import { SettingsService, _HttpClient } from '@delon/theme'; import { environment } from '@env/environment'; import { NzTabChangeEvent } from 'ng-zorro-antd/tabs'; import { finalize } from 'rxjs/operators'; @Component({ selector: 'passport-login', templateUrl: './login.component.html', styleUrls: ['./login.component.less'], providers: [SocialService], changeDetection: ChangeDetectionStrategy.OnPush }) export class UserLoginComponent implements OnDestroy { constructor( fb: FormBuilder, private router: Router, private settingsService: SettingsService, private socialService: SocialService, @Optional() @Inject(ReuseTabService) private reuseTabService: ReuseTabService, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService, private startupSrv: StartupService, private http: _HttpClient, private cdr: ChangeDetectorRef ) { this.form = fb.group({ userName: [null, [Validators.required, Validators.pattern(/^(admin|user)$/)]], password: [null, [Validators.required, Validators.pattern(/^(admin@123)$/)]], mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]], captcha: [null, [Validators.required]], remember: [true] }); } // #region fields get userName(): AbstractControl { return this.form.controls.userName; } get password(): AbstractControl { return this.form.controls.password; } get mobile(): AbstractControl { return this.form.controls.mobile; } get captcha(): AbstractControl { return this.form.controls.captcha; } form: FormGroup; error = ''; type = 0; loading = false; // #region get captcha count = 0; interval$: any; // #endregion switch({ index }: NzTabChangeEvent): void { this.type = index!; } getCaptcha(): void { if (this.mobile.invalid) { this.mobile.markAsDirty({ onlySelf: true }); this.mobile.updateValueAndValidity({ onlySelf: true }); return; } this.count = 59; this.interval$ = setInterval(() => { this.count -= 1; if (this.count <= 0) { clearInterval(this.interval$); } }, 1000); } // #endregion submit(): void { this.error = ''; if (this.type === 0) { this.userName.markAsDirty(); this.userName.updateValueAndValidity(); this.password.markAsDirty(); this.password.updateValueAndValidity(); if (this.userName.invalid || this.password.invalid) { return; } } else { this.mobile.markAsDirty(); this.mobile.updateValueAndValidity(); this.captcha.markAsDirty(); this.captcha.updateValueAndValidity(); if (this.mobile.invalid || this.captcha.invalid) { return; } } // 默认配置中对所有HTTP请求都会强制 [校验](https://ng-alain.com/auth/getting-started) 用户 Token // 然一般来说登录请求不需要校验,因此可以在请求URL加上:`/login?_allow_anonymous=true` 表示不触发用户 Token 校验 this.loading = true; this.cdr.detectChanges(); this.http .post('/login/account?_allow_anonymous=true', { type: this.type, userName: this.userName.value, password: this.password.value }) .pipe( finalize(() => { this.loading = true; this.cdr.detectChanges(); }) ) .subscribe(res => { if (res.msg !== 'ok') { this.error = res.msg; this.cdr.detectChanges(); return; } // 清空路由复用信息 this.reuseTabService.clear(); // 设置用户Token信息 // TODO: Mock expired value res.user.expired = +new Date() + 1000 * 60 * 5; this.tokenService.set(res.user); // 重新获取 StartupService 内容,我们始终认为应用信息一般都会受当前用户授权范围而影响 this.startupSrv.load().subscribe(() => { let url = this.tokenService.referrer!.url || '/'; if (url.includes('/passport')) { url = '/'; } this.router.navigateByUrl(url); }); }); } // #region social open(type: string, openType: SocialOpenType = 'href'): void { let url = ``; let callback = ``; if (environment.production) { callback = `https://ng-alain.github.io/ng-alain/#/passport/callback/${type}`; } else { callback = `http://localhost:4200/#/passport/callback/${type}`; } switch (type) { case 'auth0': url = `//cipchk.auth0.com/login?client=8gcNydIDzGBYxzqV0Vm1CX_RXH-wsWo5&redirect_uri=${decodeURIComponent(callback)}`; break; case 'github': url = `//github.com/login/oauth/authorize?client_id=9d6baae4b04a23fcafa2&response_type=code&redirect_uri=${decodeURIComponent( callback )}`; break; case 'weibo': url = `https://api.weibo.com/oauth2/authorize?client_id=1239507802&response_type=code&redirect_uri=${decodeURIComponent(callback)}`; break; } if (openType === 'window') { this.socialService .login(url, '/', { type: 'window' }) .subscribe(res => { if (res) { this.settingsService.setUser(res); this.router.navigateByUrl('/'); } }); } else { this.socialService.login(url, '/', { type: 'href' }); } } // #endregion ngOnDestroy(): void { if (this.interval$) { clearInterval(this.interval$); } } }