<script lang="ts" setup name="Tools"> import { useFullscreen } from '@vueuse/core' import type { Ref } from 'vue' import ResetPwd from './resetPwd.vue' import eventBus from '@/utils/eventBus' import useSettingsStore from '@/store/modules/settings' import useUserStore from '@/store/modules/user' import useWebsocketStore from '@/store/modules/websocket' import { formUrl } from '@/utils/scheduleDict' const props = defineProps({ // 是否显示回到总工作台图标 ishiddenBackToWorkbench: { type: Boolean, default: false, }, }) const router = useRouter() const settingsStore = useSettingsStore() const userStore = useUserStore() const websocket = useWebsocketStore() const mainPage = useMainPage() const { isFullscreen, toggle } = useFullscreen() const resetPwd = ref() interface Message { id: string message: string time: string formId: string } interface websocketMessage { createTime: string formId: string id: string messageContent: string messageTitle: string noticeDeptId: string noticeId: string } const messageList: Ref<Message[]> = ref([]) // createTime:"2023-05-16 11:08:05" // formId:"jlglwjsp" // id:"1658308307976204289" // messageContent:"文件审批" // messageTitle:"审批结果通知" // noticeDeptId:"0" // noticeId:"3" // messageList.value = [ // { id: '1', message: '示例消息', time: '2022-07-20 18:32:00' }, // { id: '2', message: '收到一条证书到期提醒', time: '2022-07-20 18:32:00' }, // { id: '3', message: '有新的借用申请待审批', time: '2022-07-20 18:32:00' }, // { id: '4', message: '您的请假申请已通过', time: '2022-07-20 18:32:00' }, // { id: '1', message: '示例消息', time: '2022-07-20 18:32:00' }, // { id: '2', message: '收到一条证书到期提醒', time: '2022-07-20 18:32:00' }, // { id: '3', message: '有新的借用申请待审批', time: '2022-07-20 18:32:00' }, // { id: '4', message: '您的请假申请已通过', time: '2022-07-20 18:32:00' }, // ] function userCommand(command: 'dashboard' | 'resetPassword' | 'setting' | 'hotkeys' | 'logout') { switch (command) { case 'dashboard': router.push({ name: 'dashboard', }) break case 'resetPassword': resetPwd.value.initDialog() break case 'setting': router.push({ name: 'personalSetting', }) break case 'hotkeys': eventBus.emit('global-hotkeys-intro-toggle') break case 'logout': userStore.logout().then(() => { router.push({ name: 'login', }) }) break } } function pro() { window.open('https://hooray.gitee.io/fantastic-admin-pro-example/', 'top') } onMounted(() => { // 连接 websocket websocket.initWebSocket() }) onBeforeMount(() => { // 断开 websocket websocket.destroyWebSocket() }) // 监听消息变化 watch(() => websocket.messageList, (newVal) => { messageList.value = newVal.map((item: websocketMessage) => ({ id: item.id, message: item.messageContent + item.messageTitle, time: item.createTime, formId: item.formId, })) }, { deep: true, immediate: true, }) const $router = useRouter() // 进入消息列表 const toMessageList = () => { // 清空消息列表 websocket.resetMessageList() // 路由跳转到指定控制台(页面暂未开发) $router.push('/workbench/approve') } // 消息详情 const toMessageDetail = (message: Message) => { // 跳转到对应申请结果页面 router.push({ path: formUrl[message.formId], }) // 消息列表清除对应消息 websocket.clearAppointMessage(message) } // 返回总工作台 const goWorkbench = () => { router.push({ path: '/workbench' }) } </script> <template> <div class="tools"> <div class="buttons"> <!-- 返回总工作台 --> <span v-if="settingsStore.mode === 'pc' && props.ishiddenBackToWorkbench" class="item" @click="goWorkbench"> <el-icon> <svg-icon name="icon-goWorkbench" /> </el-icon> </span> <span v-if="settingsStore.navSearch.enable" class="item" @click="eventBus.emit('global-search-toggle')"> <el-icon> <svg-icon name="ep:search" /> </el-icon> </span> <!-- 全屏 --> <span v-if="settingsStore.mode === 'pc' && settingsStore.toolbar.enableFullscreen" class="item" @click="toggle"> <el-icon> <svg-icon :name="isFullscreen ? 'fullscreen-exit' : 'fullscreen'" /> </el-icon> </span> <span v-if="settingsStore.toolbar.enablePageReload" class="item" @click="mainPage.reload()"> <el-icon> <svg-icon name="ep:refresh-right" /> </el-icon> </span> <span v-if="settingsStore.toolbar.enableColorScheme" class="item" @click="settingsStore.setColorScheme(settingsStore.app.colorScheme === 'dark' ? 'light' : 'dark')" > <el-icon> <svg-icon v-show="settingsStore.app.colorScheme === 'light'" name="ep:sunny" /> <svg-icon v-show="settingsStore.app.colorScheme === 'dark'" name="ep:moon" /> </el-icon> </span> <span v-if="settingsStore.toolbar.enableAppSetting" class="item" @click="eventBus.emit('global-theme-toggle')"> <el-icon> <svg-icon name="ep:setting" /> </el-icon> </span> <span v-if="settingsStore.mode === 'pc' && messageList.length > 0" class="item"> <el-popover width="300"> <template #reference> <div> <el-badge :value="messageList.length" :max="9"> <el-icon> <svg-icon name="ep:bell" /> </el-icon> </el-badge> </div> </template> <template #default> <div class="message-container"> <div v-show="messageList.length" class="message-title">消息({{ messageList.length }})</div> <el-scrollbar max-height="400px"> <div v-for="message of messageList" :key="message.id" class="message-item"> <div class="icon"> <el-icon size="18"> <svg-icon name="ep:chat-dot-square" /> </el-icon> </div> <div class="message-content" @click="toMessageDetail(message)"> <div class="message"> {{ message.message }} </div> <div class="time"> {{ message.time }} </div> </div> </div> </el-scrollbar> <div class="message-footer" @click="toMessageList"> 进入消息列表 </div> </div> </template> </el-popover> </span> </div> <el-dropdown class="user-container" size="default" @command="userCommand"> <div class="user-wrapper"> <!-- <el-avatar size="small"> <el-icon> <svg-icon name="ep:user-filled" /> </el-icon> </el-avatar> --> {{ userStore.name }} <el-icon> <svg-icon name="ep:caret-bottom" /> </el-icon> </div> <template #dropdown> <el-dropdown-menu class="user-dropdown"> <!-- <el-dropdown-item v-if="settingsStore.dashboard.enable" command="dashboard"> 控制台 </el-dropdown-item> <el-dropdown-item command="setting"> 个人设置 </el-dropdown-item> <el-dropdown-item v-if="settingsStore.mode === 'pc'" divided command="hotkeys"> 快捷键介绍 </el-dropdown-item> --> <el-dropdown-item divided command="resetPassword"> 修改密码 </el-dropdown-item> <el-dropdown-item divided command="logout"> 退出登录 </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> <reset-pwd ref="resetPwd" /> </div> </template> <style lang="scss" scoped> .tools { display: flex; align-items: center; padding: 0 20px; white-space: nowrap; .buttons { margin-right: 20px; .item { display: inline-flex; align-items: center; justify-content: center; height: 24px; width: 34px; cursor: pointer; vertical-align: middle; .el-icon { color: var(--el-text-color-primary); transition: var(--el-transition-color); } } } } .message-container { width: 100%; padding: 0 5px; .message-title { width: 100%; text-align: center; padding-bottom: 10px; font-size: 14px; border-bottom: 1px solid #ddd; } .message-item { display: flex; align-items: center; border-bottom: 1px solid #ddd; padding: 8px 5px; cursor: pointer; &:hover { background-color: #f6f6f6; } .icon { width: 26px; height: 26px; margin-right: 10px; border-radius: 40px; color: #fff; background-color: var(--el-color-primary); padding: 4px; } .message-content { flex: 1; font-size: 14px; .time { margin-top: 3px; font-size: 12px; color: #888; } } } .message-footer { margin-top: 10px; line-height: 2; text-align: center; cursor: pointer; &:hover { color: var(--el-color-primary); } } } :deep(.user-container) { display: inline-block; height: 24px; line-height: 24px; cursor: pointer; .user-wrapper { .el-avatar { vertical-align: middle; margin-top: -2px; margin-right: 4px; } } } </style>