[Angular] 閒置登出作法





app.componemt.ts

偵測事件
  // 如自動登出功能有bug 則停用以下--------
  @HostListener('window:keyup', [])
  @HostListener('window:click', [])
  @HostListener('window:wheel', [])
  @HostListener('window:mousemove', [])
  resetTimer() {
    this.authService.notifyUserAction();
  }


authService

export class AuthService {
  isLoggedIn = false;

  // ! 閒置登出時間請更改這參數的數字
  endtimeSet = 30;
  // 這邊讓單位變成分鐘秒
  endTime = this.endtimeSet * 60;

  // store the URL so we can redirect after logging in
  redirectUrl: string;

  constructor(private router: Router) {}

  // 偵測動作後重置閒置登出時間功能
  userActionOccuredSubject: Subject<void> = new Subject();
  get userActionOccured(): Observable<void> {
    return this.userActionOccuredSubject.asObservable();
  }

  // 偵測動作後重置閒置登出時間功能
  notifyUserAction() {
    this.userActionOccuredSubject.next();
    this.setTime();
  }

  login(): Observable<boolean> {
    return of(true).pipe(
      delay(1000),
      tap(val => (this.isLoggedIn = true)),
    );
  }

  logout(): void {
    this.isLoggedIn = false;

    console.log('登出');

    this.router.navigate(['login']);
  }

  // 把時間寫進去localStorage
  setTime() {
    localStorage.setItem(
      'expiredDate',
      addMinutes(new Date(), 1, this.endTime).getTime().toString(),
    );
  }
}

function addMinutes(date, minutes, endTime) {
  return new Date(date.getTime() + minutes * 1000 * endTime);
}



在要實作偵測閒置登出的html 

<app-inactivity-timer></app-inactivity-timer>



inactivity timer 元件

export class InactivityTimerComponent implements OnInit {
  notify$ = new Subject();

  constructor(
    private authService: AuthService,
    private zone: NgZone,
    public dialog: MatDialog,
  ) {
    this.authService.setTime();
    this.zone.runOutsideAngular(() => {
      this.timeCountDown();
    });
  }

  ngOnInit() {
    this.notify$.subscribe(() => {
      const idleLogoutRef = this.dialog.open(AlertDialogComponent, {
        width: '',
        disableClose: true,
        data: {
          fieldTypeName: 'inActiveLogoutAlert',
          alertTitle: '提醒',
          alertContent: '您好,您已閒置30分鐘,並將於15秒後登出。',
        },
      });

      // 如果超過時間沒回應就登出
      idleLogoutRef.afterOpened().subscribe(_ => {
        setTimeout(() => {
          this.dialog.closeAll();
          // idleLogoutRef.close();
          this.authService.logout();
        }, 15000);
      });

      // 根據使用者選擇繼續編輯還是登出
      idleLogoutRef.afterClosed().subscribe(result => {
        if (result === 'keep'{
          this.authService.setTime();
          this.timeCountDown();
        } else if (result === 'logout'{
          this.authService.logout();
        }
      });
    });
  }

  ngOnDestroy() {
    this.notify$.next();
    this.notify$.complete();
  }

  timeCountDown() {
    const i = setInterval(() => {
      const expiredDate = +localStorage.getItem('expiredDate');
      // console.log(Math.floor(new Date().getTime() - expiredDate) / 1000);

      if (new Date().getTime() - expiredDate > 0{
        this.zone.run(() => {
          this.notify$.next();
        });
        clearInterval(i);
      }
    }, 1000);
  }
}




alertDialog 提醒視窗

<!-- 閒置登出提醒 -->
<div class="" *ngIf="data.fieldTypeName === 'inActiveLogoutAlert'">
  <div class="" fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="16px">
    <mat-icon color="warn"> warning</mat-icon>
    <h3>
      {{ data.alertTitle }}
    </h3>
  </div>
  <mat-dialog-content
    ><b>{{ data.alertContent }}</b></mat-dialog-content
  >
  <div mat-dialog-actions fxLayoutAlign="center center">
    <button mat-flat-button color="accent" (click)="onIdleSelect('logout')">
      登出
    </button>
    <button mat-flat-button color="accent" (click)="onIdleSelect('keep')">
      返回繼續
    </button>
  </div>
</div>



-----------------------------------------------






但是這做法會導致build時出現錯誤

ERROR in (1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.

所以要用這個做法解決


------------------------------------------



AngularJS 解法

































留言

這個網誌中的熱門文章

[JavaScript] 將array object 根據值重新 js format的作法