perf(component): ⚡ 优化一些功能的操作体验和样式
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 后端服务地址
|
||||
# VITE_SERVICE_URL="https://hulaspark.com/api"
|
||||
VITE_SERVICE_URL="https://hulaspark.com/api"
|
||||
# # websocket服务地址
|
||||
# VITE_WEBSOCKET_URL="wss://hulaspark.com/websocket"
|
||||
VITE_WEBSOCKET_URL="wss://hulaspark.com/websocket"
|
||||
# 项目标题
|
||||
VITE_APP_TITLE="HuLa—IM"
|
||||
# 项目名称
|
||||
@@ -10,5 +10,5 @@ VITE_APP_NAME="HuLa"
|
||||
VITE_GITEE_TOKEN="a9029798336825cea39ac9e4413b8579"
|
||||
|
||||
# 启用本地的服务地址,先要注释掉上面的服务地址
|
||||
VITE_SERVICE_URL="http://127.0.0.1:9190"
|
||||
VITE_WEBSOCKET_URL="ws://127.0.0.1:8090/websocket"
|
||||
# VITE_SERVICE_URL="http://127.0.0.1:9190"
|
||||
# VITE_WEBSOCKET_URL="ws://127.0.0.1:8090/websocket"
|
||||
|
||||
@@ -160,7 +160,11 @@ const finishLoading = () => {
|
||||
loadingText.value = '确定'
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
// 定义组件实例类型
|
||||
export interface AvatarCropperInstance {
|
||||
finishLoading: () => void
|
||||
}
|
||||
defineExpose<AvatarCropperInstance>({
|
||||
finishLoading
|
||||
})
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ defineExpose<VirtualListExpose>({
|
||||
} else if (options.position === 'top') {
|
||||
// 滚动到顶部
|
||||
containerRef.value.scrollTop = 0
|
||||
} else if (typeof options.index === 'string') {
|
||||
} else if (typeof options.index === 'number') {
|
||||
// 滚动到指定索引位置
|
||||
const offset = getOffsetForIndex(options.index)
|
||||
containerRef.value.scrollTo({
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 消息为系统消息时 -->
|
||||
<div v-if="item.message.type === MsgEnum.SYSTEM">
|
||||
<div v-else-if="item.message.type === MsgEnum.SYSTEM">
|
||||
<p class="text-(12px #909090) select-none cursor-default">
|
||||
{{ item.message.body }}
|
||||
</p>
|
||||
@@ -318,7 +318,7 @@
|
||||
:size="6"
|
||||
v-if="item.message.body.reply"
|
||||
@click="jumpToReplyMsg(item.message.body.reply.id)"
|
||||
class="reply-bubble relative w-fit custom-shadow">
|
||||
class="reply-bubble relative max-w-86% w-fit custom-shadow">
|
||||
<svg class="size-14px">
|
||||
<use href="#to-top"></use>
|
||||
</svg>
|
||||
|
||||
@@ -287,7 +287,9 @@ export enum ModalEnum {
|
||||
/** 锁屏弹窗 */
|
||||
LOCK_SCREEN,
|
||||
/** 检查更新弹窗 */
|
||||
CHECK_UPDATE
|
||||
CHECK_UPDATE,
|
||||
/** 异地登录弹窗 */
|
||||
REMOTE_LOGIN
|
||||
}
|
||||
|
||||
/** MacOS键盘映射 */
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
<script setup lang="ts">
|
||||
import LoadingSpinner from '@/components/common/LoadingSpinner.vue'
|
||||
import { useMitt } from '@/hooks/useMitt.ts'
|
||||
import { ChangeTypeEnum, MittEnum, OnlineEnum, RoomTypeEnum } from '@/enums'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { ChangeTypeEnum, MittEnum, ModalEnum, OnlineEnum, RoomTypeEnum } from '@/enums'
|
||||
import { getCurrentWebviewWindow, WebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { useGlobalStore } from '@/stores/global.ts'
|
||||
import { useContactStore } from '@/stores/contacts.ts'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
@@ -36,17 +36,13 @@ import { useUserStore } from '@/stores/user'
|
||||
import { useChatStore } from '@/stores/chat'
|
||||
import { LoginSuccessResType, OnStatusChangeType, WsResponseMessageType, WsTokenExpire } from '@/services/wsType.ts'
|
||||
import type { MarkItemType, MessageType, RevokedMsgType } from '@/services/types.ts'
|
||||
import { useLogin } from '@/hooks/useLogin.ts'
|
||||
import { computedToken } from '@/services/request'
|
||||
import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification'
|
||||
import { useUserInfo } from '@/hooks/useCached.ts'
|
||||
import { emitTo } from '@tauri-apps/api/event'
|
||||
import { useThrottleFn } from '@vueuse/core'
|
||||
import apis from '@/services/apis.ts'
|
||||
import { confirm } from '@tauri-apps/plugin-dialog'
|
||||
import { useCachedStore } from '@/stores/cached'
|
||||
import { clearListener, initListener, readCountQueue } from '@/utils/ReadCountQueue'
|
||||
import { useSettingStore } from '@/stores/setting'
|
||||
|
||||
const loadingPercentage = ref(10)
|
||||
const loadingText = ref('正在加载应用...')
|
||||
@@ -93,9 +89,6 @@ const groupStore = useGroupStore()
|
||||
const userStore = useUserStore()
|
||||
const chatStore = useChatStore()
|
||||
const cachedStore = useCachedStore()
|
||||
const { logout, resetLoginState } = useLogin()
|
||||
const settingStore = useSettingStore()
|
||||
const { login } = storeToRefs(settingStore)
|
||||
// 清空未读消息
|
||||
// globalStore.unReadMark.newMsgUnreadCount = 0
|
||||
const shrinkStatus = ref(false)
|
||||
@@ -121,13 +114,13 @@ useMitt.on(MittEnum.SHRINK_WINDOW, (event: boolean) => {
|
||||
shrinkStatus.value = event
|
||||
})
|
||||
|
||||
useMitt.on(WsResponseMessageType.LOGIN_SUCCESS, (data: LoginSuccessResType) => {
|
||||
useMitt.on(WsResponseMessageType.LOGIN_SUCCESS, async (data: LoginSuccessResType) => {
|
||||
const { ...rest } = data
|
||||
// 更新一下请求里面的 token.
|
||||
computedToken.clear()
|
||||
computedToken.get()
|
||||
// 自己更新自己上线
|
||||
groupStore.batchUpdateUserStatus([
|
||||
await groupStore.batchUpdateUserStatus([
|
||||
{
|
||||
activeStatus: OnlineEnum.ONLINE,
|
||||
avatar: rest.avatar,
|
||||
@@ -148,18 +141,24 @@ useMitt.on(WsResponseMessageType.ONLINE, async (onStatusChangeType: OnStatusChan
|
||||
console.log('收到用户上线通知')
|
||||
groupStore.countInfo.onlineNum = onStatusChangeType.onlineNum
|
||||
// groupStore.countInfo.totalNum = onStatusChangeType.totalNum
|
||||
groupStore.batchUpdateUserStatus(onStatusChangeType.changeList)
|
||||
await groupStore.batchUpdateUserStatus(onStatusChangeType.changeList)
|
||||
await groupStore.refreshGroupMembers()
|
||||
})
|
||||
useMitt.on(WsResponseMessageType.TOKEN_EXPIRED, async (wsTokenExpire: WsTokenExpire) => {
|
||||
console.log('账号在其他设备登录', wsTokenExpire)
|
||||
if (userStore.userInfo.uid === wsTokenExpire.uid && userStore.userInfo.client === wsTokenExpire.client) {
|
||||
// TODO: 换成web的弹出框
|
||||
await confirm('账号在其他设备' + (wsTokenExpire.ip ? wsTokenExpire.ip : '未知IP') + '登录')
|
||||
// token已在后端清空,只需要返回登录页
|
||||
await apis.logout(login.value.autoLogin)
|
||||
await resetLoginState()
|
||||
await logout()
|
||||
if (
|
||||
Number(userStore.userInfo.uid) === Number(wsTokenExpire.uid) &&
|
||||
userStore.userInfo.client === wsTokenExpire.client
|
||||
) {
|
||||
// 聚焦主窗口
|
||||
const home = await WebviewWindow.getByLabel('home')
|
||||
await home?.setFocus()
|
||||
console.log('账号在其他设备登录', wsTokenExpire)
|
||||
useMitt.emit(MittEnum.LEFT_MODAL_SHOW, {
|
||||
type: ModalEnum.REMOTE_LOGIN,
|
||||
props: {
|
||||
ip: wsTokenExpire.ip
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
useMitt.on(WsResponseMessageType.INVALID_USER, (param: { uid: string }) => {
|
||||
|
||||
@@ -149,6 +149,7 @@ import { formatTimestamp, isDiffNow } from '@/utils/ComputedTime.ts'
|
||||
import dayjs from 'dayjs'
|
||||
import { useTauriListener } from '@/hooks/useTauriListener'
|
||||
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import type { AvatarCropperInstance } from '@/components/common/AvatarCropper.vue'
|
||||
|
||||
const appWindow = WebviewWindow.getCurrent()
|
||||
let localUserInfo = ref<Partial<UserInfoType>>({})
|
||||
@@ -161,7 +162,7 @@ const { countGraphemes } = useCommon()
|
||||
const showCropper = ref(false)
|
||||
const fileInput = ref<HTMLInputElement>()
|
||||
const localImageUrl = ref('')
|
||||
const cropperRef = useTemplateRef('cropperRef')
|
||||
const cropperRef = useTemplateRef<AvatarCropperInstance>('cropperRef')
|
||||
|
||||
// 监听裁剪窗口的关闭
|
||||
watch(
|
||||
|
||||
@@ -64,14 +64,18 @@ const moreList = ref<OPT.L.MoreList[]>([
|
||||
label: '检查更新',
|
||||
icon: 'arrow-circle-up',
|
||||
click: () => {
|
||||
useMitt.emit(MittEnum.LEFT_MODAL_SHOW, ModalEnum.CHECK_UPDATE)
|
||||
useMitt.emit(MittEnum.LEFT_MODAL_SHOW, {
|
||||
type: ModalEnum.CHECK_UPDATE
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '锁定屏幕',
|
||||
icon: 'lock',
|
||||
click: () => {
|
||||
useMitt.emit(MittEnum.LEFT_MODAL_SHOW, ModalEnum.LOCK_SCREEN)
|
||||
useMitt.emit(MittEnum.LEFT_MODAL_SHOW, {
|
||||
type: ModalEnum.LOCK_SCREEN
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<InfoEdit />
|
||||
|
||||
<!-- 弹出框 -->
|
||||
<component :is="componentMap" />
|
||||
<component :is="componentMap" v-bind="componentProps" />
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
@@ -20,22 +20,27 @@ import LeftAvatar from './components/LeftAvatar.vue'
|
||||
import ActionList from './components/ActionList.vue'
|
||||
import InfoEdit from './components/InfoEdit.vue'
|
||||
import { useMitt } from '@/hooks/useMitt.ts'
|
||||
import { lock, LockScreen, CheckUpdate } from './model.tsx'
|
||||
import { modalShow, LockScreen, CheckUpdate, RemoteLogin } from './model.tsx'
|
||||
import type { Component } from 'vue'
|
||||
import { MittEnum, ModalEnum } from '@/enums'
|
||||
|
||||
const componentMap = shallowRef<Component>()
|
||||
// 存储要传递给组件的props
|
||||
const componentProps = shallowRef<Record<string, any>>({})
|
||||
/** 弹窗组件内容映射 */
|
||||
const componentMapping: Record<number, Component> = {
|
||||
[ModalEnum.LOCK_SCREEN]: LockScreen,
|
||||
[ModalEnum.CHECK_UPDATE]: CheckUpdate
|
||||
[ModalEnum.CHECK_UPDATE]: CheckUpdate,
|
||||
[ModalEnum.REMOTE_LOGIN]: RemoteLogin
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
useMitt.on(MittEnum.LEFT_MODAL_SHOW, (event) => {
|
||||
componentMap.value = componentMapping[event as ModalEnum]
|
||||
useMitt.on(MittEnum.LEFT_MODAL_SHOW, (event: { type: ModalEnum; props?: Record<string, any> }) => {
|
||||
componentMap.value = componentMapping[event.type]
|
||||
// 保存传入的props
|
||||
componentProps.value = event.props || {}
|
||||
nextTick(() => {
|
||||
lock.value.modalShow = true
|
||||
modalShow.value = true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,13 +26,30 @@ import { useUserStore } from '@/stores/user.ts'
|
||||
import { useSettingStore } from '@/stores/setting.ts'
|
||||
import { AvatarUtils } from '@/utils/AvatarUtils'
|
||||
import { confirm } from '@tauri-apps/plugin-dialog'
|
||||
import apis from '@/services/apis'
|
||||
import { useLogin } from '@/hooks/useLogin'
|
||||
|
||||
const { logout, resetLoginState } = useLogin()
|
||||
const formRef = ref<FormInst | null>()
|
||||
const formValue = ref({
|
||||
lockPassword: ''
|
||||
})
|
||||
export const modalShow = ref(false)
|
||||
export const remotelogin = ref({
|
||||
loading: false,
|
||||
async logout() {
|
||||
remotelogin.value.loading = true
|
||||
const settingStore = useSettingStore()
|
||||
const { login } = storeToRefs(settingStore)
|
||||
// token已在后端清空,只需要返回登录页
|
||||
await apis.logout(login.value.autoLogin)
|
||||
await resetLoginState()
|
||||
await logout()
|
||||
modalShow.value = false
|
||||
remotelogin.value.loading = false
|
||||
}
|
||||
})
|
||||
export const lock = ref({
|
||||
modalShow: false,
|
||||
loading: false,
|
||||
rules: {
|
||||
lockPassword: {
|
||||
@@ -53,7 +70,7 @@ export const lock = ref({
|
||||
/** 发送锁屏事件,当打开的窗口接受到后会自动锁屏 */
|
||||
await emit(EventEnum.LOCK_SCREEN)
|
||||
lock.value.loading = false
|
||||
lock.value.modalShow = false
|
||||
modalShow.value = false
|
||||
formValue.value.lockPassword = ''
|
||||
}, 1000)
|
||||
})
|
||||
@@ -66,18 +83,18 @@ export const lock = ref({
|
||||
export const LockScreen = defineComponent(() => {
|
||||
const userStore = useUserStore()
|
||||
return () => (
|
||||
<NModal v-model:show={lock.value.modalShow} maskClosable={false} class="w-350px border-rd-8px">
|
||||
<NModal v-model:show={modalShow.value} maskClosable={false} class="w-350px border-rd-8px">
|
||||
<div class="bg-[--bg-popover] w-360px h-full p-6px box-border flex flex-col">
|
||||
{type() === 'macos' ? (
|
||||
<div
|
||||
onClick={() => (lock.value.modalShow = false)}
|
||||
onClick={() => (modalShow.value = false)}
|
||||
class="mac-close relative size-13px shadow-inner bg-#ed6a5eff rounded-50% select-none">
|
||||
<svg class="hidden size-7px color-#000 font-bold select-none absolute top-3px left-3px">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
</div>
|
||||
) : (
|
||||
<svg onClick={() => (lock.value.modalShow = false)} class="w-12px h-12px ml-a cursor-pointer select-none">
|
||||
<svg onClick={() => (modalShow.value = false)} class="w-12px h-12px ml-a cursor-pointer select-none">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
)}
|
||||
@@ -285,18 +302,18 @@ export const CheckUpdate = defineComponent(() => {
|
||||
await checkUpdate()
|
||||
})
|
||||
return () => (
|
||||
<NModal v-model:show={lock.value.modalShow} maskClosable={false} class="w-350px border-rd-8px">
|
||||
<NModal v-model:show={modalShow.value} maskClosable={false} class="w-350px border-rd-8px">
|
||||
<div class="bg-[--bg-popover] w-500px h-full p-6px box-border flex flex-col">
|
||||
{type() === 'macos' ? (
|
||||
<div
|
||||
onClick={() => (lock.value.modalShow = false)}
|
||||
onClick={() => (modalShow.value = false)}
|
||||
class="mac-close relative size-13px shadow-inner bg-#ed6a5eff rounded-50% select-none">
|
||||
<svg class="hidden size-7px color-#000 font-bold select-none absolute top-3px left-3px">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
</div>
|
||||
) : (
|
||||
<svg onClick={() => (lock.value.modalShow = false)} class="w-12px h-12px ml-a cursor-pointer select-none">
|
||||
<svg onClick={() => (modalShow.value = false)} class="w-12px h-12px ml-a cursor-pointer select-none">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
)}
|
||||
@@ -421,3 +438,68 @@ export const CheckUpdate = defineComponent(() => {
|
||||
</NModal>
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* 异地登录弹窗
|
||||
*/
|
||||
export const RemoteLogin = defineComponent({
|
||||
props: {
|
||||
ip: {
|
||||
type: String,
|
||||
default: '未知IP'
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const userStore = useUserStore()
|
||||
return () => (
|
||||
<NModal
|
||||
v-model:show={modalShow.value}
|
||||
maskClosable={false}
|
||||
class="w-350px border-rd-8px select-none cursor-default">
|
||||
<div class="bg-[--bg-popover] w-360px h-full p-6px box-border flex flex-col">
|
||||
{type() === 'macos' ? (
|
||||
<div
|
||||
onClick={remotelogin.value.logout}
|
||||
class="mac-close relative size-13px shadow-inner bg-#ed6a5eff rounded-50% select-none">
|
||||
<svg class="hidden size-7px color-#000 font-bold select-none absolute top-3px left-3px">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
</div>
|
||||
) : (
|
||||
<svg onClick={remotelogin.value.logout} class="w-12px h-12px ml-a cursor-pointer select-none">
|
||||
<use href="#close"></use>
|
||||
</svg>
|
||||
)}
|
||||
<div class="flex flex-col gap-10px p-10px select-none">
|
||||
<NFlex vertical align="center" size={30}>
|
||||
<span class="text-(14px [--text-color])">下线通知</span>
|
||||
|
||||
<div class="relative">
|
||||
<img class="rounded-full size-72px" src={AvatarUtils.getAvatarUrl(userStore.userInfo.avatar!)} />
|
||||
<div class="absolute inset-0 bg-[--avatar-hover-bg] backdrop-blur-[2px] rounded-full flex items-center justify-center">
|
||||
<svg class="size-34px text-white animate-pulse">
|
||||
<use href="#cloudError"></use>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-(13px centent [--text-color]) px-12px leading-loose mb-20px">
|
||||
您的账号在其他设备 <span class="text-#13987f">{props.ip}</span>{' '}
|
||||
登录,如非本人登录,请尽快修改密码,建议联系管理员
|
||||
</div>
|
||||
</NFlex>
|
||||
<NButton
|
||||
disabled={remotelogin.value.loading}
|
||||
loading={remotelogin.value.loading}
|
||||
onClick={remotelogin.value.logout}
|
||||
style={{ color: '#fff' }}
|
||||
class="w-full"
|
||||
color="#13987f">
|
||||
重新登录
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</NModal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,21 +4,21 @@ import type { UserInfoType, UserItem } from '@/services/types.ts'
|
||||
export enum WsResponseMessageType {
|
||||
/** 无网络连接 */
|
||||
NO_INTERNET = 'noInternet',
|
||||
/** 1.登录返回二维码 */
|
||||
/** 登录返回二维码 */
|
||||
LOGIN_QR_CODE = 'loginQrCode',
|
||||
/** 2.用户扫描成功等待授权 */
|
||||
/** 用户扫描成功等待授权 */
|
||||
WAITING_AUTHORIZE = 'waitingAuthorize',
|
||||
/** 3.用户登录成功返回用户信息 */
|
||||
/** 用户登录成功返回用户信息 */
|
||||
LOGIN_SUCCESS = 'loginSuccess',
|
||||
/** 4.收到消息 */
|
||||
/** 收到消息 */
|
||||
RECEIVE_MESSAGE = 'receiveMessage',
|
||||
/** 5.上线推送 */
|
||||
/** 上线推送 */
|
||||
ONLINE = 'online',
|
||||
/** 6.前端token失效 */
|
||||
/** 前端token失效 */
|
||||
TOKEN_EXPIRED = 'tokenExpired',
|
||||
/** 7.禁用的用户 */
|
||||
/** 禁用的用户 */
|
||||
INVALID_USER = 'invalidUser',
|
||||
/** 8.点赞、倒赞更新通知 */
|
||||
/** 点赞、倒赞更新通知 */
|
||||
MSG_MARK_ITEM = 'msgMarkItem',
|
||||
/** 消息撤回 */
|
||||
MSG_RECALL = 'msgRecall',
|
||||
@@ -31,7 +31,19 @@ export enum WsResponseMessageType {
|
||||
/** 同意好友请求 */
|
||||
REQUEST_APPROVAL_FRIEND = 'requestApprovalFriend',
|
||||
/** 用户状态改变 */
|
||||
USER_STATE_CHANGE = 'userStateChange'
|
||||
USER_STATE_CHANGE = 'userStateChange',
|
||||
/** 管理员修改群聊信息 */
|
||||
ROOM_INFO_CHANGE = 'roomInfoChange',
|
||||
/** 自己修改我在群里的信息 */
|
||||
MY_ROOM_INFO_CHANGE = 'myRoomInfoChange',
|
||||
/** 群通知消息 */
|
||||
ROOM_GROUP_MSG = 'roomGroupMsg',
|
||||
/** 群公告消息 */
|
||||
ROOM_GROUP_NOTICE_MSG = 'roomGroupNoticeMsg',
|
||||
/** 群公告已读 */
|
||||
ROOM_GROUP_NOTICE_READ_MSG = 'roomGroupNoticeReadMsg',
|
||||
/** 群解散 */
|
||||
ROOM_DISSOLUTION = 'roomDissolution'
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -149,7 +149,7 @@ export const useGroupStore = defineStore('group', () => {
|
||||
* 批量更新用户在线状态
|
||||
* @param items 需要更新状态的用户列表
|
||||
*/
|
||||
const batchUpdateUserStatus = (items: UserItem[]) => {
|
||||
const batchUpdateUserStatus = async (items: UserItem[]) => {
|
||||
for (const curUser of items) {
|
||||
const findIndex = userList.value.findIndex((item) => item.uid === curUser.uid)
|
||||
userList.value[findIndex] = {
|
||||
|
||||
@@ -103,6 +103,8 @@ svg {
|
||||
--danger-bg: #f6dfe3;
|
||||
// 头像边框颜色
|
||||
--avatar-border-color: #fff;
|
||||
// hover头像样式
|
||||
--avatar-hover-bg: rgba(255, 255, 255, 0.1);
|
||||
// 插件背景颜色
|
||||
--plugin-bg-color: #eee;
|
||||
// 列表悬浮的颜色
|
||||
@@ -193,6 +195,8 @@ html[data-theme='dark'] {
|
||||
--danger-bg: #37292c;
|
||||
// 头像边框颜色
|
||||
--avatar-border-color: #1b1b1b;
|
||||
// hover头像样式
|
||||
--avatar-hover-bg: rgba(30, 30, 30, 0.6);
|
||||
// 插件背景颜色
|
||||
--plugin-bg-color: #3b3b3b;
|
||||
// 列表悬浮的颜色
|
||||
|
||||
@@ -160,7 +160,7 @@ onMounted(() => {
|
||||
// 获取用户详情
|
||||
userStore.getUserDetailAction()
|
||||
// 自己更新自己上线
|
||||
groupStore.batchUpdateUserStatus([
|
||||
await groupStore.batchUpdateUserStatus([
|
||||
{
|
||||
activeStatus: OnlineEnum.ONLINE,
|
||||
avatar: rest.avatar,
|
||||
|
||||
Reference in New Issue
Block a user