Compare commits
2 Commits
e4c96da8a9
...
d8e64ef0e9
| Author | SHA1 | Date | |
|---|---|---|---|
| d8e64ef0e9 | |||
| fb9f6d1d00 |
BIN
assets/icon.icns
LFS
BIN
assets/icon.icns
LFS
Binary file not shown.
BIN
assets/icon.ico
LFS
BIN
assets/icon.ico
LFS
Binary file not shown.
BIN
assets/icon.png
LFS
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.
@@ -1,6 +1,6 @@
|
||||
# Nex Frontend
|
||||
|
||||
AI 网关管理前端,提供供应商配置和用量统计界面。
|
||||
AI 网关管理前端,提供供应商配置和总览界面。
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -97,7 +97,7 @@ frontend/
|
||||
│ │ └── useVersion.ts
|
||||
│ ├── pages/
|
||||
│ │ ├── Providers/ # 供应商管理(含内嵌模型管理)
|
||||
│ │ ├── Stats/ # 用量统计
|
||||
│ │ ├── Stats/ # 总览
|
||||
│ │ ├── Settings/ # 设置(开发中)
|
||||
│ │ ├── About/ # 关于页面(品牌与版本信息)
|
||||
│ │ └── NotFound.tsx
|
||||
@@ -199,7 +199,7 @@ bun run test:e2e
|
||||
- **统一模型 ID**:显示格式为 `provider_id/model_name`,用于跨协议模型识别,支持一键复制
|
||||
- **UUID 自动生成**:创建模型时后端自动生成 UUID,无需手动输入 ID
|
||||
|
||||
### 用量统计
|
||||
### 总览
|
||||
|
||||
- 查看统计数据
|
||||
- 按供应商筛选
|
||||
|
||||
@@ -18,7 +18,7 @@ test.describe('侧边栏', () => {
|
||||
test('应显示导航菜单项', async ({ page }) => {
|
||||
const aside = page.locator('aside')
|
||||
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()
|
||||
})
|
||||
|
||||
test('应能切换到用量统计', async ({ page }) => {
|
||||
await page.locator('aside').getByText('用量统计').click()
|
||||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible()
|
||||
test('应能切换到总览', async ({ page }) => {
|
||||
await page.locator('aside').getByText('总览').click()
|
||||
await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
|
||||
})
|
||||
|
||||
test('应能切换回供应商管理', async ({ page }) => {
|
||||
await page.locator('aside').getByText('用量统计').click()
|
||||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible()
|
||||
await page.locator('aside').getByText('总览').click()
|
||||
await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
|
||||
|
||||
await page.locator('aside').getByText('供应商管理').click()
|
||||
await expect(page.getByRole('heading', { name: '供应商管理' })).toBeVisible()
|
||||
@@ -51,10 +51,10 @@ test.describe('页面导航', () => {
|
||||
})
|
||||
|
||||
test('应在刷新后保持当前页面', async ({ page }) => {
|
||||
await page.locator('aside').getByText('用量统计').click()
|
||||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible()
|
||||
await page.locator('aside').getByText('总览').click()
|
||||
await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
|
||||
|
||||
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 }) => {
|
||||
await page.goto('/stats')
|
||||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
|
||||
})
|
||||
|
||||
test('应显示正确的总请求量', async ({ page }) => {
|
||||
@@ -99,7 +99,7 @@ test.describe('统计筛选', () => {
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/stats')
|
||||
await expect(page.getByRole('heading', { name: '用量统计' })).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: '总览' })).toBeVisible()
|
||||
})
|
||||
|
||||
test('按供应商筛选', async ({ page }) => {
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('AppLayout', () => {
|
||||
renderWithRouter(<AppLayout />)
|
||||
|
||||
expect(screen.getAllByText('供应商管理').length).toBeGreaterThan(0)
|
||||
expect(screen.getAllByText('用量统计').length).toBeGreaterThan(0)
|
||||
expect(screen.getAllByText('总览').length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('renders settings menu item', () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ export function AppLayout() {
|
||||
|
||||
const getPageTitle = () => {
|
||||
if (location.pathname === '/providers') return '供应商管理'
|
||||
if (location.pathname === '/stats') return '用量统计'
|
||||
if (location.pathname === '/stats') return '总览'
|
||||
if (location.pathname === '/settings') return '设置'
|
||||
if (location.pathname === '/about') return '关于'
|
||||
return APP_NAME
|
||||
@@ -73,12 +73,12 @@ export function AppLayout() {
|
||||
}
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<MenuItem value='/stats' icon={<ChartLineIcon />}>
|
||||
总览
|
||||
</MenuItem>
|
||||
<MenuItem value='/providers' icon={<ServerIcon />}>
|
||||
供应商管理
|
||||
</MenuItem>
|
||||
<MenuItem value='/stats' icon={<ChartLineIcon />}>
|
||||
用量统计
|
||||
</MenuItem>
|
||||
<MenuItem value='/settings' icon={<SettingIcon />}>
|
||||
设置
|
||||
</MenuItem>
|
||||
|
||||
@@ -14,7 +14,7 @@ export function AppRoutes() {
|
||||
<Suspense fallback={<Loading />}>
|
||||
<Routes>
|
||||
<Route element={<AppLayout />}>
|
||||
<Route index element={<Navigate to='/providers' replace />} />
|
||||
<Route index element={<Navigate to='/stats' replace />} />
|
||||
<Route path='providers' element={<ProvidersPage />} />
|
||||
<Route path='stats' element={<StatsPage />} />
|
||||
<Route path='settings' element={<SettingsPage />} />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
TBD - 提供供应商、模型配置和总览的前端管理界面
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -489,7 +489,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标和应用名称 `Nex`
|
||||
- **THEN** 侧边栏 SHALL NOT 显示旧品牌文字 `AI Gateway` 作为应用名称
|
||||
- **THEN** 侧边栏 SHALL 包含导航菜单
|
||||
- **THEN** 导航菜单项 SHALL 包含:供应商管理(ServerIcon 图标)、用量统计(ChartLineIcon 图标)、设置(SettingIcon 图标)、关于(InfoCircleIcon 图标)
|
||||
- **THEN** 导航菜单项 SHALL 按以下顺序包含:总览(ChartLineIcon 图标)、供应商管理(ServerIcon 图标)、设置(SettingIcon 图标)、关于(InfoCircleIcon 图标)
|
||||
|
||||
#### Scenario: 侧边栏折叠品牌显示
|
||||
|
||||
@@ -502,7 +502,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
|
||||
- **WHEN** 用户点击导航中的"供应商管理"
|
||||
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"用量统计"
|
||||
- **WHEN** 用户点击导航中的"总览"
|
||||
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"设置"
|
||||
- **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项
|
||||
@@ -518,10 +518,10 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
- **WHEN** 应用启动
|
||||
- **THEN** 前端 SHALL 使用 React Router v7 Library 模式(BrowserRouter)
|
||||
- **THEN** `/providers` 路径 SHALL 显示供应商管理页面
|
||||
- **THEN** `/stats` 路径 SHALL 显示用量统计页面
|
||||
- **THEN** `/stats` 路径 SHALL 显示总览页面
|
||||
- **THEN** `/settings` 路径 SHALL 显示设置页面
|
||||
- **THEN** `/about` 路径 SHALL 显示关于页面
|
||||
- **THEN** `/` 路径 SHALL 重定向到 `/providers`
|
||||
- **THEN** `/` 路径 SHALL 重定向到 `/stats`
|
||||
- **THEN** 不存在的路径 SHALL 显示 404 页面
|
||||
|
||||
#### Scenario: 路由级懒加载
|
||||
@@ -535,7 +535,7 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
|
||||
- **WHEN** 用户点击导航中的"供应商管理"
|
||||
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"用量统计"
|
||||
- **WHEN** 用户点击导航中的"总览"
|
||||
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
|
||||
|
||||
#### Scenario: URL 同步
|
||||
|
||||
Reference in New Issue
Block a user