Browse Source

style: fix code formatting and add ignore configs

- Create .prettierignore to exclude scripts and Prototype directories
- Update .eslintignore to add scripts and Prototype directories
- Auto-format src and tests with Prettier and ESLint

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
yb 6 days ago
parent
commit
d7c3a08934

+ 2 - 0
.eslintignore

@@ -6,3 +6,5 @@ src/components.d.ts
 coverage
 playwright-report
 test-results
+scripts
+Prototype

+ 10 - 0
.prettierignore

@@ -0,0 +1,10 @@
+node_modules
+dist
+*.d.ts
+src/auto-imports.d.ts
+src/components.d.ts
+coverage
+playwright-report
+test-results
+scripts
+Prototype

+ 2 - 1
src/api/stream-push.ts

@@ -19,8 +19,9 @@
  */
 
 import { get, post } from '@/utils/request'
-import type { IBaseResponse, IListResponse } from '@/types'
 import type {
+  IBaseResponse,
+  IListResponse,
   LocalVideoStreamDTO,
   StartLocalStreamRequest,
   StreamTaskDTO,

+ 1 - 1
src/layout/index.vue

@@ -186,11 +186,11 @@ import { computed, onMounted, onUnmounted, ref, reactive } from 'vue'
 import { Icon } from '@iconify/vue'
 import { useRoute, useRouter } from 'vue-router'
 import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
+import { useI18n } from 'vue-i18n'
 import LangDropdown from '@/components/LangDropdown.vue'
 import { useAppStore } from '@/store/app'
 import { useUserStore } from '@/store/user'
 import { changePassword } from '@/api/login'
-import { useI18n } from 'vue-i18n'
 
 const route = useRoute()
 const router = useRouter()

+ 1 - 1
src/locales/en.json

@@ -289,4 +289,4 @@
   "默认分辨率": "Default Resolution",
   "默认端口": "Default Port",
   "默认视角": "Default View"
-}
+}

+ 1 - 1
src/router/index.ts

@@ -1,6 +1,6 @@
 import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
-import { getToken } from '@/utils/auth'
 import NProgress from 'nprogress'
+import { getToken } from '@/utils/auth'
 import 'nprogress/nprogress.css'
 
 // NProgress 配置

+ 1 - 1
src/utils/auth.ts

@@ -4,7 +4,7 @@ const TOKEN_KEY = 'token'
  * 获取 cookie 值
  */
 function getCookie(name: string): string | null {
-  const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'))
+  const match = document.cookie.match(new RegExp(`(^| )${name}=([^;]+)`))
   return match ? decodeURIComponent(match[2]) : null
 }
 

+ 10 - 8
src/utils/dataFormat.ts

@@ -1,4 +1,5 @@
 import { ref } from 'vue'
+
 export interface FormOptions {
   value: string
   label: string
@@ -66,7 +67,7 @@ export const changeUploadDataWithCustom = (
     return {
       uploadData: {
         fileType: mapping.uploadType,
-        uploadFrom: `${basePath}${attachmentId ? '/' + attachmentId : ''}`,
+        uploadFrom: `${basePath}${attachmentId ? `/${attachmentId}` : ''}`,
         storageStyle: 6
       },
       fileType: mapping.fileType
@@ -82,7 +83,7 @@ export const changeUploadDataWithCustom = (
     return {
       uploadData: {
         fileType: mapping.uploadType,
-        uploadFrom: `${basePath}${attachmentId ? '/' + attachmentId : ''}`,
+        uploadFrom: `${basePath}${attachmentId ? `/${attachmentId}` : ''}`,
         storageStyle: 6
       },
       fileType: mapping.fileType
@@ -107,7 +108,7 @@ export const showFileSize = (_size: string | number) => {
   if (typeof size === 'string') {
     size = Number(size)
   }
-  return (size / 1024 / 1024).toFixed(3) + 'MB'
+  return `${(size / 1024 / 1024).toFixed(3)}MB`
 }
 
 //将6位以上的值 以*显示,总长度限制在10位
@@ -231,7 +232,8 @@ export const decodeHtmlEntities = (str: string) => {
 export const changeUploadData = (mimeType: string, uploadPath: string) => {
   console.log(mimeType)
 
-  let fileType, uploadType
+  let fileType
+  let uploadType
 
   switch (mimeType) {
     case 'image/jpeg':
@@ -288,7 +290,7 @@ export const changeUploadData = (mimeType: string, uploadPath: string) => {
       uploadFrom: uploadPath,
       storageStyle: 6 // This value is kept as it might be a constant for your system
     },
-    fileType: fileType
+    fileType
   }
 }
 /**
@@ -333,7 +335,7 @@ export const qs = (obj: Record<string, any>): string => {
 
 export const truncateText = (text: string, limit = 10) => {
   if (!text) return ''
-  return text.length > limit ? text.slice(0, limit) + '...' : text
+  return text.length > limit ? `${text.slice(0, limit)}...` : text
 }
 
 export const extractTextFromHTML = (text: string, limit = 10) => {
@@ -344,10 +346,10 @@ export const extractTextFromHTML = (text: string, limit = 10) => {
     const doc = parser.parseFromString(text, 'text/html')
     // Get the text content from the parsed HTML
     const plainText = doc.body.textContent || text
-    return plainText.length > limit ? plainText.slice(0, limit) + '...' : plainText
+    return plainText.length > limit ? `${plainText.slice(0, limit)}...` : plainText
   } catch (error) {
     // If parsing fails, return the original text
-    return text.length > limit ? text.slice(0, limit) + '...' : text
+    return text.length > limit ? `${text.slice(0, limit)}...` : text
   }
 }
 

+ 2 - 2
src/views/camera-vendor/index.vue

@@ -241,6 +241,8 @@
 import { ref, reactive, onMounted, computed } from 'vue'
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules, type TableInstance } from 'element-plus'
 import { Plus, Edit, Delete, Search, RefreshRight, Setting } from '@element-plus/icons-vue'
+import dayjs from 'dayjs'
+import { useI18n } from 'vue-i18n'
 import {
   listCameraVendors,
   addCameraVendor,
@@ -249,8 +251,6 @@ import {
   initCameraVendors
 } from '@/api/camera-vendor'
 import type { CameraVendorDTO, CameraVendorAddRequest, CameraVendorUpdateRequest } from '@/types'
-import dayjs from 'dayjs'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n({ useScope: 'global' })
 

+ 2 - 2
src/views/camera/index.vue

@@ -311,11 +311,11 @@
 import { ref, reactive, onMounted, computed } from 'vue'
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
 import { Plus, Edit, Delete, Search, RefreshRight, View, Connection } from '@element-plus/icons-vue'
+import dayjs from 'dayjs'
+import { useI18n } from 'vue-i18n'
 import { adminListCameras, adminAddCamera, adminUpdateCamera, adminDeleteCamera, adminCheckCamera } from '@/api/camera'
 import { listAllMachines } from '@/api/machine'
 import type { CameraInfoDTO, ChannelInfoDTO, CameraAddRequest, CameraUpdateRequest, MachineDTO } from '@/types'
-import dayjs from 'dayjs'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n({ useScope: 'global' })
 

+ 1 - 1
src/views/dashboard/index.vue

@@ -203,9 +203,9 @@
 import { ref, onMounted, computed } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n'
 import { getDashboardStats } from '@/api/stats'
 import type { DashboardStatsDTO } from '@/types'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
 const router = useRouter()

+ 1 - 1
src/views/demo/direct-url.vue

@@ -77,8 +77,8 @@
 import { ref, reactive } from 'vue'
 import { ElMessage } from 'element-plus'
 import { VideoPlay } from '@element-plus/icons-vue'
-import VideoPlayer from '@/components/VideoPlayer.vue'
 import { useI18n } from 'vue-i18n'
+import VideoPlayer from '@/components/VideoPlayer.vue'
 
 const { t } = useI18n()
 

+ 1 - 1
src/views/demo/video-demo.vue

@@ -172,8 +172,8 @@
 import { ref, reactive } from 'vue'
 import { ElMessage } from 'element-plus'
 import { VideoPlay } from '@element-plus/icons-vue'
-import VideoPlayer from '@/components/VideoPlayer.vue'
 import { useI18n } from 'vue-i18n'
+import VideoPlayer from '@/components/VideoPlayer.vue'
 
 const { t } = useI18n()
 

+ 4 - 4
src/views/live-stream/index.vue

@@ -413,17 +413,17 @@ import {
   ZoomOut,
   Close
 } from '@element-plus/icons-vue'
+import { Icon } from '@iconify/vue'
+import dayjs from 'dayjs'
+import { useI18n } from 'vue-i18n'
 import { listLiveStreams, addLiveStream, updateLiveStream, deleteLiveStream } from '@/api/live-stream'
 import { listAllLssNodes } from '@/api/lss'
 import { adminListCameras } from '@/api/camera'
-import { Icon } from '@iconify/vue'
 import { startStreamTask, stopStreamTask, getStreamPlayback } from '@/api/stream-push'
 import VideoPlayer from '@/components/VideoPlayer.vue'
 import CodeEditor from '@/components/CodeEditor.vue'
 import { ptzStart, ptzStop, getPresets, gotoPreset, type PresetInfo } from '@/api/camera'
 import type { LiveStreamDTO, LiveStreamStatus, LssNodeDTO, CameraInfoDTO, StreamChannelDTO } from '@/types'
-import dayjs from 'dayjs'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n({ useScope: 'global' })
 const route = useRoute()
@@ -1066,7 +1066,7 @@ async function handleGotoPreset(preset: PresetInfo) {
     activePresetToken.value = preset.token
     const res = await gotoPreset(currentMediaStream.value.cameraId, preset.token)
     if (res.success) {
-      ElMessage.success(t('已跳转到预置位') + `: ${preset.name || preset.token}`)
+      ElMessage.success(`${t('已跳转到预置位')}: ${preset.name || preset.token}`)
     } else {
       ElMessage.error(res.errMessage || t('跳转失败'))
     }

+ 1 - 1
src/views/login/index.vue

@@ -173,10 +173,10 @@
 import { ref, reactive, onMounted, watch } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 import { ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n'
 import LangDropdown from '@/components/LangDropdown.vue'
 import { useUserStore } from '@/store/user'
 import type { LoginParams } from '@/types'
-import { useI18n } from 'vue-i18n'
 
 const router = useRouter()
 const route = useRoute()

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

@@ -567,10 +567,14 @@
 import { ref, reactive, onMounted, computed, watch } from 'vue'
 import { Search, RefreshRight, Delete, View, Edit, VideoCamera, Plus, QuestionFilled } from '@element-plus/icons-vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { Icon } from '@iconify/vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import dayjs from 'dayjs'
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
 import { listLssNodes, deleteLssNode, setLssNodeEnabled, updateLssNode } from '@/api/lss'
 import { adminListCameras, adminAddCamera, adminUpdateCamera, adminDeleteCamera, adminGetCamera } from '@/api/camera'
 import { listCameraVendors } from '@/api/camera-vendor'
-import { Icon } from '@iconify/vue'
 import CodeEditor from '@/components/CodeEditor.vue'
 import type {
   LssNodeDTO,
@@ -584,10 +588,7 @@ import type {
   IAbly,
   CameraHeartbeatStatus
 } from '@/types'
-import type { FormInstance, FormRules } from 'element-plus'
-import dayjs from 'dayjs'
-import { useI18n } from 'vue-i18n'
-import { useRouter } from 'vue-router'
+
 const { t } = useI18n({ useScope: 'global' })
 
 const router = useRouter()
@@ -631,13 +632,13 @@ function formatCameraStatus(row: CameraInfoDTO): string {
   if (row.status === 'active') {
     // 大约5秒钟
     return `active [${formatTime(row.updatedAt)}]`
-  } else if (row.status === 'hold') {
+  }
+  if (row.status === 'hold') {
     // 大约5分钟没有返回
     return `hold [${formatTime(row.updatedAt)}]`
-  } else {
-    // 大约10分钟没有返回
-    return `dead (离线)`
   }
+  // 大约10分钟没有返回
+  return `dead (离线)`
 }
 
 // 当前激活的摄像头 ID
@@ -694,11 +695,11 @@ function formatHeartbeat(lss: LssNodeDTO | null | undefined): string {
   const time = lss.heartbeatTime || lss.updatedAt
   if (status === 'active') {
     return `active [${formatTime(time)}]`
-  } else if (status === 'hold') {
+  }
+  if (status === 'hold') {
     return `hold [${formatTime(time)}]`
-  } else {
-    return `dead (离线)`
   }
+  return `dead (离线)`
 }
 
 // 获取心跳状态样式类

+ 2 - 2
src/views/machine/index.vue

@@ -188,10 +188,10 @@
 import { ref, reactive, onMounted, computed } from 'vue'
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules, type TableInstance } from 'element-plus'
 import { Plus, Edit, Delete, Search, RefreshRight } from '@element-plus/icons-vue'
-import { listMachines, addMachine, updateMachine, deleteMachine } from '@/api/machine'
-import type { MachineDTO, MachineAddRequest, MachineUpdateRequest } from '@/types'
 import dayjs from 'dayjs'
 import { useI18n } from 'vue-i18n'
+import { listMachines, addMachine, updateMachine, deleteMachine } from '@/api/machine'
+import type { MachineDTO, MachineAddRequest, MachineUpdateRequest } from '@/types'
 
 const { t } = useI18n({ useScope: 'global' })
 

+ 1 - 1
src/views/monitor/index.vue

@@ -50,10 +50,10 @@
 import { ref, computed, onMounted } from 'vue'
 import { Plus, FolderChecked } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n'
 import VideoGrid from '@/components/monitor/VideoGrid.vue'
 import CameraSelector from '@/components/monitor/CameraSelector.vue'
 import { useMonitorStore, type GridSlot, type CameraVendor } from '@/composables/useMonitorStore'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
 

+ 1 - 1
src/views/stream/config.vue

@@ -133,9 +133,9 @@
 <script setup lang="ts">
 import { ref, reactive, computed, onMounted } from 'vue'
 import { ElMessage } from 'element-plus'
+import { useI18n } from 'vue-i18n'
 import VideoPlayer from '@/components/VideoPlayer.vue'
 import { useStreamStore } from '@/store/stream'
-import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
 

+ 1 - 1
tests/e2e/auth.spec.ts

@@ -11,7 +11,7 @@ test.describe('登录登出测试', () => {
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()

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

@@ -10,7 +10,7 @@ async function login(page: Page) {
   await page.evaluate(() => {
     localStorage.clear()
     document.cookie.split(';').forEach((c) => {
-      document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+      document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
     })
   })
   await page.reload()

+ 4 - 4
tests/e2e/lss.spec.ts

@@ -20,7 +20,7 @@ test.describe('LSS管理 CRUD 测试', () => {
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()
@@ -187,7 +187,7 @@ test.describe('LSS管理 - CodeEditor 组件测试 (JSON模式)', () => {
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()
@@ -493,7 +493,7 @@ test.describe('LSS管理 - 摄像头列表搜索测试', () => {
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()
@@ -819,7 +819,7 @@ test.describe('LSS管理 - 摄像头未创建 Live Stream 对话框测试', () =
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()

+ 1 - 1
tests/e2e/machine.spec.ts

@@ -17,7 +17,7 @@ test.describe('机器管理 CRUD 测试', () => {
     await page.evaluate(() => {
       localStorage.clear()
       document.cookie.split(';').forEach((c) => {
-        document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+        document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
       })
     })
     await page.reload()

+ 8 - 0
tests/unit/components/VideoPlayer.spec.ts

@@ -8,19 +8,27 @@ vi.mock('hls.js', () => ({
     static isSupported() {
       return true
     }
+
     static Events = {
       MANIFEST_PARSED: 'hlsManifestParsed',
       ERROR: 'hlsError'
     }
+
     static ErrorTypes = {
       NETWORK_ERROR: 'networkError',
       MEDIA_ERROR: 'mediaError'
     }
+
     loadSource = vi.fn()
+
     attachMedia = vi.fn()
+
     on = vi.fn()
+
     destroy = vi.fn()
+
     startLoad = vi.fn()
+
     recoverMediaError = vi.fn()
   }
 }))

+ 2 - 2
tests/unit/utils/auth.spec.ts

@@ -7,14 +7,14 @@ describe('Auth Utils', () => {
   beforeEach(() => {
     // Clear cookies before each test
     document.cookie.split(';').forEach((c) => {
-      document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+      document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
     })
   })
 
   afterEach(() => {
     // Clean up after each test
     document.cookie.split(';').forEach((c) => {
-      document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
+      document.cookie = c.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`)
     })
   })