mirror of
https://gitee.com/HuLaSpark/HuLa.git
synced 2024-11-29 10:18:35 +08:00
fix(store): 🐛 修复一些接口的store封装
修复重复请求的问题
This commit is contained in:
parent
d144630433
commit
46265275e5
@ -19,7 +19,7 @@
|
||||
</div>
|
||||
|
||||
<n-flex v-if="!isSearch" align="center" justify="space-between" class="pr-8px pl-8px h-42px">
|
||||
<span class="text-14px">群聊成员 {{ userList.length }}</span>
|
||||
<span class="text-14px">在线群聊成员 {{ groupStore.countInfo.onlineNum }}</span>
|
||||
<svg @click="handleSelect" class="size-14px"><use href="#search"></use></svg>
|
||||
</n-flex>
|
||||
<!-- 搜索框 -->
|
||||
@ -47,6 +47,7 @@
|
||||
id="image-chat-sidebar"
|
||||
style="max-height: calc(100vh - 130px)"
|
||||
item-resizable
|
||||
@scroll="handleScroll($event)"
|
||||
:item-size="42"
|
||||
:items="filteredUserList">
|
||||
<template #default="{ item }">
|
||||
@ -93,7 +94,7 @@
|
||||
:intersection-observer-options="{
|
||||
root: '#image-chat-sidebar'
|
||||
}">
|
||||
{{ item.name.slice(0, 1) }}
|
||||
{{ 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">
|
||||
@ -127,6 +128,7 @@ import { useDebounceFn } from '@vueuse/core'
|
||||
const groupStore = useGroupStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const groupUserList = computed(() => groupStore.userList)
|
||||
console.log('groupUserList', groupUserList.value)
|
||||
const userList = computed(() => {
|
||||
return groupUserList.value.map((item: UserItem) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -149,6 +151,16 @@ const isCollapsed = ref(true)
|
||||
const { optionsList, report, selectKey } = useChatMain()
|
||||
const { handlePopoverUpdate } = usePopover(selectKey, 'image-chat-sidebar')
|
||||
|
||||
watch(userList, (newVal) => {
|
||||
console.log('newVal', newVal)
|
||||
// 如果正在搜索,则应用搜索过滤
|
||||
if (searchRef.value) {
|
||||
filteredUserList.value = newVal.filter((user) => user.name.toLowerCase().includes(searchRef.value.toLowerCase()))
|
||||
} else {
|
||||
filteredUserList.value = newVal
|
||||
}
|
||||
})
|
||||
|
||||
const handleSelect = () => {
|
||||
isSearch.value = !isSearch.value
|
||||
nextTick(() => {
|
||||
@ -175,6 +187,19 @@ const handleSearch = useDebounceFn((value: string) => {
|
||||
filteredUserList.value = userList.value.filter((user) => user.name.toLowerCase().includes(value.toLowerCase()))
|
||||
}, 10)
|
||||
|
||||
/**
|
||||
* 处理滚动事件
|
||||
* @param event 滚动事件
|
||||
*/
|
||||
const handleScroll = (event: Event) => {
|
||||
const target = event.target as HTMLElement
|
||||
const isBottom = target.scrollHeight - target.scrollTop === target.clientHeight
|
||||
|
||||
if (isBottom && !groupStore.userListOptions.loading) {
|
||||
groupStore.loadMoreGroupMembers()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
Mitt.on(`${MittEnum.INFO_POPOVER}-Sidebar`, (event: any) => {
|
||||
selectKey.value = event.uid
|
||||
|
@ -173,7 +173,7 @@ export enum PowerEnum {
|
||||
ADMIN
|
||||
}
|
||||
|
||||
export enum IsYetEnum {
|
||||
export enum IsYesEnum {
|
||||
NO,
|
||||
YES
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export const useChatMain = (activeItem?: SessionItem) => {
|
||||
const { removeTag, userUid } = useCommon()
|
||||
const globalStore = useGlobalStore()
|
||||
const chatStore = useChatStore()
|
||||
const userInfo = useUserStore()?.userInfo
|
||||
const userStore = useUserStore()?.userInfo
|
||||
// const userInfo = useUserStore()?.userInfo
|
||||
// const chatMessageList = computed(() => chatStore.chatMessageList)
|
||||
const messageOptions = computed(() => chatStore.currentMessageOptions)
|
||||
@ -92,7 +92,7 @@ export const useChatMain = (activeItem?: SessionItem) => {
|
||||
if (isDiffNow({ time: item.message.sendTime, unit: 'minute', diff: 2 })) return
|
||||
// 判断自己是否是发送者或者是否是管理员
|
||||
const isCurrentUser = item.fromUser.uid === userUid.value
|
||||
const isAdmin = userInfo?.power === PowerEnum.ADMIN
|
||||
const isAdmin = userStore?.power === PowerEnum.ADMIN
|
||||
return isCurrentUser || isAdmin
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@
|
||||
<template v-for="item in editInfo.badgeList" :key="item.id">
|
||||
<div class="badge-item">
|
||||
<n-image
|
||||
:class="{ 'grayscale-0': item.obtain === IsYetEnum.YES }"
|
||||
:class="{ 'grayscale-0': item.obtain === IsYesEnum.YES }"
|
||||
:src="item.img"
|
||||
alt="badge"
|
||||
class="flex-center grayscale"
|
||||
@ -89,8 +89,8 @@
|
||||
preview-disabled
|
||||
round />
|
||||
<div class="tip">
|
||||
<template v-if="item.obtain === IsYetEnum.YES">
|
||||
<n-button v-if="item.wearing === IsYetEnum.NO" color="#13987f" @click="toggleWarningBadge(item)">
|
||||
<template v-if="item.obtain === IsYesEnum.YES">
|
||||
<n-button v-if="item.wearing === IsYesEnum.NO" color="#13987f" @click="toggleWarningBadge(item)">
|
||||
佩戴
|
||||
</n-button>
|
||||
</template>
|
||||
@ -114,13 +114,15 @@
|
||||
</n-modal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { IsYetEnum, MittEnum } from '@/enums'
|
||||
import { IsYesEnum, MittEnum } from '@/enums'
|
||||
import { leftHook } from '@/layout/left/hook.ts'
|
||||
import Mitt from '@/utils/Bus.ts'
|
||||
import apis from '@/services/apis.ts'
|
||||
import { type } from '@tauri-apps/plugin-os'
|
||||
import { useCommon } from '@/hooks/useCommon.ts'
|
||||
import { useUserStore } from '@/stores/user.ts'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const { login, editInfo, currentBadge, saveEditInfo, toggleWarningBadge } = leftHook()
|
||||
const { countGraphemes } = useCommon()
|
||||
|
||||
@ -131,14 +133,11 @@ onMounted(() => {
|
||||
Mitt.on(MittEnum.OPEN_EDIT_INFO, () => {
|
||||
Mitt.emit(MittEnum.CLOSE_INFO_SHOW)
|
||||
editInfo.value.show = true
|
||||
/** 获取用户的徽章列表 */
|
||||
editInfo.value.content = userStore.userInfo
|
||||
/** 获取徽章列表 */
|
||||
apis.getBadgeList().then((res) => {
|
||||
editInfo.value.badgeList = res as any
|
||||
})
|
||||
/** 获取用户信息 */
|
||||
apis.getUserInfo().then((res) => {
|
||||
editInfo.value.content = res as any
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
@ -3,7 +3,7 @@ import { useSettingStore } from '@/stores/setting.ts'
|
||||
import { useUserStore } from '@/stores/user.ts'
|
||||
import { useCachedStore } from '@/stores/cached.ts'
|
||||
import { onlineStatus } from '@/stores/onlineStatus.ts'
|
||||
import { EventEnum, IsYetEnum, MittEnum, MsgEnum, PluginEnum, ThemeEnum } from '@/enums'
|
||||
import { EventEnum, IsYesEnum, MittEnum, MsgEnum, PluginEnum, ThemeEnum } from '@/enums'
|
||||
import { BadgeType, UserInfoType } from '@/services/types.ts'
|
||||
import { useChatStore } from '@/stores/chat.ts'
|
||||
import { useUserInfo } from '@/hooks/useCached.ts'
|
||||
@ -37,19 +37,18 @@ export const leftHook = () => {
|
||||
/** 已打开窗口的列表 */
|
||||
const openWindowsList = ref(new Set())
|
||||
/** 编辑资料弹窗 */
|
||||
// TODO 这里考虑是否查接口查实时的用户信息还是直接查本地存储的用户信息 (nyh -> 2024-05-05 01:12:36)
|
||||
const editInfo = ref<{
|
||||
show: boolean
|
||||
content: UserInfoType
|
||||
content: Partial<UserInfoType>
|
||||
badgeList: BadgeType[]
|
||||
}>({
|
||||
show: false,
|
||||
content: {} as UserInfoType,
|
||||
content: {},
|
||||
badgeList: []
|
||||
})
|
||||
/** 当前用户佩戴的徽章 */
|
||||
const currentBadge = computed(() =>
|
||||
editInfo.value.badgeList.find((item) => item.obtain === IsYetEnum.YES && item.wearing === IsYetEnum.YES)
|
||||
editInfo.value.badgeList.find((item) => item.obtain === IsYesEnum.YES && item.wearing === IsYesEnum.YES)
|
||||
)
|
||||
const chatStore = useChatStore()
|
||||
const sessionList = computed(() =>
|
||||
@ -134,10 +133,6 @@ export const leftHook = () => {
|
||||
if (!badge?.id) return
|
||||
await apis.setUserBadge(badge.id)
|
||||
window.$message.success('佩戴成功')
|
||||
/** 获取用户信息 */
|
||||
apis.getUserInfo().then((res) => {
|
||||
editInfo.value.content = res as any
|
||||
})
|
||||
}
|
||||
|
||||
/* 打开并且创建modal */
|
||||
|
@ -28,8 +28,6 @@ const PUT = <T>(url: string, params?: any, abort?: AbortController) => request.p
|
||||
const DELETE = <T>(url: string, params?: any, abort?: AbortController) => request.delete<T>(url, params, abort)
|
||||
|
||||
export default {
|
||||
/** 获取用户信息 */
|
||||
getUserInfo: (): Promise<UserItem> => GET(urls.getUserInfo),
|
||||
/** 获取群成员列表 */
|
||||
getGroupList: (params?: any) => GET<ListResponse<UserItem>>(urls.getGroupUserList, params),
|
||||
/** 获取群成员统计 */
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 注意:请使用TSDoc规范进行注释,以便在使用时能够获得良好提示。
|
||||
* @see TSDoc规范https://tsdoc.org/
|
||||
**/
|
||||
import { ActEnum, IsYetEnum, MarkEnum, MsgEnum, OnlineEnum, RoomTypeEnum, SexEnum } from '@/enums'
|
||||
import { ActEnum, IsYesEnum, MarkEnum, MsgEnum, OnlineEnum, RoomTypeEnum, SexEnum } from '@/enums'
|
||||
|
||||
/**响应请求体*/
|
||||
export type ServiceResponse = {
|
||||
@ -160,9 +160,9 @@ export type BadgeType = {
|
||||
// 徽章图标
|
||||
img: string
|
||||
// 是否拥有 0否 1是
|
||||
obtain: IsYetEnum
|
||||
obtain: IsYesEnum
|
||||
// 是否佩戴 0否 1是
|
||||
wearing: IsYetEnum
|
||||
wearing: IsYesEnum
|
||||
}
|
||||
|
||||
export type MarkItemType = {
|
||||
|
@ -6,7 +6,6 @@ const prefix = VITE_SERVICE_URL
|
||||
|
||||
export default {
|
||||
// 用户相关
|
||||
getUserInfo: `${prefix + URLEnum.USER}/userInfo`, // 获取用户信息
|
||||
getBadgeList: `${prefix + URLEnum.USER}/badges`, // 获取徽章列表
|
||||
getMemberStatistic: `${prefix + URLEnum.CHAT}/public/member/statistic`,
|
||||
getUserInfoBatch: `${prefix + URLEnum.USER}/public/summary/userInfo/batch`,
|
||||
|
@ -3,7 +3,6 @@ import { useUserStore } from '@/stores/user'
|
||||
import { useChatStore } from '@/stores/chat'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { useGlobalStore } from '@/stores/global'
|
||||
import { useEmojiStore } from '@/stores/emoji'
|
||||
import { WsResponseMessageType } from '@/utils/wsType'
|
||||
import type { LoginSuccessResType, LoginInitResType, WsReqMsgContentType, OnStatusChangeType } from '@/utils/wsType'
|
||||
import type { MessageType, MarkItemType, RevokedMsgType } from '@/services/types'
|
||||
@ -108,7 +107,6 @@ class WS {
|
||||
const chatStore = useChatStore()
|
||||
const groupStore = useGroupStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const emojiStore = useEmojiStore()
|
||||
switch (params.type) {
|
||||
// 获取登录二维码
|
||||
case WsResponseMessageType.LoginQrCode: {
|
||||
@ -126,7 +124,6 @@ class WS {
|
||||
case WsResponseMessageType.LoginSuccess: {
|
||||
userStore.isSign = true
|
||||
const { token, ...rest } = params.data as LoginSuccessResType
|
||||
Mitt.emit(WsResEnum.LOGIN_SUCCESS, params.data)
|
||||
// FIXME 可以不需要赋值了,单独请求了接口。
|
||||
userStore.userInfo = { ...userStore.userInfo, ...rest }
|
||||
localStorage.setItem('USER_INFO', JSON.stringify(rest))
|
||||
@ -149,8 +146,9 @@ class WS {
|
||||
])
|
||||
// 获取用户详情
|
||||
await chatStore.getSessionList(true)
|
||||
// 自定义表情列表
|
||||
await emojiStore.getEmojiList()
|
||||
// TODO 先不获取 emoji 列表,当我点击 emoji 按钮的时候再获取
|
||||
// await emojiStore.getEmojiList()
|
||||
Mitt.emit(WsResEnum.LOGIN_SUCCESS, params.data)
|
||||
break
|
||||
}
|
||||
// 收到消息
|
||||
@ -165,6 +163,7 @@ class WS {
|
||||
groupStore.countInfo.onlineNum = data.onlineNum
|
||||
// groupStore.countInfo.totalNum = data.totalNum
|
||||
groupStore.batchUpdateUserStatus(data.changeList)
|
||||
console.log('收到用户下线通知', data)
|
||||
break
|
||||
}
|
||||
// 用户 token 过期
|
||||
|
@ -70,6 +70,7 @@ export const useCachedStore = defineStore('cached', () => {
|
||||
})
|
||||
.filter((item) => !item.lastModifyTime || isDiffNow10Min(item.lastModifyTime))
|
||||
if (!result.length) return
|
||||
// TODO 批量请求徽章详情当翻历史记录的时候会导致发送很多请求,需要优化,可以直接存储到本地
|
||||
const data = await apis.getBadgesBatch(result)
|
||||
data?.forEach(
|
||||
(item: CacheBadgeItem) =>
|
||||
@ -93,7 +94,7 @@ export const useCachedStore = defineStore('cached', () => {
|
||||
|
||||
const getGroupAtUserBaseInfo = async () => {
|
||||
if (currentRoomId.value === 1) return
|
||||
currentAtUsersList.value = await apis.getAllUserBaseInfo({ params: { roomId: currentRoomId.value } })
|
||||
currentAtUsersList.value = await apis.getAllUserBaseInfo({ roomId: currentRoomId.value })
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,7 +124,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
if (currentRoomType.value === RoomTypeEnum.GROUP) {
|
||||
groupStore.getGroupUserList(true)
|
||||
groupStore.getCountStatistic()
|
||||
// cachedStore.getGroupAtUserBaseInfo()
|
||||
cachedStore.getGroupAtUserBaseInfo()
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
// 初始化所有用户基本信息
|
||||
// userStore.isSign && (await cachedStore.initAllUserBaseInfo())
|
||||
// 联系人列表
|
||||
await contactStore.getContactList(true)
|
||||
await contactStore.getContactList()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,11 +84,11 @@ export const useContactStore = defineStore('contact', () => {
|
||||
/** 接受好友请求 */
|
||||
const onAcceptFriend = (applyId: number) => {
|
||||
// 同意好友申请
|
||||
apis.applyFriendRequest({ applyId }).then(() => {
|
||||
apis.applyFriendRequest({ applyId }).then(async () => {
|
||||
// 刷新好友申请列表
|
||||
getRequestFriendsList(true)
|
||||
await getRequestFriendsList(true)
|
||||
// 刷新好友列表
|
||||
getContactList(true)
|
||||
await getContactList(true)
|
||||
// 标识为可以发消息的人
|
||||
if (globalStore.currentSelectedContact) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
@ -82,18 +82,14 @@ export const useGroupStore = defineStore('group', () => {
|
||||
roomId: currentRoomId.value
|
||||
})
|
||||
|
||||
// 移动端控制显隐
|
||||
const showGroupList = ref(false)
|
||||
|
||||
// 获取群成员
|
||||
const getGroupUserList = async (refresh = false) => {
|
||||
const res = await apis.getGroupList({
|
||||
const data = await apis.getGroupList({
|
||||
pageSize: pageSize,
|
||||
cursor: refresh ? '' : userListOptions.cursor,
|
||||
roomId: currentRoomId.value
|
||||
})
|
||||
if (!res) return
|
||||
const data = res
|
||||
if (!data) return
|
||||
const tempNew = cloneDeep(uniqueUserList(refresh ? data.list : [...data.list, ...userList.value]))
|
||||
tempNew.sort(sorAction)
|
||||
userList.value = tempNew
|
||||
@ -114,9 +110,11 @@ export const useGroupStore = defineStore('group', () => {
|
||||
}
|
||||
|
||||
// 加载更多群成员
|
||||
const loadMore = async () => {
|
||||
if (userListOptions.isLast) return
|
||||
const loadMoreGroupMembers = async () => {
|
||||
if (userListOptions.isLast || userListOptions.loading) return
|
||||
userListOptions.loading = true
|
||||
await getGroupUserList()
|
||||
userListOptions.loading = false
|
||||
}
|
||||
|
||||
// 更新用户在线状态
|
||||
@ -128,7 +126,12 @@ export const useGroupStore = defineStore('group', () => {
|
||||
findIndex > -1 && (tempNew[findIndex].activeStatus = curUser.activeStatus)
|
||||
}
|
||||
tempNew.sort(sorAction)
|
||||
// TODO: 这里的数据为什么前后不一致
|
||||
userList.value = tempNew
|
||||
console.log(userList.value)
|
||||
setTimeout(() => {
|
||||
console.log(userList.value)
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// 过滤掉小黑子
|
||||
@ -187,13 +190,12 @@ export const useGroupStore = defineStore('group', () => {
|
||||
return {
|
||||
userList,
|
||||
userListOptions,
|
||||
loadMore,
|
||||
loadMoreGroupMembers,
|
||||
getGroupUserList,
|
||||
getCountStatistic,
|
||||
currentLordId,
|
||||
countInfo,
|
||||
batchUpdateUserStatus,
|
||||
showGroupList,
|
||||
filterUser,
|
||||
adminUidList,
|
||||
adminList,
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { StoresEnum } from '@/enums'
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ref } from 'vue'
|
||||
import apis from '@/services/apis'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { UserInfoType } from '@/services/types'
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
import wsIns from '@/services/webSocket.ts'
|
||||
import { WsRequestMsgType } from '@/utils/wsType'
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
<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) }}
|
||||
{{ item.name?.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
|
||||
<n-flex class="h-fit flex-1 truncate" justify="space-between" vertical>
|
||||
@ -127,7 +127,7 @@ watchEffect(() => {
|
||||
|
||||
onBeforeMount(() => {
|
||||
// 请求回话列表
|
||||
chatStore.getSessionList(true)
|
||||
chatStore.getSessionList()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -56,7 +56,7 @@
|
||||
<div class="flex-between-center">
|
||||
<n-avatar v-if="item.avatar" :src="item.avatar" class="size-28px bg-#ccc rounded-50%" />
|
||||
<n-avatar v-else :src="item.avatar" :color="'#909090'" class="size-28px text-10px bg-#ccc rounded-50%">
|
||||
{{ item.name.slice(0, 1) }}
|
||||
{{ item.name?.slice(0, 1) }}
|
||||
</n-avatar>
|
||||
<p class="text-14px color-#505050">{{ item.account }}</p>
|
||||
<svg @click.stop="delAccount(item)" class="w-12px h-12px">
|
||||
@ -172,12 +172,10 @@ 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)
|
||||
@ -280,8 +278,8 @@ const normalLogin = async () => {
|
||||
// ])
|
||||
// 获取用户详情
|
||||
await chatStore.getSessionList(true)
|
||||
// 自定义表情列表
|
||||
await emojiStore.getEmojiList()
|
||||
// TODO 先不获取 emoji 列表,当我点击 emoji 按钮的时候再获取
|
||||
// await emojiStore.getEmojiList()
|
||||
// TODO 这里的id暂时赋值给uid,因为后端没有统一返回uid,待后端调整
|
||||
const account = {
|
||||
...userDetail,
|
||||
|
Loading…
Reference in New Issue
Block a user