refactor: 统计页面改名为"总览"并提升至侧边栏首位
将侧边栏"用量统计"菜单项改名为"总览",移至第一位, 默认路由重定向从 /providers 改为 /stats
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
### 用量统计
|
### 总览
|
||||||
|
|
||||||
- 查看统计数据
|
- 查看统计数据
|
||||||
- 按供应商筛选
|
- 按供应商筛选
|
||||||
|
|||||||
@@ -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()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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 }) => {
|
||||||
|
|||||||
@@ -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', () => {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 />} />
|
||||||
|
|||||||
@@ -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 同步
|
||||||
|
|||||||
Reference in New Issue
Block a user