DetailTabPage.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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">{{ loader.content.value.title }}</text>
  18. <slot name="titleEnd" :content="loader.content.value" />
  19. </view>
  20. <text class="size-base color-text-content-second mt-2">{{ loader.content.value.desc }}</text>
  21. </view>
  22. </slot>
  23. <slot name="titleExtra" :content="loader.content.value" />
  24. </view>
  25. <!-- 内容切换标签 -->
  26. <view class="ml-2 mr-2">
  27. <u-tabs
  28. :list="tabs"
  29. :current="tabCurrentIndex"
  30. lineWidth="30"
  31. lineColor="#d9492e"
  32. :activeStyle="{
  33. color: '#000',
  34. fontWeight: 'bold',
  35. transform: 'scale(1.05)'
  36. }"
  37. :inactiveStyle="{
  38. color: '#606266',
  39. transform: 'scale(1)'
  40. }"
  41. :scrollable="tabs.length >= 4"
  42. class="top-tab"
  43. @click="onTabClick"
  44. />
  45. </view>
  46. <view class="d-flex flex-col radius-l bg-light p-25 mt-3" style="min-height:70vh">
  47. <!-- 简介 -->
  48. <template v-if="tabCurrentId == 0">
  49. <u-parse
  50. v-if="loader.content.value.intro"
  51. :content="loader.content.value.intro"
  52. :tagStyle="commonParserStyle"
  53. />
  54. <u-parse
  55. v-if="loader.content.value.content"
  56. :content="loader.content.value.content"
  57. :tagStyle="commonParserStyle"
  58. />
  59. </template>
  60. <!-- 图片 -->
  61. <template v-else-if="tabCurrentId == 1">
  62. <ImageGrid
  63. :images="loader.content.value.images"
  64. :rowCount="2"
  65. :preview="true"
  66. imageHeight="200rpx"
  67. />
  68. </template>
  69. <!-- 视频 -->
  70. <template v-else-if="tabCurrentId == 2">
  71. <video
  72. v-if="loader.content.value.video"
  73. class="w-100 video"
  74. autoplay
  75. :poster="loader.content.value.image"
  76. :src="loader.content.value.video"
  77. controls
  78. />
  79. </template>
  80. <!-- 音频 -->
  81. <template v-else-if="tabCurrentId == 3">
  82. <video
  83. v-if="loader.content.value.audio"
  84. class="w-100 video"
  85. autoplay
  86. :poster="loader.content.value.image"
  87. :src="loader.content.value.audio"
  88. controls
  89. />
  90. </template>
  91. <!-- 其他tab -->
  92. <slot v-else name="extraTabs" :tabCurrentId="tabCurrentId" :content="loader.content.value" />
  93. </view>
  94. <ContentNote />
  95. </view>
  96. </template>
  97. </SimplePageContentLoader>
  98. </view>
  99. </template>
  100. <script setup lang="ts">
  101. import type { GetContentDetailItem } from "@/api/CommonContent";
  102. import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
  103. import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
  104. import { useTabControl, type TabControlItem } from "@/common/composeabe/TabControl";
  105. import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
  106. import ImageGrid from "@/pages/parts/ImageGrid.vue";
  107. import ImageSwiper from "@/pages/parts/ImageSwiper.vue";
  108. import ContentNote from "@/pages/parts/ContentNote.vue";
  109. import commonParserStyle from "@/common/style/commonParserStyle";
  110. import type { PropType, Ref } from "vue";
  111. const props = defineProps({
  112. load: {
  113. type: Function as PropType<(id: number, tabsArray: Ref<TabControlItem[]>) => Promise<GetContentDetailItem>>,
  114. default: null,
  115. },
  116. extraTabs: {
  117. type: Array as PropType<TabControlItem[]>,
  118. default: () => [],
  119. },
  120. showHead: {
  121. type: Boolean,
  122. default: true,
  123. },
  124. })
  125. const emit = defineEmits([
  126. "tabChange"
  127. ])
  128. const loader = useSimplePageContentLoader<
  129. GetContentDetailItem,
  130. { id: number }
  131. >(async (params) => {
  132. if (!params)
  133. throw new Error("!params");
  134. const d = await props.load(params.id, tabsArray);
  135. tabsArray.value[1].visible = Boolean(d.images && d.images.length > 1);
  136. tabsArray.value[2].visible = Boolean(d.video);
  137. tabsArray.value[3].visible = Boolean(d.audio);
  138. if (d.title)
  139. uni.setNavigationBarTitle({ title: d.title });
  140. return d;
  141. });
  142. const {
  143. tabCurrentId,
  144. tabCurrentIndex,
  145. tabsArray,
  146. tabs,
  147. onTabClick
  148. } = useTabControl({
  149. tabs: [
  150. {
  151. id: 0,
  152. name: '简介',
  153. visible: true,
  154. },
  155. {
  156. id: 1,
  157. name: '图片',
  158. visible: true,
  159. },
  160. {
  161. id: 2,
  162. name: '视频',
  163. visible: true,
  164. },
  165. {
  166. id: 3,
  167. name: '音频',
  168. visible: true,
  169. },
  170. ...props.extraTabs,
  171. ],
  172. onTabChange(a, b) {
  173. emit("tabChange", a, b);
  174. },
  175. })
  176. useLoadQuerys({ id : 0 }, (p) => loader.loadData(p));
  177. </script>
  178. <style lang="scss">
  179. </style>