From 8ecc3e265f734db1a0de5acb615661c479650399 Mon Sep 17 00:00:00 2001 From: bboysoul Date: Sun, 20 Sep 2026 08:20:12 +0800 Subject: [PATCH] feat: add current-device logout --- frontend/e2e/mobile-ui.spec.ts | 17 +++++++++++++++-- frontend/src/App.vue | 11 ++++++++++- frontend/src/MvpPanel.vue | 19 +++++++++++++++++-- frontend/src/style.css | 2 ++ frontend/src/style.test.ts | 14 ++++++++++++++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/frontend/e2e/mobile-ui.spec.ts b/frontend/e2e/mobile-ui.spec.ts index 11a6f7a..4c4c176 100644 --- a/frontend/e2e/mobile-ui.spec.ts +++ b/frontend/e2e/mobile-ui.spec.ts @@ -1,5 +1,5 @@ import type { Page } from '@playwright/test' -import { expect, test } from './fixtures' +import { allowExpectedError, expect, test } from './fixtures' function bottomTab(page: Page, name: string) { return page.getByRole('navigation', { name: '主要导航' }).getByRole('button', { name, exact: true }) @@ -202,8 +202,21 @@ test('settings match the approved paper-ledger geometry and action hierarchy', a const box = await target.boundingBox() expect(box).not.toBeNull() expect(box!.width).toBeGreaterThanOrEqual(44) - expect(box!.height).toBeGreaterThanOrEqual(44) + expect(box!.height).toBeGreaterThanOrEqual(isMobileContract ? 44 : 40) } + + const logout = page.getByRole('button', { name: '退出登录', exact: true }) + await expect(logout).toBeVisible() + await expect(logout).toBeEnabled() + const logoutBox = await logout.boundingBox() + expect(logoutBox).not.toBeNull() + expect(logoutBox!.width).toBeGreaterThanOrEqual(88) + expect(logoutBox!.height).toBeGreaterThanOrEqual(isMobileContract ? 44 : 40) + allowExpectedError(page, 'requestfailed: POST http://127.0.0.1:5173/api/v1/auth/logout net::ERR_ABORTED') + await logout.click() + await expect(page.getByRole('button', { name: '登录', exact: true })).toBeVisible() + await expect(page.getByText('欢迎回来,继续把生活理顺。')).toBeVisible() + expect(await page.request.get('/api/v1/me')).not.toBeOK() }) test('task, habit, countdown, memo, action and confirmation overlays share the modal contract', async ({ page }, testInfo) => { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index de21e73..b858163 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -455,6 +455,15 @@ async function bootstrap() { authReady.value = true } } +function completeLogout() { + authenticated.value = false + password.value = '' + error.value = '' + mobileSidebar.value = false + mobileDetail.value = false + selectedTask.value = null +} + async function submitAuth() { error.value = '' try { @@ -1588,7 +1597,7 @@ onUnmounted(() => {

{{ activeName }}

diff --git a/frontend/src/MvpPanel.vue b/frontend/src/MvpPanel.vue index 9ad6bfb..36199aa 100644 --- a/frontend/src/MvpPanel.vue +++ b/frontend/src/MvpPanel.vue @@ -1,6 +1,6 @@