This commit is contained in:
2025-09-27 17:41:43 +08:00
parent fe3e24b945
commit 96b396500e
10 changed files with 76 additions and 84 deletions

View File

@@ -2,12 +2,9 @@
import {onMounted, ref, computed, defineAsyncComponent, type Component, onUnmounted} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 图标已移至对应组件
import 'element-plus/dist/index.css'
import {authApi} from './api/auth'
import {deviceApi, type DeviceItem, type DeviceQuota} from './api/device'
// 面板按需加载,互不影响且可缓存
const LoginDialog = defineAsyncComponent(() => import('./components/auth/LoginDialog.vue'))
const RegisterDialog = defineAsyncComponent(() => import('./components/auth/RegisterDialog.vue'))
const NavigationBar = defineAsyncComponent(() => import('./components/layout/NavigationBar.vue'))
@@ -147,9 +144,15 @@ async function handleLoginSuccess(data: { token: string; permissions?: string })
// 建立SSE连接
SSEManager.connect()
} catch (e) {
// 设备注册失败不影响登录流程,静默处理
console.warn('设备注册失败:', e)
} catch (e: any) {
// 设备注册失败时回滚登录状态
isAuthenticated.value = false
showAuthDialog.value = true
await authApi.deleteTokenCache()
ElMessage({
message: e?.message || '设备注册失败,请重试',
type: 'error'
})
}
}

View File

@@ -15,37 +15,37 @@ export interface DeviceItem {
lastActiveAt?: string
}
// 统一处理AjaxResult格式
function handleAjaxResult(res: any) {
if (res?.code !== 200) {
throw new Error(res?.msg || '操作失败')
}
return res.data
}
export const deviceApi = {
getQuota(username: string) {
return http.get<DeviceQuota | any>(`${base}/quota`, { username }).then((res: any) => {
if (res && typeof res.limit !== 'undefined') return res as DeviceQuota
if (res && typeof res.code === 'number') return (res.data as DeviceQuota) || { limit: 0, used: 0 }
return (res?.data as DeviceQuota) || { limit: 0, used: 0 }
})
getQuota(username: string): Promise<DeviceQuota> {
return http.get(`${base}/quota`, { username }).then(handleAjaxResult)
},
list(username: string) {
return http.get<DeviceItem[] | any>(`${base}/list`, { username }).then((res: any) => {
if (Array.isArray(res)) return res as DeviceItem[]
if (res && typeof res.code === 'number') return (res.data as DeviceItem[]) || []
return (res?.data as DeviceItem[]) || []
})
list(username: string): Promise<DeviceItem[]> {
return http.get(`${base}/list`, { username }).then(handleAjaxResult)
},
register(payload: { username: string }) {
return http.post(`${base}/register`, payload)
return http.post(`${base}/register`, payload).then(handleAjaxResult)
},
remove(payload: { deviceId: string }) {
return http.postVoid(`${base}/remove`, payload)
return http.post(`${base}/remove`, payload).then(handleAjaxResult)
},
heartbeat(payload: { username: string; deviceId: string; version?: string }) {
return http.postVoid(`${base}/heartbeat`, payload)
return http.post(`${base}/heartbeat`, payload).then(handleAjaxResult)
},
offline(payload: { deviceId: string }) {
return http.postVoid(`${base}/offline`, payload)
return http.post(`${base}/offline`, payload).then(handleAjaxResult)
},
}

View File

@@ -3,6 +3,7 @@ import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { User } from '@element-plus/icons-vue'
import { authApi } from '../../api/auth'
import { deviceApi } from '../../api/device'
interface Props {
modelValue: boolean
@@ -30,6 +31,10 @@ async function handleAuth() {
authLoading.value = true
try {
// 1. 先检查设备限制
await deviceApi.register({ username: authForm.value.username })
// 2. 设备检查通过,进行登录
const data = await authApi.login(authForm.value)
emit('loginSuccess', {
token: data.token,

View File

@@ -4,7 +4,6 @@ import 'element-plus/dist/index.css'
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus, {
locale: zhCn,