1
0

2 Commits

Author SHA1 Message Date
d8e64ef0e9 chore: 更新应用图标资源 2026-05-07 15:34:25 +08:00
fb9f6d1d00 refactor: 统计页面改名为"总览"并提升至侧边栏首位
将侧边栏"用量统计"菜单项改名为"总览",移至第一位,
默认路由重定向从 /providers 改为 /stats
2026-05-07 15:05:45 +08:00
19 changed files with 50 additions and 50 deletions

Binary file not shown.

BIN
assets/icon.ico LFS

Binary file not shown.

BIN
assets/icon.png LFS

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,6 @@
# Nex Frontend # Nex Frontend
AI 网关管理前端,提供供应商配置和用量统计界面。 AI 网关管理前端,提供供应商配置和总览界面。
## 技术栈 ## 技术栈
@@ -97,7 +97,7 @@ frontend/
│ │ └── useVersion.ts │ │ └── useVersion.ts
│ ├── pages/ │ ├── pages/
│ │ ├── Providers/ # 供应商管理(含内嵌模型管理) │ │ ├── Providers/ # 供应商管理(含内嵌模型管理)
│ │ ├── Stats/ # 用量统计 │ │ ├── Stats/ # 总览
│ │ ├── Settings/ # 设置(开发中) │ │ ├── Settings/ # 设置(开发中)
│ │ ├── About/ # 关于页面(品牌与版本信息) │ │ ├── About/ # 关于页面(品牌与版本信息)
│ │ └── NotFound.tsx │ │ └── NotFound.tsx
@@ -199,7 +199,7 @@ bun run test:e2e
- **统一模型 ID**:显示格式为 `provider_id/model_name`,用于跨协议模型识别,支持一键复制 - **统一模型 ID**:显示格式为 `provider_id/model_name`,用于跨协议模型识别,支持一键复制
- **UUID 自动生成**:创建模型时后端自动生成 UUID无需手动输入 ID - **UUID 自动生成**:创建模型时后端自动生成 UUID无需手动输入 ID
### 用量统计 ### 总览
- 查看统计数据 - 查看统计数据
- 按供应商筛选 - 按供应商筛选

View File

@@ -18,7 +18,7 @@ test.describe('侧边栏', () => {
test('应显示导航菜单项', async ({ page }) => { test('应显示导航菜单项', async ({ page }) => {
const aside = page.locator('aside') const aside = page.locator('aside')
await expect(aside.getByText('供应商管理')).toBeVisible() await expect(aside.getByText('供应商管理')).toBeVisible()
await expect(aside.getByText('用量统计')).toBeVisible() await expect(aside.getByText('总览')).toBeVisible()
}) })
}) })
@@ -28,14 +28,14 @@ test.describe('页面导航', () => {
await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible() await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible()
}) })
test('应能切换到用量统计', async ({ page }) => { test('应能切换到总览', async ({ page }) => {
await page.locator('aside').getByText('用量统计').click() await page.locator('aside').getByText('总览').click()
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
}) })
test('应能切换回供应商管理', async ({ page }) => { test('应能切换回供应商管理', async ({ page }) => {
await page.locator('aside').getByText('用量统计').click() await page.locator('aside').getByText('总览').click()
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
await page.locator('aside').getByText('供应商管理').click() await page.locator('aside').getByText('供应商管理').click()
await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible() await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible()
@@ -51,10 +51,10 @@ test.describe('页面导航', () => {
}) })
test('应在刷新后保持当前页面', async ({ page }) => { test('应在刷新后保持当前页面', async ({ page }) => {
await page.locator('aside').getByText('用量统计').click() await page.locator('aside').getByText('总览').click()
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
await page.reload() await page.reload()
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
}) })
}) })

View File

@@ -41,7 +41,7 @@ test.describe('统计概览', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await page.goto('/stats') await page.goto('/stats')
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
}) })
test('应显示正确的总请求量', async ({ page }) => { test('应显示正确的总请求量', async ({ page }) => {
@@ -99,7 +99,7 @@ test.describe('统计筛选', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await page.goto('/stats') await page.goto('/stats')
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible() await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
}) })
test('按供应商筛选', async ({ page }) => { test('按供应商筛选', async ({ page }) => {

View File

@@ -31,7 +31,7 @@ describe('AppLayout', () => {
renderWithRouter(<AppLayout />) renderWithRouter(<AppLayout />)
expect(screen.getAllByText('供应商管理').length).toBeGreaterThan(0) expect(screen.getAllByText('供应商管理').length).toBeGreaterThan(0)
expect(screen.getAllByText('用量统计').length).toBeGreaterThan(0) expect(screen.getAllByText('总览').length).toBeGreaterThan(0)
}) })
it('renders settings menu item', () => { it('renders settings menu item', () => {

View File

@@ -20,7 +20,7 @@ export function AppLayout() {
const getPageTitle = () => { const getPageTitle = () => {
if (location.pathname === '/providers') return '供应商管理' if (location.pathname === '/providers') return '供应商管理'
if (location.pathname === '/stats') return '用量统计' if (location.pathname === '/stats') return '总览'
if (location.pathname === '/settings') return '设置' if (location.pathname === '/settings') return '设置'
if (location.pathname === '/about') return '关于' if (location.pathname === '/about') return '关于'
return APP_NAME return APP_NAME
@@ -73,12 +73,12 @@ export function AppLayout() {
} }
style={{ height: '100%' }} style={{ height: '100%' }}
> >
<MenuItem value='/stats' icon={<ChartLineIcon />}>
</MenuItem>
<MenuItem value='/providers' icon={<ServerIcon />}> <MenuItem value='/providers' icon={<ServerIcon />}>
</MenuItem> </MenuItem>
<MenuItem value='/stats' icon={<ChartLineIcon />}>
</MenuItem>
<MenuItem value='/settings' icon={<SettingIcon />}> <MenuItem value='/settings' icon={<SettingIcon />}>
</MenuItem> </MenuItem>

View File

@@ -14,7 +14,7 @@ export function AppRoutes() {
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
<Routes> <Routes>
<Route element={<AppLayout />}> <Route element={<AppLayout />}>
<Route index element={<Navigate to='/providers' replace />} /> <Route index element={<Navigate to='/stats' replace />} />
<Route path='providers' element={<ProvidersPage />} /> <Route path='providers' element={<ProvidersPage />} />
<Route path='stats' element={<StatsPage />} /> <Route path='stats' element={<StatsPage />} />
<Route path='settings' element={<SettingsPage />} /> <Route path='settings' element={<SettingsPage />} />

View File

@@ -2,7 +2,7 @@
## Purpose ## Purpose
TBD - 提供供应商、模型配置和用量统计的前端管理界面 TBD - 提供供应商、模型配置和总览的前端管理界面
## Requirements ## Requirements
@@ -489,7 +489,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标和应用名称 `Nex` - **THEN** 侧边栏顶部 SHALL 显示统一应用图标和应用名称 `Nex`
- **THEN** 侧边栏 SHALL NOT 显示旧品牌文字 `AI Gateway` 作为应用名称 - **THEN** 侧边栏 SHALL NOT 显示旧品牌文字 `AI Gateway` 作为应用名称
- **THEN** 侧边栏 SHALL 包含导航菜单 - **THEN** 侧边栏 SHALL 包含导航菜单
- **THEN** 导航菜单项 SHALL 包含供应商管理ServerIcon 图标、用量统计ChartLineIcon 图标、设置SettingIcon 图标、关于InfoCircleIcon 图标) - **THEN** 导航菜单项 SHALL 按以下顺序包含总览ChartLineIcon 图标、供应商管理ServerIcon 图标、设置SettingIcon 图标、关于InfoCircleIcon 图标)
#### Scenario: 侧边栏折叠品牌显示 #### Scenario: 侧边栏折叠品牌显示
@@ -502,7 +502,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **WHEN** 用户点击导航中的"供应商管理" - **WHEN** 用户点击导航中的"供应商管理"
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项 - **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
- **WHEN** 用户点击导航中的"用量统计" - **WHEN** 用户点击导航中的"总览"
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项 - **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
- **WHEN** 用户点击导航中的"设置" - **WHEN** 用户点击导航中的"设置"
- **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项 - **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项
@@ -518,10 +518,10 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **WHEN** 应用启动 - **WHEN** 应用启动
- **THEN** 前端 SHALL 使用 React Router v7 Library 模式BrowserRouter - **THEN** 前端 SHALL 使用 React Router v7 Library 模式BrowserRouter
- **THEN** `/providers` 路径 SHALL 显示供应商管理页面 - **THEN** `/providers` 路径 SHALL 显示供应商管理页面
- **THEN** `/stats` 路径 SHALL 显示用量统计页面 - **THEN** `/stats` 路径 SHALL 显示总览页面
- **THEN** `/settings` 路径 SHALL 显示设置页面 - **THEN** `/settings` 路径 SHALL 显示设置页面
- **THEN** `/about` 路径 SHALL 显示关于页面 - **THEN** `/about` 路径 SHALL 显示关于页面
- **THEN** `/` 路径 SHALL 重定向到 `/providers` - **THEN** `/` 路径 SHALL 重定向到 `/stats`
- **THEN** 不存在的路径 SHALL 显示 404 页面 - **THEN** 不存在的路径 SHALL 显示 404 页面
#### Scenario: 路由级懒加载 #### Scenario: 路由级懒加载
@@ -535,7 +535,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
- **WHEN** 用户点击导航中的"供应商管理" - **WHEN** 用户点击导航中的"供应商管理"
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项 - **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
- **WHEN** 用户点击导航中的"用量统计" - **WHEN** 用户点击导航中的"总览"
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项 - **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
#### Scenario: URL 同步 #### Scenario: URL 同步