details.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <template>
  2. <FlexCol :padding="[0,0,50,0]">
  3. <SimplePageContentLoader :loader="loader">
  4. <template v-if="loader.content.value">
  5. <FlexCol :gap="20">
  6. <swiper
  7. v-if="loader.content.value.images.length > 0"
  8. circular
  9. :indicator-dots="true"
  10. :autoplay="true"
  11. :interval="3000"
  12. :duration="1000"
  13. :style="{ height: '500rpx' }"
  14. >
  15. <swiper-item v-for="(item, key) in loader.content.value.images" :key="key">
  16. <Image
  17. :src="item"
  18. width="100%"
  19. :height="500"
  20. :radius="20"
  21. mode="aspectFill"
  22. touchable
  23. @click="onPreviewImage(key)"
  24. />
  25. </swiper-item>
  26. </swiper>
  27. <Image
  28. v-else-if="loader.content.value.image"
  29. :radius="20"
  30. :src="loader.content.value.image"
  31. mode="widthFix"
  32. width="100%"
  33. />
  34. <FlexCol :padding="20" :gap="14">
  35. <H2>{{ loader.content.value.title }}</H2>
  36. <FlexRow>
  37. <Text v-if="loader.content.value.from" :text="`来源:${loader.content.value.from}`" fontConfig="subText" />
  38. <Text :text="DataDateUtils.formatDate(loader.content.value.publishAt, 'YYYY-MM-dd')" fontConfig="subText" />
  39. </FlexRow>
  40. </FlexCol>
  41. <FlexCol :padding="20" :radius="20">
  42. <Parse
  43. v-if="loader.content.value.content"
  44. :content="loader.content.value.content"
  45. />
  46. <Parse
  47. v-if="loader.content.value.intro"
  48. :content="(loader.content.value.intro as string)"
  49. />
  50. <Parse
  51. v-if="loader.content.value.value"
  52. :content="(loader.content.value.value as string)"
  53. />
  54. <Text v-if="emptyContent" fontConfig="subText">暂无简介</Text>
  55. </FlexCol>
  56. <!-- 推荐 -->
  57. <FlexCol v-if="recommendListLoader.content.value?.length" :padding="20">
  58. <H4>相关推荐</H4>
  59. <Box2LineImageRightShadow
  60. titleColor="black"
  61. v-for="item in recommendListLoader.content.value"
  62. :key="item.id"
  63. :image="item.thumbnail || item.image || AppCofig.defaultImage"
  64. :title="item.title"
  65. :desc="item.desc"
  66. :badge="(item.badge as string)"
  67. :wideImage="true"
  68. @click="goDetails(item.id)"
  69. />
  70. </FlexCol>
  71. <!-- 广告 -->
  72. <!-- <ad /> -->
  73. </FlexCol>
  74. </template>
  75. </SimplePageContentLoader>
  76. </FlexCol>
  77. </template>
  78. <script setup lang="ts">
  79. import { computed } from "vue";
  80. import { useSimpleDataLoader } from "@/common/composeabe/SimpleDataLoader";
  81. import { useSimplePageContentLoader } from "@/common/composeabe/SimplePageContentLoader";
  82. import { useSwiperImagePreview } from "@/common/composeabe/SwiperImagePreview";
  83. import { useLoadQuerys } from "@/common/composeabe/LoadQuerys";
  84. import { navTo } from "@/components/utils/PageAction";
  85. import { onShareTimeline, onShareAppMessage } from "@dcloudio/uni-app";
  86. import { DataDateUtils } from "@imengyu/js-request-transform";
  87. import type { GetContentDetailItem } from "@/api/CommonContent";
  88. import SimplePageContentLoader from "@/common/components/SimplePageContentLoader.vue";
  89. import Parse from "@/components/display/parse/Parse.vue";
  90. import CommonContent, { GetContentListParams } from "@/api/CommonContent";
  91. import Box2LineImageRightShadow from "@/common/components/parts/Box2LineImageRightShadow.vue";
  92. import AppCofig from "@/common/config/AppCofig";
  93. import FlexCol from "@/components/layout/FlexCol.vue";
  94. import Image from "@/components/basic/Image.vue";
  95. import H4 from "@/components/typography/H4.vue";
  96. import Text from "@/components/basic/Text.vue";
  97. import H2 from "@/components/typography/H2.vue";
  98. import FlexRow from "@/components/layout/FlexRow.vue";
  99. const loader = useSimplePageContentLoader<
  100. GetContentDetailItem,
  101. { id: number }
  102. >(async (params) => {
  103. if (!params)
  104. throw new Error("!params");
  105. const res = await CommonContent.getContentDetail(params.id);
  106. //console.log(res);
  107. uni.setNavigationBarTitle({ title: res.title });
  108. return res;
  109. });
  110. const { onPreviewImage } = useSwiperImagePreview(() => loader.content.value?.images || [])
  111. const emptyContent = computed(() => (loader.content.value?.content
  112. || loader.content.value?.intro as string
  113. || loader.content.value?.value as string
  114. || '').trim() === '')
  115. const recommendListLoader = useSimpleDataLoader(async () => {
  116. if (!querys.value.modelId)
  117. return []
  118. return (await CommonContent.getContentList(new GetContentListParams()
  119. .setModelId(querys.value.modelId)
  120. .setMainBodyColumnId(querys.value.mainBodyColumnId)
  121. .setSelfValues({
  122. mainBodyId: querys.value.mainBodyId,
  123. })
  124. , 1, 10)).list.filter((p) => p.id !== querys.value.id);
  125. });
  126. function goDetails(id: number) {
  127. navTo('/pages/article/details', {
  128. id,
  129. mainBodyColumnId: querys.value.mainBodyColumnId,
  130. modelId: querys.value.modelId,
  131. mainBodyId: querys.value.mainBodyId,
  132. });
  133. }
  134. const { querys } = useLoadQuerys({
  135. id: 0,
  136. mainBodyColumnId: 0,
  137. mainBodyId: 0,
  138. modelId: 0,
  139. }, (t) => loader.loadData(t));
  140. function getPageShareData() {
  141. if (!loader.content.value)
  142. return { title: '文章详情', imageUrl: '' }
  143. return {
  144. title: loader.content.value.title,
  145. imageUrl: loader.content.value.images[0],
  146. }
  147. }
  148. onShareTimeline(() => {
  149. return getPageShareData();
  150. })
  151. onShareAppMessage(() => {
  152. return getPageShareData();
  153. })
  154. </script>