src/app/business/services/http/login.service.ts | ●●●●● patch | view | raw | blame | history | |
src/app/core/net/default.interceptor.ts | ●●●●● patch | view | raw | blame | history | |
src/app/routes/passport/login/login.component.html | ●●●●● patch | view | raw | blame | history | |
src/app/routes/passport/login/login.component.ts | ●●●●● patch | view | raw | blame | history | |
src/app/routes/reports/query/query.component.ts | ●●●●● patch | view | raw | blame | history |
src/app/business/services/http/login.service.ts
@@ -23,12 +23,14 @@ // 每2秒检查一次刷新token的时间点 setInterval( () => { if (this.needFreshFromLocal && this.isReachRefreshTime()) { if (this.canRefreshToken() && this.needFreshFromLocal && this.isReachRefreshTime()) { const _refreshToken = this._refreshToken; // 记录刷新时间 this.setRefreshTime(); // 置空needfreshtoken localStorage.setItem('needRefreshToken', 'false'); const _refreshToken = this._refreshToken; localStorage.setItem('needRefreshToken', 'false'); if (!!_refreshToken) { this.http.get(this.urls.refreshToken, {headers: {'X-Refrsh-Token': 'Bearer ' + _refreshToken}} ) .subscribe( @@ -75,7 +77,7 @@ return localStorage.needRefreshToken === 'true'; } private setRefreshTime() { localStorage.setItem('refreshTime', new Date().getTime().toString()); localStorage.setItem('refreshTime', new Date().getTime().toString()); } private setNeedRefreshToken() { localStorage.setItem('needRefreshToken', 'true'); @@ -84,11 +86,27 @@ const expiredTime = Number(localStorage.expiredTime); return !!this.refreshTime && !!expiredTime && this.refreshTime + (expiredTime / 2) * 60000 < new Date().getTime(); } get refreshTime(): number { private get refreshTime(): number { return Number(localStorage.refreshTime); } public clearRefreshToken() { localStorage.expiredTime = null; localStorage.refreshTime = null; localStorage.refreshToken = null; this.authorization = null; localStorage.removeItem('expiredTime'); localStorage.removeItem('refreshTime'); localStorage.removeItem('refreshToken'); } private canRefreshToken() { return !!localStorage.getItem('expiredTime') && !!localStorage.getItem('refreshTime') && !!localStorage.getItem('refreshToken'); } public refreshToken () { // 设置需要刷新token this.setNeedRefreshToken(); if (this.canRefreshToken()) { // 设置需要刷新token this.setNeedRefreshToken(); } } } src/app/core/net/default.interceptor.ts
@@ -22,25 +22,37 @@ @Injectable() export class DefaultInterceptor implements HttpInterceptor { private unLoginHandle: Subject<HttpErrorResponse> = new Subject<HttpErrorResponse>(); constructor(private injector: Injector) { this.unLoginHandle.debounceTime(100).subscribe(event => { if (!!event.error) { let errorMsg = ''; const erroCode = Number.parseInt(event.error['errorCode']); switch (erroCode) { case 10: errorMsg = '未登录,请登录'; break; case 11: errorMsg = '登录过期,请重新登录'; break; case 12: errorMsg = '账号过期,请联系供应商'; break; default: errorMsg = '登录过期,请重新登录'; break; } this.model.info({ title: errorMsg, onOk: () => this.goTo('/passport/login') }); } let isExpireModelShow = false; this.unLoginHandle.debounceTime(3000).subscribe( (event: HttpErrorResponse) => { const canExpireModelShow = !isExpireModelShow; isExpireModelShow = true; if (canExpireModelShow && !!event.error) { let errorMsg = ''; const erroCode = !!event.error['errorCode'] ? Number.parseInt(event.error['errorCode']) : 0; switch (erroCode) { case 10: errorMsg = '未登录,请登录'; break; case 11: errorMsg = '登录过期,请重新登录'; break; case 12: errorMsg = '账号过期,请联系供应商'; break; case 0: errorMsg = '服务器处于离线状态'; break; default: errorMsg = '登录过期,请重新登录'; break; } // 清空refresh信息,不再刷新 this.loginService.clearRefreshToken(); this.model.info({ title: errorMsg, onOk: () => { isExpireModelShow = false; this.goTo('/passport/login'); } }); } }); } get loginService(): LoginService { return this.injector.get<LoginService>(LoginService); } get msg(): NzMessageService { return this.injector.get(NzMessageService); } @@ -55,7 +67,8 @@ // 可能会因为 `throw` 导出无法执行 `_HttpClient` 的 `end()` 操作 // this.injector.get(_HttpClient).end(); // 业务处理:一些通用操作 switch (event.status) { const status = !!event.status ? event.status : 401; switch (status) { case 200: // 业务层级错误处理,以下假如响应体的 `status` 若不为 `0` 表示业务级异常 // 并显示 `error_message` 内容 @@ -70,7 +83,7 @@ break; case 401: // 未登录状态码 // this.goTo('/passport/login'); if (location.hash && !location.hash.endsWith('login')) { if (!this.isLoginPage) { this.unLoginHandle.next(<HttpErrorResponse>event); } break; @@ -87,13 +100,11 @@ return of(event); } } private get isLoginPage(): boolean { return !!location && !!location.hash && location.hash.endsWith('login'); } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> { if (!req.headers.get('X-Refrsh-Token')) { const loginService = <LoginService>this.injector.get(LoginService); loginService.refreshToken(); } Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> { // 统一加上服务端前缀 let url = req.url; if (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('assets')) { @@ -107,12 +118,22 @@ return next.handle(newReq).pipe( mergeMap((event: any) => { // 允许统一对请求错误处理,这是因为一个请求若是业务上错误的情况下其HTTP请求的状态是200的情况下需要 if (event instanceof HttpResponse && event.status === 200) return this.handleData(event); if (event instanceof HttpResponse && event.status === 200) { // 刷新token的请求,不设置刷新 if (!this.isLoginPage && !!newReq.headers && !newReq.headers.get('X-Refrsh-Token') && !url.startsWith('assets')) { this.loginService.refreshToken(); } return this.handleData(event); } // 若一切都正常,则后续操作 return of(event); }), catchError((err: HttpErrorResponse) => this.handleData(err)) catchError((err: HttpErrorResponse) => { return this.handleData(err); }) ); } } src/app/routes/passport/login/login.component.html
@@ -23,6 +23,7 @@ <div nz-form-explain *ngIf="(password.dirty || password.touched) && password.errors?.required">请输入密码!</div> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.password_incorrect">输入用户名或者密码错误!</p> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.account_expired">账号已经过期,请联系供应商!</p> <p nz-form-explain [ngStyle]="{'color': 'red'}" *ngIf="validateError.server_offline">服务器处于离线状态!</p> </div> </div> <div nz-form-item nz-row> src/app/routes/passport/login/login.component.ts
@@ -11,6 +11,7 @@ import { ReuseTabService } from '@delon/abc'; import { environment } from '@env/environment'; import { CookieService } from 'angular2-cookie/services/cookies.service'; import { debounce } from 'rxjs/operators'; @Component({ selector: 'passport-login', templateUrl: './login.component.html', @@ -85,8 +86,11 @@ if (this.mobile.invalid || this.captcha.invalid) return; } this.loading = true; this.loginService.validate(this.userName.value, this.password.value).subscribe( this.loginService.validate(this.userName.value, this.password.value).subscribe( (res: Authorization) => { this.validateError['password_incorrect'] = false; this.validateError['account_expired'] = false; this.validateError['server_offline'] = false; if (res.token != null) { // 清空路由复用信息 this.reuseTabService.clear(); @@ -99,7 +103,7 @@ this.router.navigate(['/']); } }, (err: HttpErrorResponse) => { (err: HttpErrorResponse) => { if (!!err) { const errMsg = err.error; console.log(errMsg); @@ -109,6 +113,9 @@ } else if (errMsg.status === 401 && errMsg.errorCode === 12) { this.validateError['account_expired'] = true; this.loading = false; } else if (!errMsg.status && !errMsg.errorCode) { this.validateError['server_offline'] = true; this.loading = false; } } } src/app/routes/reports/query/query.component.ts
@@ -8,7 +8,6 @@ import * as moment from 'moment'; import { ExampleService } from '@business/services/util/example.service'; import { DeviceService } from '@business/services/http/device.service'; import { environment } from '@env/environment'; import { CascaderOption } from 'ng-zorro-antd/src/cascader/nz-cascader.component'; import { AreacodeService } from '@business/services/http/areacode.service'; import { MonitorPointService } from '@business/services/http/monitor-point.service'; @@ -90,7 +89,7 @@ this.isChartCollapse = !this.isChartCollapse; } public deviceOptions: Device[] = []; public dataCondition: DataCondition = {areaRangeId: 320583, areaRange: AreaRange.AREA, deviceDimension:DeviceDimension.NONE}; public dataCondition: DataCondition = {areaRangeId: 320583, areaRange: AreaRange.AREA, deviceDimension: DeviceDimension.NONE}; public dimensionOptions: MonitorPoint[] = []; @@ -100,18 +99,18 @@ set actualYear(year) { this.actualTime.setFullYear(Number(year)); } dimensionsChange(text?: string){ switch(this.dimensionItem.value){ dimensionsChange(text?: string) { switch (this.dimensionItem.value) { case DeviceDimension.MONITORPOINT: this.monitorPointsChange(text);break; this.monitorPointsChange(text); break; case DeviceDimension.PROFESSION: this.professionsChange(text);break; this.professionsChange(text); break; } } professionsChange(text?: string){ this.http.get<ResultBean<any[]>>(environment.SERVER_BASH_URL+"profession/getall").subscribe( professionsChange(text?: string) { this.http.get<ResultBean<any[]>>('profession/getall').subscribe( result => { if(!!result.code){ if (!!result.code) { this.dimensionOptions = result.data; } } @@ -148,7 +147,7 @@ if (!!this.deviceDimension) { const example = new ExampleService(); const deviceDimensionProperty = this.dimensionItem.value === DeviceDimension.MONITORPOINT ?'monitorPointId':'professionId'; this.dimensionItem.value === DeviceDimension.MONITORPOINT ? 'monitorPointId' : 'professionId'; if (!!text) { example.or().andEqualTo({ name: deviceDimensionProperty, value: this.deviceDimension.id }) .andLike({name: 'text', value: text}); @@ -237,7 +236,7 @@ ); this.actualYearOptions = this.newArray(this.actualYear - 9, 10).map(item => Number(item)).reverse(); // 省市区 初始值 this.http.get(environment.SERVER_BASH_URL + 'organization/get-my-org').subscribe( this.http.get('organization/get-my-org').subscribe( (res: ResultBean<Organization>) => { if (res.code === ResultCode.SUCCESS) { const org = res.data; @@ -278,10 +277,10 @@ this.dimensionItem = this.dimensions[0]; // this.dimensionsChange(); } public get sensorsLength():number { return this.sensorOptions.length>0?this.sensorOptions[0].children.length:0; public get sensorsLength(): number { return this.sensorOptions.length > 0 ? this.sensorOptions[0].children.length : 0; } public get sensorsSelect():number{ public get sensorsSelect(): number { return Object.keys(this._sensors).length; } public areaLazyLoad(event: { option: CascaderOption, index: number, resolve: (children: CascaderOption[]) => void, reject: () => void }) { @@ -320,26 +319,26 @@ if ( isChanged ) { this._areas = areas; this.deviceDimension = null; if(this.dimensionItem.value === DeviceDimension.MONITORPOINT){ if (this.dimensionItem.value === DeviceDimension.MONITORPOINT) { this.dimensionsChange(); } } } // 第二步 设置 监控站点, 值变 改变设备选项,值为null 置空设备选项和设备值 public dimensionItem:{label: string,value: DeviceDimension}; public dimensions:{label: string,value: DeviceDimension}[] = [ {label:"监控站点",value:DeviceDimension.MONITORPOINT}, {label:"监控行业",value:DeviceDimension.PROFESSION} public dimensionItem: {label: string, value: DeviceDimension}; public dimensions: {label: string, value: DeviceDimension}[] = [ {label: '监控站点', value: DeviceDimension.MONITORPOINT}, {label: '监控行业', value: DeviceDimension.PROFESSION} ]; public get otherDimensions():{label: string,value: DeviceDimension}[] { public get otherDimensions(): {label: string, value: DeviceDimension}[] { return this.dimensions.filter( item => { return item.value != this.dimensionItem.value; return item.value !== this.dimensionItem.value; } ); } public selectDimension(option:{label: string,value: DeviceDimension}){ public selectDimension(option: {label: string, value: DeviceDimension}) { this.dimensionItem = option; this.dimensionsChange(); this._deviceDimension = null; @@ -347,8 +346,8 @@ this.device = null; this.deviceOptions = null; } public _deviceDimension: {id: number,name: string}; get deviceDimension(): {id: number,name: string} { public _deviceDimension: {id: number, name: string}; get deviceDimension(): {id: number, name: string} { return this._deviceDimension; } set deviceDimension(value) { @@ -495,7 +494,7 @@ const dimValue: number = !!this._deviceDimension ? this._deviceDimension.id : null; const devValue: number = !!this._device ? this._device.id : null; const areasData = [ devValue, dimValue, Number(this._areas.slice(-1).pop().value)]; if(!!this.deviceDimension){ if (!!this.deviceDimension) { this.dataCondition.dimensionValue = this._deviceDimension.id; this.dataCondition.deviceDimension = this.dimensionItem.value; } @@ -507,10 +506,10 @@ case 0: this.dataCondition.areaRange = AreaRange.DEVICE; break; case 1: // 维度为监控点 if(this.dimensionItem.value === DeviceDimension.MONITORPOINT){ if (this.dimensionItem.value === DeviceDimension.MONITORPOINT) { this.dataCondition.areaRange = AreaRange.MONITORPOINT; // 维度为行业 }else{ } else { // 重新标定区域范围 this.switchAreas(); // 重新设置区域值 @@ -566,7 +565,7 @@ // 清空数据 this.grid.data = []; console.log(lineChartCriteria); this.http.post(environment.SERVER_BASH_URL + '/report/line-chart', lineChartCriteria).subscribe( this.http.post('/report/line-chart', lineChartCriteria).subscribe( (res: ResultBean<{[key: string]: Array<Array<number>>}>) => { if (res.code === 1) { const data = res.data; @@ -609,7 +608,7 @@ } ); } private switchAreas(): void{ private switchAreas(): void { switch (this._areas.length ) { case 1: this.dataCondition.areaRange = AreaRange.PROVINCE; break; case 2: this.dataCondition.areaRange = AreaRange.CITY; break; @@ -682,7 +681,7 @@ public _chartTitleTemp = ''; public _tableTitleTemp = ''; public reloadChartTitle(): void { const names = ['辖区', '地区', '维度','时间','项目']; const names = ['辖区', '地区', '维度', '时间', '项目']; switch ( this.dataCondition.areaRange ) { case AreaRange.MONITORPOINT : names[0] = '监控站点'; @@ -696,17 +695,17 @@ break; } // 维度命名 if(!!this._deviceDimension){ switch(this.dataCondition.deviceDimension){ if (!!this._deviceDimension) { switch (this.dataCondition.deviceDimension) { case DeviceDimension.PROFESSION : names[2] ='['+this._deviceDimension.name+']'; names[2] = '[' + this._deviceDimension.name + ']'; break; default : names[2] =''; names[2] = ''; break; } }else{ names[2] =''; } else { names[2] = ''; } names[3] = moment(this.actualTime).format(this._timeType.dateFormat);