mirror of
https://gitee.com/HuLaSpark/HuLa.git
synced 2024-12-01 19:28:07 +08:00
fix(service): 🐛 修复http模块没有设置请求头导致请求报错问题
完善登录逻辑和自动登录逻辑
This commit is contained in:
parent
54ee3ff168
commit
153896480e
@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<!-- 好友详情 -->
|
||||
<n-flex v-if="content.type === RoomTypeEnum.SINGLE" vertical align="center" :size="30" class="mt-60px select-none">
|
||||
<n-image
|
||||
width="146px"
|
||||
height="146px"
|
||||
style="border: 2px solid #fff"
|
||||
class="rounded-50%"
|
||||
:src="item.avatar"
|
||||
alt="" />
|
||||
<n-avatar v-if="item.avatar" class="rounded-50% size-146px border-(2px solid #fff)" :src="item.avatar" />
|
||||
|
||||
<n-avatar
|
||||
v-else
|
||||
:color="'#909090'"
|
||||
class="rounded-50% size-146px text-28px border-(2px solid #fff)"
|
||||
:src="item.avatar">
|
||||
{{ item.name!.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
|
||||
<span class="text-(20px [--text-color])">{{ item.name }}</span>
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
</n-virtual-list>
|
||||
</div>
|
||||
|
||||
<!-- 发送按钮 TODO 建议不要放在外面会影响视觉效果,可以放在发送按钮里面做提示,发送按钮需要修改一下大小 (nyh -> 2024-09-01 23:41:34) -->
|
||||
<!-- 发送按钮 -->
|
||||
<n-flex align="center" justify="space-between" :size="12">
|
||||
<n-config-provider :theme="lightTheme">
|
||||
<n-button-group size="small" class="pr-20px">
|
||||
|
@ -85,16 +85,6 @@
|
||||
<div class="pl-20px flex flex-col items-end gap-6px">
|
||||
<MsgInput ref="MsgInputRef" />
|
||||
</div>
|
||||
|
||||
<div v-if="isGuest" class="fuzzy">
|
||||
<n-flex align="center" :size="0" class="pb-60px text-(14px [--text-color])">
|
||||
<p>当前为</p>
|
||||
<p class="color-#c14053 px-2px">游客模式</p>
|
||||
<p>,请</p>
|
||||
<p @click="logout(true)" class="color-#13987f px-4px cursor-pointer">扫码登录</p>
|
||||
<p>后使用</p>
|
||||
</n-flex>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@ -104,20 +94,12 @@ import { LimitEnum, MsgEnum } from '@/enums'
|
||||
import { useCommon } from '@/hooks/useCommon.ts'
|
||||
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { emit } from '@tauri-apps/api/event'
|
||||
import { useLogin } from '@/hooks/useLogin.ts'
|
||||
import { useSettingStore } from '@/stores/setting.ts'
|
||||
|
||||
const { logout } = useLogin()
|
||||
const { open, onChange, reset } = useFileDialog()
|
||||
const { login } = useSettingStore()
|
||||
const MsgInputRef = ref()
|
||||
const msgInputDom = ref()
|
||||
const emojiShow = ref()
|
||||
const { insertNode, triggerInputEvent, getEditorRange, imgPaste, FileOrVideoPaste } = useCommon()
|
||||
/**
|
||||
* 是否为游客模式
|
||||
*/
|
||||
const isGuest = computed(() => login.accountInfo.token === 'test')
|
||||
|
||||
/**
|
||||
* 选择表情,并把表情插入输入框
|
||||
@ -185,13 +167,6 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.fuzzy {
|
||||
@apply bg-transparent select-none cursor-default size-full absolute-flex-center;
|
||||
overflow: hidden;
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
:deep(.n-input .n-input-wrapper) {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -99,6 +99,7 @@
|
||||
round
|
||||
v-if="avatarExists(item.fromUser.uid)"
|
||||
:size="34"
|
||||
:color="'#909090'"
|
||||
@click="selectKey = item.message.id"
|
||||
class="select-none"
|
||||
:src="getAvatarSrc(item.fromUser.uid)"
|
||||
|
@ -65,6 +65,7 @@
|
||||
:special-menu="report">
|
||||
<n-flex @click="selectKey = item.uid" :key="item.uid" :size="10" align="center" class="item">
|
||||
<n-avatar
|
||||
v-if="item.avatar"
|
||||
lazy
|
||||
round
|
||||
class="grayscale"
|
||||
@ -77,6 +78,23 @@
|
||||
:intersection-observer-options="{
|
||||
root: '#image-chat-sidebar'
|
||||
}"></n-avatar>
|
||||
|
||||
<n-avatar
|
||||
v-else
|
||||
lazy
|
||||
round
|
||||
class="grayscale text-10px"
|
||||
:class="{ 'grayscale-0': item.activeStatus === OnlineEnum.ONLINE }"
|
||||
:color="'#909090'"
|
||||
:size="24"
|
||||
:src="item.avatar"
|
||||
fallback-src="/logo.png"
|
||||
:render-placeholder="() => null"
|
||||
:intersection-observer-options="{
|
||||
root: '#image-chat-sidebar'
|
||||
}">
|
||||
{{ item.name.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
<span class="text-12px truncate flex-1">{{ item.name }}</span>
|
||||
<div v-if="item.uid === 1" class="flex p-4px rounded-4px bg-#f5dadf size-fit select-none">
|
||||
<span class="text-(10px #d5304f)">群主</span>
|
||||
|
@ -16,20 +16,13 @@ export const useLogin = () => {
|
||||
|
||||
/**
|
||||
* 登出账号
|
||||
* @param isToQrcode 是否返回到二维码页面
|
||||
*/
|
||||
const logout = async (isToQrcode = false) => {
|
||||
const logout = async () => {
|
||||
const { createWebviewWindow } = useWindow()
|
||||
localStorage.removeItem('USER_INFO')
|
||||
localStorage.removeItem('TOKEN')
|
||||
// todo 退出账号 需要关闭其他的全部窗口
|
||||
await createWebviewWindow('登录', 'login', 320, 448, 'home', false, 320, 448).then(() => {
|
||||
emit(EventEnum.LOGOUT)
|
||||
emit('logout_success')
|
||||
// 用于跳转到二维码页面
|
||||
if (isToQrcode) {
|
||||
localStorage.setItem('isToQrcode', '1')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,20 @@
|
||||
<n-flex :size="20" class="p-22px select-none" vertical>
|
||||
<!-- 头像 -->
|
||||
<n-flex justify="center">
|
||||
<n-avatar :size="80" :src="editInfo.content.avatar" round style="border: 3px solid #fff" />
|
||||
<n-avatar
|
||||
v-if="editInfo.content.avatar"
|
||||
:size="80"
|
||||
:src="editInfo.content.avatar"
|
||||
round
|
||||
style="border: 3px solid #fff" />
|
||||
|
||||
<n-avatar
|
||||
v-else
|
||||
:size="80"
|
||||
:color="'#909090'"
|
||||
:src="editInfo.content.avatar"
|
||||
round
|
||||
style="border: 3px solid #fff" />
|
||||
</n-flex>
|
||||
<n-flex v-if="currentBadge" align="center" justify="center">
|
||||
<span class="text-(14px #707070)">当前佩戴的徽章:</span>
|
||||
|
@ -4,10 +4,14 @@ import Mitt from '@/utils/Bus.ts'
|
||||
import { useLogin } from '@/hooks/useLogin.ts'
|
||||
import { useSettingStore } from '@/stores/setting.ts'
|
||||
import apis from '@/services/apis.ts'
|
||||
import { LoginStatus, useWsLoginStore } from '@/stores/ws.ts'
|
||||
import { useUserStore } from '@/stores/user.ts'
|
||||
|
||||
const { createWebviewWindow } = useWindow()
|
||||
const { logout } = useLogin()
|
||||
const settingStore = useSettingStore()
|
||||
const loginStore = useWsLoginStore()
|
||||
const userStore = useUserStore()
|
||||
const { login } = storeToRefs(settingStore)
|
||||
/**
|
||||
* 这里的顶部的操作栏使用pinia写入了localstorage中
|
||||
@ -97,7 +101,15 @@ const moreList = ref<OPT.L.MoreList[]>([
|
||||
.logout()
|
||||
.then(async () => {
|
||||
await logout()
|
||||
// 如果没有设置自动登录,则清除用户信息
|
||||
if (!login.value.autoLogin) {
|
||||
login.value.accountInfo.token = ''
|
||||
userStore.userInfo = {}
|
||||
localStorage.removeItem('USER_INFO')
|
||||
localStorage.removeItem('TOKEN')
|
||||
}
|
||||
userStore.isSign = false
|
||||
loginStore.loginStatus = LoginStatus.Init
|
||||
})
|
||||
.catch(() => {
|
||||
window.$message.error('退出账号失败')
|
||||
|
@ -47,7 +47,7 @@ export default {
|
||||
/** 标记消息,点赞等 */
|
||||
markMsg: (data?: MarkMsgReq) => PUT<void>(urls.markMsg, data),
|
||||
/** 获取用户详细信息 */
|
||||
getUserDetail: () => GET<UserInfoType>(urls.getUserInfoDetail, {}),
|
||||
getUserDetail: () => GET<UserInfoType>(urls.getUserInfoDetail),
|
||||
/** 获取徽章列表 */
|
||||
getBadgeList: (): Promise<BadgeType> => GET(urls.getBadgeList),
|
||||
/** 设置用户勋章 */
|
||||
|
@ -33,9 +33,22 @@ async function Http<T>(
|
||||
fullResponse?: true,
|
||||
abort?: AbortController
|
||||
): Promise<{ data: Promise<T>; resp: Response }> {
|
||||
// 获取token
|
||||
const token = localStorage.getItem('TOKEN')
|
||||
|
||||
// 构建请求头
|
||||
const httpHeaders = new Headers(options.headers || {})
|
||||
|
||||
// 设置Content-Type
|
||||
if (!httpHeaders.has('Content-Type') && !(options.body instanceof FormData)) {
|
||||
httpHeaders.set('Content-Type', 'application/json')
|
||||
}
|
||||
|
||||
// 设置Authorization
|
||||
if (token) {
|
||||
httpHeaders.set('Authorization', `Bearer ${token}`)
|
||||
}
|
||||
|
||||
// 构建 fetch 请求选项
|
||||
const fetchOptions: RequestInit = {
|
||||
method: options.method,
|
||||
|
@ -40,11 +40,11 @@ class WS {
|
||||
worker.postMessage(`{"type":"initWS","value":${token ? `"${token}"` : null}}`)
|
||||
}
|
||||
|
||||
onWorkerMsg = (e: MessageEvent<any>) => {
|
||||
onWorkerMsg = async (e: MessageEvent<any>) => {
|
||||
const params: { type: string; value: unknown } = JSON.parse(e.data)
|
||||
switch (params.type) {
|
||||
case 'message': {
|
||||
this.onMessage(params.value as string)
|
||||
await this.onMessage(params.value as string)
|
||||
break
|
||||
}
|
||||
case 'open': {
|
||||
@ -100,7 +100,7 @@ class WS {
|
||||
}
|
||||
|
||||
// 收到消息回调
|
||||
onMessage = (value: string) => {
|
||||
onMessage = async (value: string) => {
|
||||
// FIXME 可能需要 try catch,
|
||||
const params: { type: WsResponseMessageType; data: unknown } = JSON.parse(value)
|
||||
const loginStore = useWsLoginStore()
|
||||
@ -148,14 +148,14 @@ class WS {
|
||||
}
|
||||
])
|
||||
// 获取用户详情
|
||||
chatStore.getSessionList(true)
|
||||
await chatStore.getSessionList(true)
|
||||
// 自定义表情列表
|
||||
emojiStore.getEmojiList()
|
||||
await emojiStore.getEmojiList()
|
||||
break
|
||||
}
|
||||
// 收到消息
|
||||
case WsResponseMessageType.ReceiveMessage: {
|
||||
chatStore.pushMsg(params.data as MessageType)
|
||||
await chatStore.pushMsg(params.data as MessageType)
|
||||
Mitt.emit(MittEnum.SEND_MESSAGE, params.data)
|
||||
break
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { StoresEnum } from '../enums'
|
||||
import { StoresEnum } from '@/enums'
|
||||
|
||||
export const useLoginHistoriesStore = defineStore(
|
||||
StoresEnum.LOGIN_HISTORY,
|
||||
|
@ -101,7 +101,7 @@
|
||||
|
||||
<n-flex v-if="!isLogining && !isWrongPassword" justify="space-around" align="center" :size="0" class="options">
|
||||
<p class="text-(14px #fefefe)" @click="isUnlockPage = false">返回</p>
|
||||
<p class="text-(14px #fefefe)" @click="logout()">退出登录</p>
|
||||
<p class="text-(14px #fefefe)" @click="logout">退出登录</p>
|
||||
<p class="text-(14px #fefefe)">忘记密码</p>
|
||||
<p class="text-(14px #fff)" @click="unlock">进入系统</p>
|
||||
</n-flex>
|
||||
|
@ -29,15 +29,28 @@
|
||||
:key="item.uid">
|
||||
<n-flex align="center" :size="10" class="h-75px pl-6px pr-8px flex-1 truncate">
|
||||
<n-avatar
|
||||
v-if="useUserInfo(item.uid).value.avatar"
|
||||
round
|
||||
bordered
|
||||
:color="'#fff'"
|
||||
:size="44"
|
||||
class="grayscale"
|
||||
:class="{ 'grayscale-0': item.activeStatus === OnlineEnum.ONLINE }"
|
||||
:src="useUserInfo(item.uid).value.avatar"
|
||||
fallback-src="/logo.png" />
|
||||
|
||||
<n-avatar
|
||||
v-else
|
||||
round
|
||||
bordered
|
||||
:color="'#909090'"
|
||||
:size="44"
|
||||
class="grayscale"
|
||||
:class="{ 'grayscale-0': item.activeStatus === OnlineEnum.ONLINE }"
|
||||
:src="useUserInfo(item.uid).value.avatar"
|
||||
fallback-src="/logo.png">
|
||||
{{ useUserInfo(item.uid).value.name?.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
|
||||
<n-flex vertical justify="space-between" class="h-fit flex-1 truncate">
|
||||
<span class="text-14px leading-tight flex-1 truncate">{{
|
||||
useUserInfo(item.uid).value.name
|
||||
|
@ -17,7 +17,11 @@
|
||||
@dblclick="handleMsgDblclick(item)"
|
||||
@select="$event.click(item)">
|
||||
<n-flex :size="10" align="center" class="h-75px pl-6px pr-8px flex-1">
|
||||
<n-avatar :color="'#fff'" :size="44" :src="item.avatar" bordered fallback-src="/logo.png" round />
|
||||
<n-avatar v-if="item.avatar" :size="44" :src="item.avatar" bordered fallback-src="/logo.png" round />
|
||||
|
||||
<n-avatar v-else :color="'#909090'" :size="44" :src="item.avatar" bordered fallback-src="/logo.png" round>
|
||||
{{ item.name.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
|
||||
<n-flex class="h-fit flex-1 truncate" justify="space-between" vertical>
|
||||
<n-flex :size="4" align="center" class="flex-1 truncate" justify="space-between">
|
||||
|
@ -151,15 +151,21 @@
|
||||
<script setup lang="ts">
|
||||
import router from '@/router'
|
||||
import { useWindow } from '@/hooks/useWindow.ts'
|
||||
import { delay } from 'lodash-es'
|
||||
import { lightTheme } from 'naive-ui'
|
||||
import { useSettingStore } from '@/stores/setting.ts'
|
||||
import { useLogin } from '@/hooks/useLogin.ts'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { useLoginHistoriesStore } from '@/stores/loginHistory.ts'
|
||||
import apis from '@/services/apis.ts'
|
||||
import { useUserStore } from '@/stores/user.ts'
|
||||
import { computedToken } from '@/services/request.ts'
|
||||
import { useChatStore } from '@/stores/chat.ts'
|
||||
import { useEmojiStore } from '@/stores/emoji.ts'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const userStore = useUserStore()
|
||||
const chatStore = useChatStore()
|
||||
const emojiStore = useEmojiStore()
|
||||
const loginHistoriesStore = useLoginHistoriesStore()
|
||||
const { loginHistories } = loginHistoriesStore
|
||||
const { login } = storeToRefs(settingStore)
|
||||
@ -232,14 +238,37 @@ const normalLogin = async () => {
|
||||
loading.value = true
|
||||
apis
|
||||
.login({ ...info.value } as unknown as User)
|
||||
.then((token) => {
|
||||
.then(async (token) => {
|
||||
loginText.value = '登录成功, 正在跳转'
|
||||
delay(async () => {
|
||||
if (interruptLogin.value) return
|
||||
userStore.isSign = true
|
||||
login.value.accountInfo.token = token
|
||||
// 获取用户信息
|
||||
// TODO 这里的id暂时赋值给uid,因为后端没有统一返回uid,待后端调整
|
||||
// localStorage.setItem('USER_INFO', JSON.stringify(rest))
|
||||
localStorage.setItem('TOKEN', token)
|
||||
// 需要删除二维码,因为用户可能先跳转到二维码界面再回到登录界面,会导致二维码一直保持在内存中
|
||||
if (localStorage.getItem('wsLogin')) {
|
||||
localStorage.removeItem('wsLogin')
|
||||
}
|
||||
// 更新一下请求里面的 token.
|
||||
computedToken.clear()
|
||||
computedToken.get()
|
||||
// 获取用户详情
|
||||
const userDetail = await apis.getUserDetail()
|
||||
// 自己更新自己上线
|
||||
// groupStore.batchUpdateUserStatus([
|
||||
// {
|
||||
// activeStatus: OnlineEnum.ONLINE,
|
||||
// avatar: rest.avatar,
|
||||
// lastOptTime: Date.now(),
|
||||
// name: rest.name,
|
||||
// uid: rest.uid
|
||||
// }
|
||||
// ])
|
||||
// 获取用户详情
|
||||
await chatStore.getSessionList(true)
|
||||
// 自定义表情列表
|
||||
await emojiStore.getEmojiList()
|
||||
// TODO 这里的id暂时赋值给uid,因为后端没有统一返回uid,待后端调整
|
||||
const account = {
|
||||
...userDetail,
|
||||
uid: (userDetail as any).id,
|
||||
@ -248,9 +277,9 @@ const normalLogin = async () => {
|
||||
loading.value = false
|
||||
settingStore.setAccountInfo(account)
|
||||
loginHistoriesStore.addLoginHistory(account)
|
||||
await setLoginState()
|
||||
// 打开主界面
|
||||
await openHomeWindow()
|
||||
}, 1000)
|
||||
})
|
||||
.catch(() => {
|
||||
window.$message.error('登录失败')
|
||||
@ -268,15 +297,14 @@ const autoLogin = () => {
|
||||
loading.value = true
|
||||
// TODO 检查用户网络是否连接 (nyh -> 2024-03-16 12:06:59)
|
||||
loginText.value = '网络连接中'
|
||||
// TODO 退出账号后不知道为什么请求头的token被移除了导致checkToken请求401
|
||||
apis
|
||||
.checkToken()
|
||||
.then(() => {
|
||||
window.$message.success('登录成功,正在跳转首页')
|
||||
delay(async () => {
|
||||
.then(async () => {
|
||||
loginText.value = '登录成功, 正在跳转'
|
||||
loading.value = false
|
||||
await openHomeWindow()
|
||||
await setLoginState()
|
||||
}, 1000)
|
||||
})
|
||||
.catch(() => {
|
||||
window.$message.error('登录失败')
|
||||
@ -317,13 +345,6 @@ const enterKey = (e: KeyboardEvent) => {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 判断是否需要马上跳转到二维码登录页面
|
||||
if (localStorage.getItem('isToQrcode')) {
|
||||
router.push('/qrCode')
|
||||
await nextTick(() => {
|
||||
localStorage.removeItem('isToQrcode')
|
||||
})
|
||||
}
|
||||
await getCurrentWebviewWindow().show()
|
||||
// 自动登录
|
||||
if (login.value.autoLogin && login.value.accountInfo.token) {
|
||||
|
Loading…
Reference in New Issue
Block a user