CommonCategoryBlocks.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <template>
  2. <!--通用内容首页小分块组件-->
  3. <FlexCol width="100%">
  4. <!-- 分类 -->
  5. <template v-for="(category,i) in categoryDatas" :key="i">
  6. <HomeTitle
  7. v-if="category.showTitle"
  8. :title="category.title"
  9. :titleLevel="category.textLevel"
  10. :showMore="category.showMore !== false"
  11. :moreText="category.moreText || '更多'"
  12. @clickMore="category.morePage"
  13. />
  14. <!--预制块-->
  15. <template v-if="category.type === 'CalendarBlock'">
  16. <CalendarBlock v-bind="category.blockProps" />
  17. </template>
  18. <template v-else-if="category.type === 'StatsBlock'">
  19. <StatsBlock v-bind="category.blockProps" />
  20. </template>
  21. <template v-else-if="category.type === 'MapBlock'">
  22. <MapCategoryBlock v-bind="category.blockProps" />
  23. </template>
  24. <template v-else-if="category.type === 'AudioBlock'">
  25. <AudioBlock v-bind="category.blockProps" />
  26. </template>
  27. <!--通用列表-->
  28. <SimplePageContentLoader v-else-if="category.data" :loader="category.data" >
  29. <FlexCol>
  30. <template v-if="category.type === 'article'">
  31. <Box2LineRightShadow
  32. v-for="(item, i) in category.data.content.value"
  33. :key="i"
  34. :title="item.title"
  35. :desc="item.desc"
  36. :tags="(item.bottomTags as string[])"
  37. @click="category.detailsPage(item)"
  38. />
  39. </template>
  40. <template v-else-if="category.type === 'large-image'">
  41. <FlexCol>
  42. <Box2LineLargeImageUserShadow
  43. v-for="(item, i) in category.data.content.value"
  44. titleColor="title-text"
  45. fixSize
  46. title1
  47. :key="i"
  48. :title="item.title"
  49. :desc="item.desc"
  50. :image="item.image"
  51. :tags="(item.bottomTags as string[])"
  52. @click="category.detailsPage(item)"
  53. />
  54. </FlexCol>
  55. </template>
  56. <template v-else-if="category.type === 'large-image2'">
  57. <scroll-view scroll-x>
  58. <FlexRow>
  59. <Box2LineLargeImageUserShadow
  60. v-for="(item, i) in category.data.content.value"
  61. classNames="width-2-3 mr-2"
  62. titleColor="title-text"
  63. fixSize
  64. title1
  65. :key="i"
  66. :title="item.title"
  67. :desc="item.desc"
  68. :image="item.image"
  69. :tags="(item.bottomTags as string[])"
  70. @click="category.detailsPage(item)"
  71. />
  72. </FlexRow>
  73. </scroll-view>
  74. </template>
  75. <template v-else-if="category.type === 'horizontal-large'">
  76. <scroll-view scroll-x>
  77. <view class="pb-3 pt-3 d-flex flex-row overflow-visible align-stretch">
  78. <Box2LineLargeImageUserShadow
  79. v-for="(item, i) in category.data.content.value"
  80. classNames="width-2-3 mr-2"
  81. titleColor="title-text"
  82. title1
  83. fixSize
  84. :key="i"
  85. :title="item.title"
  86. :desc="item.desc"
  87. :image="item.thumbnail || item.image"
  88. :tags="(item.bottomTags as string[])"
  89. @click="category.detailsPage(item)"
  90. />
  91. </view>
  92. </scroll-view>
  93. </template>
  94. <template v-else-if="category.type === 'large-grid2'">
  95. <FlexRow wrap align="stretch" justify="space-between" overflow="visible">
  96. <Box2LineLargeImageUserShadow
  97. v-for="(item, i) in category.data.content.value"
  98. titleColor="title-text"
  99. width="calc(50% - 10rpx)"
  100. fixSize
  101. :key="i"
  102. :title="item.title"
  103. :desc="item.desc"
  104. :image="item.image"
  105. :tags="(item.bottomTags as string[])"
  106. @click="category.detailsPage(item)"
  107. />
  108. </FlexRow>
  109. </template>
  110. <template v-else-if="category.type === 'small-grid2'">
  111. <view class="d-flex flex-row justify-between flex-wrap">
  112. <view
  113. v-for="(tab, k) in category.data.content.value"
  114. :key="k"
  115. class="grid4-item position-relative mb-3"
  116. @click="category.detailsPage(tab)"
  117. >
  118. <text
  119. class="tag bg-mask-white color-primary radius-l p-1 position-absolute size-s text-lines-1"
  120. >
  121. {{ tab.title }}
  122. </text>
  123. <Image
  124. width="100%"
  125. :height="250"
  126. :radius="15"
  127. :defaultImage="AppCofig.defaultImage"
  128. :src="tab.thumbnail || tab.image"
  129. mode="aspectFit"
  130. />
  131. </view>
  132. </view>
  133. </template>
  134. <template v-else-if="category.type === 'simple-text'">
  135. <FlexCol>
  136. <Box2LineImageRightShadow
  137. v-for="(item, i) in category.data.content.value"
  138. titleColor="title-text"
  139. :border="false"
  140. fixSize
  141. :key="i"
  142. :title="item.title"
  143. :desc="item.desc"
  144. :showImage="false"
  145. :tags="(item.bottomTags as string[])"
  146. />
  147. </FlexCol>
  148. </template>
  149. <template v-else>
  150. <Box2LineImageRightShadow
  151. v-for="(item, i) in category.data.content.value"
  152. titleColor="title-text"
  153. fixSize
  154. :key="i"
  155. :title="item.title"
  156. :desc="item.desc"
  157. :image="item.image"
  158. :tags="(item.bottomTags as string[])"
  159. @click="category.detailsPage(item)"
  160. />
  161. </template>
  162. </FlexCol>
  163. </SimplePageContentLoader>
  164. </template>
  165. </FlexCol>
  166. </template>
  167. <script setup lang="ts">;
  168. import { computed, onMounted, watch, type PropType } from 'vue';
  169. import CommonContent, { CommonContentApi, GetContentListItem, GetContentListParams } from '@/api/CommonContent';
  170. import { navCommonDetail, navCommonList, resolveCommonContentGetPageDetailUrlAuto, resolveCommonContentSolveProps, useHomeCommonCategoryBlock, type HomeCommonCategoryBlockProps, type IHomeCommonCategoryBlock } from '../common/CommonContent';
  171. import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
  172. import { navTo } from '@/components/utils/PageAction';
  173. import HomeTitle from '@/pages/parts/HomeTitle.vue';
  174. import SimplePageContentLoader from '@/common/components/SimplePageContentLoader.vue';
  175. import Box2LineImageRightShadow from '@/pages/parts/Box2LineImageRightShadow.vue';
  176. import Box2LineRightShadow from '@/pages/parts/Box2LineRightShadow.vue';
  177. import FlexCol from '@/components/layout/FlexCol.vue';
  178. import FlexRow from '@/components/layout/FlexRow.vue';
  179. import CalendarBlock from '@/pages/travel/calendar/block.vue';
  180. import Box2LineLargeImageUserShadow from '@/pages/parts/Box2LineLargeImageUserShadow.vue';
  181. import StatsBlock from '@/pages/blocks/StatsBlock.vue';
  182. import MapCategoryBlock from '@/pages/blocks/MapBlock.vue';
  183. import Image from '@/components/basic/Image.vue';
  184. import AppCofig from '@/common/config/AppCofig';
  185. import type { CategoryDefine } from './CommonCategoryBlocks';
  186. import type { IHomeCommonCategoryDynamicDataDetailContent } from './CommonCategoryDynamicData';
  187. import AudioBlock from '@/pages/blocks/AudioBlock.vue';
  188. const props = defineProps({
  189. /**
  190. * 分类定义
  191. */
  192. categoryDefine: {
  193. type: Array as PropType<CategoryDefine[]>,
  194. default: () => [],
  195. }
  196. });
  197. const categoryDatas = computed(() => props.categoryDefine.map(item => {
  198. if (!item.content)
  199. return {
  200. ...item,
  201. detailsPage: () => {},
  202. morePage: () => {
  203. if (item.morePage)
  204. navTo(item.morePage, {});
  205. },
  206. data: null,
  207. };
  208. const defaultDetailsPageHandler = (dataItem: GetContentListItem) => {
  209. const id = dataItem.id;
  210. const content = item.content as CommonContentApi;
  211. if (item.detailsPage) {
  212. if (item.detailsPage === 'byContent')
  213. navTo(resolveCommonContentGetPageDetailUrlAuto(dataItem), { id });
  214. else
  215. navTo(item.detailsPage, { id });
  216. } else {
  217. navCommonDetail({
  218. id,
  219. mainBodyColumnId: content.mainBodyColumnId,
  220. modelId: content.modelId,
  221. })
  222. }
  223. };
  224. if (item.content instanceof CommonContentApi) {
  225. return {
  226. ...item,
  227. detailsPage: defaultDetailsPageHandler,
  228. morePage: () => {
  229. const content = item.content as CommonContentApi;
  230. if (item.morePage) {
  231. navTo(item.morePage, {});
  232. } else {
  233. navCommonList({
  234. title: item.title,
  235. mainBodyColumnId: content.mainBodyColumnId,
  236. modelId: content.modelId,
  237. detailsPage: item.detailsPage,
  238. dataSolve: item.dataSolve || [],
  239. })
  240. }
  241. },
  242. data: useSimpleDataLoader(async () => {
  243. let res = (await (item.content as CommonContentApi)
  244. .getContentList(new GetContentListParams(), 1, item.count || 4))
  245. .list;
  246. return resolveCommonContentSolveProps(res, item.dataSolve || []);;
  247. }, false)
  248. }
  249. } else {
  250. switch (item.content.type) {
  251. case 'CommonCategoryBlock':
  252. return {
  253. ...item,
  254. detailsPage: item.content.goDetail,
  255. morePage: item.content.goList,
  256. data: item.content.loader,
  257. }
  258. case 'detailContent':
  259. return {
  260. ...item,
  261. detailsPage: defaultDetailsPageHandler,
  262. morePage: () => {},
  263. data: useSimpleDataLoader(async () => {
  264. console.log(item);
  265. const data = item.data as IHomeCommonCategoryDynamicDataDetailContent;
  266. const res = await CommonContent.getContentDetail(data.params!.id, undefined, data.params!.modelId || undefined);
  267. return resolveCommonContentSolveProps([res as any], item.dataSolve || []);;
  268. }, false),
  269. }
  270. default: {
  271. const block = useHomeCommonCategoryBlock({
  272. ...item.content,
  273. dataSolve: item.dataSolve ?? [],
  274. }, false);
  275. return {
  276. ...item,
  277. detailsPage: block.goDetail,
  278. morePage: block.goList,
  279. data: block.loader,
  280. }
  281. }
  282. }
  283. }
  284. }));
  285. function loadCategoryDatas() {
  286. categoryDatas.value.forEach(item => {
  287. if (item.data)
  288. item.data.loadData(undefined, true);
  289. })
  290. }
  291. watch(categoryDatas, loadCategoryDatas);
  292. onMounted( loadCategoryDatas);
  293. </script>