fix: 退出登录补防抖加载

This commit is contained in:
2026-08-05 21:45:40 +08:00
parent 370d8e7769
commit 4e8aa15b71
2 changed files with 34 additions and 6 deletions
+21
View File
@@ -69,4 +69,25 @@ describe('MyHead.vue', () => {
expect(ElMessage.success).toHaveBeenCalledWith('已退出登录') expect(ElMessage.success).toHaveBeenCalledWith('已退出登录')
expect(router.currentRoute.value.path).toBe('/login') expect(router.currentRoute.value.path).toBe('/login')
}) })
it('prevents repeated logout while request is pending', async () => {
let resolveLogout!: (value: any) => void
vi.mocked(logout).mockImplementation(
() => new Promise((resolve) => { resolveLogout = resolve }),
)
localStorage.setItem('isLoggedIn', 'true')
const wrapper = await mountAt('/study')
const first = wrapper.vm.handleLogout()
const second = wrapper.vm.handleLogout()
await Promise.resolve()
expect(logout).toHaveBeenCalledTimes(1)
expect(wrapper.vm.loggingOut).toBe(true)
resolveLogout({ code: 200 })
await Promise.all([first, second])
expect(wrapper.vm.loggingOut).toBe(false)
})
}) })
+10 -3
View File
@@ -20,6 +20,7 @@
type="success" type="success"
plain plain
class="logout-btn" class="logout-btn"
:loading="loggingOut"
@click="handleLogout" @click="handleLogout"
> >
退出登录 退出登录
@@ -28,7 +29,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from "vue"; import { computed, ref } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import router from "@/router"; import router from "@/router";
@@ -38,20 +39,26 @@ const route = useRoute();
const isLoginRoute = computed(() => route.path === "/login"); const isLoginRoute = computed(() => route.path === "/login");
const showBackButton = computed(() => route.path !== "/login" && route.path !== "/welcome"); const showBackButton = computed(() => route.path !== "/login" && route.path !== "/welcome");
const pageTitle = computed(() => route.meta?.title as string | undefined); const pageTitle = computed(() => route.meta?.title as string | undefined);
const loggingOut = ref(false);
const handleLogout = async () => { const handleLogout = async () => {
if (loggingOut.value) return;
loggingOut.value = true;
try {
try { try {
await logout(); await logout();
} catch { } catch {
// 后端退出失败时,仍然清理前端登录态,避免用户被卡住。 // 后端退出失败时,仍然清理前端登录态,避免用户被卡住。
} finally { }
localStorage.removeItem("isLoggedIn"); localStorage.removeItem("isLoggedIn");
ElMessage.success("已退出登录"); ElMessage.success("已退出登录");
await router.push("/login"); await router.push("/login");
} finally {
loggingOut.value = false;
} }
}; };
defineExpose({ isLoginRoute, showBackButton, pageTitle, handleLogout }); defineExpose({ isLoginRoute, showBackButton, pageTitle, loggingOut, handleLogout });
</script> </script>
<style scoped> <style scoped>