1
0

feat: 统一品牌标识、关于页面三卡片布局与版本诊断功能

- 统一品牌为 Nex:侧边栏、托盘 tooltip、HTML 标题、favicon (PNG 替代 SVG)
- 重构关于页面为三卡片布局(品牌/版本/链接),版本状态 Tag 绝对定位右上角
- 新增 GET /api/version 后端接口,返回 version/commit/build_time
- 新增前端版本一致性诊断:匹配/不匹配/不可判断三种状态
- 同步 delta specs 到主 specs 并归档变更
This commit is contained in:
2026-05-05 03:28:22 +08:00
parent 9e33e570af
commit 8eea30ea11
42 changed files with 1316 additions and 111 deletions

View File

@@ -0,0 +1,88 @@
import { render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { useBackendVersion } from '@/hooks/useVersion'
import AboutPage from '@/pages/About'
vi.mock('@/hooks/useVersion', () => ({
useBackendVersion: vi.fn(),
}))
vi.mock('@/constants/app', () => ({
APP_NAME: 'Nex',
APP_DESCRIPTION: 'AI Gateway - 统一的大模型 API 网关',
APP_WEBSITE: 'https://github.com/nex/gateway',
APP_VERSION: '0.1.0',
}))
const mockUseBackendVersion = useBackendVersion as ReturnType<typeof vi.fn>
describe('AboutPage', () => {
beforeEach(() => {
mockUseBackendVersion.mockReturnValue({
data: { version: '0.1.0', commit: 'abc1234', buildTime: '2026-05-05T00:00:00Z' },
isError: false,
isLoading: false,
} as ReturnType<typeof useBackendVersion>)
})
it('renders brand, description and links', () => {
render(<AboutPage />)
expect(screen.getByRole('heading', { name: 'Nex' })).toBeInTheDocument()
expect(screen.getByText('AI Gateway - 统一的大模型 API 网关')).toBeInTheDocument()
expect(screen.getByText('GitHub')).toHaveAttribute('href', 'https://github.com/nex/gateway')
})
it('shows frontend and backend versions', () => {
render(<AboutPage />)
expect(screen.getByText('前端版本')).toBeInTheDocument()
expect(screen.getAllByText('0.1.0').length).toBeGreaterThan(0)
expect(screen.getByText('abc1234')).toBeInTheDocument()
expect(screen.getByText('2026-05-05T00:00:00Z')).toBeInTheDocument()
})
it('shows matched status', () => {
render(<AboutPage />)
expect(screen.getByText('版本一致')).toBeInTheDocument()
})
it('shows mismatched status', () => {
mockUseBackendVersion.mockReturnValue({
data: { version: '0.2.0', commit: 'abc1234', buildTime: '2026-05-05T00:00:00Z' },
isError: false,
isLoading: false,
} as ReturnType<typeof useBackendVersion>)
render(<AboutPage />)
expect(screen.getByText('版本不一致')).toBeInTheDocument()
expect(screen.getByText(/用于部署诊断/)).toBeInTheDocument()
})
it('shows unknown status for dev backend version', () => {
mockUseBackendVersion.mockReturnValue({
data: { version: 'dev', commit: 'unknown', buildTime: 'unknown' },
isError: false,
isLoading: false,
} as ReturnType<typeof useBackendVersion>)
render(<AboutPage />)
expect(screen.getByText('无法判断版本')).toBeInTheDocument()
})
it('shows unavailable status on backend request failure', () => {
mockUseBackendVersion.mockReturnValue({
data: undefined,
isError: true,
isLoading: false,
} as ReturnType<typeof useBackendVersion>)
render(<AboutPage />)
expect(screen.getByText('无法获取后端版本')).toBeInTheDocument()
expect(screen.getByText(/后端版本接口暂时不可用/)).toBeInTheDocument()
})
})