1
This commit is contained in:
@@ -134,56 +134,43 @@ function handleMenuSelect(key: string) {
|
||||
async function handleLoginSuccess(data: { token: string; permissions?: string }) {
|
||||
isAuthenticated.value = true
|
||||
showAuthDialog.value = false
|
||||
showRegDialog.value = false // 确保注册对话框也关闭
|
||||
showRegDialog.value = false
|
||||
|
||||
try {
|
||||
// 保存token到本地数据库
|
||||
await authApi.saveToken(data.token)
|
||||
|
||||
const username = getUsernameFromToken(data.token)
|
||||
currentUsername.value = username
|
||||
userPermissions.value = data?.permissions || ''
|
||||
await deviceApi.register({username})
|
||||
|
||||
// 建立SSE连接
|
||||
SSEManager.connect()
|
||||
} catch (e: any) {
|
||||
// 设备注册失败时回滚登录状态
|
||||
isAuthenticated.value = false
|
||||
showAuthDialog.value = true
|
||||
await authApi.deleteTokenCache()
|
||||
ElMessage({
|
||||
message: e?.message || '设备注册失败,请重试',
|
||||
type: 'error'
|
||||
})
|
||||
ElMessage.error(e?.message || '设备注册失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
// 主动设置设备离线
|
||||
try {
|
||||
const deviceId = await getClientIdFromToken()
|
||||
if (deviceId) {
|
||||
await deviceApi.offline({ deviceId })
|
||||
}
|
||||
if (deviceId) await deviceApi.offline({ deviceId })
|
||||
} catch (error) {
|
||||
console.warn('离线通知失败:', error)
|
||||
}
|
||||
|
||||
const token = await authApi.getToken()
|
||||
if (token) {
|
||||
await authApi.logout(token)
|
||||
}
|
||||
try {
|
||||
const tokenRes: any = await authApi.getToken()
|
||||
const token = typeof tokenRes === 'string' ? tokenRes : tokenRes?.data
|
||||
if (token) await authApi.logout(token)
|
||||
} catch {}
|
||||
|
||||
await authApi.deleteTokenCache()
|
||||
// 清理前端状态
|
||||
isAuthenticated.value = false
|
||||
currentUsername.value = ''
|
||||
userPermissions.value = ''
|
||||
showAuthDialog.value = true
|
||||
showDeviceDialog.value = false
|
||||
|
||||
// 关闭SSE连接
|
||||
SSEManager.disconnect()
|
||||
}
|
||||
|
||||
@@ -199,12 +186,8 @@ async function handleUserClick() {
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
await logout()
|
||||
ElMessage({
|
||||
message: '已退出登录',
|
||||
type: 'success'
|
||||
})
|
||||
} catch {
|
||||
}
|
||||
ElMessage.success('已退出登录')
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function showRegisterDialog() {
|
||||
@@ -218,26 +201,23 @@ function backToLogin() {
|
||||
}
|
||||
|
||||
async function checkAuth() {
|
||||
const authRequiredMenus = ['rakuten', 'amazon', 'zebra', 'shopee']
|
||||
|
||||
try {
|
||||
await authApi.sessionBootstrap().catch(() => undefined)
|
||||
const token = await authApi.getToken()
|
||||
const tokenRes: any = await authApi.getToken()
|
||||
const token = typeof tokenRes === 'string' ? tokenRes : tokenRes?.data
|
||||
|
||||
if (token) {
|
||||
const response = await authApi.verifyToken(token)
|
||||
if (response?.success) {
|
||||
isAuthenticated.value = true
|
||||
currentUsername.value = getUsernameFromToken(token) || ''
|
||||
SSEManager.connect()
|
||||
return
|
||||
}
|
||||
await authApi.deleteTokenCache()
|
||||
await authApi.verifyToken(token)
|
||||
isAuthenticated.value = true
|
||||
currentUsername.value = getUsernameFromToken(token) || ''
|
||||
SSEManager.connect()
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// 忽略
|
||||
await authApi.deleteTokenCache()
|
||||
}
|
||||
|
||||
if (authRequiredMenus.includes(activeMenu.value)) {
|
||||
if (['rakuten', 'amazon', 'zebra', 'shopee'].includes(activeMenu.value)) {
|
||||
showAuthDialog.value = true
|
||||
}
|
||||
}
|
||||
@@ -246,11 +226,11 @@ async function getClientIdFromToken(token?: string) {
|
||||
try {
|
||||
let t = token
|
||||
if (!t) {
|
||||
t = await authApi.getToken()
|
||||
const tokenRes: any = await authApi.getToken()
|
||||
t = typeof tokenRes === 'string' ? tokenRes : tokenRes?.data
|
||||
}
|
||||
if (!t) return ''
|
||||
|
||||
const payload = JSON.parse(atob(t.split('.')[1] || ''))
|
||||
const payload = JSON.parse(atob(t.split('.')[1]))
|
||||
return payload.clientId || ''
|
||||
} catch {
|
||||
return ''
|
||||
@@ -259,7 +239,7 @@ async function getClientIdFromToken(token?: string) {
|
||||
|
||||
function getUsernameFromToken(token: string) {
|
||||
try {
|
||||
const payload = JSON.parse(atob(token.split('.')[1] || ''))
|
||||
const payload = JSON.parse(atob(token.split('.')[1]))
|
||||
return payload.username || ''
|
||||
} catch {
|
||||
return ''
|
||||
@@ -273,21 +253,24 @@ const SSEManager = {
|
||||
if (this.connection) return
|
||||
|
||||
try {
|
||||
const token = await authApi.getToken()
|
||||
if (!token) return
|
||||
const tokenRes: any = await authApi.getToken()
|
||||
const token = typeof tokenRes === 'string' ? tokenRes : tokenRes?.data
|
||||
if (!token) {
|
||||
console.warn('SSE连接失败: 没有有效的 token')
|
||||
return
|
||||
}
|
||||
|
||||
const clientId = await getClientIdFromToken(token)
|
||||
if (!clientId) return
|
||||
if (!clientId) {
|
||||
console.warn('SSE连接失败: 无法从 token 获取 clientId')
|
||||
return
|
||||
}
|
||||
|
||||
let sseUrl = 'http://192.168.1.89:8080/monitor/account/events'
|
||||
try {
|
||||
const resp = await fetch('/api/config/server')
|
||||
if (resp.ok) {
|
||||
const config = await resp.json()
|
||||
sseUrl = config.sseUrl || sseUrl
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
if (resp.ok) sseUrl = (await resp.json()).sseUrl || sseUrl
|
||||
} catch {}
|
||||
|
||||
const src = new EventSource(`${sseUrl}?clientId=${clientId}&token=${token}`)
|
||||
this.connection = src
|
||||
@@ -296,15 +279,13 @@ const SSEManager = {
|
||||
src.onerror = () => this.handleError()
|
||||
} catch (e: any) {
|
||||
console.warn('SSE连接失败:', e?.message || e)
|
||||
this.disconnect()
|
||||
}
|
||||
},
|
||||
|
||||
handleMessage(e: MessageEvent) {
|
||||
try {
|
||||
// 处理ping心跳
|
||||
if (e.type === 'ping') {
|
||||
return // ping消息自动保持连接,无需处理
|
||||
}
|
||||
if (e.type === 'ping') return
|
||||
|
||||
console.log('SSE消息:', e.data)
|
||||
const payload = JSON.parse(e.data)
|
||||
@@ -314,17 +295,11 @@ const SSEManager = {
|
||||
break
|
||||
case 'DEVICE_REMOVED':
|
||||
logout()
|
||||
ElMessage({
|
||||
message: '您的设备已被移除,请重新登录',
|
||||
type: 'warning'
|
||||
})
|
||||
ElMessage.warning('您的设备已被移除,请重新登录')
|
||||
break
|
||||
case 'FORCE_LOGOUT':
|
||||
logout()
|
||||
ElMessage({
|
||||
message: '会话已失效,请重新登录',
|
||||
type: 'warning'
|
||||
})
|
||||
ElMessage.warning('会话已失效,请重新登录')
|
||||
break
|
||||
case 'PERMISSIONS_UPDATED':
|
||||
checkAuth()
|
||||
@@ -336,18 +311,16 @@ const SSEManager = {
|
||||
},
|
||||
|
||||
handleError() {
|
||||
this.disconnect()
|
||||
setTimeout(() => this.connect(), 3000)
|
||||
if (!this.connection) return
|
||||
try { this.connection.close() } catch {}
|
||||
this.connection = null
|
||||
console.warn('SSE连接失败,已断开')
|
||||
},
|
||||
|
||||
disconnect() {
|
||||
if (this.connection) {
|
||||
try {
|
||||
this.connection.close()
|
||||
} catch {
|
||||
}
|
||||
this.connection = null
|
||||
}
|
||||
if (!this.connection) return
|
||||
try { this.connection.close() } catch {}
|
||||
this.connection = null
|
||||
},
|
||||
}
|
||||
|
||||
@@ -366,26 +339,22 @@ function openSettings() {
|
||||
|
||||
async function fetchDeviceData() {
|
||||
if (!currentUsername.value) {
|
||||
ElMessage({
|
||||
message: '未获取到用户名,请重新登录',
|
||||
type: 'warning'
|
||||
})
|
||||
ElMessage.warning('未获取到用户名,请重新登录')
|
||||
return
|
||||
}
|
||||
try {
|
||||
deviceLoading.value = true
|
||||
const [quota, list] = await Promise.all([
|
||||
const [quotaRes, listRes] = await Promise.all([
|
||||
deviceApi.getQuota(currentUsername.value),
|
||||
deviceApi.list(currentUsername.value),
|
||||
])
|
||||
deviceQuota.value = quota || {limit: 0, used: 0}
|
||||
]) as any[]
|
||||
|
||||
deviceQuota.value = quotaRes?.data || quotaRes || {limit: 0, used: 0}
|
||||
const clientId = await getClientIdFromToken()
|
||||
devices.value = (list || []).map(d => ({...d, isCurrent: d.deviceId === clientId})) as any
|
||||
const list = listRes?.data || listRes || []
|
||||
devices.value = list.map(d => ({...d, isCurrent: d.deviceId === clientId}))
|
||||
} catch (e: any) {
|
||||
ElMessage({
|
||||
message: e?.message || '获取设备列表失败',
|
||||
type: 'error'
|
||||
})
|
||||
ElMessage.error(e?.message || '获取设备列表失败')
|
||||
} finally {
|
||||
deviceLoading.value = false
|
||||
}
|
||||
@@ -403,21 +372,12 @@ async function confirmRemoveDevice(row: DeviceItem & { isCurrent?: boolean }) {
|
||||
devices.value = devices.value.filter(d => d.deviceId !== row.deviceId)
|
||||
deviceQuota.value.used = Math.max(0, (deviceQuota.value.used || 0) - 1)
|
||||
|
||||
// 如果是本机设备被移除,执行logout
|
||||
const clientId = await getClientIdFromToken()
|
||||
if (row.deviceId === clientId) {
|
||||
await logout()
|
||||
}
|
||||
if (row.deviceId === clientId) await logout()
|
||||
|
||||
ElMessage({
|
||||
message: '已移除设备',
|
||||
type: 'success'
|
||||
})
|
||||
ElMessage.success('已移除设备')
|
||||
} catch (e: any) {
|
||||
ElMessage({
|
||||
message: '移除设备失败: ' + ((e as any)?.message || '未知错误'),
|
||||
type: 'error'
|
||||
})
|
||||
if (e !== 'cancel') ElMessage.error('移除设备失败: ' + (e?.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user