Files
art-design/src/components/core/layouts/art-header-bar/index.vue
T
浅念 5d906087d3 Squashed commit of the following:
commit 0e84bedb67
Author: 浅念 <email@sample.com>
Date:   Fri Aug 15 16:31:55 2025 +0800

    v1.0.2 更新内容

commit f5deb7b8f7
Author: 浅念 <email@sample.com>
Date:   Wed Aug 13 19:27:49 2025 +0800

    添加菜单 权限 等页面

commit e797cb24de
Author: 浅念 <email@sample.com>
Date:   Mon Aug 11 19:24:24 2025 +0800

    添加工单附件  及样式

commit 619311dfbe
Author: chenlan <suya123456>
Date:   Fri Aug 8 22:13:25 2025 +0800

    添加crm  归属客户

commit b402e522bf
Author: 浅念 <email@sample.com>
Date:   Thu Aug 7 10:51:17 2025 +0800

    询单权限校验

commit f950f665a9
Author: 浅念 <email@sample.com>
Date:   Thu Aug 7 10:10:45 2025 +0800

    添加 询单图片预览

commit 8deecc8197
Author: 浅念 <email@sample.com>
Date:   Wed Aug 6 18:36:42 2025 +0800

    修改用户页面 询单

commit 3e24d1905f
Author: 浅念 <email@sample.com>
Date:   Tue Aug 5 18:25:32 2025 +0800

    添加用户页面 客户页面接口 等

commit 7542d80e38
Author: 浅念 <email@sample.com>
Date:   Mon Aug 4 18:05:07 2025 +0800

    修改 仪表盘页面样式

commit e5548f95e4
Author: 浅念 <email@sample.com>
Date:   Mon Aug 4 14:50:55 2025 +0800

    修改询单字段  仪表盘页面  及添加管理端客户页面

commit d30ea5b7bf
Author: 浅念 <email@sample.com>
Date:   Mon Aug 4 14:48:58 2025 +0800

    添加echarts 插件

commit 0e4160c5ca
Author: 浅念 <email@sample.com>
Date:   Fri Aug 1 18:27:22 2025 +0800

    仪表盘接口

commit bd23288acd
Author: 浅念 <email@sample.com>
Date:   Fri Aug 1 18:26:46 2025 +0800

    修改 仪表盘

commit 6bfb940881
Author: 浅念 <email@sample.com>
Date:   Fri Aug 1 10:01:35 2025 +0800

    客户列表 添加公海详情展示

commit b50f650565
Author: 浅念 <email@sample.com>
Date:   Thu Jul 31 17:26:36 2025 +0800

    修改 客户标签样式  个人信息添加邮箱 修复关闭全部页面404

commit ea1dbb7af4
Author: 浅念 <email@sample.com>
Date:   Wed Jul 30 18:50:31 2025 +0800

    修改公海和询单页面

commit 1bfbb95bd9
Author: 浅念 <email@sample.com>
Date:   Wed Jul 30 17:23:09 2025 +0800

    修改样式和添加用户数据显示

commit a9f5f76b35
Author: 浅念 <email@sample.com>
Date:   Wed Jul 30 15:06:03 2025 +0800

    设置默认页面

commit 3ea9d3d5df
Author: 浅念 <email@sample.com>
Date:   Wed Jul 30 11:46:31 2025 +0800

    修改飞书登录 公司id 系统id 获取不到问题  客户及公海添加用户信息显示

commit 0cef82279f
Author: 浅念 <email@sample.com>
Date:   Tue Jul 29 16:42:36 2025 +0800

    修改工单 客户等页面

commit 695ebbcc71
Author: 浅念 <email@sample.com>
Date:   Fri Jul 25 17:50:04 2025 +0800

    修改默认值

commit ffc194a1c1
Author: 浅念 <email@sample.com>
Date:   Fri Jul 25 17:05:33 2025 +0800

    飞书授权添加系统码  及登录进入页面路由

commit 48b95e252f
Author: 浅念 <email@sample.com>
Date:   Fri Jul 25 15:48:49 2025 +0800

    回收站添加占位

commit 382011d592
Author: 浅念 <email@sample.com>
Date:   Fri Jul 25 15:11:50 2025 +0800

    修改登录页样式公海数据 个人信息默认图

commit 0f790269db
Author: 浅念 <email@sample.com>
Date:   Fri Jul 25 09:16:55 2025 +0800

    修改字段名称

commit f18cfdb69e
Author: 浅念 <email@sample.com>
Date:   Thu Jul 24 17:28:51 2025 +0800

    调整代码格式

commit 858147fbbd
Author: 浅念 <email@sample.com>
Date:   Thu Jul 24 10:17:22 2025 +0800

    修改token刷新 及修改询单详情展示

commit c333b907e6
Author: 浅念 <email@sample.com>
Date:   Wed Jul 23 18:22:56 2025 +0800

    对接询单接口

commit 7979a31e36
Author: 浅念 <email@sample.com>
Date:   Wed Jul 23 14:40:02 2025 +0800

    修改代码格式

commit 4a39387865
Author: 浅念 <email@sample.com>
Date:   Wed Jul 23 14:07:13 2025 +0800

    设置客户列表权限

commit fc4de02582
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 17:08:13 2025 +0800

    feat(router): 调整菜单

commit 2ffe0c9753
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 17:04:16 2025 +0800

    feat(crmApi.ts): 调整结构

commit c3fb2c48d3
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 17:00:25 2025 +0800

    feat(router): 路由调整

commit c5b0a8265a
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 16:54:06 2025 +0800

    chore: 添加询单页面及调整菜单

commit ca06c9bc46
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 16:35:43 2025 +0800

    询单页面及菜单

commit 3b6de4c7fa
Merge: d3bb4ec 85e8b9b
Author: 浅念 <email@sample.com>
Date:   Tue Jul 22 09:22:20 2025 +0800

    Merge branch 'master' into feature/crm_pc

commit d3bb4ec6e5
Merge: c7d8908 d7ab6f1
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 18:22:55 2025 +0800

    Merge branch 'master' into feature/crm_pc

    # Conflicts:
    #	.gitignore
    #	src/api/crmApi.ts
    #	src/api/usersApi.ts
    #	src/store/modules/user.ts
    #	src/utils/http/index.ts
    #	src/views/auth/login/index.vue
    #	src/views/crmpc/customer/Show.vue
    #	src/views/crmpc/customer/index.vue

commit c7d890809c
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 18:12:16 2025 +0800

    添加系统码

commit 31cd18fade
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 18:02:48 2025 +0800

    Merge branch 'master' into feature/crm_pc

    # Conflicts:
    #	.gitignore

commit 59c9c97c08
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 17:56:52 2025 +0800

    Merge branch 'master' into feature/crm_pc

    # Conflicts:
    #	.gitignore

commit d4b577c42e
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 13:03:56 2025 +0800

    feat(crm): 添加相关图片

commit e4967760b7
Merge: 0c67666 85102fc
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 11:25:49 2025 +0800

    Finish crm_pc

commit 85102fcf32
Author: 浅念 <email@sample.com>
Date:   Mon Jul 21 11:24:06 2025 +0800

    crm 接口对接

commit 0c67666793
Author: 浅念 <email@sample.com>
Date:   Wed Jul 16 17:18:14 2025 +0800

    添加上传头部信息

commit a41c75f703
Author: 浅念 <email@sample.com>
Date:   Tue Jul 15 09:40:53 2025 +0800

    修改页面

commit 22ae0e86c8
Author: 浅念 <email@sample.com>
Date:   Mon Jul 14 17:59:02 2025 +0800

    修改页面

commit 812e3c4b0c
Author: 浅念 <email@sample.com>
Date:   Mon Jul 14 10:09:10 2025 +0800

    修改菜单问题

commit 2ad479b006
Author: 浅念 <email@sample.com>
Date:   Fri Jul 11 19:45:57 2025 +0800

    修改样式

commit 5802e157bf
Author: 浅念 <email@sample.com>
Date:   Fri Jul 11 19:43:34 2025 +0800

    修改工单

commit 713d43f7b4
Author: 浅念 <email@sample.com>
Date:   Fri Jul 11 18:37:16 2025 +0800

    添加登录

commit 719911918f
Author: 浅念 <email@sample.com>
Date:   Fri Jul 4 17:16:38 2025 +0800

    项目创建

commit ce47b39fa5
Author: 浅念 <email@sample.com>
Date:   Wed Jul 2 09:37:51 2025 +0800

    删除
2025-08-15 16:37:41 +08:00

420 lines
14 KiB
Vue

<template>
<div class="layout-top-bar" :class="[tabStyle]" :style="{ width: topBarWidth() }">
<div class="menu">
<div class="left" style="display: flex">
<!-- 系统信息 -->
<div class="top-header" @click="toHome" v-if="isTopMenu">
<ArtLogo class="logo" />
<p v-if="width >= 1400">{{ AppConfig.systemInfo.name }}</p>
</div>
<ArtLogo class="logo2" @click="toHome" />
<!-- 菜单按钮 -->
<div class="btn-box" v-if="isLeftMenu && showMenuButton">
<div class="btn menu-btn">
<i class="iconfont-sys" @click="visibleMenu">&#xe6ba;</i>
</div>
</div>
<!-- 刷新按钮 -->
<div class="btn-box" v-if="showRefreshButton">
<div class="btn refresh-btn" :style="{ marginLeft: !isLeftMenu ? '10px' : '0' }">
<i class="iconfont-sys" @click="reload()"> &#xe6b3; </i>
</div>
</div>
<!-- 快速入口 -->
<!-- <ArtFastEnter v-if="width >= 1200" /> -->
<!-- 面包屑 -->
<ArtBreadcrumb
v-if="(showCrumbs && isLeftMenu) || (showCrumbs && isDualMenu)"
:style="{ paddingLeft: !showRefreshButton && !showMenuButton ? '10px' : '0' }"
/>
<!-- 顶部菜单 -->
<ArtHorizontalMenu v-if="isTopMenu" :list="menuList" :width="menuTopWidth" />
<!-- 混合菜单-顶部 -->
<ArtMixedMenu v-if="isTopLeftMenu" :list="menuList" :width="menuTopWidth" />
</div>
<div class="right">
<!-- 搜索 -->
<!-- <div class="search-wrap">
<div class="search-input" @click="openSearchDialog">
<div class="left">
<i class="iconfont-sys">&#xe710;</i>
<span>{{ $t('topBar.search.title') }}</span>
</div>
<div class="search-keydown">
<i class="iconfont-sys" v-if="isWindows">&#xeeac;</i>
<i class="iconfont-sys" v-else>&#xe9ab;</i>
<span>k</span>
</div>
</div>
</div> -->
<div class="btn-box screen-box" @click="clearCachefn">
<div class="btn">
<i class="iconfont-sys">&#xe847;</i>
</div>
</div>
<!-- 全屏按钮 -->
<div class="btn-box screen-box" @click="toggleFullScreen">
<div
class="btn"
:class="{ 'full-screen-btn': !isFullscreen, 'exit-full-screen-btn': isFullscreen }"
>
<i class="iconfont-sys">{{ isFullscreen ? '&#xe62d;' : '&#xe8ce;' }}</i>
</div>
</div>
<!-- 通知 -->
<!-- <div class="btn-box notice-btn" @click="visibleNotice">
<div class="btn notice-button">
<i class="iconfont-sys notice-btn">&#xe6c2;</i>
<span class="count notice-btn"></span>
</div>
</div> -->
<!-- 聊天 -->
<!-- <div class="btn-box chat-btn" @click="openChat">
<div class="btn chat-button">
<i class="iconfont-sys">&#xe89a;</i>
<span class="dot"></span>
</div>
</div> -->
<!-- 语言 -->
<!-- <div class="btn-box" v-if="showLanguage">
<el-dropdown @command="changeLanguage" popper-class="langDropDownStyle">
<div class="btn language-btn">
<i class="iconfont-sys">&#xe611;</i>
</div>
<template #dropdown>
<el-dropdown-menu>
<div v-for="item in languageOptions" :key="item.value" class="lang-btn-item">
<el-dropdown-item
:command="item.value"
:class="{ 'is-selected': locale === item.value }"
>
<span class="menu-txt">{{ item.label }}</span>
<i v-if="locale === item.value" class="iconfont-sys">&#xe621;</i>
</el-dropdown-item>
</div>
</el-dropdown-menu>
</template>
</el-dropdown>
</div> -->
<!-- 设置 -->
<!-- <div class="btn-box" @click="openSetting">
<el-popover :visible="showSettingGuide" placement="bottom-start" :width="190" :offset="0">
<template #reference>
<div class="btn setting-btn">
<i class="iconfont-sys">&#xe6d0;</i>
</div>
</template>
<template #default>
<p
>{{ $t('topBar.guide.title')
}}<span :style="{ color: systemThemeColor }"> {{ $t('topBar.guide.theme') }} </span
>、 <span :style="{ color: systemThemeColor }"> {{ $t('topBar.guide.menu') }} </span
>{{ $t('topBar.guide.description') }}
</p>
</template>
</el-popover>
</div> -->
<!-- 切换主题 -->
<div class="btn-box" @click="themeAnimation">
<div class="btn theme-btn">
<i class="iconfont-sys">{{ isDark ? '&#xe6b5;' : '&#xe725;' }}</i>
</div>
</div>
<!-- 用户头像、菜单 -->
<div class="user">
<el-popover
ref="userMenuPopover"
placement="bottom-end"
:width="240"
:hide-after="0"
:offset="10"
trigger="hover"
:show-arrow="false"
popper-class="user-menu-popover"
popper-style="border: 1px solid var(--art-border-dashed-color); border-radius: calc(var(--custom-radius) / 2 + 4px); padding: 5px 16px; 5px 16px;"
>
<template #reference>
<img
class="cover"
:src="getUserInfo.user.avatar ? getUserInfo.user.avatar : '@imgs/user/avatar.webp'"
/>
</template>
<template #default>
<div class="user-menu-box">
<!-- <div class="user-head">
<img class="cover" src="@imgs/user/avatar.webp" style="float: left" />
<div class="user-wrap">
<span class="name">{{ userInfo.user.id }}</span>
<span class="roles">
<template v-for="(role, idx) in userInfo.user.roles" :key="role">
<span>{{ role }}</span><span v-if="idx < userInfo.user.roles.length - 1">, </span>
</template>
</span>
<span class="phone">{{ userInfo.user.phone }}</span>
<span class="email">{{ userInfo.user.email }}</span>
</div>
</div> -->
<ul class="user-menu" style="border: none">
<li @click="gouserInfo()">
<i class="menu-icon iconfont-sys">&#xe734;</i>
<span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span>
</li>
<li @click="goPage('/work/myOrder')">
<i class="menu-icon iconfont-sys">&#xe828;</i>
<span class="menu-txt">我的工单</span>
</li>
<!-- <li @click="goPage('/crmpc/recycle')">
<i class="menu-icon iconfont-sys">&#xe828;</i>
<span class="menu-txt">回收站</span>
</li> -->
<!-- <li @click="goPage('/system/user-center')">
<i class="menu-icon iconfont-sys">&#xe734;</i>
<span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span>
</li>
<li @click="toDocs()">
<i class="menu-icon iconfont-sys" style="font-size: 15px">&#xe828;</i>
<span class="menu-txt">{{ $t('topBar.user.docs') }}</span>
</li>
<li @click="toGithub()">
<i class="menu-icon iconfont-sys">&#xe8d6;</i>
<span class="menu-txt">{{ $t('topBar.user.github') }}</span>
</li> -->
<!-- <li @click="lockScreen()">
<i class="menu-icon iconfont-sys">&#xe817;</i>
<span class="menu-txt">{{ $t('topBar.user.lockScreen') }}</span>
</li> -->
<div class="line"></div>
<div class="logout-btn" @click="loginOut">
{{ $t('topBar.user.logout') }}
</div>
</ul>
</div>
</template>
</el-popover>
</div>
</div>
</div>
<ArtWorkTab />
<art-notification v-model:value="showNotice" ref="notice" />
</div>
</template>
<script setup lang="ts">
import { LanguageEnum, MenuTypeEnum, MenuWidth } from '@/enums/appEnum'
import { useSettingStore } from '@/store/modules/setting'
import { useUserStore } from '@/store/modules/user'
import { useFullscreen } from '@vueuse/core'
import { ElMessageBox } from 'element-plus'
import { HOME_PAGE } from '@/router/routesAlias'
import { useI18n } from 'vue-i18n'
import { mittBus } from '@/utils/sys'
import { useMenuStore } from '@/store/modules/menu'
import AppConfig from '@/config'
import { manageService } from '@/api/adminApi'
import { languageOptions } from '@/locales'
const isWindows = navigator.userAgent.includes('Windows')
const { locale } = useI18n()
const settingStore = useSettingStore()
const userStore = useUserStore()
const router = useRouter()
const { getUserInfo, home_page } = useUserStore()
const {
showMenuButton,
showRefreshButton,
showLanguage,
menuOpen,
showCrumbs,
systemThemeColor,
showSettingGuide,
menuType,
isDark,
tabStyle
} = storeToRefs(settingStore)
const { language } = storeToRefs(userStore)
const { menuList } = storeToRefs(useMenuStore())
const showNotice = ref(false)
const notice = ref(null)
const userMenuPopover = ref()
const isLeftMenu = computed(() => menuType.value === MenuTypeEnum.LEFT)
const isDualMenu = computed(() => menuType.value === MenuTypeEnum.DUAL_MENU)
const isTopMenu = computed(() => menuType.value === MenuTypeEnum.TOP)
const isTopLeftMenu = computed(() => menuType.value === MenuTypeEnum.TOP_LEFT)
import { useCommon } from '@/composables/useCommon'
import { WEB_LINKS } from '@/utils/constants'
import { themeAnimation } from '@/utils/theme/animation'
const { t } = useI18n()
const { width } = useWindowSize()
const menuTopWidth = computed(() => {
return width.value * 0.5
})
onMounted(() => {
initLanguage()
document.addEventListener('click', bodyCloseNotice)
})
onUnmounted(() => {
document.removeEventListener('click', bodyCloseNotice)
})
const { isFullscreen, toggle: toggleFullscreen } = useFullscreen()
const toggleFullScreen = () => {
toggleFullscreen()
}
const clearCachefn = () => {
manageService.clearCache().then((res) => {
ElMessage.success(res.data?.message || '成功!')
// setTimeout(() => {
window.location.reload()
// }, 5000)
})
}
const topBarWidth = (): string => {
const { TOP, DUAL_MENU, TOP_LEFT } = MenuTypeEnum
const { getMenuOpenWidth } = settingStore
const { isFirstLevel } = router.currentRoute.value.meta
const type = menuType.value
const isMenuOpen = menuOpen.value
const isTopLayout = type === TOP || (type === TOP_LEFT && isFirstLevel)
if (isTopLayout) {
return '100%'
}
if (type === DUAL_MENU) {
return isFirstLevel ? 'calc(100% - 80px)' : `calc(100% - 80px - ${getMenuOpenWidth})`
}
return isMenuOpen ? `calc(100% - ${getMenuOpenWidth})` : `calc(100% - ${MenuWidth.CLOSE})`
}
const visibleMenu = () => {
settingStore.setMenuOpen(!menuOpen.value)
}
const goPage = (path: string) => {
router.push(path)
}
const { systemsid } = useUserStore()
const gouserInfo = () => {
if (systemsid == '1') {
router.push('/admin/user/user_info')
} else {
router.push('/system/user-center')
}
}
// const toDocs = () => {
// window.open(WEB_LINKS.DOCS)
// }
// const toGithub = () => {
// window.open(WEB_LINKS.GITHUB)
// }
const toHome = () => {
router.push(home_page)
}
const loginOut = () => {
closeUserMenu()
setTimeout(() => {
ElMessageBox.confirm(t('common.logOutTips'), t('common.tips'), {
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
customClass: 'login-out-dialog'
}).then(() => {
userStore.logOut()
})
}, 200)
}
const reload = (time: number = 0) => {
setTimeout(() => {
useCommon().refresh()
}, time)
}
const initLanguage = () => {
locale.value = language.value
}
const changeLanguage = (lang: LanguageEnum) => {
if (locale.value === lang) return
locale.value = lang
userStore.setLanguage(lang)
reload(50)
}
const openSetting = () => {
mittBus.emit('openSetting')
// 隐藏设置引导
if (showSettingGuide.value) {
settingStore.hideSettingGuide()
}
// 打开设置引导
// settingStore.openSettingGuide()
}
const openSearchDialog = () => {
mittBus.emit('openSearchDialog')
}
const bodyCloseNotice = (e: any) => {
let { className } = e.target
if (showNotice.value) {
if (typeof className === 'object') {
showNotice.value = false
return
}
if (className.indexOf('notice-btn') === -1) {
showNotice.value = false
}
}
}
const visibleNotice = () => {
showNotice.value = !showNotice.value
}
const openChat = () => {
mittBus.emit('openChat')
}
const lockScreen = () => {
mittBus.emit('openLockScreen')
}
const closeUserMenu = () => {
setTimeout(() => {
userMenuPopover.value.hide()
}, 100)
}
</script>
<style lang="scss" scoped>
@use './style';
@use './mobile';
</style>