index.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <template>
  2. <router-layout v-if="isQianKun" />
  3. <ele-pro-layout
  4. v-else
  5. :menus="menus"
  6. :tabs="theme.tabs"
  7. :collapse="theme.collapse"
  8. :side-nav-collapse="theme.sideNavCollapse"
  9. :body-fullscreen="theme.bodyFullscreen"
  10. :show-tabs="theme.showTabs"
  11. :show-footer="theme.showFooter"
  12. :head-style="theme.headStyle"
  13. :side-style="theme.sideStyle"
  14. :layout-style="theme.layoutStyle"
  15. :side-menu-style="theme.sideMenuStyle"
  16. :tab-style="theme.tabStyle"
  17. :fixed-header="theme.fixedHeader"
  18. :fixed-sidebar="theme.fixedSidebar"
  19. :fixed-body="theme.fixedBody"
  20. :body-full="theme.bodyFull"
  21. :logo-auto-size="theme.logoAutoSize"
  22. :colorful-icon="theme.colorfulIcon"
  23. :side-unique-open="theme.sideUniqueOpen"
  24. :style-responsive="theme.styleResponsive"
  25. :project-name="PROJECT_NAME"
  26. :hide-footers="HIDE_FOOTERS"
  27. :hide-sidebars="HIDE_SIDEBARS"
  28. :repeatable-tabs="REPEATABLE_TABS"
  29. :home-title="HOME_TITLE || $t('layout.home')"
  30. :home-path="HOME_PATH"
  31. :layout-path="LAYOUT_PATH"
  32. :redirect-path="REDIRECT_PATH"
  33. :tab-sortable="true"
  34. :locale="locale"
  35. :i18n="i18n"
  36. @update:collapse="updateCollapse"
  37. @update:side-nav-collapse="updateSideNavCollapse"
  38. @update:body-fullscreen="updateBodyFullscreen"
  39. @tab-add="addPageTab"
  40. @tab-remove="removePageTab"
  41. @tab-remove-all="removeAllPageTab"
  42. @tab-remove-left="removeLeftPageTab"
  43. @tab-remove-right="removeRightPageTab"
  44. @tab-remove-other="removeOtherPageTab"
  45. @tabSortChange="setPageTabs"
  46. @reload-page="reloadPageTab"
  47. @logo-click="onLogoClick"
  48. @screen-size-change="screenSizeChange"
  49. @set-home-components="setHomeComponents"
  50. @tab-context-menu="onTabContextMenu"
  51. >
  52. <!-- 路由出口 -->
  53. <router-layout />
  54. <!-- logo 图标 -->
  55. <template v-slot:logo>
  56. <img src="@/assets/logo.png" alt="logo" />
  57. </template>
  58. <!-- 顶栏右侧区域 -->
  59. <template v-slot:right>
  60. <header-tools :fullscreen="fullscreen" @fullscreen="onFullscreen" />
  61. </template>
  62. <!-- 全局页脚 -->
  63. <!-- <template v-slot:footer>
  64. <page-footer />
  65. </template> -->
  66. <!-- 自定义菜单标题增加徽章、小红点 -->
  67. <template v-slot:title="{ title, item }">
  68. <span>{{ title }} </span>
  69. <div v-if="item.meta && item.meta.badge" class="ele-menu-badge">
  70. <el-badge :value="item.meta.badge" :type="item.meta.badgeColor" />
  71. </div>
  72. </template>
  73. <template v-slot:top-title="{ title, item }">
  74. <span>{{ title }} </span>
  75. <div v-if="item.meta && item.meta.badge" class="ele-menu-badge">
  76. <el-badge :value="item.meta.badge" :type="item.meta.badgeColor" />
  77. </div>
  78. </template>
  79. <template v-slot:nav-title="{ title, item }">
  80. <span>{{ title }} </span>
  81. <div v-if="item.meta && item.meta.badge" class="ele-menu-badge">
  82. <el-badge :value="item.meta.badge" :type="item.meta.badgeColor" />
  83. </div>
  84. </template>
  85. </ele-pro-layout>
  86. </template>
  87. <script>
  88. import { mapGetters } from 'vuex';
  89. import { toggleFullscreen, isFullscreen } from 'ele-admin';
  90. import RouterLayout from '@/components/RouterLayout/index.vue';
  91. import HeaderTools from './components/header-tools.vue';
  92. // import PageFooter from './components/page-footer.vue';
  93. import {
  94. PROJECT_NAME,
  95. HIDE_SIDEBARS,
  96. HIDE_FOOTERS,
  97. REPEATABLE_TABS,
  98. HOME_TITLE,
  99. HOME_PATH,
  100. LAYOUT_PATH,
  101. REDIRECT_PATH,
  102. I18N_ENABLE
  103. } from '@/config/setting';
  104. import {
  105. addPageTab,
  106. removePageTab,
  107. removeAllPageTab,
  108. removeLeftPageTab,
  109. removeRightPageTab,
  110. removeOtherPageTab,
  111. reloadPageTab,
  112. setHomeComponents,
  113. setPageTabs
  114. } from '@/utils/page-tab-util';
  115. export default {
  116. name: 'EleLayout',
  117. components: {
  118. RouterLayout,
  119. HeaderTools
  120. // PageFooter
  121. },
  122. data() {
  123. return {
  124. PROJECT_NAME,
  125. HIDE_SIDEBARS,
  126. HIDE_FOOTERS,
  127. REPEATABLE_TABS,
  128. HOME_PATH,
  129. HOME_TITLE,
  130. LAYOUT_PATH,
  131. REDIRECT_PATH,
  132. // 是否全屏
  133. fullscreen: false
  134. };
  135. },
  136. computed: {
  137. isQianKun() {
  138. return window.__POWERED_BY_QIANKUN__;
  139. },
  140. // 当前语言
  141. locale() {
  142. return this.$i18n.locale;
  143. },
  144. // 菜单数据
  145. menus() {
  146. return this.$store.state.user.menus;
  147. },
  148. // 主题状态
  149. ...mapGetters(['theme'])
  150. },
  151. methods: {
  152. /* 侧栏折叠切换 */
  153. updateCollapse(value) {
  154. // console.log('value:', this.$store.state.user.menus);
  155. this.$store.dispatch('theme/setCollapse', value);
  156. },
  157. /* 双侧栏一级折叠切换 */
  158. updateSideNavCollapse(value) {
  159. this.$store.dispatch('theme/setSideNavCollapse', value);
  160. },
  161. /* 内容区域全屏切换 */
  162. updateBodyFullscreen(value) {
  163. this.$store.dispatch('theme/setBodyFullscreen', value);
  164. },
  165. /* logo 点击事件 */
  166. onLogoClick(isHome) {
  167. isHome || this.$router.push(LAYOUT_PATH);
  168. },
  169. /* 监听屏幕尺寸改变 */
  170. screenSizeChange() {
  171. this.$store.dispatch('theme/updateScreenSize');
  172. this.fullscreen = isFullscreen();
  173. },
  174. /* 全屏切换 */
  175. onFullscreen() {
  176. try {
  177. this.fullscreen = toggleFullscreen();
  178. } catch (e) {
  179. this.$message.error('您的浏览器不支持全屏模式');
  180. }
  181. },
  182. /* 页签右键菜单点击事件 */
  183. onTabContextMenu({ key, tabKey, item, active }) {
  184. switch (key) {
  185. case 'reload': // 刷新
  186. reloadPageTab({
  187. isHome: !item,
  188. fullPath: item?.fullPath ?? tabKey
  189. });
  190. break;
  191. case 'close': // 关闭当前
  192. removePageTab({
  193. key: item?.fullPath ?? tabKey,
  194. active
  195. });
  196. break;
  197. case 'left': // 关闭左侧
  198. removeLeftPageTab({
  199. key: tabKey,
  200. active
  201. });
  202. break;
  203. case 'right': // 关闭右侧
  204. removeRightPageTab({
  205. key: tabKey,
  206. active
  207. });
  208. break;
  209. case 'other': // 关闭其他
  210. removeOtherPageTab({
  211. key: tabKey,
  212. active
  213. });
  214. break;
  215. }
  216. },
  217. /* 菜单标题国际化 */
  218. i18n(_path, key) {
  219. if (!I18N_ENABLE || !key) {
  220. return;
  221. }
  222. const k = 'route.' + key + '._name';
  223. const title = this.$t(k);
  224. if (title !== k) {
  225. return title;
  226. }
  227. },
  228. //
  229. addPageTab,
  230. removePageTab,
  231. removeAllPageTab,
  232. removeLeftPageTab,
  233. removeRightPageTab,
  234. removeOtherPageTab,
  235. reloadPageTab,
  236. setHomeComponents,
  237. setPageTabs
  238. }
  239. };
  240. </script>
  241. <style lang="scss">
  242. .ele-admin-layout {
  243. .ele-admin-logo {
  244. font-size: 18px !important;
  245. img {
  246. width: 50px !important;
  247. height: auto !important;
  248. }
  249. }
  250. }
  251. // 侧栏菜单徽章样式,定位在右侧垂直居中并调小尺寸
  252. .ele-menu-badge {
  253. position: absolute;
  254. top: 50%;
  255. right: 14px;
  256. line-height: 1;
  257. margin-top: -9px;
  258. font-size: 0;
  259. .el-badge__content {
  260. height: 18px;
  261. line-height: 18px;
  262. border-radius: 9px;
  263. border: none;
  264. min-width: 18px;
  265. padding: 0 4px;
  266. box-sizing: border-box;
  267. }
  268. }
  269. // 父级菜单标题中右侧多定位一点,避免与箭头重合
  270. .el-submenu > .el-submenu__title .ele-menu-badge {
  271. right: 36px;
  272. }
  273. // 折叠悬浮中样式调整
  274. .el-menu--popup {
  275. .el-submenu > .el-submenu__title .ele-menu-badge {
  276. right: 20px;
  277. }
  278. }
  279. // 侧栏折叠后样式调整
  280. .ele-admin-collapse .ele-admin-sidebar-menus > .el-scrollbar {
  281. & > .el-scrollbar__wrap > .el-scrollbar__view > .el-menu {
  282. & > .el-menu-item,
  283. & > .el-submenu > .el-submenu__title {
  284. .ele-menu-badge {
  285. top: 2px;
  286. right: 2px;
  287. margin: 0;
  288. }
  289. }
  290. }
  291. }
  292. // 顶栏菜单标题中样式调整
  293. .ele-admin-header-nav > .el-scrollbar > .el-scrollbar__wrap {
  294. & > .el-scrollbar__view > .el-menu {
  295. & > .el-menu-item,
  296. & > .el-submenu > .el-submenu__title {
  297. .ele-menu-badge {
  298. position: static;
  299. right: auto;
  300. top: auto;
  301. display: inline-block;
  302. vertical-align: 6px;
  303. margin: 0 0 0 2px;
  304. }
  305. }
  306. }
  307. }
  308. // 双侧栏时一级侧栏菜单中样式调整,定位在右上角
  309. .ele-admin-sidebar-nav-menu > .el-scrollbar > .el-scrollbar__wrap {
  310. & > .el-scrollbar__view > .el-menu {
  311. & > .el-menu-item,
  312. & > .el-submenu > .el-submenu__title {
  313. .ele-menu-badge {
  314. top: 0;
  315. right: 0;
  316. margin: 0;
  317. }
  318. }
  319. }
  320. }
  321. // 双侧栏时一级侧栏菜单折叠后样式调整
  322. .ele-admin-nav-collapse .ele-admin-sidebar-nav-menu > .el-scrollbar {
  323. & > .el-scrollbar__wrap > .el-scrollbar__view > .el-menu {
  324. & > .el-menu-item,
  325. & > .el-submenu > .el-submenu__title {
  326. .ele-menu-badge {
  327. top: 0;
  328. right: 0;
  329. }
  330. }
  331. }
  332. }
  333. .ele-admin-layout .ele-admin-logo img {
  334. height: auto !important;
  335. width: 80px !important;
  336. margin-right: 5px;
  337. max-height: 35px
  338. }
  339. </style>