浏览代码

feat(ui, routing, tests): enhance UI components and update routing structure

- Added new styles for pagination and buttons to improve visual consistency, including blue background and white text for active states.
- Updated routing structure to reflect new paths for LSS and LiveStream management, changing from `/lss` to `/lss-manage` and `/live-stream` to `/live-stream-manage`.
- Modified tests to align with the new routing paths and ensure functionality remains intact.
- Implemented pagination functionality in the camera list view, enhancing user experience with better navigation.
yb 3 天之前
父节点
当前提交
76c21a7840
共有 6 个文件被更改,包括 445 次插入77 次删除
  1. 44 0
      src/assets/styles/theme/element-override.scss
  2. 12 2
      src/layout/index.vue
  3. 26 10
      src/router/index.ts
  4. 56 13
      src/views/lss/index.vue
  5. 24 24
      tests/e2e/live-stream.spec.ts
  6. 283 28
      tests/e2e/lss.spec.ts

+ 44 - 0
src/assets/styles/theme/element-override.scss

@@ -172,6 +172,50 @@
   .el-pager li {
     border-radius: var(--radius-sm);
   }
+
+  // #4542: 分页当前页使用蓝底白字
+  &.is-background {
+    .el-pager li:not(.is-disabled).is-active {
+      background-color: #409eff !important;
+      color: #ffffff !important;
+    }
+  }
+}
+
+// #4545: 按钮统一大小和圆角
+.el-button {
+  border-radius: 4px;
+  min-height: 32px;
+  padding: 8px 15px;
+  font-size: 14px;
+
+  &.el-button--small {
+    min-height: 24px;
+    padding: 5px 11px;
+    font-size: 12px;
+  }
+
+  &.el-button--large {
+    min-height: 40px;
+    padding: 12px 19px;
+    font-size: 14px;
+  }
+}
+
+// #4594: 删除确认对话框确定按钮蓝底白字
+.el-message-box {
+  .el-message-box__btns {
+    .el-button--primary {
+      background-color: #409eff !important;
+      border-color: #409eff !important;
+      color: #ffffff !important;
+
+      &:hover {
+        background-color: #66b1ff !important;
+        border-color: #66b1ff !important;
+      }
+    }
+  }
 }
 
 // 对话框

+ 12 - 2
src/layout/index.vue

@@ -215,8 +215,18 @@ interface MenuItem {
 // Menu configuration with Iconify icon names
 const menuItems: MenuItem[] = [
   { path: '/', title: '仪表盘', icon: 'mdi:view-dashboard' },
-  { path: '/lss', title: 'LSS 管理', icon: 'mdi:power-plug' },
-  { path: '/live-stream', title: 'LiveStream 管理', icon: 'mdi:broadcast' },
+  {
+    path: '/lss-manage',
+    title: 'LSS 管理',
+    icon: 'mdi:power-plug',
+    children: [{ path: '/lss-manage/list', title: 'LSS 列表', icon: 'mdi:format-list-bulleted' }]
+  },
+  {
+    path: '/live-stream-manage',
+    title: 'LiveStream 管理',
+    icon: 'mdi:broadcast',
+    children: [{ path: '/live-stream-manage/list', title: 'LiveStream 列表', icon: 'mdi:format-list-bulleted' }]
+  },
   { path: '/cc', title: 'Cloudflare Stream', icon: 'mdi:cloud' },
   { path: '/camera-vendor', title: '摄像头配置', icon: 'mdi:cctv' },
   { path: '/webrtc', title: 'WebRTC 流', icon: 'mdi:wifi' },

+ 26 - 10
src/router/index.ts

@@ -45,16 +45,32 @@ const routes: RouteRecordRaw[] = [
         meta: { title: '摄像头厂家', icon: 'OfficeBuilding' }
       },
       {
-        path: 'lss',
-        name: 'LSS',
-        component: () => import('@/views/lss/index.vue'),
-        meta: { title: 'LSS 列表', icon: 'Connection' }
-      },
-      {
-        path: 'live-stream',
-        name: 'LiveStream',
-        component: () => import('@/views/live-stream/index.vue'),
-        meta: { title: 'LiveStream 管理', icon: 'VideoCamera' }
+        path: 'lss-manage',
+        name: 'LssManage',
+        meta: { title: 'LSS 管理', icon: 'Connection' },
+        redirect: '/lss-manage/list',
+        children: [
+          {
+            path: 'list',
+            name: 'LssList',
+            component: () => import('@/views/lss/index.vue'),
+            meta: { title: 'LSS 列表', icon: 'List' }
+          }
+        ]
+      },
+      {
+        path: 'live-stream-manage',
+        name: 'LiveStreamManage',
+        meta: { title: 'LiveStream 管理', icon: 'VideoCamera' },
+        redirect: '/live-stream-manage/list',
+        children: [
+          {
+            path: 'list',
+            name: 'LiveStreamList',
+            component: () => import('@/views/live-stream/index.vue'),
+            meta: { title: 'LiveStream 列表', icon: 'List' }
+          }
+        ]
       },
       {
         path: 'cloud',

+ 56 - 13
src/views/lss/index.vue

@@ -280,8 +280,18 @@
                 </template>
               </el-table-column>
             </el-table>
-            <div v-if="cameraList.length > 0" class="camera-count">
-              {{ t('共') }} {{ cameraList.length }} {{ t('个设备') }}
+            <div class="camera-pagination">
+              <el-pagination
+                v-model:current-page="cameraCurrentPage"
+                v-model:page-size="cameraPageSize"
+                :page-sizes="[10, 15, 20, 50]"
+                :total="cameraTotal"
+                layout="total, sizes, prev, pager, next"
+                background
+                small
+                @size-change="handleCameraSizeChange"
+                @current-change="handleCameraPageChange"
+              />
             </div>
           </div>
 
@@ -314,10 +324,19 @@
               <el-form :model="cameraSearchForm" inline>
                 <el-form-item>
                   <el-input
-                    v-model.trim="cameraSearchForm.keyword"
-                    :placeholder="t('IP / 设备ID / 名称')"
+                    v-model.trim="cameraSearchForm.cameraId"
+                    :placeholder="t('设备ID')"
                     clearable
-                    style="width: 200px"
+                    style="width: 150px"
+                    @keyup.enter="handleCameraSearch"
+                  />
+                </el-form-item>
+                <el-form-item>
+                  <el-input
+                    v-model.trim="cameraSearchForm.cameraName"
+                    :placeholder="t('设备名称')"
+                    clearable
+                    style="width: 150px"
                     @keyup.enter="handleCameraSearch"
                   />
                 </el-form-item>
@@ -360,9 +379,9 @@
                   <el-button type="primary" link @click="handleViewRunParams(row)">查看</el-button>
                 </template>
               </el-table-column>
-              <el-table-column prop="brand" :label="t('厂商')" min-width="90">
+              <el-table-column prop="vendorName" :label="t('厂商')" min-width="90">
                 <template #default="{ row }">
-                  {{ formatBrand(row.brand) }}
+                  {{ formatBrand(row.vendorName) }}
                 </template>
               </el-table-column>
               <el-table-column prop="model" :label="t('型号')" min-width="130" show-overflow-tooltip />
@@ -802,6 +821,11 @@ const deviceActiveTab = ref('camera')
 const cameraList = ref<CameraInfoDTO[]>([])
 const cameraVendorList = ref<CameraVendorDTO[]>([])
 
+// 摄像头分页
+const cameraCurrentPage = ref(1)
+const cameraPageSize = ref(15)
+const cameraTotal = ref(0)
+
 // 摄像头搜索表单
 const cameraSearchForm = reactive({
   cameraId: '',
@@ -1012,7 +1036,11 @@ async function loadCameraList() {
   cameraList.value = []
 
   try {
-    const params: any = { lssId: currentLss.value.lssId }
+    const params: any = {
+      lssId: currentLss.value.lssId,
+      page: cameraCurrentPage.value,
+      size: cameraPageSize.value
+    }
 
     if (cameraSearchForm.cameraId) {
       params.cameraId = cameraSearchForm.cameraId
@@ -1029,6 +1057,7 @@ async function loadCameraList() {
     const res = await adminListCameras(params)
     if (res.success && res.data) {
       cameraList.value = res.data.list || []
+      cameraTotal.value = res.data.total || 0
     } else {
       ElMessage.error(res.errMessage || '获取摄像头列表失败')
     }
@@ -1041,6 +1070,7 @@ async function loadCameraList() {
 }
 
 function handleCameraSearch() {
+  cameraCurrentPage.value = 1
   loadCameraList()
 }
 
@@ -1048,6 +1078,18 @@ function handleCameraReset() {
   cameraSearchForm.cameraId = ''
   cameraSearchForm.cameraName = ''
   cameraSearchForm.status = ''
+  cameraCurrentPage.value = 1
+  loadCameraList()
+}
+
+function handleCameraSizeChange(val: number) {
+  cameraPageSize.value = val
+  cameraCurrentPage.value = 1
+  loadCameraList()
+}
+
+function handleCameraPageChange(val: number) {
+  cameraCurrentPage.value = val
   loadCameraList()
 }
 
@@ -1289,8 +1331,10 @@ async function handleDelete(row: LssNodeDTO) {
 // 监听 tab 切换,加载对应数据
 watch(editActiveTab, (newTab) => {
   if (newTab === 'camera' && currentLss.value) {
-    cameraSearchForm.keyword = ''
+    cameraSearchForm.cameraId = ''
+    cameraSearchForm.cameraName = ''
     cameraSearchForm.status = ''
+    cameraCurrentPage.value = 1
     loadCameraList()
   }
 })
@@ -1351,11 +1395,10 @@ onMounted(() => {
   }
 }
 
-.camera-count {
+.camera-pagination {
   margin-top: 16px;
-  text-align: right;
-  color: #666;
-  font-size: 14px;
+  display: flex;
+  justify-content: flex-end;
 }
 
 .status-text {

+ 24 - 24
tests/e2e/live-stream.spec.ts

@@ -27,7 +27,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('按 Stream SN 搜索 - 验证参数传递', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -59,7 +59,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('按 Name 搜索 - 验证参数传递', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -91,7 +91,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('按 LSS 搜索 - 验证参数传递', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -131,7 +131,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('按设备ID搜索 - 验证参数传递', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -163,7 +163,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('组合搜索 - 多字段同时搜索', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -199,7 +199,7 @@ test.describe('LiveStream 管理 - 搜索功能测试', () => {
    */
   test('重置搜索条件 - 清空所有输入', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 填入搜索条件
     await page.getByPlaceholder('stream sn').fill('test-sn')
@@ -233,7 +233,7 @@ test.describe('LiveStream 管理 - BUG 回归测试', () => {
    */
   test('BUG: 按设备ID搜索 EEE1 应该只返回 1 条匹配记录', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -265,7 +265,7 @@ test.describe('LiveStream 管理 - BUG 回归测试', () => {
 test.describe('LiveStream 管理 - 页面功能测试', () => {
   test('LiveStream 管理页面正确显示', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 验证页面标题
     await expect(page.locator('text=LiveStream 管理')).toBeVisible()
@@ -287,7 +287,7 @@ test.describe('LiveStream 管理 - 页面功能测试', () => {
 
   test('打开新增 LiveStream 抽屉', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 点击新增按钮
     await page.getByRole('button', { name: '新增' }).click()
@@ -308,7 +308,7 @@ test.describe('LiveStream 管理 - 页面功能测试', () => {
 
   test('分页功能正常', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -328,7 +328,7 @@ test.describe('LiveStream 管理 - 页面功能测试', () => {
     await page.getByText('LiveStream 管理').first().click()
 
     // 验证跳转到 LiveStream 管理页面
-    await expect(page).toHaveURL(/\/live-stream/)
+    await expect(page).toHaveURL(/\/live-stream-manage\/list/)
     await expect(page.locator('text=LiveStream 管理')).toBeVisible()
   })
 })
@@ -339,7 +339,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 验证头部显示Bash Script标签和复制按钮', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -371,7 +371,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 复制按钮功能', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -397,7 +397,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 编辑器可编辑', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -429,7 +429,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 抽屉包含取消和更新按钮', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -456,7 +456,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 图标显示为绿色', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -479,7 +479,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 更新命令模板并验证保存成功', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -533,7 +533,7 @@ test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () =>
    */
   test('CodeEditor Bash模式 - 替换全部命令模板并验证保存', async ({ page }) => {
     await login(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -700,7 +700,7 @@ test.describe('LiveStream 管理 - 从 LSS 页面创建流程', () => {
     await expect(drawer).not.toBeVisible({ timeout: 3000 })
 
     // 验证仍在 live-stream 页面
-    await expect(page).toHaveURL(/\/live-stream/)
+    await expect(page).toHaveURL(/\/live-stream-manage\/list/)
   })
 
   /**
@@ -758,7 +758,7 @@ test.describe('LiveStream 管理 - Bug修复验证测试', () => {
    */
   test('Bug #4627 - 时间列正确格式化显示', async ({ page }) => {
     await loginHelper(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -782,7 +782,7 @@ test.describe('LiveStream 管理 - Bug修复验证测试', () => {
    */
   test('Bug #4628 - 命令模板抽屉按钮显示"取消"而非"关闭"', async ({ page }) => {
     await loginHelper(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -806,7 +806,7 @@ test.describe('LiveStream 管理 - Bug修复验证测试', () => {
    */
   test('Bug #4629 - 命令模板使用抽屉而非对话框', async ({ page }) => {
     await loginHelper(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 等待表格加载
     await page.waitForSelector('tbody tr', { timeout: 10000 })
@@ -830,7 +830,7 @@ test.describe('LiveStream 管理 - Bug修复验证测试', () => {
    */
   test('Bug #4630 - 搜索框placeholder显示"名称"而非"name"', async ({ page }) => {
     await loginHelper(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 验证名称搜索框的placeholder是"名称"
     const nameInput = page.getByPlaceholder('名称')
@@ -846,7 +846,7 @@ test.describe('LiveStream 管理 - Bug修复验证测试', () => {
    */
   test('Bug #4541 - 重置按钮使用灰底白字', async ({ page }) => {
     await loginHelper(page)
-    await page.goto('/live-stream')
+    await page.goto('/live-stream-manage/list')
 
     // 获取重置按钮
     const resetButton = page.getByRole('button', { name: '重置' })

+ 283 - 28
tests/e2e/lss.spec.ts

@@ -33,7 +33,7 @@ test.describe('LSS管理 CRUD 测试', () => {
 
   test('LSS管理页面正确显示', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 验证页面标题 (Bug #4537: 页面标题从 "LSS 管理" 改为 "LSS 列表")
     await expect(page.locator('text=LSS 列表')).toBeVisible()
@@ -54,7 +54,7 @@ test.describe('LSS管理 CRUD 测试', () => {
 
   test('编辑LSS节点 - 修改Name和Address', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -100,7 +100,7 @@ test.describe('LSS管理 CRUD 测试', () => {
 
   test('查询LSS节点', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -128,7 +128,7 @@ test.describe('LSS管理 CRUD 测试', () => {
 
   test('重置搜索条件', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 填入搜索条件
     await page.getByPlaceholder('LSS ID').fill('test-id')
@@ -145,7 +145,7 @@ test.describe('LSS管理 CRUD 测试', () => {
 
   test('查看LSS节点设备列表', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -175,7 +175,7 @@ test.describe('LSS管理 CRUD 测试', () => {
     await page.getByText('LSS 列表').first().click()
 
     // 验证跳转到 LSS 管理页面
-    await expect(page).toHaveURL(/\/lss/)
+    await expect(page).toHaveURL(/\/lss-manage\/list/)
     await expect(page.locator('text=LSS 列表')).toBeVisible()
   })
 })
@@ -203,7 +203,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 验证头部显示JSON标签和按钮', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -244,7 +244,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 复制按钮功能', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -280,7 +280,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 格式化按钮功能', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -319,7 +319,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 无效JSON显示错误提示', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -363,7 +363,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 更新参数配置并验证保存成功', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -426,7 +426,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
    */
   test('CodeEditor JSON模式 - 更新运行参数并验证保存成功', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -506,7 +506,7 @@ test.describe('LSS管理 - 摄像头列表搜索测试', () => {
 
   // 打开摄像头列表辅助函数
   async function openCameraList(page: Page) {
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击 Device List 按钮打开设备列表 - 点击编辑按钮进入 LSS 编辑抽屉
@@ -832,7 +832,7 @@ test.describe('LSS管理 - 摄像头未创建 Live Stream 对话框测试', () =
 
   // 打开摄像头列表辅助函数
   async function openCameraList(page: Page) {
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击编辑按钮进入 LSS 编辑抽屉
@@ -956,7 +956,7 @@ test.describe('LSS管理 - 摄像头未创建 Live Stream 对话框测试', () =
     await expect(messageBox).not.toBeVisible({ timeout: 3000 })
 
     // 验证仍在 LSS 页面
-    await expect(page).toHaveURL(/\/lss/)
+    await expect(page).toHaveURL(/\/lss-manage\/list/)
   })
 
   /**
@@ -1047,7 +1047,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4535 - 重置按钮清除所有搜索条件包括排序状态', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1087,7 +1087,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4536 - 心跳状态显示为英文格式', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1108,7 +1108,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4537 - 页面标题显示为"LSS 列表"', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待页面加载
     await page.waitForTimeout(500)
@@ -1127,7 +1127,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4538 - 分页默认显示15条/页', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1147,7 +1147,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4538 - 分页选项包含15条/页选项', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1178,7 +1178,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4540 - 查询按钮使用蓝底白字', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待页面加载
     await page.waitForTimeout(500)
@@ -1203,7 +1203,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4541 - 重置按钮使用灰底白字', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待页面加载
     await page.waitForTimeout(500)
@@ -1228,7 +1228,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4542 - 分页当前页使用蓝底白字', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1250,7 +1250,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4557 - 摄像头列表状态下拉框显示英文选项', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
 
     // 等待表格加载
     await page.waitForTimeout(1000)
@@ -1310,7 +1310,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
       })
     })
 
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击编辑按钮进入 LSS 编辑抽屉
@@ -1367,7 +1367,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
       })
     })
 
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击编辑按钮进入 LSS 编辑抽屉
@@ -1417,7 +1417,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
    */
   test('Bug #4569 - 编辑摄像头抽屉标题显示"摄像头详情"', async ({ page }) => {
     await login(page)
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击编辑按钮进入 LSS 编辑抽屉
@@ -1475,7 +1475,7 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
       })
     })
 
-    await page.goto('/lss')
+    await page.goto('/lss-manage/list')
     await page.waitForTimeout(1000)
 
     // 点击编辑按钮进入 LSS 编辑抽屉
@@ -1510,4 +1510,259 @@ test.describe('LSS管理 - Bug修复验证测试', () => {
       expect(timeText).toMatch(/\d{4}-\d{2}-\d{2}|\-/)
     }
   })
+
+  /**
+   * Bug #4545: 按钮大小统一,圆角框
+   */
+  test('Bug #4545 - 按钮有统一的圆角', async ({ page }) => {
+    await login(page)
+    await page.goto('/lss-manage/list')
+
+    // 等待页面加载
+    await page.waitForTimeout(500)
+
+    // 获取查询按钮
+    const searchButton = page.locator('[data-id="btn-search"]')
+    await expect(searchButton).toBeVisible()
+
+    // 验证按钮有圆角
+    const borderRadius = await searchButton.evaluate((el) => {
+      return window.getComputedStyle(el).borderRadius
+    })
+    // 验证圆角值不为0
+    expect(borderRadius).not.toBe('0px')
+    expect(parseInt(borderRadius)).toBeGreaterThanOrEqual(4)
+  })
+
+  /**
+   * Bug #4549: LSS列表作为「LSS 管理」的子菜单
+   */
+  test('Bug #4549 - LSS列表作为LSS管理的子菜单', async ({ page }) => {
+    await login(page)
+
+    // 等待侧边栏加载
+    await page.waitForTimeout(500)
+
+    // 验证"LSS 管理"父菜单存在
+    const lssManageMenu = page.locator('.layout__nav-item--parent').filter({ hasText: 'LSS 管理' })
+    await expect(lssManageMenu).toBeVisible()
+
+    // 点击展开子菜单
+    await lssManageMenu.click()
+    await page.waitForTimeout(300)
+
+    // 验证"LSS 列表"子菜单存在
+    const lssListMenu = page.locator('.layout__nav-item--child').filter({ hasText: 'LSS 列表' })
+    await expect(lssListMenu).toBeVisible()
+
+    // 点击子菜单导航到页面
+    await lssListMenu.click()
+    await expect(page).toHaveURL(/\/lss-manage\/list/)
+  })
+
+  /**
+   * Bug #4554 & #4555: 摄像头列表搜索字段
+   */
+  test('Bug #4554/#4555 - 摄像头列表有设备ID和设备名称搜索字段', async ({ page }) => {
+    await login(page)
+    await page.goto('/lss-manage/list')
+    await page.waitForTimeout(1000)
+
+    // 点击编辑按钮进入 LSS 编辑抽屉
+    const editButton = page.locator('tbody tr').first().locator('button').nth(1)
+    await expect(editButton).toBeVisible({ timeout: 10000 })
+    await editButton.click()
+
+    // 等待 LSS 编辑抽屉打开
+    const drawer = page.locator('.el-drawer').filter({ hasText: 'LSS详情' })
+    await expect(drawer).toBeVisible({ timeout: 5000 })
+
+    // 点击"摄像头列表" Tab
+    await drawer.locator('.el-tabs__item').filter({ hasText: '摄像头列表' }).click()
+    await page.waitForTimeout(500)
+
+    // 验证有"设备ID"搜索框
+    await expect(drawer.getByPlaceholder('设备ID')).toBeVisible()
+
+    // 验证有"名称"搜索框
+    await expect(drawer.getByPlaceholder('名称')).toBeVisible()
+
+    // 验证没有"IP / 设备ID / 名称"混合搜索框
+    const mixedSearch = drawer.getByPlaceholder('IP / 设备ID / 名称')
+    await expect(mixedSearch).not.toBeVisible()
+  })
+
+  /**
+   * Bug #4562: 摄像头列表有分页功能
+   */
+  test('Bug #4562 - 摄像头列表有分页功能', async ({ page }) => {
+    await login(page)
+    await page.goto('/lss-manage/list')
+    await page.waitForTimeout(1000)
+
+    // 点击编辑按钮进入 LSS 编辑抽屉
+    const editButton = page.locator('tbody tr').first().locator('button').nth(1)
+    await expect(editButton).toBeVisible({ timeout: 10000 })
+    await editButton.click()
+
+    // 等待 LSS 编辑抽屉打开
+    const drawer = page.locator('.el-drawer').filter({ hasText: 'LSS详情' })
+    await expect(drawer).toBeVisible({ timeout: 5000 })
+
+    // 点击"摄像头列表" Tab
+    await drawer.locator('.el-tabs__item').filter({ hasText: '摄像头列表' }).click()
+    await page.waitForTimeout(500)
+
+    // 验证分页组件存在
+    await expect(drawer.locator('.el-pagination')).toBeVisible()
+  })
+
+  /**
+   * Bug #4567: List厂商显示和详情页一样
+   */
+  test('Bug #4567 - 厂商列使用vendorName字段', async ({ page }) => {
+    await login(page)
+
+    // Mock 摄像头列表 API 返回带有 vendorName 的数据
+    await page.route('**/admin/camera/list*', async (route) => {
+      await route.fulfill({
+        status: 200,
+        contentType: 'application/json',
+        body: JSON.stringify({
+          success: true,
+          errCode: 0,
+          data: {
+            list: [
+              {
+                id: 1,
+                cameraId: 'CAM_001',
+                cameraName: '测试摄像头',
+                lssId: 'LSS_001',
+                status: 'active',
+                vendorName: 'hikvision',
+                model: 'DS-2CD2T45'
+              }
+            ],
+            total: 1
+          }
+        })
+      })
+    })
+
+    await page.goto('/lss-manage/list')
+    await page.waitForTimeout(1000)
+
+    // 点击编辑按钮进入 LSS 编辑抽屉
+    const editButton = page.locator('tbody tr').first().locator('button').nth(1)
+    await expect(editButton).toBeVisible({ timeout: 10000 })
+    await editButton.click()
+
+    // 等待 LSS 编辑抽屉打开
+    const drawer = page.locator('.el-drawer').filter({ hasText: 'LSS详情' })
+    await expect(drawer).toBeVisible({ timeout: 5000 })
+
+    // 点击"摄像头列表" Tab
+    await drawer.locator('.el-tabs__item').filter({ hasText: '摄像头列表' }).click()
+    await page.waitForTimeout(500)
+
+    // 验证厂商列显示正确的格式化名称
+    const vendorCell = drawer.locator('tbody tr').first().locator('td').nth(5)
+    const vendorText = await vendorCell.textContent()
+    expect(vendorText).toContain('HIKVISION')
+  })
+
+  /**
+   * Bug #4588: 参数配置更新按钮蓝底白字
+   */
+  test('Bug #4588 - 参数配置更新按钮使用蓝底白字', async ({ page }) => {
+    await login(page)
+    await page.goto('/lss-manage/list')
+    await page.waitForTimeout(1000)
+
+    // 点击编辑按钮进入 LSS 编辑抽屉
+    const editButton = page.locator('tbody tr').first().locator('button').nth(1)
+    await expect(editButton).toBeVisible({ timeout: 10000 })
+    await editButton.click()
+
+    // 等待 LSS 编辑抽屉打开
+    const drawer = page.locator('.el-drawer').filter({ hasText: 'LSS详情' })
+    await expect(drawer).toBeVisible({ timeout: 5000 })
+
+    // 点击"摄像头列表" Tab
+    await drawer.locator('.el-tabs__item').filter({ hasText: '摄像头列表' }).click()
+    await page.waitForTimeout(500)
+
+    // 点击参数配置"查看"按钮
+    const viewButton = drawer.locator('tbody tr').first().locator('button:has-text("查看")').first()
+    if ((await viewButton.count()) > 0) {
+      await viewButton.click()
+
+      // 等待参数配置抽屉打开
+      const paramsDrawer = page.locator('.el-drawer').filter({ hasText: '参数配置' })
+      await expect(paramsDrawer).toBeVisible({ timeout: 5000 })
+
+      // 验证更新按钮是蓝色
+      const updateButton = paramsDrawer.locator('button:has-text("更新")')
+      await expect(updateButton).toHaveClass(/el-button--primary/)
+    }
+  })
+
+  /**
+   * Bug #4594: 删除确认对话框确定按钮蓝底白字
+   */
+  test('Bug #4594 - 删除确认对话框确定按钮蓝底白字', async ({ page }) => {
+    await login(page)
+
+    // Mock 摄像头列表 API
+    await page.route('**/admin/camera/list*', async (route) => {
+      await route.fulfill({
+        status: 200,
+        contentType: 'application/json',
+        body: JSON.stringify({
+          success: true,
+          errCode: 0,
+          data: {
+            list: [{ id: 1, cameraId: 'CAM_001', cameraName: '测试', status: 'active' }],
+            total: 1
+          }
+        })
+      })
+    })
+
+    await page.goto('/lss-manage/list')
+    await page.waitForTimeout(1000)
+
+    // 点击编辑按钮进入 LSS 编辑抽屉
+    const editButton = page.locator('tbody tr').first().locator('button').nth(1)
+    await expect(editButton).toBeVisible({ timeout: 10000 })
+    await editButton.click()
+
+    // 等待 LSS 编辑抽屉打开
+    const drawer = page.locator('.el-drawer').filter({ hasText: 'LSS详情' })
+    await expect(drawer).toBeVisible({ timeout: 5000 })
+
+    // 点击"摄像头列表" Tab
+    await drawer.locator('.el-tabs__item').filter({ hasText: '摄像头列表' }).click()
+    await page.waitForTimeout(500)
+
+    // 点击删除按钮
+    await drawer.locator('tbody tr').first().locator('button').last().click()
+
+    // 等待确认对话框
+    const messageBox = page.locator('.el-message-box')
+    await expect(messageBox).toBeVisible({ timeout: 5000 })
+
+    // 验证确定按钮是蓝色
+    const confirmButton = messageBox.locator('button.el-button--primary')
+    await expect(confirmButton).toBeVisible()
+
+    const bgColor = await confirmButton.evaluate((el) => {
+      return window.getComputedStyle(el).backgroundColor
+    })
+    // #409EFF 的 RGB 值为 rgb(64, 158, 255)
+    expect(bgColor).toMatch(/rgb\(64,\s*158,\s*255\)|rgba\(64,\s*158,\s*255/)
+
+    // 关闭对话框
+    await messageBox.locator('button:has-text("取消")').click()
+  })
 })