BaseLayout.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <script setup lang="ts">
  2. import { throttle } from 'lodash'
  3. import { storeToRefs } from 'pinia'
  4. import settings from '@/api/settings'
  5. import PageHeader from '@/components/PageHeader'
  6. import { useSettingsStore, useUserStore } from '@/pinia'
  7. import FooterLayout from './FooterLayout.vue'
  8. import HeaderLayout from './HeaderLayout.vue'
  9. import SideBar from './SideBar.vue'
  10. const route = useRoute()
  11. const router = useRouter()
  12. const drawerVisible = ref(false)
  13. const collapsed = ref(false)
  14. const hideLayoutSidebar = ref(false)
  15. function _init() {
  16. collapsed.value = collapse()
  17. hideLayoutSidebar.value = getClientWidth() < 600
  18. }
  19. const init = throttle(_init, 50)
  20. onMounted(init)
  21. addEventListener('resize', init)
  22. onUnmounted(() => {
  23. removeEventListener('resize', init)
  24. })
  25. function getClientWidth() {
  26. return document.body.clientWidth
  27. }
  28. function collapse() {
  29. return getClientWidth() < 1080
  30. }
  31. const { server_name } = storeToRefs(useSettingsStore())
  32. settings.get_server_name().then(r => {
  33. server_name.value = r.name
  34. })
  35. const breadList = ref([])
  36. provide('breadList', breadList)
  37. const userStore = useUserStore()
  38. const { token } = storeToRefs(userStore)
  39. const settingsStore = useSettingsStore()
  40. const { route_path } = storeToRefs(settingsStore)
  41. watch(route, () => {
  42. route_path.value = route.path
  43. })
  44. onMounted(() => {
  45. router.push(route_path.value)
  46. })
  47. </script>
  48. <template>
  49. <ALayout :key="token" class="full-screen-wrapper min-h-screen">
  50. <div class="drawer-sidebar">
  51. <ADrawer
  52. v-model:open="drawerVisible"
  53. :closable="false"
  54. placement="left"
  55. width="256"
  56. @close="drawerVisible = false"
  57. >
  58. <SideBar />
  59. </ADrawer>
  60. </div>
  61. <ALayoutSider
  62. v-if="!hideLayoutSidebar"
  63. v-model:collapsed="collapsed"
  64. collapsible
  65. :style="{ zIndex: 11 }"
  66. theme="light"
  67. class="layout-sider"
  68. >
  69. <SideBar />
  70. </ALayoutSider>
  71. <ALayout class="main-container">
  72. <ALayoutHeader :style="{ position: 'sticky', top: '0', zIndex: 10, width: '100%' }">
  73. <HeaderLayout @click-un-fold="drawerVisible = true" />
  74. </ALayoutHeader>
  75. <ALayoutContent>
  76. <PageHeader />
  77. <div class="router-view">
  78. <RouterView v-slot="{ Component, route }">
  79. <Transition name="slide-fade">
  80. <component
  81. :is="Component"
  82. :key="route.path"
  83. />
  84. </Transition>
  85. </RouterView>
  86. </div>
  87. </ALayoutContent>
  88. <ALayoutFooter>
  89. <FooterLayout />
  90. </ALayoutFooter>
  91. </ALayout>
  92. </ALayout>
  93. </template>
  94. <style lang="less" scoped>
  95. .layout-sider {
  96. @media (max-width: 600px) {
  97. display: none;
  98. }
  99. }
  100. .drawer-sidebar {
  101. @media (min-width: 600px) {
  102. display: none;
  103. }
  104. }
  105. </style>
  106. <style lang="less">
  107. .layout-sider .sidebar {
  108. ul.ant-menu-inline.ant-menu-root {
  109. height: calc(100vh - 160px);
  110. overflow-y: auto;
  111. overflow-x: hidden;
  112. .ant-menu-item {
  113. width: unset;
  114. }
  115. }
  116. ul.ant-menu-inline-collapsed {
  117. height: calc(100vh - 200px);
  118. overflow-y: auto;
  119. overflow-x: hidden;
  120. }
  121. }
  122. </style>
  123. <style lang="less">
  124. .slide-fade-enter-active {
  125. transition: all .3s ease-in-out;
  126. }
  127. .slide-fade-leave-active {
  128. transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
  129. }
  130. .slide-fade-enter-from, .slide-fade-enter-to, .slide-fade-leave-to
  131. /* .slide-fade-leave-active for below version 2.1.8 */ {
  132. transform: translateX(10px);
  133. opacity: 0;
  134. }
  135. body {
  136. overflow: unset !important;
  137. }
  138. .ant-layout-header {
  139. padding: 0 !important;
  140. }
  141. .ant-layout-sider {
  142. &.ant-layout-sider-has-trigger {
  143. padding-bottom: 0;
  144. }
  145. box-shadow: 2px 0 8px rgba(29, 35, 41, 0.05);
  146. }
  147. .ant-drawer-body {
  148. .sidebar .logo {
  149. box-shadow: 0 1px 0 0 #e8e8e8;
  150. }
  151. .ant-menu-inline, .ant-menu-vertical, .ant-menu-vertical-left {
  152. border-right: 0 !important;
  153. }
  154. }
  155. .ant-table-small {
  156. font-size: 13px;
  157. }
  158. .header-notice-wrapper .ant-tabs-content {
  159. max-height: 250px;
  160. }
  161. .header-notice-wrapper .ant-tabs-tabpane-active {
  162. overflow-y: scroll;
  163. }
  164. .ant-layout-footer {
  165. @media (max-width: 320px) {
  166. padding: 10px;
  167. }
  168. }
  169. .ant-layout-content {
  170. min-height: auto;
  171. .router-view {
  172. padding: 20px;
  173. @media (max-width: 512px) {
  174. padding: 20px 0;
  175. }
  176. position: relative;
  177. }
  178. }
  179. .ant-layout-footer {
  180. text-align: center;
  181. }
  182. </style>