fix(service): 🐛 修复请求接口bug

优化用户在线状态展示
This commit is contained in:
nongyehong 2024-11-05 17:43:58 +08:00
parent 7b530297ac
commit f3723d4e5a
15 changed files with 71 additions and 146 deletions

View File

@ -9,5 +9,6 @@ index.html
src/assets
.eslintrc.cjs
**/config
src-tauri/**
commitlint.config.cjs
auto-imports.d.ts

View File

@ -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>

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
})

View File

@ -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, {

View File

@ -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;

View File

@ -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}`)

View File

@ -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)
}
}

View File

@ -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]))

View File

@ -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 {

View File

@ -123,7 +123,7 @@ watchEffect(() => {
onBeforeMount(() => {
//
chatStore.getSessionList()
chatStore.getSessionList(true)
})
onMounted(() => {