DetailTabPage.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <!-- TAB分页的详情页 -->
  3. <view class="d-flex flex-col bg-base">
  4. <SimplePageContentLoader :loader="loader">
  5. <template v-if="loader.content.value">
  6. <view class="d-flex flex-col">
  7. <!-- 轮播大图 -->
  8. <ImageSwiper
  9. v-if="showHead"
  10. :images="loader.content.value.images"
  11. />
  12. <!-- 标题区域 -->
  13. <view class="d-flex flex-col mt-3 p-3">
  14. <slot name="title" :content="loader.content.value">
  15. <view class="d-flex flex-col">
  16. <view class="d-flex flex-row align-center">
  17. <text :class="'size-lll font-songti font-bold color-text-content flex-shrink-1 mr-2' + (props.showDeadBox && loader.content.value.titleBox ? ' border-all-text' : '')">
  18. {{ loader.content.value.title }}
  19. </text>
  20. <slot name="titleEnd" :content="loader.content.value" />
  21. </view>
  22. <text class="size-base color-text-content-second mt-2">{{ loader.content.value.desc }}</text>
  23. </view>
  24. </slot>
  25. <slot name="titleExtra" :content="loader.content.value" />
  26. </view>
  27. <!-- 内容切换标签 -->
  28. <view class="ml-2 mr-2">
  29. <Tabs
  30. :tabs="tabs"
  31. v-model:currentIndex="tabCurrentIndex"
  32. :autoScroll="true"
  33. :autoItemWidth="false"
  34. :defaultIndicatorWidth="130"
  35. :width="710"
  36. class="top-tab"
  37. />
  38. </view>
  39. <view class="d-flex flex-col radius-l bg-light p-25 mt-3" style="min-height:70vh">
  40. <slot name="extraTabs" :tabCurrentId="tabCurrentId" :content="loader.content.value" />
  41. </view>
  42. <ContentNote />
  43. </view>
  44. <LikeFooter :content="loader.content.value">
  45. <template #left>
  46. <ArticleCorrect :content="loader.content.value" />
  47. </template>
  48. </LikeFooter>
  49. </template>
  50. </SimplePageContentLoader>
  51. </view>
  52. </template>
  53. <script setup lang="ts">
  54. import { computed } from "vue";
  55. import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
  56. import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
  57. import { useTabControl } from "@/common/composeabe/TabControl";
  58. import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
  59. import ImageSwiper from "@/pages/parts/ImageSwiper.vue";
  60. import ContentNote from "@/pages/parts/ContentNote.vue";
  61. import Tabs from "@/components/nav/Tabs.vue";
  62. import LikeFooter from "@/pages/parts/LikeFooter.vue";
  63. import ArticleCorrect from "@/pages/parts/ArticleCorrect.vue";
  64. import type { GetContentDetailItem } from "@/api/CommonContent";
  65. import type { DetailTabPageProps, DetailTabPageTabsArray } from "./DetailTabPage";
  66. const props = withDefaults(defineProps<DetailTabPageProps>(), {
  67. extraTabs: () => [],
  68. showHead: true,
  69. showDeadBox: false,
  70. })
  71. const emit = defineEmits([
  72. "tabChange",
  73. "loaded"
  74. ])
  75. const emptyContent = computed(() => {
  76. return !(loader.content.value?.intro as string || '').trim() && !(loader.content.value?.content || '').trim();
  77. })
  78. const loader = useSimplePageContentLoader<
  79. GetContentDetailItem,
  80. { id: number }
  81. >(async (params) => {
  82. if (!params)
  83. throw new Error("!params");
  84. if (!props.load)
  85. throw new Error("!props.load");
  86. const d = await props.load(params.id, tabsArrayObject);
  87. if (d.title)
  88. uni.setNavigationBarTitle({ title: d.title });
  89. setTimeout(() => {
  90. if (emptyContent.value) {
  91. if (d.video)
  92. tabCurrentIndex.value = 1;
  93. else if (d.video)
  94. tabCurrentIndex.value = 2;
  95. }
  96. }, 200);
  97. emit("loaded", d);
  98. return d;
  99. });
  100. const {
  101. tabCurrentId,
  102. tabCurrentIndex,
  103. tabsArray,
  104. tabs,
  105. } = useTabControl({
  106. tabs: props.extraTabs,
  107. onTabChange(a, b) {
  108. emit("tabChange", a, b);
  109. },
  110. })
  111. const tabsArrayObject : DetailTabPageTabsArray = {
  112. tabsArray,
  113. getTabById(id: number) {
  114. return tabsArray.value.find(t => t.id == id);
  115. }
  116. }
  117. useLoadQuerys({ id : 0 }, (p) => loader.loadData(p));
  118. defineExpose({
  119. load(params: { id: number }) {
  120. loader.loadData(params, true);
  121. },
  122. getPageShareData() {
  123. const content = loader.content.value;
  124. if (!content)
  125. return {};
  126. const res = {
  127. title: content.title,
  128. imageUrl: content.image,
  129. };
  130. return res;
  131. }
  132. })
  133. </script>
  134. <style lang="scss">
  135. </style>