fix:优化吊舱后台登录逻辑

master
zhoulexin 4 weeks ago
parent 2079a63bdc
commit bdd4bfd582

@ -0,0 +1,55 @@
import { ref } from 'vue'
import { newPodApi } from '@/api/user'
// 模块级变量,确保所有组件实例共享同一个定时器状态
let keepAliveTimer = null
const isRunning = ref(false)
export function useKeepAlive() {
const callKeepAlive = async () => {
const session = localStorage.getItem('newPodSession')
if (!session) {
stopKeepAlive()
return
}
try {
await newPodApi({
session: Number(session),
id: 2,
call: {
service: 'rpc',
method: 'keepAlive'
},
params: {
timeout: 60
}
})
} catch (e) {
console.error('KeepAlive error:', e)
}
}
const startKeepAlive = () => {
if (keepAliveTimer) return // 已启动,避免重复
const session = localStorage.getItem('newPodSession')
if (!session) return
isRunning.value = true
callKeepAlive()
keepAliveTimer = setInterval(callKeepAlive, 60000)
}
const stopKeepAlive = () => {
if (keepAliveTimer) {
clearInterval(keepAliveTimer)
keepAliveTimer = null
}
isRunning.value = false
}
return {
isRunning,
startKeepAlive,
stopKeepAlive
}
}

@ -36,25 +36,14 @@ 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
}
}

@ -7,7 +7,7 @@ function createService(baseURL) {
const service = axios.create({
baseURL: baseURL,
timeout: 15000
timeout: 120000
})
// 请求拦截器

@ -59,9 +59,9 @@
<div class="focus-controls">
<div class="control-row">
<el-button-group>
<el-button icon="ZoomOut" @click="focusing(-1)" />
<el-button icon="ZoomOut" @mousedown="focusing(-1)" @mouseup="focusing(0)" />
<el-button disabled class="control-label">调焦</el-button>
<el-button icon="ZoomIn" @click="focusing(1)" />
<el-button icon="ZoomIn" @mousedown="focusing(1)" @mouseup="focusing(0)" />
</el-button-group>
</div>
</div>
@ -72,9 +72,9 @@
<div class="focus-controls">
<div class="control-row">
<el-button-group>
<el-button icon="ZoomOut" @click="focus(-1)" />
<el-button icon="ZoomOut" @mousedown="focus(-1)" @mouseup="focus(0)" />
<el-button disabled class="control-label">聚焦</el-button>
<el-button icon="ZoomIn" @click="focus(1)" />
<el-button icon="ZoomIn" @mousedown="focus(1)" @mouseup="focus(0)" />
</el-button-group>
</div>
</div>
@ -85,9 +85,9 @@
<div class="aperture-controls">
<div class="control-row">
<el-button-group>
<el-button icon="ZoomOut" @click="aperture(-1)" />
<el-button icon="ZoomOut" @mousedown="aperture(-1)" @mouseup="aperture(0)" />
<el-button disabled class="control-label">光圈</el-button>
<el-button icon="ZoomIn" @click="aperture(1)" />
<el-button icon="ZoomIn" @mousedown="aperture(1)" @mouseup="aperture(0)" />
</el-button-group>
</div>
</div>
@ -135,24 +135,46 @@
>
{{ recordingStates[index] ? '停止' : '录屏' }}
</el-button>
<el-button size="small" icon="FullScreen">放大</el-button>
<el-button size="small" icon="FullScreen" @click="openEnlarge(index)"></el-button>
</div>
</div>
</div>
</div>
</div>
<!-- 放大弹窗 -->
<el-dialog
v-model="enlargeVisible"
:title="enlargeTitle"
fullscreen
destroy-on-close
:close-on-press-escape="true"
@closed="handleEnlargeClosed"
>
<div class="enlarge-video-body">
<WebRtcPlayer
v-if="enlargeVisible && deviceInfos.cameras && enlargedIndex !== null"
:key="'enlarge-' + enlargedIndex"
:src="`${deviceInfos.cameras[enlargedIndex]?.videoStreaming}/whep`"
/>
</div>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, markRaw } from 'vue'
import { ref, onMounted, onBeforeUnmount, markRaw, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import sha256 from 'js-sha256'
import { getPodInfos } from '@/api/pod_detail'
import { newPodApi } from '@/api/user'
import { TopLeft, Top, TopRight, Back, Refresh, Right, BottomLeft, Bottom, BottomRight } from '@element-plus/icons-vue'
import fileHttp from '@/utils/fileHttp'
import WebRtcPlayer from '@/components/WebRtcPlayer.vue'
import { useKeepAlive } from '@/composables/useKeepAlive'
const { startKeepAlive } = useKeepAlive()
const { stopKeepAlive } = useKeepAlive()
// 33
const directionRows = [
[
@ -192,19 +214,12 @@ const podInfo = async () => {
}
}
//
const newPodSession = localStorage.getItem('newPodSession')
const params = {
"session": Number(newPodSession),
"id": 2,
"call": {
"service": "ptz",
"method": "setPTZCmd"
},
}
const newPodSession = ref(0)
const params = ref({})
//
const controlPod = (x,y) => {
const reqParams = {
...params,
...params.value,
"params": {
"channel": 0,
"continuousPanTiltSpace": {
@ -213,14 +228,14 @@ const controlPod = (x,y) => {
}
}
}
newPodApi(reqParams)
podApi(reqParams)
}
//
const isRotating = ref(false)
const podRotation = ()=>{
isRotating.value = !isRotating.value
const reqParams = {
...params,
...params.value,
"params": {
"channel": 0,
"autoPanCtrl": {
@ -228,12 +243,12 @@ const podRotation = ()=>{
}
}
}
newPodApi(reqParams)
podApi(reqParams)
}
//
const focusing = async(val) => {
const focusing = (val) => {
const reqParams = {
...params,
...params.value,
"params": {
"channel": 0,
"continuousZoomSpace": {
@ -241,14 +256,12 @@ const focusing = async(val) => {
}
}
}
await newPodApi(reqParams)
reqParams.params.continuousZoomSpace.z = 0
newPodApi(reqParams)
podApi(reqParams)
}
//
const focus = async(val) => {
const focus = (val) => {
const reqParams = {
...params,
...params.value,
"params": {
"channel": 0,
"focusCtrl": {
@ -256,14 +269,12 @@ const focus = async(val) => {
}
}
}
await newPodApi(reqParams)
reqParams.params.focusCtrl.focus = 0
newPodApi(reqParams)
podApi(reqParams)
}
//
const aperture = async(val) => {
const aperture = (val) => {
const reqParams = {
...params,
...params.value,
"params": {
"channel": 0,
"irisCtrl": {
@ -271,15 +282,13 @@ const aperture = async(val) => {
}
}
}
await newPodApi(reqParams)
reqParams.params.irisCtrl.iris = 0
newPodApi(reqParams)
podApi(reqParams)
}
//
const wiperCtrl = ref(false)
const wiper = () => {
const reqParams = {
"session": Number(newPodSession),
"session": Number(newPodSession.value),
"id": 2,
"call": {
"service": "ptz",
@ -289,14 +298,14 @@ const wiper = () => {
"wiper": wiperCtrl.value ? "on" : "off"
}
}
newPodApi(reqParams)
podApi(reqParams)
}
//
const initialization = ref(false)
const lensInitialization = async() => {
initialization.value = true
const reqParams = {
"session": Number(newPodSession),
"session": Number(newPodSession.value),
"id": 2,
"call": {
"service": "ptz",
@ -306,13 +315,37 @@ const lensInitialization = async() => {
"channel": 0
}
}
await newPodApi(reqParams)
await podApi(reqParams)
initialization.value = false
}
const podApi = async (reqParams) => {
const res = await newPodApi(reqParams)
if(res.error && !res.result){
console.error('设备session失效即将刷新请求')
await podLogout()
await loadPod()
newPodApi(reqParams)
}
}
//
const goBack = () => {
const goBack = async() => {
await podLogout()
router.push('/home')
}
const podLogout = async () => {
const params = {
"session": Number(newPodSession.value),
"id": 2,
"call": {
"service": "rpc",
"method": "logout"
}
}
// 退
await newPodApi(params)
localStorage.removeItem('newPodSession')
stopKeepAlive()
}
const playerRefs = ref([])
const recordingStates = ref({})
@ -380,6 +413,23 @@ const handleRecordStatus = (index, status) => {
recordingStates.value[index] = status
}
//
const enlargedIndex = ref(null)
const enlargeVisible = ref(false)
const enlargeTitle = computed(() => {
if (enlargedIndex.value !== null && deviceInfos.value.cameras) {
return deviceInfos.value.cameras[enlargedIndex.value]?.cameraLocation || '视频放大'
}
return '视频放大'
})
const openEnlarge = (index) => {
enlargedIndex.value = index
enlargeVisible.value = true
}
const handleEnlargeClosed = () => {
enlargedIndex.value = null
}
//
const uploadImageToServer = async (blob, index) => {
const formData = new FormData()
@ -394,12 +444,58 @@ const uploadImageToServer = async (blob, index) => {
ElMessage.error('截图上传失败')
}
}
const generateRandomString = (length = 6) => {
// + ( I, O )
const chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
let result = '';
const charsLength = chars.length;
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charsLength);
result += chars[randomIndex];
}
return result;
}
const loadPod = async() => {
//
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
}
})
newPodSession.value = podLogin.params.session
params.value = {
"session": Number(newPodSession.value),
"id": 2,
"call": {
"service": "ptz",
"method": "setPTZCmd"
},
}
localStorage.setItem('newPodSession', podLogin.params.session)
startKeepAlive()
}
onMounted(() => {
loadPod()
podInfo()
})
onBeforeUnmount(() => {
podLogout()
})
</script>
@ -640,4 +736,21 @@ onBeforeUnmount(() => {
object-fit: contain;
}
}
:deep(.el-dialog.is-fullscreen) {
.el-dialog__body {
padding: 0;
height: calc(100% - 56px);
background: #000;
}
}
.enlarge-video-body {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #000;
}
</style>

@ -44,14 +44,14 @@
<canvas ref="faceCanvasRef" class="face-canvas"></canvas>
</div>
</div>
<div class="camera-card">
<!-- <div class="camera-card">
<div class="camera-header">
<span class="camera-title"></span>
</div>
<div class="camera-video" style="color: white; display: flex; align-items: center; justify-content: center;">
<span>暂无画面</span>
</div>
</div>
</div> -->
</div>
</template>

@ -129,7 +129,6 @@ const loading = ref(false)
const showAddDialog = ref(false)
const editData = ref(null)
const isEdit = ref(false)
//
const viewDetail = (item) => {
router.push({

@ -108,8 +108,6 @@ import { useRouter, useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/stores/user'
import { newPodApi } from '@/api/user'
import md5 from 'js-md5'
import sha256 from 'js-sha256'
import AuthLogo from '@/components/AuthLogo.vue'
import AuthBackground from '@/components/AuthBackground.vue'
@ -175,20 +173,6 @@ const loginRules = {
{ required: true, message: '请输入密码', trigger: 'blur' }
]
}
const generateRandomString = (length = 6) => {
// + ( I, O )
const chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
let result = '';
const charsLength = chars.length;
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charsLength);
result += chars[randomIndex];
}
return result;
}
const handleLogin = async () => {
if (!loginFormRef.value) return
@ -198,25 +182,6 @@ 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()

Loading…
Cancel
Save