index.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <template>
  2. <n-layout class="layout" :position="fixedMenu" has-sider>
  3. <!-- 折叠时的 -->
  4. <n-layout-sider
  5. v-if="
  6. !isMobile && isMixMenuNoneSub && (navMode === 'vertical' || navMode === 'horizontal-mix')
  7. "
  8. :show-trigger="false"
  9. @collapse="false"
  10. :position="fixedMenu"
  11. @expand="collapsed = false"
  12. :collapsed="false"
  13. collapse-mode="width"
  14. :collapsed-width="64"
  15. :width="leftMenuWidth"
  16. :native-scrollbar="false"
  17. :inverted="inverted"
  18. class="layout-sider"
  19. >
  20. <Logo :collapsed="collapsed" />
  21. <AsideMenu v-model:collapsed="collapsed" v-model:location="getMenuLocation" />
  22. </n-layout-sider>
  23. <n-drawer
  24. v-model:show="showSideDrawder"
  25. :width="menuWidth"
  26. :placement="'left'"
  27. class="layout-side-drawer"
  28. >
  29. <Logo :collapsed="collapsed" />
  30. <AsideMenu @clickMenuItem="collapsed = false" />
  31. </n-drawer>
  32. <n-layout :inverted="inverted">
  33. <n-layout-header :inverted="getHeaderInverted" :position="fixedHeader">
  34. <PageHeader v-model:collapsed="collapsed" :inverted="inverted" />
  35. </n-layout-header>
  36. <n-layout-content
  37. class="layout-content"
  38. :class="{ 'layout-default-background': getDarkTheme === false }"
  39. >
  40. <div
  41. class="layout-content-main"
  42. :class="{
  43. 'layout-content-main-fix': fixedMulti,
  44. 'fluid-header': fixedHeader === 'static'
  45. }"
  46. >
  47. <TabsView v-if="isMultiTabs" v-model:collapsed="collapsed" />
  48. <div
  49. class="main-view"
  50. :class="{
  51. 'main-view-fix': fixedMulti,
  52. noMultiTabs: !isMultiTabs,
  53. 'mt-3': !isMultiTabs
  54. }"
  55. >
  56. <MainView />
  57. </div>
  58. </div>
  59. </n-layout-content>
  60. <n-back-top :right="30" class="myBackTop" />
  61. </n-layout>
  62. </n-layout>
  63. </template>
  64. <script lang="ts" setup>
  65. import { ref, unref, computed, onMounted } from 'vue'
  66. import { Logo } from './components/Logo'
  67. import { TabsView } from './components/TagsView'
  68. import { MainView } from './components/Main'
  69. import { AsideMenu } from './components/Menu'
  70. import { PageHeader } from './components/Header'
  71. import { useProjectSetting } from '@/hooks/setting/useProjectSetting'
  72. import { useDesignSetting } from '@/hooks/setting/useDesignSetting'
  73. import { useRoute } from 'vue-router'
  74. import { useProjectSettingStore } from '@/store/modules/projectSetting'
  75. const { getDarkTheme } = useDesignSetting()
  76. const {
  77. // getShowFooter,
  78. getNavMode,
  79. getNavTheme,
  80. getHeaderSetting,
  81. getMenuSetting,
  82. getMultiTabsSetting
  83. } = useProjectSetting()
  84. const settingStore = useProjectSettingStore()
  85. const navMode = getNavMode
  86. const collapsed = ref<boolean>(false)
  87. const { mobileWidth, menuWidth } = unref(getMenuSetting)
  88. const isMobile = computed<boolean>({
  89. get: () => settingStore.getIsMobile,
  90. set: (val) => settingStore.setIsMobile(val)
  91. })
  92. const fixedHeader = computed(() => {
  93. const { fixed } = unref(getHeaderSetting)
  94. return fixed ? 'absolute' : 'static'
  95. })
  96. const isMixMenuNoneSub = computed(() => {
  97. const mixMenu = settingStore.menuSetting.mixMenu
  98. const currentRoute = useRoute()
  99. if (unref(navMode) != 'horizontal-mix') return true
  100. if (unref(navMode) === 'horizontal-mix' && mixMenu && currentRoute.meta.isRoot) {
  101. return false
  102. }
  103. return true
  104. })
  105. const fixedMenu = computed(() => {
  106. const { fixed } = unref(getHeaderSetting)
  107. return fixed ? 'absolute' : 'static'
  108. })
  109. const isMultiTabs = computed(() => {
  110. return unref(getMultiTabsSetting).show
  111. })
  112. const fixedMulti = computed(() => {
  113. return unref(getMultiTabsSetting).fixed
  114. })
  115. const inverted = computed(() => {
  116. return ['dark', 'header-dark'].includes(unref(getNavTheme))
  117. })
  118. const getHeaderInverted = computed(() => {
  119. const navTheme = unref(getNavTheme)
  120. return ['light', 'header-dark'].includes(navTheme) ? unref(inverted) : !unref(inverted)
  121. })
  122. const leftMenuWidth = computed(() => {
  123. const { minMenuWidth, menuWidth } = unref(getMenuSetting)
  124. return collapsed.value ? minMenuWidth : menuWidth
  125. })
  126. // const getChangeStyle = computed(() => {
  127. // const { minMenuWidth, menuWidth } = unref(getMenuSetting);
  128. // return {
  129. // 'padding-left': collapsed.value ? `${minMenuWidth}px` : `${menuWidth}px`,
  130. // };
  131. // });
  132. const getMenuLocation = computed(() => {
  133. return 'left'
  134. })
  135. // 控制显示或隐藏移动端侧边栏
  136. const showSideDrawder = computed({
  137. get: () => isMobile.value && collapsed.value,
  138. set: (val) => (collapsed.value = val)
  139. })
  140. //判断是否触发移动端模式
  141. const checkMobileMode = () => {
  142. if (document.body.clientWidth <= mobileWidth) {
  143. isMobile.value = true
  144. } else {
  145. isMobile.value = false
  146. }
  147. collapsed.value = false
  148. }
  149. const watchWidth = () => {
  150. const Width = document.body.clientWidth
  151. if (Width <= 950) {
  152. collapsed.value = true
  153. } else collapsed.value = false
  154. checkMobileMode()
  155. }
  156. onMounted(() => {
  157. checkMobileMode()
  158. window.addEventListener('resize', watchWidth)
  159. })
  160. </script>
  161. <style lang="less">
  162. .myBackTop {
  163. z-index: 5000;
  164. }
  165. .layout-side-drawer {
  166. background-color: rgb(0, 20, 40);
  167. .layout-sider {
  168. min-height: 100vh;
  169. box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
  170. position: relative;
  171. z-index: 13;
  172. transition: all 0.2s ease-in-out;
  173. }
  174. }
  175. </style>
  176. <style lang="less" scoped>
  177. .layout {
  178. display: flex;
  179. flex-direction: row;
  180. flex: auto;
  181. &-default-background {
  182. background: #f5f7f9;
  183. }
  184. .layout-sider {
  185. min-height: 100vh;
  186. box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
  187. position: relative;
  188. z-index: 13;
  189. transition: all 0.2s ease-in-out;
  190. }
  191. .layout-sider-fix {
  192. position: fixed;
  193. top: 0;
  194. left: 0;
  195. }
  196. .ant-layout {
  197. overflow: hidden;
  198. }
  199. .layout-right-fix {
  200. overflow-x: hidden;
  201. padding-left: 200px;
  202. min-height: 100vh;
  203. transition: all 0.2s ease-in-out;
  204. }
  205. .layout-content {
  206. flex: auto;
  207. min-height: 100vh;
  208. }
  209. .n-layout-header.n-layout-header--absolute-positioned {
  210. z-index: 11;
  211. }
  212. .n-layout-footer {
  213. background: none;
  214. }
  215. }
  216. .layout-content-main {
  217. margin: 0 10px 10px;
  218. position: relative;
  219. padding-top: 64px;
  220. }
  221. .layout-content-main-fix {
  222. padding-top: 64px;
  223. }
  224. .fluid-header {
  225. padding-top: 0;
  226. }
  227. .main-view-fix {
  228. padding-top: 44px;
  229. }
  230. .noMultiTabs {
  231. padding-top: 0;
  232. }
  233. </style>