From e181f04c642204e79749af93fa921875ff6c21ba Mon Sep 17 00:00:00 2001 From: baoshiwei <baoshiwei@shlanbao.cn> Date: 星期二, 20 五月 2025 10:46:35 +0800 Subject: [PATCH] refactor(qms): 重构趋势图展示逻辑 --- src/layout/components/Navbar.vue | 255 +++++++++++++++++++++++++++++++-------------------- 1 files changed, 155 insertions(+), 100 deletions(-) diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index 483800d..01cc22e 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -1,15 +1,110 @@ -<script setup lang="ts"> -import useAppStore from '@/store/modules/app' -import useUserStore from '@/store/modules/user' -import useSettingsStore from '@/store/modules/settings' -import { getTenantList } from "@/api/login"; -import { dynamicClear, dynamicTenant } from "@/api/system/tenant"; -import { ComponentInternalInstance } from "vue"; -import { TenantVO } from "@/api/types"; +<template> + <div class="navbar"> + <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" /> + <breadcrumb v-if="!settingsStore.topNav" id="breadcrumb-container" class="breadcrumb-container" /> + <top-nav v-if="settingsStore.topNav" id="topmenu-container" class="topmenu-container" /> -const appStore = useAppStore() -const userStore = useUserStore() -const settingsStore = useSettingsStore() + <div class="right-menu flex align-center"> + <template v-if="appStore.device !== 'mobile'"> + <el-select + v-if="userId === 1 && tenantEnabled" + v-model="companyName" + class="min-w-244px" + clearable + filterable + reserve-keyword + :placeholder="proxy.$t('navbar.selectTenant')" + @change="dynamicTenantEvent" + @clear="dynamicClearEvent" + > + <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option> + <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> + </el-select> + + <!-- <header-search id="header-search" class="right-menu-item" /> --> + <search-menu ref="searchMenuRef" /> + <el-tooltip content="鎼滅储" effect="dark" placement="bottom"> + <div class="right-menu-item hover-effect" @click="openSearchMenu"> + <svg-icon class-name="search-icon" icon-class="search" /> + </div> + </el-tooltip> + <!-- 娑堟伅 --> + <el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom"> + <div> + <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false"> + <template #reference> + <el-badge :value="newNotice > 0 ? newNotice : ''" :max="99"> + <svg-icon icon-class="message" /> + </el-badge> + </template> + <template #default> + <notice></notice> + </template> + </el-popover> + </div> + </el-tooltip> + <el-tooltip content="Github" effect="dark" placement="bottom"> + <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" /> + </el-tooltip> + + <el-tooltip :content="proxy.$t('navbar.document')" effect="dark" placement="bottom"> + <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" /> + </el-tooltip> + + <el-tooltip :content="proxy.$t('navbar.full')" effect="dark" placement="bottom"> + <screenfull id="screenfull" class="right-menu-item hover-effect" /> + </el-tooltip> + + <el-tooltip :content="proxy.$t('navbar.language')" effect="dark" placement="bottom"> + <lang-select id="lang-select" class="right-menu-item hover-effect" /> + </el-tooltip> + + <el-tooltip :content="proxy.$t('navbar.layoutSize')" effect="dark" placement="bottom"> + <size-select id="size-select" class="right-menu-item hover-effect" /> + </el-tooltip> + </template> + <div class="avatar-container"> + <el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand"> + <div class="avatar-wrapper"> + <img :src="userStore.avatar" class="user-avatar" /> + <el-icon><caret-bottom /></el-icon> + </div> + <template #dropdown> + <el-dropdown-menu> + <router-link v-if="!dynamic" to="/user/profile"> + <el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item> + </router-link> + <el-dropdown-item v-if="settingsStore.showSettings" command="setLayout"> + <span>{{ proxy.$t('navbar.layoutSetting') }}</span> + </el-dropdown-item> + <el-dropdown-item divided command="logout"> + <span>{{ proxy.$t('navbar.logout') }}</span> + </el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + </div> + </div> + </div> +</template> + +<script setup lang="ts"> +import SearchMenu from './TopBar/search.vue'; +import useAppStore from '@/store/modules/app'; +import useUserStore from '@/store/modules/user'; +import useSettingsStore from '@/store/modules/settings'; +import useNoticeStore from '@/store/modules/notice'; +import { getTenantList } from '@/api/login'; +import { dynamicClear, dynamicTenant } from '@/api/system/tenant'; +import { TenantVO } from '@/api/types'; +import notice from './notice/index.vue'; +import router from '@/router'; + +const appStore = useAppStore(); +const userStore = useUserStore(); +const settingsStore = useSettingsStore(); +const noticeStore = storeToRefs(useNoticeStore()); +const newNotice = ref(<number>0); const { proxy } = getCurrentInstance() as ComponentInternalInstance; @@ -20,57 +115,71 @@ const dynamic = ref(false); // 绉熸埛寮�鍏� const tenantEnabled = ref(true); +// 鎼滅储鑿滃崟 +const searchMenuRef = ref<InstanceType<typeof SearchMenu>>(); + +const openSearchMenu = () => { + searchMenuRef.value?.openSearch(); +}; // 鍔ㄦ�佸垏鎹� const dynamicTenantEvent = async (tenantId: string) => { if (companyName.value != null && companyName.value !== '') { await dynamicTenant(tenantId); dynamic.value = true; - proxy?.$tab.closeAllPage(); - proxy?.$router.push('/'); + await proxy?.$router.push('/'); + await proxy?.proxy.$tab.closeAllPage(); + await proxy?.proxy.$tab.refreshPage(); } -} +}; const dynamicClearEvent = async () => { await dynamicClear(); dynamic.value = false; - proxy?.$tab.closeAllPage(); - proxy?.$router.push('/') -} + await proxy?.$router.push('/'); + await proxy?.proxy.$tab.closeAllPage(); + await proxy?.proxy.$tab.refreshPage(); +}; /** 绉熸埛鍒楄〃 */ const initTenantList = async () => { - const { data } = await getTenantList(); + const { data } = await getTenantList(true); tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled; if (tenantEnabled.value) { - tenantList.value = data.voList; + tenantList.value = data.voList; } -} +}; defineExpose({ - initTenantList, -}) + initTenantList +}); const toggleSideBar = () => { - appStore.toggleSideBar() -} + appStore.toggleSideBar(false); +}; const logout = async () => { await ElMessageBox.confirm('纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�', '鎻愮ず', { confirmButtonText: '纭畾', cancelButtonText: '鍙栨秷', type: 'warning' - }) - await userStore.logout() - location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'; -} + }); + userStore.logout().then(() => { + router.replace({ + path: '/login', + query: { + redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/') + } + }); + }); +}; -const emits = defineEmits(['setLayout']) +const emits = defineEmits(['setLayout']); const setLayout = () => { emits('setLayout'); -} +}; // 瀹氫箟Command鏂规硶瀵硅薄 閫氳繃key鐩存帴璋冪敤鏂规硶 -const commandMap: {[key: string]: any} = { +const commandMap: { [key: string]: any } = { setLayout, logout }; @@ -79,78 +188,24 @@ if (commandMap[command]) { commandMap[command](); } -} +}; +//鐢ㄦ繁搴︾洃鍚� 娑堟伅 +watch( + () => noticeStore.state.value.notices, + (newVal) => { + newNotice.value = newVal.filter((item: any) => !item.read).length; + }, + { deep: true } +); </script> -<template> - <div class="navbar"> - <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> - <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" /> - <top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" /> - - <div class="right-menu flex align-center"> - <template v-if="appStore.device !== 'mobile'"> - <el-select - v-model="companyName" - clearable - filterable - reserve-keyword - placeholder="璇烽�夋嫨绉熸埛" - v-if="userId === 1 && tenantEnabled" - @change="dynamicTenantEvent" - @clear="dynamicClearEvent" - > - <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option> - <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> - </el-select> - - <header-search id="header-search" class="right-menu-item" /> - - <el-tooltip content="婧愮爜鍦板潃" effect="dark" placement="bottom"> - <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" /> - </el-tooltip> - - <el-tooltip content="鏂囨。鍦板潃" effect="dark" placement="bottom"> - <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" /> - </el-tooltip> - - <el-tooltip content="鍏ㄥ睆" effect="dark" placement="bottom"> - <screenfull id="screenfull" class="right-menu-item hover-effect" /> - </el-tooltip> - - <el-tooltip content="甯冨眬澶у皬" effect="dark" placement="bottom"> - <size-select id="size-select" class="right-menu-item hover-effect" /> - </el-tooltip> - </template> - <div class="avatar-container"> - <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click"> - <div class="avatar-wrapper"> - <img :src="userStore.avatar" class="user-avatar" /> - <el-icon><caret-bottom /></el-icon> - </div> - <template #dropdown> - <el-dropdown-menu> - <router-link to="/user/profile" v-if="!dynamic"> - <el-dropdown-item>涓汉涓績</el-dropdown-item> - </router-link> - <el-dropdown-item command="setLayout"> - <span>甯冨眬璁剧疆</span> - </el-dropdown-item> - <el-dropdown-item divided command="logout"> - <span>閫�鍑虹櫥褰�</span> - </el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - </div> - </div> - </div> -</template> - <style lang="scss" scoped> - :deep(.el-select .el-input__wrapper) { - height:30px; + height: 30px; +} + +:deep(.el-badge__content.is-fixed) { + top: 12px; } .flex { @@ -165,7 +220,7 @@ height: 50px; overflow: hidden; position: relative; - background: #fff; + //background: #fff; box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); .hamburger-container { -- Gitblit v1.9.3