Browse Source

feat:登录过期后,停止AI输出; 隐藏退出按钮

zhangwl 1 month ago
parent
commit
d81544c6c2
3 changed files with 37 additions and 28 deletions
  1. 1 1
      chat-ai-ui-main/.env
  2. 9 9
      chat-ai-ui-main/src/components/Header.vue
  3. 27 18
      chat-ai-ui-main/src/stores/chat.ts

+ 1 - 1
chat-ai-ui-main/.env

@@ -1,2 +1,2 @@
-#VITE_API_URL=http://localhost:8000
+#VITE_API_URL=http://localhost:8000/main
 VITE_API_URL=https://aisearch.zhongsou.com/main

+ 9 - 9
chat-ai-ui-main/src/components/Header.vue

@@ -97,15 +97,15 @@ const logout = async () => {
       </span>
 
       <!-- 退出按钮 -->
-      <button
-        @click="logout"
-        class="flex items-center space-x-1 text-gray-400 hover:text-red-400 transition-colors duration-200 px-3 py-1 rounded hover:bg-gray-700"
-      >
-        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
-        </svg>
-        <span>退出</span>
-      </button>
+<!--      <button-->
+<!--        @click="logout"-->
+<!--        class="flex items-center space-x-1 text-gray-400 hover:text-red-400 transition-colors duration-200 px-3 py-1 rounded hover:bg-gray-700"-->
+<!--      >-->
+<!--        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">-->
+<!--          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>-->
+<!--        </svg>-->
+<!--        <span>退出</span>-->
+<!--      </button>-->
     </div>
   </div>
 </template>

+ 27 - 18
chat-ai-ui-main/src/stores/chat.ts

@@ -2,8 +2,7 @@ import { defineStore } from 'pinia';
 import { ref } from 'vue';
 import axios from 'axios';
 import { useUserStore } from './user';
-
-let refreshTokenPromise: Promise<any> | null = null;
+import { refreshAuthToken } from '../utils/auth';
 
 axios.interceptors.response.use(
   response => response,
@@ -13,24 +12,13 @@ axios.interceptors.response.use(
     if (error.response?.status === 401 && !originalRequest._retry) {
       originalRequest._retry = true;
 
-      if (!refreshTokenPromise) {
-        const userStore = useUserStore();
-        refreshTokenPromise = axios.post(
-          `${import.meta.env.VITE_API_URL}/users/refresh`,
-          { refresh_token: userStore.refreshToken }
-        ).finally(() => { refreshTokenPromise = null; });
-      }
-
       try {
-        const { data } = await refreshTokenPromise;
-        const userStore = useUserStore();
-        userStore.setUser({ userId: data.access_token, name: userStore.name!, refreshToken: data.refresh_token });
-        originalRequest.headers.Authorization = `Bearer ${data.access_token}`;
+        const newToken = await refreshAuthToken();
+        originalRequest.headers.Authorization = `Bearer ${newToken}`;
         return axios(originalRequest);
       } catch {
         const userStore = useUserStore();
         userStore.logout();
-        window.location.href = '/';
         return Promise.reject(error);
       }
     }
@@ -185,14 +173,35 @@ export const useChatStore = defineStore('chat', () => {
     });
 
     try {
-      const response = await fetch(`${import.meta.env.VITE_API_URL}/chat/chat`, {
+      const fetchOptions: RequestInit = {
         method: 'POST',
         headers: {
           'Content-Type': 'application/json',
           'Authorization': `Bearer ${userStore.userId}`,
-        },
+        } as Record<string, string>,
         body: JSON.stringify({ messages: historySnapshot, stream: true, sessionId: sessionId.value }),
-      });
+      };
+
+      let response = await fetch(`${import.meta.env.VITE_API_URL}/chat/chat`, fetchOptions);
+
+      // 401 处理:刷新 token 后重试一次
+      if (response.status === 401) {
+        try {
+          const newToken = await refreshAuthToken();
+          (fetchOptions.headers as Record<string, string>)['Authorization'] = `Bearer ${newToken}`;
+          response = await fetch(`${import.meta.env.VITE_API_URL}/chat/chat`, fetchOptions);
+        } catch {
+          userStore.logout();
+          messages.value[aiMessageIndex] = {
+            role: 'assistant',
+            content: '登录已过期,请重新登录',
+            displayContent: '登录已过期,请重新登录',
+            ...blankMeta(),
+          };
+          isLoading.value = false;
+          return;
+        }
+      }
 
       if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
       if (!response.body) throw new Error('ReadableStream not supported');