Skip to content

Commit 67cad46

Browse files
committed
perf(view): ⚡ 优化登录逻辑
1 parent b08e7d8 commit 67cad46

File tree

9 files changed

+439
-152
lines changed

9 files changed

+439
-152
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"typescript": "^5.7.2",
131131
"unplugin-auto-import": "^19.0.0",
132132
"unplugin-vue-components": "^28.0.0",
133-
"vite": "6.1.0",
133+
"vite": "6.2.0",
134134
"vitest": "^3.0.5",
135135
"vue-tsc": "^2.2.0"
136136
},

pnpm-lock.yaml

+387-119
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common/exception.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export enum ErrorType {
55
Validation = 'Validation',
66
Authentication = 'Authentication',
77
Unknown = 'Unknown',
8-
TokenExpired = 'TokenExpired'
8+
TokenExpired = 'TokenExpired',
9+
TokenInvalid = 'TokenInvalid'
910
}
1011

1112
export interface ErrorDetails {

src/mobile/login.vue

+2-3
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ const normalLogin = async () => {
128128
loading.value = true
129129
const { account, password } = info.value
130130
apis
131-
.mobileLogin({ account, password })
131+
.login({ account, password, source: 'mobile' })
132132
.then(async (res) => {
133133
loginDisabled.value = true
134134
loginText.value = '登录成功, 正在跳转'
@@ -169,9 +169,8 @@ const normalLogin = async () => {
169169
* @param item 账户信息
170170
* */
171171
const giveAccount = (item: UserInfoType) => {
172-
const { account, password, avatar, name, uid } = item
172+
const { account, avatar, name, uid } = item
173173
info.value.account = account || ''
174-
info.value.password = password || ''
175174
info.value.avatar = avatar
176175
info.value.name = name
177176
info.value.uid = uid

src/services/apis.ts

-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ export default {
131131
}),
132132
/** 账号密码登录 */
133133
login: (user: LoginUserReq, abort?: AbortController) => POST<API.Login>(urls.login, user, abort),
134-
/** 移动端登录 */
135-
mobileLogin: (user: LoginUserReq, abort?: AbortController) => POST<API.Login>(urls.mobileLogin, user, abort),
136134
/** 退出登录 */
137135
logout: () => POST<string>(urls.logout),
138136
/** 注册 */

src/services/http.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ async function Http<T = any>(
238238
window.dispatchEvent(new Event('needReLogin'))
239239
throw error
240240
}
241+
} else if (error.type === ErrorType.TokenInvalid) {
242+
// Token无效的情况直接抛出错误,不尝试刷新
243+
throw error
241244
}
242245
throw error
243246
}
@@ -255,7 +258,13 @@ async function Http<T = any>(
255258
function getErrorType(status: number): ErrorType {
256259
if (status >= 500) return ErrorType.Server
257260
if (status === 401) {
258-
console.log('🔄 Token已过期,准备刷新...')
261+
console.log('🔄 Token无效,清除token并重新登录...')
262+
// 触发重新登录事件
263+
window.dispatchEvent(new Event('needReLogin'))
264+
return ErrorType.TokenInvalid
265+
}
266+
if (status === 40004) {
267+
console.log('🔄 Token需要续签,准备刷新...')
259268
return ErrorType.TokenExpired
260269
}
261270
if (status === 403) {

src/services/types.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export type LoginUserReq = {
4141
account: string
4242
/** 密码 */
4343
password: string
44+
/** 登录方式 pc/mobile */
45+
source: 'pc' | 'mobile'
4446
}
4547

4648
export type RegisterUserReq = {
@@ -185,10 +187,12 @@ export type MarkMsgReq = {
185187
export type UserInfoType = {
186188
/** 用户唯一标识 */
187189
uid: number
188-
/** 用户头像 */
190+
/** 用户账号 */
189191
account: string
190-
/** 用户头像 */
191-
password: string
192+
/** Hula号 */
193+
accountCode: string
194+
/** 密码 */
195+
password?: string
192196
/** 用户头像 */
193197
avatar: string
194198
/** 用户名 */

src/services/urls.ts

-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ export default {
6060
login: `${prefix + URLEnum.TOKEN}/login`,
6161
// 续签
6262
refreshToken: `${prefix + URLEnum.TOKEN}/refreshToken`,
63-
// 移动端登录
64-
mobileLogin: `${prefix + URLEnum.TOKEN}/mobileLogin`,
6563
// 退出登录
6664
logout: `${prefix + URLEnum.TOKEN}/logout`,
6765
// 检查token是否有效

src/views/loginWindow/Login.vue

+30-20
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,12 @@ import { AvatarUtils } from '@/utils/AvatarUtils'
170170
import { useMitt } from '@/hooks/useMitt'
171171
import { WsResponseMessageType } from '@/services/wsType'
172172
import { useNetwork } from '@vueuse/core'
173-
import { computedToken } from '@/services/request'
174-
import ws from '@/services/webSocket'
175-
import { useGlobalStore } from '@/stores/global.ts'
176173
import { useUserStatusStore } from '@/stores/userStatus'
177174
178175
const settingStore = useSettingStore()
179176
const userStore = useUserStore()
180-
const globalStore = useGlobalStore()
181177
const userStatusStore = useUserStatusStore()
182178
const { stateId } = storeToRefs(userStatusStore)
183-
const { isTrayMenuShow } = storeToRefs(globalStore)
184179
/** 网络连接是否正常 */
185180
const { isOnline } = useNetwork()
186181
const loginHistoriesStore = useLoginHistoriesStore()
@@ -206,8 +201,9 @@ const accountPH = ref('输入HuLa账号')
206201
const passwordPH = ref('输入HuLa密码')
207202
/** 登录按钮的文本内容 */
208203
const loginText = ref('登录')
204+
/** 是否直接跳转 */
205+
const isJumpDirectly = ref(false)
209206
const { createWebviewWindow } = useWindow()
210-
const route = useRoute()
211207
212208
watchEffect(() => {
213209
loginDisabled.value = !(info.value.account && info.value.password && protocol.value)
@@ -272,13 +268,11 @@ const normalLogin = async (auto = false) => {
272268
loading.value = true
273269
// 根据auto参数决定从哪里获取登录信息
274270
const loginInfo = auto ? (userStore.userInfo as UserInfoType) : info.value
275-
const { account, password } = loginInfo
271+
const { account } = loginInfo
276272
277273
apis
278-
.login({ account, password })
274+
.login({ account, password: info.value.password, source: 'pc' })
279275
.then(async (res) => {
280-
console.log(res)
281-
282276
loginDisabled.value = true
283277
loginText.value = '登录成功, 正在跳转'
284278
userStore.isSign = true
@@ -369,30 +363,46 @@ const enterKey = (e: KeyboardEvent) => {
369363
}
370364
371365
onBeforeMount(async () => {
372-
// 如果不是自动登录且当前在登录页面,清除 TOKEN,防止用户直接使用控制台退出导致登录前还没有退出账号就继续登录
373-
if (!login.value.autoLogin && route.path === '/login' && TOKEN.value) {
374-
await apis.logout()
375-
isTrayMenuShow.value = false
376-
computedToken.clear()
377-
// 重新初始化 WebSocket 连接,此时传入 null 作为 token
378-
ws.initConnect()
379-
const headers = new Headers()
380-
headers.append('Authorization', '')
366+
const token = localStorage.getItem('TOKEN')
367+
const refreshToken = localStorage.getItem('REFRESH_TOKEN')
368+
369+
if (token && refreshToken) {
370+
isJumpDirectly.value = true
371+
try {
372+
// 验证token有效性
373+
await userStore.getUserDetailAction()
374+
// token有效,直接打开主窗口
375+
await openHomeWindow()
376+
return // 直接返回,不执行后续的登录相关逻辑
377+
} catch (error) {
378+
isJumpDirectly.value = false
379+
// token无效,清除token并重置状态
380+
localStorage.removeItem('TOKEN')
381+
localStorage.removeItem('REFRESH_TOKEN')
382+
userStore.userInfo = {}
383+
userStore.isSign = false
384+
}
381385
}
382386
})
383387
384388
onMounted(async () => {
385-
await getCurrentWebviewWindow().show()
389+
// 只有在需要登录的情况下才显示登录窗口
390+
if (!isJumpDirectly.value) {
391+
await getCurrentWebviewWindow().show()
392+
}
393+
386394
useMitt.on(WsResponseMessageType.NO_INTERNET, () => {
387395
loginDisabled.value = true
388396
loginText.value = '服务异常断开'
389397
})
398+
390399
// 自动登录
391400
if (login.value.autoLogin && TOKEN.value) {
392401
normalLogin(true)
393402
} else {
394403
loginHistories.length > 0 && giveAccount(loginHistories[0])
395404
}
405+
396406
window.addEventListener('click', closeMenu, true)
397407
window.addEventListener('keyup', enterKey)
398408
})

0 commit comments

Comments
 (0)