appMain.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. // return isNumber(stretch.value)
  39. // ? stretch.value + "px"
  40. // : stretch.value
  41. // ? "1440px"
  42. // : "100%";
  43. });
  44. const getSectionStyle = computed(() => {
  45. return [
  46. hideTabs.value && layout ? "padding-top: 48px;" : "",
  47. !hideTabs.value && layout ? "padding-top: 81px;" : "",
  48. hideTabs.value && !layout.value ? "padding-top: 48px;" : "",
  49. !hideTabs.value && !layout.value ? "padding-top: 81px;" : "",
  50. props.fixedHeader
  51. ? ""
  52. : `padding-top: 0;${
  53. hideTabs.value
  54. ? "min-height: calc(100vh - 48px);"
  55. : "min-height: calc(100vh - 86px);"
  56. }`
  57. ];
  58. });
  59. const transitionMain = defineComponent({
  60. props: {
  61. route: {
  62. type: undefined,
  63. required: true
  64. }
  65. },
  66. render() {
  67. const transitionName =
  68. transitions.value(this.route)?.name || "fade-transform";
  69. const enterTransition = transitions.value(this.route)?.enterTransition;
  70. const leaveTransition = transitions.value(this.route)?.leaveTransition;
  71. return h(
  72. Transition,
  73. {
  74. name: enterTransition ? "pure-classes-transition" : transitionName,
  75. enterActiveClass: enterTransition
  76. ? `animate__animated ${enterTransition}`
  77. : undefined,
  78. leaveActiveClass: leaveTransition
  79. ? `animate__animated ${leaveTransition}`
  80. : undefined,
  81. mode: "out-in",
  82. appear: true
  83. },
  84. {
  85. default: () => [this.$slots.default()]
  86. }
  87. );
  88. }
  89. });
  90. </script>
  91. <template>
  92. <section
  93. :class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
  94. class="mainBG"
  95. :style="getSectionStyle"
  96. >
  97. <router-view>
  98. <template #default="{ Component, route }">
  99. <KeepAliveFrame :currComp="Component" :currRoute="route">
  100. <template #default="{ Comp, fullPath, frameInfo }">
  101. <el-scrollbar
  102. v-if="props.fixedHeader"
  103. :wrap-style="{
  104. display: 'flex',
  105. 'flex-wrap': 'wrap',
  106. // 'max-width': getMainWidth,
  107. margin: '0 auto',
  108. transition: 'all 300ms cubic-bezier(0.4, 0, 0.2, 1)'
  109. }"
  110. :view-style="{
  111. display: 'flex',
  112. flex: 'auto',
  113. overflow: 'hidden',
  114. 'flex-direction': 'column'
  115. }"
  116. >
  117. <el-backtop
  118. title="回到顶部"
  119. target=".app-main .el-scrollbar__wrap"
  120. >
  121. <backTop />
  122. </el-backtop>
  123. <div class="grow">
  124. <transitionMain :route="route">
  125. <keep-alive
  126. v-if="isKeepAlive"
  127. :include="usePermissionStoreHook().cachePageList"
  128. >
  129. <component
  130. :is="Comp"
  131. :key="fullPath"
  132. :frameInfo="frameInfo"
  133. class="main-content"
  134. />
  135. </keep-alive>
  136. <component
  137. :is="Comp"
  138. v-else
  139. :key="fullPath"
  140. :frameInfo="frameInfo"
  141. class="main-content"
  142. />
  143. </transitionMain>
  144. </div>
  145. <Footer v-if="!hideFooter" />
  146. </el-scrollbar>
  147. <div v-else class="grow">
  148. <transitionMain :route="route">
  149. <keep-alive
  150. v-if="isKeepAlive"
  151. :include="usePermissionStoreHook().cachePageList"
  152. >
  153. <component
  154. :is="Comp"
  155. :key="fullPath"
  156. :frameInfo="frameInfo"
  157. class="main-content"
  158. />
  159. </keep-alive>
  160. <component
  161. :is="Comp"
  162. v-else
  163. :key="fullPath"
  164. :frameInfo="frameInfo"
  165. class="main-content"
  166. />
  167. </transitionMain>
  168. </div>
  169. </template>
  170. </KeepAliveFrame>
  171. </template>
  172. </router-view>
  173. <!-- 页脚 -->
  174. <Footer v-if="!hideFooter && !props.fixedHeader" />
  175. </section>
  176. </template>
  177. <style scoped>
  178. .app-main {
  179. position: relative;
  180. width: 100%;
  181. height: 100vh;
  182. overflow-x: hidden;
  183. /* border: 1px solid blue; */
  184. }
  185. .app-main-nofixed-header {
  186. position: relative;
  187. display: flex;
  188. flex-direction: column;
  189. width: 100%;
  190. }
  191. .main-content {
  192. margin: 24px;
  193. }
  194. .mainBG {
  195. /* z-index: 1; */
  196. background: white !important;
  197. }
  198. </style>