mirror of
https://gitee.com/HuLaSpark/HuLa.git
synced 2024-12-01 19:28:07 +08:00
fix(service): 🐛 修复请求接口bug
优化用户在线状态展示
This commit is contained in:
parent
7b530297ac
commit
f3723d4e5a
@ -9,5 +9,6 @@ index.html
|
||||
src/assets
|
||||
.eslintrc.cjs
|
||||
**/config
|
||||
src-tauri/**
|
||||
commitlint.config.cjs
|
||||
auto-imports.d.ts
|
@ -11,7 +11,10 @@
|
||||
class="p-[0_30px]"
|
||||
v-for="(item, index) in contactStore.requestFriendsList"
|
||||
:key="index">
|
||||
<n-flex align="center" justify="space-between" class="bg-[--center-bg-color] rounded-10px p-20px box-border">
|
||||
<n-flex
|
||||
align="center"
|
||||
justify="space-between"
|
||||
class="bg-[--center-bg-color] rounded-10px p-20px box-border border-(1px solid [--bg-popover])">
|
||||
<n-flex align="center" :size="10">
|
||||
<n-avatar round size="large" :src="useUserInfo(item.uid).value.avatar" class="mr-10px" />
|
||||
<n-flex vertical :size="12">
|
||||
@ -42,7 +45,7 @@
|
||||
@click="contactStore.onAcceptFriend(item.applyId)">
|
||||
接受
|
||||
</n-button>
|
||||
<span class="text-(12px [--text-color])" v-else>已添加</span>
|
||||
<span class="text-(12px #64a29c)" v-else>已同意</span>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
|
@ -52,7 +52,9 @@
|
||||
</n-flex>
|
||||
|
||||
<!-- 群聊详情 -->
|
||||
<div v-else class="flex flex-col flex-1 mt-60px gap-30px select-none p-[0_40px] box-border">
|
||||
<div
|
||||
v-else-if="content.type === RoomTypeEnum.GROUP"
|
||||
class="flex flex-col flex-1 mt-60px gap-30px select-none p-[0_40px] box-border">
|
||||
<!-- 群聊头像以及简介 -->
|
||||
<n-flex align="center" justify="space-between">
|
||||
<n-flex align="center">
|
||||
|
@ -341,7 +341,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { EventEnum, MittEnum, MsgEnum, RoomTypeEnum } from '@/enums'
|
||||
import { type MessageType, SessionItem } from '@/services/types.ts'
|
||||
import { SessionItem } from '@/services/types.ts'
|
||||
import Mitt from '@/utils/Bus.ts'
|
||||
import { usePopover } from '@/hooks/usePopover.ts'
|
||||
import { useWindow } from '@/hooks/useWindow.ts'
|
||||
@ -492,28 +492,28 @@ const jumpToReplyMsg = (key: number) => {
|
||||
* @param index 下标
|
||||
* @param id 用户ID
|
||||
*/
|
||||
const addToDomUpdateQueue = (index: number, id: number) => {
|
||||
// 使用 nextTick 确保虚拟列表渲染完最新的项目后进行滚动
|
||||
nextTick(() => {
|
||||
if (!floatFooter.value || id === userUid.value) {
|
||||
virtualListInst.value?.scrollTo({ position: 'bottom', debounce: true })
|
||||
}
|
||||
/** data-key标识的气泡,添加前缀用于区分用户消息,不然气泡动画会被覆盖 */
|
||||
const dataKey = id === userUid.value ? `U${index}` : `Q${index}`
|
||||
const lastMessageElement = document.querySelector(`[data-key="${dataKey}"]`) as HTMLElement
|
||||
if (lastMessageElement) {
|
||||
// 添加动画类
|
||||
lastMessageElement.classList.add('bubble-animation')
|
||||
// 监听动画结束事件
|
||||
const handleAnimationEnd = () => {
|
||||
lastMessageElement.classList.remove('bubble-animation')
|
||||
lastMessageElement.removeEventListener('animationend', handleAnimationEnd)
|
||||
}
|
||||
lastMessageElement.addEventListener('animationend', handleAnimationEnd)
|
||||
}
|
||||
})
|
||||
chatStore.clearNewMsgCount()
|
||||
}
|
||||
// const addToDomUpdateQueue = (index: number, id: number) => {
|
||||
// // 使用 nextTick 确保虚拟列表渲染完最新的项目后进行滚动
|
||||
// nextTick(() => {
|
||||
// if (!floatFooter.value || id === userUid.value) {
|
||||
// virtualListInst.value?.scrollTo({ position: 'bottom', debounce: true })
|
||||
// }
|
||||
// /** data-key标识的气泡,添加前缀用于区分用户消息,不然气泡动画会被覆盖 */
|
||||
// const dataKey = id === userUid.value ? `U${index}` : `Q${index}`
|
||||
// const lastMessageElement = document.querySelector(`[data-key="${dataKey}"]`) as HTMLElement
|
||||
// if (lastMessageElement) {
|
||||
// // 添加动画类
|
||||
// lastMessageElement.classList.add('bubble-animation')
|
||||
// // 监听动画结束事件
|
||||
// const handleAnimationEnd = () => {
|
||||
// lastMessageElement.classList.remove('bubble-animation')
|
||||
// lastMessageElement.removeEventListener('animationend', handleAnimationEnd)
|
||||
// }
|
||||
// lastMessageElement.addEventListener('animationend', handleAnimationEnd)
|
||||
// }
|
||||
// })
|
||||
// chatStore.clearNewMsgCount()
|
||||
// }
|
||||
|
||||
/** 点击后滚动到底部 */
|
||||
const scrollBottom = () => {
|
||||
@ -563,20 +563,11 @@ onMounted(() => {
|
||||
// 滚动到底部
|
||||
virtualListInst.value?.scrollTo({ position: 'bottom', debounce: true })
|
||||
})
|
||||
/**! 启动图标闪烁 需要设置"resources": ["sec-tauri/图标放置的文件夹"]*/
|
||||
// invoke('tray_blink', {
|
||||
// isRun: true,
|
||||
// ms: 500,
|
||||
// iconPath1: 'tray/msg.png',
|
||||
// iconPath2: 'tray/msg-sub.png'
|
||||
// }).catch((error) => {
|
||||
// console.error('设置图标失败:', error)
|
||||
// Mitt.on(MittEnum.SEND_MESSAGE, (event: MessageType) => {
|
||||
// nextTick(() => {
|
||||
// addToDomUpdateQueue(event.message.id, event.fromUser.uid)
|
||||
// })
|
||||
// })
|
||||
Mitt.on(MittEnum.SEND_MESSAGE, (event: MessageType) => {
|
||||
nextTick(() => {
|
||||
addToDomUpdateQueue(event.message.id, event.fromUser.uid)
|
||||
})
|
||||
})
|
||||
Mitt.on(`${MittEnum.INFO_POPOVER}-Main`, (event: any) => {
|
||||
selectKey.value = event.uid
|
||||
infoPopover.value = true
|
||||
|
@ -7,6 +7,7 @@ import apis from '@/services/apis.ts'
|
||||
import { useContactStore } from '@/stores/contacts'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useGlobalStore } from '@/stores/global.ts'
|
||||
import { isDiffNow } from '@/utils/ComputedTime.ts'
|
||||
|
||||
export const useChatMain = (activeItem?: SessionItem) => {
|
||||
const { removeTag, userUid } = useCommon()
|
||||
@ -87,6 +88,9 @@ export const useChatMain = (activeItem?: SessionItem) => {
|
||||
chatStore.updateRecallStatus({ msgId: item.message.id })
|
||||
},
|
||||
visible: (item: MessageType) => {
|
||||
// 判断当前选择的信息的发送时间是否超过2分钟
|
||||
if (isDiffNow({ time: item.message.sendTime, unit: 'minute', diff: 2 })) return
|
||||
// 判断自己是否是发送者或者是否是管理员
|
||||
const isCurrentUser = item.fromUser.uid === userUid.value
|
||||
const isAdmin = userInfo?.power === PowerEnum.ADMIN
|
||||
return isCurrentUser || isAdmin
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { emit } from '@tauri-apps/api/event'
|
||||
import axios from 'axios'
|
||||
import { EventEnum } from '@/enums'
|
||||
import { useWindow } from '@/hooks/useWindow.ts'
|
||||
|
||||
@ -21,9 +20,6 @@ export const useLogin = () => {
|
||||
const { createWebviewWindow } = useWindow()
|
||||
localStorage.removeItem('USER_INFO')
|
||||
localStorage.removeItem('TOKEN')
|
||||
// 清空axios请求头
|
||||
const instance = axios.create()
|
||||
instance.defaults.headers.common.Authorization = ''
|
||||
// todo 退出账号 需要关闭其他的全部窗口
|
||||
await createWebviewWindow('登录', 'login', 320, 448, 'home', false, 320, 448).then(() => {
|
||||
emit(EventEnum.LOGOUT)
|
||||
|
@ -220,14 +220,12 @@ export const CheckUpdate = defineComponent(() => {
|
||||
switch (event.event) {
|
||||
case 'Started':
|
||||
total.value = event.data.contentLength ? event.data.contentLength : 0
|
||||
console.log(`started downloading ${event.data.contentLength} bytes`)
|
||||
break
|
||||
case 'Progress':
|
||||
downloaded.value += event.data.chunkLength
|
||||
percentage.value = parseFloat(((downloaded.value / total.value) * 100 + '').substring(0, 4))
|
||||
break
|
||||
case 'Finished':
|
||||
console.log('download finished')
|
||||
window.$message.success('安装包下载成功,3s后重启并安装')
|
||||
setTimeout(() => {
|
||||
updating.value = false
|
||||
|
@ -5,15 +5,15 @@
|
||||
<!-- 需要判断当前路由是否是信息详情界面 -->
|
||||
<ChatBox :active-item="activeItem" v-if="msgBoxShow && isChat && activeItem !== -1" />
|
||||
|
||||
<Details :content="DetailsContent" v-else-if="detailsShow && isDetails" />
|
||||
<Details :content="DetailsContent" v-else-if="detailsShow && isDetails && DetailsContent.type !== 'apply'" />
|
||||
|
||||
<!-- 好友申请列表 -->
|
||||
<ApplyList v-else-if="DetailsContent && DetailsContent.type === 'apply'" />
|
||||
<ApplyList v-else-if="DetailsContent && isDetails && DetailsContent.type === 'apply'" />
|
||||
|
||||
<!-- 聊天界面背景图标 -->
|
||||
<div v-else class="flex-center size-full select-none">
|
||||
<img
|
||||
v-if="imgTheme === ThemeEnum.DARK && themes.versatile === 'default'"
|
||||
v-if="imgTheme === ThemeEnum.DARK && themes.versatile === 'default' && !isDetails"
|
||||
class="w-110px h-100px"
|
||||
src="@/assets/img/hula_bg_d.svg"
|
||||
alt="" />
|
||||
@ -80,7 +80,6 @@ onMounted(() => {
|
||||
DetailsContent.value = event.context
|
||||
})
|
||||
Mitt.on(MittEnum.DETAILS_SHOW, (event: any) => {
|
||||
console.log('event', event)
|
||||
DetailsContent.value = event.context
|
||||
detailsShow.value = event.detailsShow as boolean
|
||||
})
|
||||
|
@ -82,7 +82,7 @@ export default {
|
||||
POST<EmojiItem[]>(urls.sendAddFriendRequest, params),
|
||||
/** 同意好友申请 */
|
||||
applyFriendRequest: (params: { applyId: number }) => PUT(urls.sendAddFriendRequest, params),
|
||||
/** 同意好友申请 */
|
||||
/** 删除好友 */
|
||||
deleteFriend: (params: { targetUid: number }) => DELETE(urls.deleteFriend, params),
|
||||
/** 好友申请未读数 */
|
||||
newFriendCount: () => GET<{ unReadCount: number }>(urls.newFriendCount),
|
||||
@ -101,11 +101,11 @@ export default {
|
||||
/** 删除群成员 */
|
||||
removeGroupMember: (params: { roomId: number; uid: number }) => DELETE(urls.inviteGroupMember, params),
|
||||
/** 群组详情 */
|
||||
groupDetail: (params: { id: number }) => GET<GroupDetailReq>(urls.groupDetail, { params }),
|
||||
groupDetail: (params: { id: number }) => GET<GroupDetailReq>(urls.groupDetail, params),
|
||||
/** 会话详情 */
|
||||
sessionDetail: (params: { id: number }) => GET<SessionItem>(urls.sessionDetail, { params }),
|
||||
/** 会话详情(联系人列表发消息用) */
|
||||
sessionDetailWithFriends: (params: { uid: number }) => GET<SessionItem>(urls.sessionDetailWithFriends, { params }),
|
||||
sessionDetailWithFriends: (params: { uid: number }) => GET<SessionItem>(urls.sessionDetailWithFriends, params),
|
||||
/** 添加群管理 */
|
||||
addAdmin: ({ roomId, uidList }: { roomId: number; uidList: number[] }) =>
|
||||
PUT<boolean>(urls.addAdmin, {
|
||||
|
@ -82,77 +82,3 @@ async function Http<T>(
|
||||
}
|
||||
|
||||
export default Http
|
||||
|
||||
// import { fetch } from '@tauri-apps/plugin-http';
|
||||
// import * as qs from 'qs';
|
||||
|
||||
// const isAbsoluteURL = (url: string) => {
|
||||
// return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
|
||||
// };
|
||||
|
||||
// const combineURLs = (baseURL: string, relativeURL: string) => {
|
||||
// return relativeURL
|
||||
// ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
|
||||
// : baseURL;
|
||||
// };
|
||||
|
||||
// const buildFullPath = (baseURL: string, requestedURL: string) => {
|
||||
// if (baseURL && !isAbsoluteURL(requestedURL)) {
|
||||
// return combineURLs(baseURL, requestedURL);
|
||||
// }
|
||||
// return requestedURL;
|
||||
// };
|
||||
|
||||
// const buildURL = (url: string | string[], params: any) => {
|
||||
// if (!params) {
|
||||
// return url;
|
||||
// }
|
||||
// const serializedParams = qs.stringify(params);
|
||||
// if (serializedParams) {
|
||||
// url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
|
||||
// }
|
||||
// return url;
|
||||
// };
|
||||
|
||||
// const server = '';
|
||||
// const baseURL = `${server}/api/`;
|
||||
|
||||
// const BODY_TYPE = {
|
||||
// Form: 'Form',
|
||||
// Json: 'Json',
|
||||
// Text: 'Text',
|
||||
// Bytes: 'Bytes',
|
||||
// };
|
||||
|
||||
// const commonOptions = {
|
||||
// timeout: 60,
|
||||
// };
|
||||
|
||||
// const http = (url: string, options: any = {}) => {
|
||||
// const params = { ...options.params };
|
||||
// if (!options.headers) options.headers = {};
|
||||
// // todo 可以往 headers 中添加 token 或 cookie 等信息
|
||||
|
||||
// if (options?.body) {
|
||||
// if (options.body.type === BODY_TYPE.Form) {
|
||||
// options.headers['Content-Type'] = 'multipart/form-data';
|
||||
// }
|
||||
// }
|
||||
|
||||
// options = { ...commonOptions, ...options };
|
||||
// let fetchUrl:string = buildFullPath(baseURL, url)
|
||||
// return fetch(<string>buildURL(fetchUrl, params), options)
|
||||
// .then((res: any) => {
|
||||
// const { status, data } = res
|
||||
// if (status >= 200 && status < 400) {
|
||||
// return { data };
|
||||
// }
|
||||
// return Promise.reject({ status, data });
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// console.error(err);
|
||||
// return Promise.reject(err);
|
||||
// });
|
||||
// };
|
||||
|
||||
// export default http;
|
||||
|
@ -181,7 +181,7 @@ const responseInterceptor = async <T>(
|
||||
|
||||
const resp = data.resp
|
||||
const serviceData = (await data.data) as ServiceResponse
|
||||
|
||||
console.log(data)
|
||||
//检查发送请求是否成功
|
||||
if (resp.status > 400) {
|
||||
let message = ''
|
||||
@ -228,13 +228,11 @@ const responseInterceptor = async <T>(
|
||||
}
|
||||
return Promise.reject(`err: ${message}, status: ${resp.status}`)
|
||||
}
|
||||
console.log(data)
|
||||
//检查服务端返回是否成功,并且中断请求
|
||||
if (!serviceData.success) {
|
||||
window.$message.error(serviceData.errMsg)
|
||||
return Promise.reject(`http error: ${serviceData.errMsg}`)
|
||||
}
|
||||
console.log(data)
|
||||
return Promise.resolve(serviceData.data)
|
||||
} catch (err) {
|
||||
return Promise.reject(`http error: ${err}`)
|
||||
|
@ -5,7 +5,6 @@ import type { MarkItemType, MessageType, RevokedMsgType, SessionItem } from '@/s
|
||||
import { MarkEnum, MsgEnum, RoomTypeEnum } from '@/enums'
|
||||
import { computedTimeBlock } from '@/utils/ComputedTime.ts'
|
||||
import { useCachedStore } from '@/stores/cached'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useGlobalStore } from '@/stores/global'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { useContactStore } from '@/stores/contacts'
|
||||
@ -18,7 +17,7 @@ let isFirstInit = false
|
||||
export const useChatStore = defineStore('chat', () => {
|
||||
const route = useRoute()
|
||||
const cachedStore = useCachedStore()
|
||||
const userStore = useUserStore()
|
||||
// const userStore = useUserStore()
|
||||
const globalStore = useGlobalStore()
|
||||
const groupStore = useGroupStore()
|
||||
const contactStore = useContactStore()
|
||||
@ -125,7 +124,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
if (currentRoomType.value === RoomTypeEnum.GROUP) {
|
||||
groupStore.getGroupUserList(true)
|
||||
groupStore.getCountStatistic()
|
||||
cachedStore.getGroupAtUserBaseInfo()
|
||||
// cachedStore.getGroupAtUserBaseInfo()
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +218,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
// 请求第一个群成员列表
|
||||
currentRoomType.value === RoomTypeEnum.GROUP && (await groupStore.getGroupUserList(true))
|
||||
// 初始化所有用户基本信息
|
||||
userStore.isSign && (await cachedStore.initAllUserBaseInfo())
|
||||
// userStore.isSign && (await cachedStore.initAllUserBaseInfo())
|
||||
// 联系人列表
|
||||
await contactStore.getContactList(true)
|
||||
}
|
||||
@ -279,8 +278,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
detailResponse = await apis.sessionDetail({ id: msg.message.roomId })
|
||||
}
|
||||
if (detailResponse) {
|
||||
const data = detailResponse
|
||||
updateSessionLastActiveTime(msg.message.roomId, data)
|
||||
updateSessionLastActiveTime(msg.message.roomId, detailResponse)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,6 @@ export const useGroupStore = defineStore('group', () => {
|
||||
roomId: currentRoomId.value
|
||||
}
|
||||
})
|
||||
console.log(res)
|
||||
if (!res) return
|
||||
const data = res
|
||||
const tempNew = cloneDeep(uniqueUserList(refresh ? data.list : [...data.list, ...userList.value]))
|
||||
|
@ -15,9 +15,7 @@
|
||||
<ContextMenu @contextmenu="showMenu($event)" @select="handleSelect($event.label)" :menu="menuList">
|
||||
<n-collapse-item title="我的好友" name="1">
|
||||
<template #header-extra>
|
||||
<span class="text-(10px #707070)">
|
||||
{{ contactStore.contactsList.length }}/{{ contactStore.contactsList.length }}
|
||||
</span>
|
||||
<span class="text-(10px #707070)"> {{ onlineCount }}/{{ contactStore.contactsList.length }} </span>
|
||||
</template>
|
||||
|
||||
<!-- 用户框 多套一层div来移除默认的右键事件然后覆盖掉因为margin空隙而导致右键可用 -->
|
||||
@ -35,6 +33,8 @@
|
||||
bordered
|
||||
:color="'#fff'"
|
||||
:size="44"
|
||||
class="grayscale"
|
||||
:class="{ 'grayscale-0': item.activeStatus === OnlineEnum.ONLINE }"
|
||||
:src="useUserInfo(item.uid).value.avatar"
|
||||
fallback-src="/logo.png" />
|
||||
|
||||
@ -43,9 +43,15 @@
|
||||
useUserInfo(item.uid).value.name
|
||||
}}</span>
|
||||
|
||||
<span class="text leading-tight text-12px flex-1 truncate">
|
||||
[⛅今日天气] 说的很经典哈萨克的哈萨克看到贺卡上
|
||||
</span>
|
||||
<div class="text leading-tight text-12px flex-y-center gap-2px flex-1 truncate">
|
||||
[
|
||||
<img
|
||||
class="size-14px"
|
||||
:src="`/status/${item.activeStatus === OnlineEnum.ONLINE ? 'online.png' : 'offline.png'}`"
|
||||
alt="离线" />
|
||||
{{ item.activeStatus === OnlineEnum.ONLINE ? '在线' : '离线' }}
|
||||
]
|
||||
</div>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
@ -74,7 +80,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import Mitt from '@/utils/Bus.ts'
|
||||
import { MittEnum, RoomTypeEnum } from '@/enums'
|
||||
import { MittEnum, OnlineEnum, RoomTypeEnum } from '@/enums'
|
||||
import { useContactStore } from '@/stores/contacts.ts'
|
||||
import { useUserInfo } from '@/hooks/useCached.ts'
|
||||
|
||||
@ -88,6 +94,10 @@ const activeItem = ref(0)
|
||||
const detailsShow = ref(false)
|
||||
const shrinkStatus = ref(false)
|
||||
const contactStore = useContactStore()
|
||||
/** 统计在线用户人数 */
|
||||
const onlineCount = computed(() => {
|
||||
return contactStore.contactsList.filter((item) => item.activeStatus === OnlineEnum.ONLINE).length
|
||||
})
|
||||
/** 监听独立窗口关闭事件 */
|
||||
watchEffect(() => {
|
||||
Mitt.on(MittEnum.SHRINK_WINDOW, async (event) => {
|
||||
@ -98,7 +108,6 @@ watchEffect(() => {
|
||||
const handleClick = (index: number, type: number) => {
|
||||
detailsShow.value = true
|
||||
activeItem.value = index
|
||||
console.log(index, type)
|
||||
const data = {
|
||||
context: {
|
||||
type: type,
|
||||
@ -123,6 +132,7 @@ const handleApply = () => {
|
||||
type: 'apply'
|
||||
}
|
||||
})
|
||||
activeItem.value = 0
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -145,7 +155,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.active {
|
||||
background: var(--bg-active-msg);
|
||||
background: var(--msg-active-color);
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
.text {
|
||||
|
@ -123,7 +123,7 @@ watchEffect(() => {
|
||||
|
||||
onBeforeMount(() => {
|
||||
// 请求回话列表
|
||||
chatStore.getSessionList()
|
||||
chatStore.getSessionList(true)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user