You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.6 KiB

  1. <script setup lang="ts">
  2. import {
  3. h,
  4. ref,
  5. computed,
  6. Transition,
  7. defineComponent,
  8. getCurrentInstance
  9. } from "vue";
  10. import { RouterView } from "vue-router";
  11. import backTop from "/@/assets/svg/back_top.svg";
  12. import { usePermissionStoreHook } from "/@/store/modules/permission";
  13. const props = defineProps({
  14. fixedHeader: Boolean
  15. });
  16. const keepAlive: Boolean = ref(
  17. getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
  18. );
  19. const instance =
  20. getCurrentInstance().appContext.app.config.globalProperties.$storage;
  21. const transitions = computed(() => {
  22. return route => {
  23. return route.meta.transition;
  24. };
  25. });
  26. const hideTabs = computed(() => {
  27. return instance?.sets.hideTabs;
  28. });
  29. const layout = computed(() => {
  30. return instance?.layout.layout === "vertical";
  31. });
  32. const transitionMain = defineComponent({
  33. render() {
  34. return h(
  35. Transition,
  36. {
  37. name:
  38. transitions.value(this.route) &&
  39. this.route.meta.transition.enterTransition
  40. ? "pure-classes-transition"
  41. : (transitions.value(this.route) &&
  42. this.route.meta.transition.name) ||
  43. "fade-transform",
  44. enterActiveClass:
  45. transitions.value(this.route) &&
  46. `animate__animated ${this.route.meta.transition.enterTransition}`,
  47. leaveActiveClass:
  48. transitions.value(this.route) &&
  49. `animate__animated ${this.route.meta.transition.leaveTransition}`,
  50. mode: "out-in",
  51. appear: true
  52. },
  53. {
  54. default: () => [this.$slots.default()]
  55. }
  56. );
  57. },
  58. props: {
  59. route: {
  60. type: undefined,
  61. required: true
  62. }
  63. }
  64. });
  65. </script>
  66. <template>
  67. <section
  68. :class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
  69. :style="[
  70. hideTabs && layout ? 'padding-top: 48px;' : '',
  71. !hideTabs && layout ? 'padding-top: 85px;' : '',
  72. hideTabs && !layout ? 'padding-top: 48px' : '',
  73. !hideTabs && !layout ? 'padding-top: 98px;' : ''
  74. ]"
  75. >
  76. <router-view>
  77. <template #default="{ Component, route }">
  78. <el-scrollbar v-if="props.fixedHeader">
  79. <el-backtop title="回到顶部" target=".app-main .el-scrollbar__wrap">
  80. <backTop />
  81. </el-backtop>
  82. <transitionMain :route="route">
  83. <keep-alive
  84. v-if="keepAlive"
  85. :include="usePermissionStoreHook().cachePageList"
  86. >
  87. <component
  88. :is="Component"
  89. :key="route.fullPath"
  90. class="main-content"
  91. />
  92. </keep-alive>
  93. <component
  94. v-else
  95. :is="Component"
  96. :key="route.fullPath"
  97. class="main-content"
  98. />
  99. </transitionMain>
  100. </el-scrollbar>
  101. <div v-else>
  102. <transitionMain :route="route">
  103. <keep-alive
  104. v-if="keepAlive"
  105. :include="usePermissionStoreHook().cachePageList"
  106. >
  107. <component
  108. :is="Component"
  109. :key="route.fullPath"
  110. class="main-content"
  111. />
  112. </keep-alive>
  113. <component
  114. v-else
  115. :is="Component"
  116. :key="route.fullPath"
  117. class="main-content"
  118. />
  119. </transitionMain>
  120. </div>
  121. </template>
  122. </router-view>
  123. </section>
  124. </template>
  125. <style scoped>
  126. .app-main {
  127. width: 100%;
  128. height: 100vh;
  129. position: relative;
  130. overflow-x: hidden;
  131. }
  132. .app-main-nofixed-header {
  133. width: 100%;
  134. min-height: 100vh;
  135. position: relative;
  136. }
  137. .main-content {
  138. margin: 24px;
  139. }
  140. </style>