From 32c8939eb594136b962c7f71d151751681454495 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 13:59:33 +0800 Subject: [PATCH] refine Semi UI identity workflow --- .../apps/web/src/v2/auth/AuthGate.tsx | 7 +++-- .../apps/web/src/v2/layout/AppShell.tsx | 13 +++++---- .../apps/web/src/v2/productionEntry.test.ts | 9 ++++++ .../web/src/v2/shared/PasswordInput.test.tsx | 19 ++++++++++++ .../apps/web/src/v2/shared/PasswordInput.tsx | 28 ++++++++++++++++++ .../apps/web/src/v2/styles/workspace.css | 29 ++++++++++++++++--- 6 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 vehicle-data-platform/apps/web/src/v2/shared/PasswordInput.test.tsx create mode 100644 vehicle-data-platform/apps/web/src/v2/shared/PasswordInput.tsx diff --git a/vehicle-data-platform/apps/web/src/v2/auth/AuthGate.tsx b/vehicle-data-platform/apps/web/src/v2/auth/AuthGate.tsx index df1e6665..d9459503 100644 --- a/vehicle-data-platform/apps/web/src/v2/auth/AuthGate.tsx +++ b/vehicle-data-platform/apps/web/src/v2/auth/AuthGate.tsx @@ -3,6 +3,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { Banner, Button, Card, Input, Spin, Tabs, Tag, Typography } from '@douyinfe/semi-ui'; import { FormEvent, ReactNode, useCallback, useContext, useEffect, useState, createContext } from 'react'; import { api } from '../../api/client'; +import { PasswordInput } from '../shared/PasswordInput'; import { clearAccessToken, getAccessToken, PLATFORM_UNAUTHORIZED_EVENT, PlatformSession, setAccessToken } from './session'; const { Title, Text } = Typography; @@ -176,8 +177,8 @@ export function AuthGate({ children }: { children: ReactNode }) { > diff --git a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx index 9901a670..fba01eb1 100644 --- a/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx +++ b/vehicle-data-platform/apps/web/src/v2/layout/AppShell.tsx @@ -15,7 +15,7 @@ import { IconUser, IconExit } from '@douyinfe/semi-icons'; -import { Avatar, Banner, Button, Card, Dropdown, Input, Layout, Modal, Nav, SideSheet, Tag, Typography } from '@douyinfe/semi-ui'; +import { Avatar, Banner, Button, Card, Dropdown, Layout, Modal, Nav, SideSheet, Tag, Typography } from '@douyinfe/semi-ui'; import { type CSSProperties, FormEvent, type MouseEvent, useEffect, useLayoutEffect, useState } from 'react'; import { NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { api } from '../../api/client'; @@ -24,6 +24,7 @@ import { hasMenu } from '../auth/session'; import { useMobileLayout } from '../hooks/useMobileLayout'; import { useSideSheetA11y } from '../hooks/useSideSheetA11y'; import { preloadRoute, scheduleIdleRoutePreloads, shouldPreloadRouteOnIntent } from '../routing/routeModules'; +import { PasswordInput } from '../shared/PasswordInput'; const { Header, Sider, Content } = Layout; const { Text, Title } = Typography; @@ -226,7 +227,7 @@ function PasswordDialog({ onClose, onChanged }: { onClose: () => void; onChanged return
修改登录密码
} + title={
修改登录密码
} aria-label="修改登录密码" onCancel={onClose} closeOnEsc={!pending} @@ -234,14 +235,14 @@ function PasswordDialog({ onClose, onChanged }: { onClose: () => void; onChanged footer={null} >
- - - + + +
10–128 位字符 大小写字母、数字、特殊字符至少三类
- + {confirmationStarted ? {passwordsMatch ? '两次输入一致' : '两次输入的新密码不一致'} : null} {error ? : null}
diff --git a/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts b/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts index 0a441daf..7965cd9e 100644 --- a/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts +++ b/vehicle-data-platform/apps/web/src/v2/productionEntry.test.ts @@ -16,6 +16,7 @@ const reconciliationSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/R const profileSyncPanelSource = readFileSync(resolve(process.cwd(), 'src/v2/pages/VehicleProfileSyncPanel.tsx'), 'utf8'); const sourceEvidenceSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/VehicleSourceEvidencePanel.tsx'), 'utf8'); const mobileFilterToggleSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/MobileFilterToggle.tsx'), 'utf8'); +const passwordInputSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/PasswordInput.tsx'), 'utf8'); const workspaceFilterPanelSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceFilterPanel.tsx'), 'utf8'); const workspaceMetricRailSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/WorkspaceMetricRail.tsx'), 'utf8'); const segmentedTabsSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/SegmentedTabs.tsx'), 'utf8'); @@ -26,6 +27,7 @@ const vehicleCandidateListSource = readFileSync(resolve(process.cwd(), 'src/v2/s const recoveryActionsSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/RecoveryActions.tsx'), 'utf8'); const detailTriggerRowSource = readFileSync(resolve(process.cwd(), 'src/v2/shared/detailTriggerRow.ts'), 'utf8'); const appShellSource = readFileSync(resolve(process.cwd(), 'src/v2/layout/AppShell.tsx'), 'utf8'); +const authGateSource = readFileSync(resolve(process.cwd(), 'src/v2/auth/AuthGate.tsx'), 'utf8'); const routeBoundarySource = readFileSync(resolve(process.cwd(), 'src/v2/routing/RouteBoundary.tsx'), 'utf8'); const fleetMapSource = readFileSync(resolve(process.cwd(), 'src/v2/map/FleetMap.tsx'), 'utf8'); const trackMapSource = readFileSync(resolve(process.cwd(), 'src/v2/map/TrackMap.tsx'), 'utf8'); @@ -490,6 +492,13 @@ describe('V2 production entry', () => { expect(appShellSource).toContain('