diff --git a/index.html b/index.html
index aa34e5c..c09c3ba 100644
--- a/index.html
+++ b/index.html
@@ -2,6 +2,7 @@
录制中 {{ recordTime }}s
@@ -36,6 +42,7 @@ const emit = defineEmits(['record-status-change','record-complete']);
const videoRef = ref(null);
const error = ref('');
+const loading = ref(false);
let pc = null;
// --- 录屏相关状态 ---
@@ -59,6 +66,8 @@ const disconnect = () => {
// 2. 连接 WebRTC
const connect = async () => {
+ loading.value = true;
+ error.value = '';
try {
pc = new RTCPeerConnection();
pc.ontrack = (event) => {
@@ -85,6 +94,11 @@ const connect = async () => {
} catch (e) {
error.value = '连接失败,请检查视频地址';
console.error(e);
+ } finally {
+ let timeout = setTimeout(() => {
+ loading.value = false;
+ clearTimeout(timeout);
+ }, 1500);
}
};
@@ -215,6 +229,29 @@ defineExpose({
.video-player { width: 100%; height: 100%; object-fit: contain; }
.error-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; }
+.loading-overlay {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: rgba(255, 255, 255, 0.85);
+ font-size: 14px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.spinner {
+ width: 20px;
+ height: 20px;
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ border-top-color: #409eff;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+}
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
.recording-indicator {
position: absolute;
top: 10px;
diff --git a/src/layout/index.vue b/src/layout/index.vue
index c3b4a89..c4c130d 100644
--- a/src/layout/index.vue
+++ b/src/layout/index.vue
@@ -2,10 +2,8 @@
{
const token = ref(localStorage.getItem('token') || '')
@@ -36,15 +36,25 @@ export const useUserStore = defineStore('user', () => {
const logout = async () => {
if (isLoggingOut.value) return
isLoggingOut.value = true
-
+ const params = {
+ "session": 2878481200,
+ "id": 2,
+ "call": {
+ "service": "rpc",
+ "method": "logout"
+ }
+ }
try {
await logoutApi()
+ // 退出后台吊舱登录
+ await newPodApi(params)
} catch (e) {
// 忽略logout接口错误
} finally {
token.value = ''
userInfo.value = null
localStorage.removeItem('token')
+ localStorage.removeItem('newPodSession')
isLoggingOut.value = false
}
}
diff --git a/src/views/detail/index.vue b/src/views/detail/index.vue
index 8734ce3..6d86dd4 100644
--- a/src/views/detail/index.vue
+++ b/src/views/detail/index.vue
@@ -192,8 +192,9 @@ const podInfo = async () => {
}
}
// 控制设备
+const newPodSession = localStorage.getItem('newPodSession')
const params = {
- "session": 671150784,
+ "session": Number(newPodSession),
"id": 2,
"call": {
"service": "ptz",
@@ -278,7 +279,7 @@ const aperture = async(val) => {
const wiperCtrl = ref(false)
const wiper = () => {
const reqParams = {
- "session": 671150784,
+ "session": Number(newPodSession),
"id": 2,
"call": {
"service": "ptz",
@@ -295,7 +296,7 @@ const initialization = ref(false)
const lensInitialization = async() => {
initialization.value = true
const reqParams = {
- "session": 671150784,
+ "session": Number(newPodSession),
"id": 2,
"call": {
"service": "ptz",
diff --git a/src/views/face-recognition/components/AiChatPanel.vue b/src/views/face-recognition/components/AiChatPanel.vue
index 22ef717..36d7305 100644
--- a/src/views/face-recognition/components/AiChatPanel.vue
+++ b/src/views/face-recognition/components/AiChatPanel.vue
@@ -97,12 +97,13 @@
@keydown.enter.exact.prevent="handleSend"
/>
-
+
-
+
+ 取消
清空
确定
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index 5756147..04c908f 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -176,32 +176,20 @@ const loginRules = {
]
}
const generateRandomString = (length = 6) => {
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- let result = ''
+ // 定义字符集:数字 + 大写字母 (去除了易混淆的 I, O 等,可根据需求调整)
+ const chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
+
+ let result = '';
+ const charsLength = chars.length;
+
for (let i = 0; i < length; i++) {
- result += chars.charAt(Math.floor(Math.random() * chars.length))
+ const randomIndex = Math.floor(Math.random() * charsLength);
+ result += chars[randomIndex];
}
- return result
+
+ return result;
}
const handleLogin = async () => {
- // const random = generateRandomString()
- // const podLogin = await newPodApi({
- // "session": 0,
- // "id": 2,
- // "call": {
- // "service": "rpc",
- // "method": "login"
- // },
- // "params": {
- // "userName": "admin",
- // "password": sha256(md5('abcd1234')+random),
- // "random": random,
- // "ip": "127.0.0.1",
- // "port": 80,
- // "encryptType": 1
- // }
- // })
- // return;
if (!loginFormRef.value) return
await loginFormRef.value.validate(async (valid) => {
@@ -210,6 +198,25 @@ const handleLogin = async () => {
try {
const res = await userStore.login(loginForm)
if (res.success) {
+ // 登录后台吊舱管理
+ const random = generateRandomString()
+ const podLogin = await newPodApi({
+ "session": 0,
+ "id": 2,
+ "call": {
+ "service": "rpc",
+ "method": "login"
+ },
+ "params": {
+ "userName": "admin",
+ "password": sha256(sha256('abcd1234') + random),
+ "random": random,
+ "ip": "127.0.0.1",
+ "port": 80,
+ "encryptType": 1
+ }
+ })
+ localStorage.setItem('newPodSession', podLogin.params.session)
// 处理记住密码
if (rememberMe.value) {
saveCredentials()