Ver Fonte

fix: simplify login flow - URL params → localStorage → show login modal via data binding

gangvy há 5 meses atrás
pai
commit
5e88d7d306
3 ficheiros alterados com 39 adições e 34 exclusões
  1. 1 1
      src/app/app.html
  2. 36 30
      src/app/app.ts
  3. 2 3
      src/app/login-modal.component.ts

+ 1 - 1
src/app/app.html

@@ -1,5 +1,5 @@
 <!-- Login Modal -->
-<app-login-modal #loginModal (loginSuccess)="onLoginSuccess($event)"></app-login-modal>
+<app-login-modal [visible]="needLogin" (loginSuccess)="onLoginSuccess($event)"></app-login-modal>
 
 <!-- Header -->
 <div class="page-header">

+ 36 - 30
src/app/app.ts

@@ -1,4 +1,4 @@
-import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { LoginModalComponent } from './login-modal.component';
 
@@ -45,9 +45,8 @@ interface OrderData {
   templateUrl: './app.html',
   styleUrl: './app.scss'
 })
-export class App implements OnInit, AfterViewInit {
+export class App implements OnInit {
   @ViewChild('qrCanvas', { static: false }) qrCanvasRef!: ElementRef<HTMLCanvasElement>;
-  @ViewChild('loginModal') loginModalRef!: LoginModalComponent;
 
   // URL params
   authId = '';
@@ -99,44 +98,51 @@ export class App implements OnInit, AfterViewInit {
     this.apigId = params.get('apigid') || '';
     this.funId = params.get('fun_id') || DEFAULT_FUN_ID;
 
+    // 1. URL 已提供足够参数 → 直接加载
     if (this.authId || (this.userId && this.apigId)) {
-      // URL 已提供足够参数,直接加载
+      console.log('[AUTH] URL 参数充足,直接加载');
       this.loadApig();
+      return;
     }
-    // 其他情况在 ngAfterViewInit 中处理(等 ViewChild 就绪)
-  }
 
-  ngAfterViewInit(): void {
-    // 如果已经开始加载,不需要登录
-    if (this.authId || (this.userId && this.apigId)) return;
-
-    if (this.apigId && !this.userId) {
-      // 有 apigId 但没有 user → 尝试自动登录或显示登录弹窗
-      this.tryAutoLoginOrShowModal();
-    } else {
-      // 什么参数都没有(或只有 user 没有 apigId)→ 显示登录弹窗
-      this.needLogin = true;
-      this.loginModalRef?.show();
+    // 2. URL 没有 user → 检查 localStorage 缓存
+    const cachedUserId = localStorage.getItem('apig_user_id');
+    const cachedToken = localStorage.getItem('apig_session_token');
+    if (cachedUserId && cachedToken) {
+      console.log('[AUTH] 从 localStorage 恢复用户:', cachedUserId);
+      this.userId = cachedUserId;
+      this.loggedInUser = cachedUserId;
+      if (this.apigId) {
+        this.loadApig();
+        // 后台验证 token 是否还有效
+        this.validateCachedToken(cachedToken, cachedUserId);
+        return;
+      }
     }
+
+    // 3. 什么都没有 → 显示登录弹窗
+    console.log('[AUTH] 未检测到用户,显示登录弹窗');
+    this.needLogin = true;
   }
 
-  async tryAutoLoginOrShowModal(): Promise<void> {
-    // 检查是否已有 Parse 登录态
+  async validateCachedToken(token: string, userId: string): Promise<void> {
     try {
-      const existing = await this.loginModalRef?.checkExistingLogin();
-      if (existing?.userId) {
-        console.log('[AUTH] 已有登录用户:', existing.userId);
-        this.userId = existing.userId;
-        this.loggedInUser = existing.userId;
-        this.loadApig();
-        return;
+      const resp = await fetch(`${API_BASE}/parse/users/me`, {
+        headers: {
+          'X-Parse-Application-Id': APP_ID,
+          'X-Parse-Session-Token': token
+        }
+      });
+      const data = await resp.json();
+      if (!data.objectId) {
+        console.warn('[AUTH] 缓存 token 已失效,需要重新登录');
+        localStorage.removeItem('apig_user_id');
+        localStorage.removeItem('apig_session_token');
+        this.needLogin = true;
       }
     } catch (e) {
-      console.warn('[AUTH] 检查登录态失败:', e);
+      console.warn('[AUTH] 验证 token 失败:', e);
     }
-    // 没有登录态 → 显示登录弹窗
-    this.needLogin = true;
-    setTimeout(() => this.loginModalRef?.show(), 100);
   }
 
   onLoginSuccess(event: { userId: string; sessionToken: string }): void {

+ 2 - 3
src/app/login-modal.component.ts

@@ -1,4 +1,4 @@
-import { Component, Output, EventEmitter, signal } from '@angular/core';
+import { Component, Input, Output, EventEmitter, signal } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 
@@ -236,9 +236,8 @@ const APP_ID = 'ncloudmaster';
   `]
 })
 export class LoginModalComponent {
+  @Input() visible = false;
   @Output() loginSuccess = new EventEmitter<{ userId: string; sessionToken: string }>();
-
-  visible = false;
   phone = '';
   code = '';
   errorMsg = '';