3 files added
	
		
		4 files modified
	
	
 
	
	
	
	
	
	
	
	
 |  |  | 
 |  |  |     ], | 
 |  |  |     providers: [ | 
 |  |  |         { provide: LOCALE_ID, useValue: 'zh-Hans' },  | 
 |  |  |         // TODO 暂时关闭登陆验证        | 
 |  |  |         //{ provide: HTTP_INTERCEPTORS, useClass: SimpleInterceptor, multi: true},     | 
 |  |  |         { provide: HTTP_INTERCEPTORS, useClass: SimpleInterceptor, multi: true},     | 
 |  |  |         { provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true},     | 
 |  |  |         { provide: ALAIN_I18N_TOKEN, useClass: I18NService, multi: false }, | 
 |  |  |         StartupService, | 
 
 |  |  | 
 |  |  |                 <span class="title">ng-alain</span> | 
 |  |  |             </a> | 
 |  |  |         </div> | 
 |  |  |         <p class="desc">武林中最有影响力的《葵花宝典》;欲练神功,挥刀自宫</p> | 
 |  |  |         <p class="desc"></p> | 
 |  |  |     </div> | 
 |  |  |     <router-outlet></router-outlet> | 
 |  |  |     <global-footer [links]="links"> | 
 
| New file | 
 |  |  | 
 |  |  | <form nz-form [formGroup]="form" (ngSubmit)="submit()" role="form"> | 
 |  |  |     <nz-alert *ngIf="error" [nzType]="'error'" [nzMessage]="error" [nzShowIcon]="true" class="mb-lg"></nz-alert> | 
 |  |  |     <div nz-form-item> | 
 |  |  |         <div nz-form-control [nzValidateStatus]="userName"> | 
 |  |  |             <nz-input formControlName="userName" [nzPlaceHolder]="'admin'" [nzSize]="'large'"> | 
 |  |  |                 <ng-template #prefix> | 
 |  |  |                     <i class="anticon anticon-user"></i> | 
 |  |  |                 </ng-template> | 
 |  |  |             </nz-input> | 
 |  |  |             <ng-container *ngIf="userName.dirty || userName.touched"> | 
 |  |  |                 <p nz-form-explain *ngIf="userName.errors?.required">请输入账户名!</p> | 
 |  |  |                 <p nz-form-explain *ngIf="userName.errors?.minlength">至少五个字符</p> | 
 |  |  |             </ng-container> | 
 |  |  |         </div> | 
 |  |  |     </div> | 
 |  |  |     <div nz-form-item> | 
 |  |  |         <div nz-form-control [nzValidateStatus]="password"> | 
 |  |  |             <nz-input formControlName="password" [nzPlaceHolder]="'888888'" [nzType]="'password'" [nzSize]="'large'"> | 
 |  |  |                 <ng-template #prefix> | 
 |  |  |                     <i class="anticon anticon-lock"></i> | 
 |  |  |                 </ng-template> | 
 |  |  |             </nz-input> | 
 |  |  |             <div nz-form-explain *ngIf="(password.dirty || password.touched) && password.errors?.required">请输入密码!</div> | 
 |  |  |         </div> | 
 |  |  |     </div> | 
 |  |  |     <div nz-form-item nz-row> | 
 |  |  |         <div nz-col [nzSpan]="12"> | 
 |  |  |             <label nz-checkbox formControlName="remember"> | 
 |  |  |                 <span>自动登录</span> | 
 |  |  |             </label> | 
 |  |  |         </div> | 
 |  |  |         <div nz-col [nzSpan]="12" class="text-right"> | 
 |  |  |             <a class="forgot" (click)="msg.error('请找欧阳锋')">忘记密码?</a> | 
 |  |  |         </div> | 
 |  |  |     </div> | 
 |  |  |     <div nz-form-item> | 
 |  |  |         <button nz-button [nzType]="'primary'" [nzLoading]="loading" [nzSize]="'large'" class="ant-btn__block"> | 
 |  |  |             <span>登录</span> | 
 |  |  |         </button> | 
 |  |  |     </div> | 
 |  |  | </form> | 
 |  |  | <div class="other"> | 
 |  |  |     其他登录方式 | 
 |  |  |     <nz-tooltip [nzTitle]="'in fact Auth0 via window'"> | 
 |  |  |         <span nz-tooltip class="icon-alipay" (click)="open('auth0', 'window')"></span> | 
 |  |  |     </nz-tooltip> | 
 |  |  |     <nz-tooltip [nzTitle]="'in fact Github via redirect'"> | 
 |  |  |         <span nz-tooltip class="icon-taobao" (click)="open('github')"></span> | 
 |  |  |     </nz-tooltip> | 
 |  |  |     <nz-tooltip [nzTitle]="'真的是微博'"> | 
 |  |  |         <span nz-tooltip class="icon-weibo" (click)="open('weibo', 'window')"></span> | 
 |  |  |     </nz-tooltip> | 
 |  |  |     <a class="register" routerLink="/passport/register">注册账户</a> | 
 |  |  | </div> | 
 
| New file | 
 |  |  | 
 |  |  | @import '~@delon/theme/styles/antd/themes/default.less'; | 
 |  |  |  | 
 |  |  | :host { | 
 |  |  |     display: block; | 
 |  |  |     width: 368px; | 
 |  |  |     margin: 0 auto; | 
 |  |  |  | 
 |  |  |     ::ng-deep { | 
 |  |  |         .tabs { | 
 |  |  |             padding: 0 2px; | 
 |  |  |             margin: 0 -2px; | 
 |  |  |             .ant-tabs-tab { | 
 |  |  |                 font-size: 16px; | 
 |  |  |                 line-height: 24px; | 
 |  |  |             } | 
 |  |  |             .ant-input-affix-wrapper .ant-input:not(:first-child) { | 
 |  |  |                 padding-left: 34px; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .ant-tabs .ant-tabs-bar { | 
 |  |  |             border-bottom: 0; | 
 |  |  |             margin-bottom: 24px; | 
 |  |  |             text-align: center; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .ant-form-item { | 
 |  |  |             margin-bottom: 24px; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .icon-alipay, .icon-taobao, .icon-weibo { | 
 |  |  |             display: inline-block; | 
 |  |  |             width: 24px; | 
 |  |  |             height: 24px; | 
 |  |  |             background: url('https://gw.alipayobjects.com/zos/rmsportal/itDzjUnkelhQNsycranf.svg'); | 
 |  |  |             margin-left: 16px; | 
 |  |  |             vertical-align: middle; | 
 |  |  |             cursor: pointer; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .icon-alipay { | 
 |  |  |             background-position: -24px 0; | 
 |  |  |  | 
 |  |  |             &:hover { | 
 |  |  |                 background-position: 0 0; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .icon-taobao { | 
 |  |  |             background-position: -24px -24px; | 
 |  |  |  | 
 |  |  |             &:hover { | 
 |  |  |                 background-position: 0 -24px; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .icon-weibo { | 
 |  |  |             background-position: -24px -48px; | 
 |  |  |  | 
 |  |  |             &:hover { | 
 |  |  |                 background-position: 0 -48px; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         .other { | 
 |  |  |             text-align: left; | 
 |  |  |             margin-top: 24px; | 
 |  |  |             line-height: 22px; | 
 |  |  |  | 
 |  |  |             .register { | 
 |  |  |             float: right; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | import { SettingsService } from '@delon/theme'; | 
 |  |  | import { Component, OnDestroy, Inject } from '@angular/core'; | 
 |  |  | import { Router } from '@angular/router'; | 
 |  |  | import { FormGroup, FormBuilder, Validators } from '@angular/forms'; | 
 |  |  | import { NzMessageService } from 'ng-zorro-antd'; | 
 |  |  | import { SocialService, SocialOpenType, ITokenService, DA_SERVICE_TOKEN } from '@delon/auth'; | 
 |  |  | import { environment } from '@env/environment'; | 
 |  |  |  | 
 |  |  | @Component({ | 
 |  |  |     selector: 'passport-login', | 
 |  |  |     templateUrl: './login.component.html', | 
 |  |  |     styleUrls: [ './login.component.less' ], | 
 |  |  |     providers: [ SocialService ] | 
 |  |  | }) | 
 |  |  | export class UserLoginComponent implements OnDestroy { | 
 |  |  |  | 
 |  |  |     form: FormGroup; | 
 |  |  |     error = ''; | 
 |  |  |     type = 0; | 
 |  |  |     loading = false; | 
 |  |  |  | 
 |  |  |     constructor( | 
 |  |  |         fb: FormBuilder, | 
 |  |  |         private router: Router, | 
 |  |  |         public msg: NzMessageService, | 
 |  |  |         private settingsService: SettingsService, | 
 |  |  |         private socialService: SocialService, | 
 |  |  |         @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) { | 
 |  |  |         this.form = fb.group({ | 
 |  |  |             userName: [null, [Validators.required, Validators.minLength(5)]], | 
 |  |  |             password: [null, Validators.required], | 
 |  |  |             mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]], | 
 |  |  |             captcha: [null, [Validators.required]], | 
 |  |  |             remember: [true] | 
 |  |  |         }); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     // region: fields | 
 |  |  |  | 
 |  |  |     get userName() { return this.form.controls.userName; } | 
 |  |  |     get password() { return this.form.controls.password; } | 
 |  |  |     get mobile() { return this.form.controls.mobile; } | 
 |  |  |     get captcha() { return this.form.controls.captcha; } | 
 |  |  |  | 
 |  |  |     // endregion | 
 |  |  |  | 
 |  |  |     switch(ret: any) { | 
 |  |  |         this.type = ret.index; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     // region: get captcha | 
 |  |  |  | 
 |  |  |     count = 0; | 
 |  |  |     interval$: any; | 
 |  |  |  | 
 |  |  |     getCaptcha() { | 
 |  |  |         this.count = 59; | 
 |  |  |         this.interval$ = setInterval(() => { | 
 |  |  |             this.count -= 1; | 
 |  |  |             if (this.count <= 0) | 
 |  |  |                 clearInterval(this.interval$); | 
 |  |  |         }, 1000); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     // endregion | 
 |  |  |  | 
 |  |  |     submit() { | 
 |  |  |         this.error = ''; | 
 |  |  |         if (this.type === 0) { | 
 |  |  |             this.userName.markAsDirty(); | 
 |  |  |             this.password.markAsDirty(); | 
 |  |  |             if (this.userName.invalid || this.password.invalid) return; | 
 |  |  |         } else { | 
 |  |  |             this.mobile.markAsDirty(); | 
 |  |  |             this.captcha.markAsDirty(); | 
 |  |  |             if (this.mobile.invalid || this.captcha.invalid) return; | 
 |  |  |         } | 
 |  |  |         // mock http | 
 |  |  |         this.loading = true; | 
 |  |  |         setTimeout(() => { | 
 |  |  |             this.loading = false; | 
 |  |  |             if (this.type === 0) { | 
 |  |  |                 if (this.userName.value !== 'admin' || this.password.value !== '123456') { | 
 |  |  |                     this.error = `账户或密码错误`; | 
 |  |  |                     return; | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             this.tokenService.set({ | 
 |  |  |                 token: '123456789', | 
 |  |  |                 name: this.userName.value, | 
 |  |  |                 email: `cipchk@qq.com`, | 
 |  |  |                 id: 10000, | 
 |  |  |                 time: +new Date | 
 |  |  |             }); | 
 |  |  |             this.router.navigate(['/']); | 
 |  |  |         }, 1000); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     // region: social | 
 |  |  |  | 
 |  |  |     open(type: string, openType: SocialOpenType = 'href') { | 
 |  |  |         let url = ``; | 
 |  |  |         let callback = ``; | 
 |  |  |         if (environment.production) | 
 |  |  |             callback = 'https://cipchk.github.io/ng-alain/callback/' + type; | 
 |  |  |         else | 
 |  |  |             callback = 'http://localhost:4200/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$); | 
 |  |  |     } | 
 |  |  | } | 
 
 |  |  | 
 |  |  | import { DashboardAnalysisComponent } from './dashboard/analysis/analysis.component'; | 
 |  |  | import { DashboardMonitorComponent } from './dashboard/monitor/monitor.component'; | 
 |  |  | import { DashboardWorkplaceComponent } from './dashboard/workplace/workplace.component'; | 
 |  |  | import { UserLoginComponent } from 'app/routes/passport/login/login.component'; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | const routes: Routes = [ | 
 |  |  | 
 |  |  |             { path: 'sensors', loadChildren: './sensors/sensors.module#SensorsModule' }, | 
 |  |  |             { path: 'systems', loadChildren: './systems/systems.module#SystemsModule' }, | 
 |  |  |         ] | 
 |  |  |     },    // passport | 
 |  |  |     { | 
 |  |  |         path: 'passport', | 
 |  |  |         component: LayoutPassportComponent, | 
 |  |  |         children: [ | 
 |  |  |             { path: 'login', component: UserLoginComponent } | 
 |  |  |         ] | 
 |  |  |     }, | 
 |  |  |     { path: '**', redirectTo: 'dashboard' } | 
 |  |  | ]; | 
 
 |  |  | 
 |  |  | import { UserLoginComponent } from './passport/login/login.component'; | 
 |  |  | import { DateService } from '@business/services/util/date.service'; | 
 |  |  | import { _HttpClient } from '@delon/theme'; | 
 |  |  | import { NgModule } from '@angular/core'; | 
 |  |  | 
 |  |  |         DashboardV1Component, | 
 |  |  |         DashboardAnalysisComponent, | 
 |  |  |         DashboardMonitorComponent, | 
 |  |  |         DashboardWorkplaceComponent | 
 |  |  |         DashboardWorkplaceComponent, | 
 |  |  |         UserLoginComponent | 
 |  |  |     ], | 
 |  |  |     providers: [ | 
 |  |  |         _HttpClient, |