appMain.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <script setup lang="ts">
  2. import Footer from "./footer/index.vue";
  3. import { useGlobal, isNumber } from "@pureadmin/utils";
  4. import KeepAliveFrame from "./keepAliveFrame/index.vue";
  5. import backTop from "@/assets/svg/back_top.svg?component";
  6. import { h, computed, Transition, defineComponent } from "vue";
  7. import { usePermissionStoreHook } from "@/store/modules/permission";
  8. const props = defineProps({
  9. fixedHeader: Boolean
  10. });
  11. const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
  12. const isKeepAlive = computed(() => {
  13. return $config?.KeepAlive;
  14. });
  15. const transitions = computed(() => {
  16. return route => {
  17. return route.meta.transition;
  18. };
  19. });
  20. const hideTabs = computed(() => {
  21. return $storage?.configure.hideTabs;
  22. });
  23. const hideFooter = computed(() => {
  24. return $storage?.configure.hideFooter;
  25. });
  26. const stretch = computed(() => {
  27. return $storage?.configure.stretch;
  28. });
  29. const layout = computed(() => {
  30. return $storage?.layout.layout === "vertical";
  31. });
  32. const getMainWidth = computed(() => {
  33. return isNumber(stretch.value)
  34. ? stretch.value + "px"
  35. : stretch.value
  36. ? "1440px"
  37. : "100%";
  38. });
  39. const getSectionStyle = computed(() => {
  40. return [
  41. hideTabs.value && layout ? "padding-top: 48px;" : "",
  42. !hideTabs.value && layout ? "padding-top: 81px;" : "",
  43. hideTabs.value && !layout.value ? "padding-top: 48px;" : "",
  44. !hideTabs.value && !layout.value ? "padding-top: 81px;" : "",
  45. props.fixedHeader
  46. ? ""
  47. : `padding-top: 0;${
  48. hideTabs.value
  49. ? "min-height: calc(100vh - 48px);"
  50. : "min-height: calc(100vh - 86px);"
  51. }`
  52. ];
  53. });
  54. const transitionMain = defineComponent({
  55. props: {
  56. route: {
  57. type: undefined,
  58. required: true
  59. }
  60. },
  61. render() {
  62. const transitionName =
  63. transitions.value(this.route)?.name || "fade-transform";
  64. const enterTransition = transitions.value(this.route)?.enterTransition;
  65. const leaveTransition = transitions.value(this.route)?.leaveTransition;
  66. return h(
  67. Transition,
  68. {
  69. name: enterTransition ? "pure-classes-transition" : transitionName,
  70. enterActiveClass: enterTransition
  71. ? `animate__animated ${enterTransition}`
  72. : undefined,
  73. leaveActiveClass: leaveTransition
  74. ? `animate__animated ${leaveTransition}`
  75. : undefined,
  76. mode: "out-in",
  77. appear: true
  78. },
  79. {
  80. default: () => [this.$slots.default()]
  81. }
  82. );
  83. }
  84. });
  85. </script>
  86. <template>
  87. <section
  88. :class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
  89. :style="getSectionStyle"
  90. >
  91. <router-view>
  92. <template #default="{ Component, route }">
  93. <KeepAliveFrame :currComp="Component" :currRoute="route">
  94. <template #default="{ Comp, fullPath, frameInfo }">
  95. <el-scrollbar
  96. v-if="props.fixedHeader"
  97. :wrap-style="{
  98. display: 'flex',
  99. 'flex-wrap': 'wrap',
  100. 'max-width': getMainWidth,
  101. margin: '0 auto',
  102. transition: 'all 300ms cubic-bezier(0.4, 0, 0.2, 1)'
  103. }"
  104. :view-style="{
  105. display: 'flex',
  106. flex: 'auto',
  107. overflow: 'hidden',
  108. 'flex-direction': 'column'
  109. }"
  110. >
  111. <el-backtop
  112. title="回到顶部"
  113. target=".app-main .el-scrollbar__wrap"
  114. >
  115. <backTop />
  116. </el-backtop>
  117. <div class="grow">
  118. <transitionMain :route="route">
  119. <keep-alive
  120. v-if="isKeepAlive"
  121. :include="usePermissionStoreHook().cachePageList"
  122. >
  123. <component
  124. :is="Comp"
  125. :key="fullPath"
  126. :frameInfo="frameInfo"
  127. class="main-content"
  128. />
  129. </keep-alive>
  130. <component
  131. :is="Comp"
  132. v-else
  133. :key="fullPath"
  134. :frameInfo="frameInfo"
  135. class="main-content"
  136. />
  137. </transitionMain>
  138. </div>
  139. <Footer v-if="!hideFooter" />
  140. </el-scrollbar>
  141. <div v-else class="grow">
  142. <transitionMain :route="route">
  143. <keep-alive
  144. v-if="isKeepAlive"
  145. :include="usePermissionStoreHook().cachePageList"
  146. >
  147. <component
  148. :is="Comp"
  149. :key="fullPath"
  150. :frameInfo="frameInfo"
  151. class="main-content"
  152. />
  153. </keep-alive>
  154. <component
  155. :is="Comp"
  156. v-else
  157. :key="fullPath"
  158. :frameInfo="frameInfo"
  159. class="main-content"
  160. />
  161. </transitionMain>
  162. </div>
  163. </template>
  164. </KeepAliveFrame>
  165. </template>
  166. </router-view>
  167. <!-- 页脚 -->
  168. <Footer v-if="!hideFooter && !props.fixedHeader" />
  169. </section>
  170. </template>
  171. <style scoped>
  172. .app-main {
  173. position: relative;
  174. width: 100%;
  175. height: 100vh;
  176. overflow-x: hidden;
  177. /* border: 1px solid blue; */
  178. }
  179. .app-main-nofixed-header {
  180. position: relative;
  181. display: flex;
  182. flex-direction: column;
  183. width: 100%;
  184. }
  185. .main-content {
  186. margin: 24px;
  187. }
  188. </style>