DetailTabPage.vue 6.0 KB

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