liujintao 4 săptămâni în urmă
părinte
comite
af1f328176

+ 1 - 1
.env.development

@@ -5,7 +5,7 @@ VITE_PUBLIC_PATH='/'
 ## 路由模式 hash 或 html5
 VITE_ROUTER_HISTORY='html5'
 
-VITE_HOST_IP = '192.168.32.100'
+VITE_HOST_IP = '192.168.1.52'
 
 VITE_VIDEO_PORT = '8000'
 

+ 13 - 1
src/api/protocol.ts

@@ -1,7 +1,19 @@
 import { request } from '@/utils/request'
 
+interface OnvifConfig {
+    OnvifEnable: boolean
+    IpAddr: string
+    Port: string
+    OnvifName: string
+    Password: string
+}
+
+interface OnvifResponse {
+    data: OnvifConfig
+}
+
 export function getOnvifProtocolApi() {
-    return request({
+    return request<OnvifResponse>({
         url: `/API/V1.0/Video/Onvif`,
         method: 'get'
     })

+ 3 - 2
src/views/remoteViewing/index.vue

@@ -46,8 +46,9 @@
       <div class="info-item">
         <label>Instructions</label>
         <ol class="instructions-list">
-          <li>Ensure the device is online. If offline, check your network connection and refresh.</li>
-          <li>Use the ZOSI mobile app to scan the QR code to add this device for remote viewing.</li>
+          <li>Ensure the device is connected to the internet and the status shows as "Online". If it is not online, please check your network connection and click the "Refresh" button.</li>
+          <li>Please refer to the device manual and follow the instructions to download the corresponding official app.</li>
+          <li>Open the app, use the scan function to scan the QR code above, and you will complete the device addition to enable remote viewing.</li>
         </ol>
       </div>
     </div>

+ 2 - 2
src/views/settings/alarmSettings/components/lineCrossingDetection/index.vue

@@ -64,7 +64,7 @@ function getLineCrossingDetectionInfo() {
   getLineCrossingDetection().then(resp => {
     form.Enable = resp.data.Enable
     form.Sensitivity = resp.data.Sensitivity
-    form.LightFlashEn = resp.data.LightFlashEn
+    form.LightFlashEn = resp.data.LightFlashEn ?? false
     form.schedule = resp.data.DailyArmMasks
     form.AudioAlarmAB = resp.data.AudioAlarmAB
     form.AudioAlarmBA = resp.data.AudioAlarmBA
@@ -160,4 +160,4 @@ function handleSave() {
     }
   }
 }
-</style>
+</style>

+ 32 - 11
src/views/settings/audioVideo/components/video/index.vue

@@ -119,8 +119,12 @@
 
 <script setup lang="ts">
 import { reactive, ref, onMounted } from 'vue'
-import { ElMessage } from 'element-plus'
-import { getVideoEncodePara, putVideoEncodePara } from '@/api/setting'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { getVideoEncodePara, putVideoEncodePara, cameraReset } from '@/api/setting'
+import { useUserStore } from '@/stores/modules/user'
+import { useRouter } from 'vue-router'
+
+const router = useRouter()
 
 // 主码流参数
 const mainStream = reactive({
@@ -129,7 +133,7 @@ const mainStream = reactive({
   MainFps: 25,
   MainBitRate: 3072,
   MainEcdFmat: 0,
-  MainFrameTime: 100
+  MainFrameTime: 150
 })
 
 // 子码流参数
@@ -139,7 +143,7 @@ const subStream = reactive({
   SecondFps: 25,
   SecondBitRate: 3072,
   SecondEcdFmat: 0,
-  SecondFrameTime: 100
+  SecondFrameTime: 150
 })
 
 // 实时模式
@@ -153,7 +157,7 @@ const mainResolutionOptions = [
   { value: 3, label: '2304*1296 (3M)' },
   { value: 2, label: '1920*1080 (1080P)' },
   { value: 1, label: '1280*720 (720P)' },
-  { value: 0, label: '640*360' },
+  // { value: 0, label: '640*360' },
 ]
 
 // 子码流分辨率选项
@@ -202,14 +206,14 @@ async function resetDefaults() {
   mainStream.MainFps = 25
   mainStream.MainBitRate = 3072
   mainStream.MainEcdFmat = 0
-  mainStream.MainFrameTime = 100
+  mainStream.MainFrameTime = 150
   // 子码流
   subStream.SecondResolution = 0
   subStream.encodeType = 0
   subStream.SecondFps = 25
   subStream.SecondBitRate = 3072
   subStream.SecondEcdFmat = 0
-  subStream.SecondFrameTime = 100
+  subStream.SecondFrameTime = 150
 
   // realtimeMode.value = false
 
@@ -246,25 +250,42 @@ async function fetchParams() {
 
 // 保存参数
 async function saveParams() {
+  try {
+    // 保存前提示用户需要重启才能生效
+    await ElMessageBox.confirm(
+      'Changing the video settings will restart the device.',
+      'Note',
+      {
+        confirmButtonText: 'OK',
+        cancelButtonText: 'Cancel',
+        type: 'warning',
+        confirmButtonClass: 'el-button--danger'
+      }
+    )
+  } catch {
+    // 用户取消,不执行保存
+    return
+  }
+
   try {
     const data = {
       MainResolution: mainStream.MainResolution,
-      // mainEncodeType: mainStream.encodeType,
       MainFps: mainStream.MainFps,
       MainBitRate: mainStream.MainBitRate,
       MainEcdFmat: mainStream.MainEcdFmat,
       MainFrameTime: mainStream.MainFrameTime,
       SecondResolution: subStream.SecondResolution,
-      // subEncodeType: subStream.encodeType,
       SecondFps: subStream.SecondFps,
       SecondBitRate: subStream.SecondBitRate,
       SecondEcdFmat: subStream.SecondEcdFmat,
       SecondFrameTime: subStream.SecondFrameTime,
-      // realtimeMode: realtimeMode.value ? 1 : 0
     }
     const res = await putVideoEncodePara(data)
     if (res.data === 'ok\n') {
-      ElMessage.success('Save Successful')
+      await cameraReset({ reboot: 1 })   // 保存成功后执行重启
+      ElMessage.success('Operation successful. Please wait a moment...')
+      useUserStore().logout()
+      router.push('/login')
     }
   } catch (e) {
     ElMessage.warning('Save Failed')

+ 6 - 3
src/views/settings/imageDisplay/components/osd/index.vue

@@ -54,7 +54,7 @@
           <!-- 显示时间 -->
           <div class="form-item">
             <el-checkbox v-model="form.EnTime">Display Time:</el-checkbox>
-            <span class="form-item__value" v-if="form.EnTime">{{ currentTime }}</span>
+            <span class="form-item__value" v-if="form.EnTime">{{ currentTime2 }}</span>
           </div>
 
           <!-- 显示码率 -->
@@ -163,6 +163,8 @@ function confirmEditName() {
 
 // 实时时间显示
 const currentTime = ref('')
+const currentTime2 = ref('')
+
 let timeTimer: ReturnType<typeof setInterval> | null = null
 
 function updateTime() {
@@ -175,7 +177,8 @@ function updateTime() {
   const h = String(now.getHours()).padStart(2, '0')
   const m = String(now.getMinutes()).padStart(2, '0')
   const s = String(now.getSeconds()).padStart(2, '0')
-  currentTime.value = `${y}-${M}-${d} ${w} ${h}:${m}:${s}`
+  currentTime.value = `${M}-${d}-${y}\u00A0\u00A0\u00A0${h}:${m}:${s}\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0${w}`
+  currentTime2.value = `${M}-${d}-${y} ${h}:${m}:${s} ${w}`
 }
 
 // OSD拖拽相关
@@ -352,7 +355,7 @@ onUnmounted(() => {
   pointer-events: auto;
   cursor: move;
   padding: 2px 6px;
-  font-size: 16px;
+  font-size: 18px;
   font-weight: 500;
   color: #ed0c0c;
   white-space: nowrap;

+ 19 - 8
src/views/settings/netSettings/index.vue

@@ -10,14 +10,12 @@
             <div class="section-title">Port Settings</div>
             <div class="port-row">
               <span class="label">Port:</span>
-              <el-input-number
+              <el-input
                 v-model="Port"
-                :min="1"
-                :max="65535"
-                :step="1"
-                :controls="false"
                 placeholder="1-65535"
                 style="width: 220px;"
+                type="text"
+                @input="handlePortInput"
               />
             </div>
           </div>
@@ -33,18 +31,21 @@
 </template>
 
 <script setup lang="ts">
-import {ref} from "vue";
+import {ref, onMounted} from "vue";
 import IP from './components/IP/index.vue'
 import NetworkDiagnostics from './components/networkDiagnostics/index.vue'
 import { getNetworkPort, putNetworkPort } from '@/api/setting'
+import { ElMessage } from 'element-plus';
 
 const activeName = ref('first')
 const Port = ref('')
 
 function getPortSetting() {
   getNetworkPort().then(res => {
-    if (res.data) {
+    if (res.data && res.data.Port ) {
       Port.value = res.data.Port
+    } else {
+      Port.value = ''
     }
   })
 }
@@ -53,9 +54,19 @@ onMounted(() => {
   getPortSetting()
 })
 
+function handlePortInput(){
+  // 只允许输入数字
+  Port.value = Port.value.replace(/[^0-9]/g, '');
+}
+
 function handleSave(){
+  const portValue = Number(Port.value);
+  if (portValue < 1 || portValue > 65535) {
+    ElMessage.error('Port must be between 1 and 65535');
+    return;
+  }
   putNetworkPort({
-    Port: Number(Port.value)
+    Port: portValue
   }).then(res => {
     if (res.data === 'ok\n') {
       ElMessage.success('Save success')

+ 12 - 39
src/views/standardProtocol/components/onvif/index.vue

@@ -14,14 +14,14 @@
         </el-form-item>
 
         <template v-if="onvifConfig.OnvifEnable">
-          <!-- IP Address -->
-          <el-form-item label="IP Address" prop="IpAddr">
-            <el-input v-model="onvifConfig.IpAddr" placeholder="Enter IP address"/>
+          <!-- IP地址(只读) -->
+          <el-form-item label="IP Address">
+            <el-input v-model="onvifConfig.IpAddr" disabled/>
           </el-form-item>
 
-          <!-- Port -->
-          <el-form-item label="Port" prop="Port">
-            <el-input v-model="onvifConfig.Port" placeholder="Enter port number"/>
+          <!-- 端口(只读) -->
+          <el-form-item label="Port">
+            <el-input v-model="onvifConfig.Port" disabled/>
           </el-form-item>
 
           <!-- ONVIF Username -->
@@ -34,11 +34,12 @@
             <el-input v-model="onvifConfig.Password" type="password" placeholder="Enter ONVIF password" show-password/>
           </el-form-item>
 
-          <!-- Save Button -->
+        </template>
+         <!-- Save Button -->
           <el-form-item>
             <el-button type="primary" @click="saveOnvifConfig" :loading="saving">Save</el-button>
           </el-form-item>
-        </template>
+          
       </el-form>
 
       <!-- Access Example -->
@@ -95,45 +96,17 @@ const saving = ref(false)
 const showSaveToast = ref(false)
 const showCopyToast = ref(false)
 
-// IP address validation
-const validateIp = (_rule: any, value: string, callback: any) => {
-  if (!value) return callback(new Error('Please enter IP address'))
-  const ipReg = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
-  if (!ipReg.test(value)) {
-    callback(new Error('Please enter a valid IP address'))
-  } else {
-    callback()
-  }
-}
-
-// Port validation
-const validatePort = (_rule: any, value: string, callback: any) => {
-  if (!value) return callback(new Error('Please enter port number'))
-  const port = Number(value)
-  if (!Number.isInteger(port) || port < 1 || port > 65535) {
-    callback(new Error('Port range is 1-65535'))
-  } else {
-    callback()
-  }
-}
-
-// Dynamically generate validation rules based on ONVIF switch
+// 动态生成表单验证规则(IP和端口为只读,无需校验)
 const formRules = computed<FormRules>(() => {
   if (!onvifConfig.value.OnvifEnable) return {}
   return {
-    IpAddr: [
-      {required: true, validator: validateIp, trigger: 'blur'}
-    ],
-    Port: [
-      {required: true, validator: validatePort, trigger: 'blur'}
-    ],
     OnvifName: [
       {required: true, message: 'Please enter username', trigger: 'blur'},
-      {min: 6, max: 16, message: 'Username must be 6-16 characters', trigger: 'blur'}
+      {min: 5, max: 16, message: 'Username must be 6-16 characters', trigger: 'blur'}
     ],
     Password: [
       {required: true, message: 'Please enter password', trigger: 'blur'},
-      {min: 6, max: 16, message: 'Password must be 6-16 characters', trigger: 'blur'}
+      {min: 5, max: 16, message: 'Password must be 6-16 characters', trigger: 'blur'}
     ]
   }
 })

+ 1 - 1
src/views/standardProtocol/components/rtsp/index.vue

@@ -75,7 +75,7 @@ import {getUserSettingApi} from '@/api/setting'
 import {getRtspPasswordApi} from '@/api/userManagement'
 
 const passwordVerificationEnabled = ref(false)
-const cameraIp = ref('192.168.1.100')
+const cameraIp = ref('localhost')
 const showCopyToast = ref(false)
 const NIC = 1