Jelajahi Sumber

feat(login): 增强登录和组织切换功能- 添加登录和切换组织时的加载状态管理
- 实现登录成功后触发自定义事件以重新检查同步状态- 在首页增加同步配置的loading状态和完成状态管理-优化健康检查逻辑,确保同步完成后再进行路由跳转
- 增加对登录成功事件的监听,自动重新执行健康检查
- 完善错误处理和用户提示信息
- 清理组件卸载时的事件监听器避免内存泄漏

panqiuyao 1 bulan lalu
induk
melakukan
5c6c095e6d
2 mengubah file dengan 115 tambahan dan 39 penghapusan
  1. 56 35
      frontend/src/components/login/index.vue
  2. 59 4
      frontend/src/views/Home/index.vue

+ 56 - 35
frontend/src/components/login/index.vue

@@ -194,33 +194,42 @@ const loginRules = reactive({
 })
 
 const handleLogin = async () => {
-
-  const  res = await  useUserInfoStore.loginAction({
-    "site":1,
-    "username":loginForm.username,
-    "password":activeTab.value === '0' ? loginForm.password : loginForm.code,
-    "type": activeTab.value,
-    "device":"aigc-camera",
-    "platform":"aigc-camera"
-  })
-  switch(res.data.is_need_select_company){
-    case 40006:
-      showCompany()
-      break;
-    case 40007:
-      ElMessage.error('当前没有所属组织')
-      break;
-    default:
-      await  useUserInfoStore.getInfo()
-      // 登录成功后同步数据
-      await syncAfterLogin()
-      useUserInfoStore.updateLoginShow(false)
-      setTimeout(()=>{
-      //  window.location.reload()
-      },100)
+  loading.value = true;
+  
+  try {
+    const  res = await  useUserInfoStore.loginAction({
+      "site":1,
+      "username":loginForm.username,
+      "password":activeTab.value === '0' ? loginForm.password : loginForm.code,
+      "type": activeTab.value,
+      "device":"aigc-camera",
+      "platform":"aigc-camera"
+    })
+    switch(res.data.is_need_select_company){
+      case 40006:
+        showCompany()
         break;
+      case 40007:
+        ElMessage.error('当前没有所属组织')
+        break;
+      default:
+        await  useUserInfoStore.getInfo()
+        // 登录成功后同步数据
+        await syncAfterLogin()
+        useUserInfoStore.updateLoginShow(false)
+        // 触发首页重新检查同步状态
+        window.dispatchEvent(new CustomEvent('login-success'));
+        setTimeout(()=>{
+        //  window.location.reload()
+        },100)
+          break;
+    }
+  } catch (error) {
+    console.error('登录失败:', error);
+    ElMessage.error('登录失败,请重试');
+  } finally {
+    loading.value = false;
   }
-
 }
 const pageStatus = ref(1)
 const companyId = ref('')
@@ -250,16 +259,28 @@ async function  showCompany() {
 // 切换组织
 async function toggleCompany() {
   if (!companyId.value) return false
-  const res = await selectCompany({
-    id: companyId.value
-  })
-  await  useUserInfoStore.getInfo()
-  // 选择公司后也需要同步数据
-  await syncAfterLogin()
-  useUserInfoStore.updateLoginShow(false)
-  setTimeout(()=>{
-    // window.location.reload()
-  },100)
+  
+  loading.value = true;
+  
+  try {
+    const res = await selectCompany({
+      id: companyId.value
+    })
+    await  useUserInfoStore.getInfo()
+    // 选择公司后也需要同步数据
+    await syncAfterLogin()
+    useUserInfoStore.updateLoginShow(false)
+    // 触发首页重新检查同步状态
+    window.dispatchEvent(new CustomEvent('login-success'));
+    setTimeout(()=>{
+      // window.location.reload()
+    },100)
+  } catch (error) {
+    console.error('切换组织失败:', error);
+    ElMessage.error('切换组织失败,请重试');
+  } finally {
+    loading.value = false;
+  }
 }
 
 const sendVerificationCode = () => {

+ 59 - 4
frontend/src/views/Home/index.vue

@@ -3,7 +3,7 @@
 
     <template  #title><div @click="handleSettingClick" v-log="{ describe: { action: '点击首页标题' } }">首页</div></template>
   </headerBar>
-  <div class="home-container" v-loading="loading">
+  <div class="home-container" v-loading="loading || syncLoading" :element-loading-text="syncLoading ? '正在同步配置...' : '正在加载...'">
     <!-- 背景图片 -->
     <img src="@/assets/images/home/bg.png" alt="背景图片" class="background-image" />
 
@@ -25,7 +25,7 @@
 import headerBar from "@/components/header-bar/index.vue";
 import { useRouter } from "vue-router";
 import configInfo from '@/stores/modules/config';
-import { ref, onMounted } from 'vue';
+import { ref, onMounted, onUnmounted } from 'vue';
 import axios from 'axios';
 import client from "@/stores/modules/client";
 import icpList from '@/utils/ipc';
@@ -36,6 +36,8 @@ import tokenInfo from "@/stores/modules/token";
 
 const router = useRouter();
 const loading = ref(true);
+const syncLoading = ref(false); // 同步配置的loading状态
+const syncCompleted = ref(false); // 同步是否完成
 
 // 用户状态管理 - 在 onMounted 中初始化
 let configInfoStore: any;
@@ -56,26 +58,50 @@ function socketConnect(){
   socketStore.connectSocket();
 }
 
-const goCheck = () => {
+const goCheck = async () => {
   // 检查登录状态
   if (!tokenInfoStore.getToken) {
     useUserInfoStore.updateLoginShow(true);
     return;
   }
 
+  // 如果正在同步,显示提示
+  if (syncLoading.value) {
+    console.log('正在同步配置,请稍候...');
+    return;
+  }
+
+  // 如果未同步完成,等待同步
+  if (!syncCompleted.value) {
+    console.log('等待配置同步完成...');
+    return;
+  }
+
   configInfoStore.updateAppModel(1);
   router.push({
     name: 'PhotographyCheck'
   });
 };
 
-const goShot = () => {
+const goShot = async () => {
   // 检查登录状态
   if (!tokenInfoStore.getToken) {
     useUserInfoStore.updateLoginShow(true);
     return;
   }
 
+  // 如果正在同步,显示提示
+  if (syncLoading.value) {
+    console.log('正在同步配置,请稍候...');
+    return;
+  }
+
+  // 如果未同步完成,等待同步
+  if (!syncCompleted.value) {
+    console.log('等待配置同步完成...');
+    return;
+  }
+
   socketConnect();
   configInfoStore.updateAppModel(2);
   router.push({
@@ -97,15 +123,29 @@ const checkHealth = async () => {
         const token = tokenInfoStore.getToken;
         if (token && token.trim() !== '') {
           try {
+            syncLoading.value = true; // 开始同步
+            syncCompleted.value = false; // 重置同步状态
+            
             // 导入同步函数
             const { syncAfterLogin } = await import('@/apis/setting');
             await syncAfterLogin();
             console.log('健康检查后数据同步成功');
+            
+            syncCompleted.value = true; // 同步完成
           } catch (syncError) {
             console.error('健康检查后数据同步失败:', syncError);
+            syncCompleted.value = false; // 同步失败
             // 同步失败不影响主流程
+          } finally {
+            syncLoading.value = false; // 结束同步loading
           }
+        } else {
+          // 未登录状态,直接设置同步完成
+          syncCompleted.value = true;
         }
+      } else {
+        // 未登录状态,直接设置同步完成
+        syncCompleted.value = true;
       }
     }
   } catch (error) {
@@ -219,6 +259,13 @@ const checkForUpdates = async () => {
 
 
 
+// 监听登录成功事件
+const handleLoginSuccess = () => {
+  console.log('检测到登录成功,重新检查同步状态');
+  // 重新执行健康检查和同步
+  checkHealth();
+};
+
 // 在组件挂载时执行健康检查和版本检查
 onMounted(() => {
   // 初始化 store
@@ -226,12 +273,20 @@ onMounted(() => {
   useUserInfoStore = useUserInfo();
   tokenInfoStore = tokenInfo();
 
+  // 监听登录成功事件
+  window.addEventListener('login-success', handleLoginSuccess);
+
   checkHealth();
   // 延迟执行版本检查,避免影响健康检查
   setTimeout(() => {
     checkForUpdates();
   }, 1000);
 });
+
+// 组件卸载时清理事件监听器
+onUnmounted(() => {
+  window.removeEventListener('login-success', handleLoginSuccess);
+});
 </script>