tree.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <template>
  2. <FlexCol>
  3. <FlexCol :margin="[10,0,0,0]">
  4. <Text textAlign="center" text="一人添果,全村增光;乡源树茂,故土名扬" fontConfig="primaryTitle" fontSize="35rpx" />
  5. </FlexCol>
  6. <VillageTree />
  7. <FlexCol :padding="30">
  8. <FlexCol>
  9. <FlexRow center>
  10. <Progress
  11. :value="60"
  12. :backgroundStyle="{
  13. background: 'linear-gradient(to bottom, #280502, #a44e17)',
  14. }"
  15. :progressStyle="{
  16. borderImageSource: 'url(https://xy.wenlvti.net/app_static/images/village/ImageProgress.png)',
  17. borderImageSlice: `5 25 5 25 fill`,
  18. borderImageWidth: `0px 15px`,
  19. borderImageRepeat: 'stretch',
  20. borderRadius: '10px',
  21. overflow: 'hidden',
  22. }"
  23. :width="300"
  24. :height="30"
  25. />
  26. </FlexRow>
  27. <Height height="space.lg" />
  28. <FlexRow center gap="gap.md">
  29. <Icon icon="https://xy.wenlvti.net/app_static/images/village/IconLight.png" :size="50" />
  30. <Text text="乡源光 30%" fontConfig="contentText" fontSize="30rpx" color="#E79412" />
  31. </FlexRow>
  32. <Height height="space.md" />
  33. <Text textAlign="center" text="再浇水5次 可升级" fontConfig="secondText" />
  34. </FlexCol>
  35. <Height height="space.xl" />
  36. <FlexRow justify="space-around" :padding="[0, 30]">
  37. <Touchable center direction="column" flexBasis="22%">
  38. <Image src="https://xy.wenlvti.net/app_static/images/village/IconCollect.png" :width="130" mode="widthFix" />
  39. <Text text="拾果" fontConfig="contentText" />
  40. </Touchable>
  41. <Touchable center direction="column" flexBasis="22%">
  42. <Image src="https://xy.wenlvti.net/app_static/images/village/IconFertilization.png" :width="130" mode="widthFix" />
  43. <Text text="施肥" fontConfig="contentText" />
  44. </Touchable>
  45. <Touchable center direction="column" flexBasis="22%">
  46. <Image src="https://xy.wenlvti.net/app_static/images/village/IconWatering.png" :width="130" mode="widthFix" />
  47. <Text text="浇水" fontConfig="contentText" textAlign="center" />
  48. </Touchable>
  49. <Touchable center direction="column" flexBasis="22%" @click="handleGoBless">
  50. <Image src="https://xy.wenlvti.net/app_static/images/village/IconBlessing.png" :width="130" mode="widthFix" />
  51. <Text text="赐福" fontConfig="contentText" textAlign="center" />
  52. </Touchable>
  53. </FlexRow>
  54. <HomeTitle title="最新动态" />
  55. <SimplePageContentLoader :loader="infoLoader" :emptyView="{ text: '冷冷清清,等你来添光加彩' }">
  56. <FlexCol gap="gap.lg">
  57. <FlexRow
  58. v-for="item in infoLoader.content.value" :key="item.id"
  59. backgroundColor="background.tertiary"
  60. radius="radius.md"
  61. :padding="[20, 30]"
  62. gap="gap.lg"
  63. align="center"
  64. >
  65. <Avatar
  66. :url="item.head"
  67. defaultAvatar="https://xy.wenlvti.net/app_static/images/village/PlaceholderVolunteer.png"
  68. :size="80"
  69. radius="50%"
  70. />
  71. <Text :text="item.content" fontConfig="contentText" :innerStyle="{ flex: 1 }" />
  72. <BackgroundBox
  73. backgroundImage="https://xy.wenlvti.net/app_static/images/village/TagNormal.png"
  74. :backgroundCutBorder="[10, 10, 10, 10]"
  75. :backgroundCutBorderSize="[10, 10, 10, 10]"
  76. :padding="[15, 30]"
  77. >
  78. <Text :text="item.levelText" fontConfig="contentText" />
  79. </BackgroundBox>
  80. </FlexRow>
  81. </FlexCol>
  82. </SimplePageContentLoader>
  83. <HomeTitle title="乡源赐福" />
  84. <FlexRow wrap>
  85. <Touchable
  86. v-for="(item, index) in blessingInfoLoader.content.value"
  87. :key="item.id"
  88. center
  89. flexBasis="30%"
  90. gap="gap.sm"
  91. direction="column"
  92. :margin="[10,0,0,0]"
  93. @click="handleBuyBless(item)"
  94. >
  95. <BackgroundBox
  96. backgroundImage="https://xy.wenlvti.net/app_static/images/village/ImageBlessingCount.png"
  97. backgroundPosition="center"
  98. :padding="[10, 20]"
  99. >
  100. <Text :text="index + 1" color="white" />
  101. </BackgroundBox>
  102. <Image :src="item.image" :width="210" :height="250" radius="radius.md" mode="aspectFill" />
  103. <BackgroundBox
  104. backgroundImage="https://xy.wenlvti.net/app_static/images/village/ImageBlessingBar.png"
  105. :padding="10"
  106. :width="210"
  107. >
  108. <Text textAlign="center" :text="item.name" fontConfig="contentText" fontFamily="SongtiSCBlack" color="white" />
  109. </BackgroundBox>
  110. </Touchable>
  111. </FlexRow>
  112. </FlexCol>
  113. </FlexCol>
  114. <BlessBuyDialog ref="blessBuyDialogRef" :currentBless="currentBless" />
  115. </template>
  116. <script setup lang="ts">
  117. import { ref, watch } from 'vue';
  118. import { useVillageStore } from '@/store/village';
  119. import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
  120. import HomeTitle from '@/common/components/parts/HomeTitle.vue';
  121. import Text from '@/components/basic/Text.vue';
  122. import FlexCol from '@/components/layout/FlexCol.vue';
  123. import VillageTree from '../components/VillageTree.vue';
  124. import FlexRow from '@/components/layout/FlexRow.vue';
  125. import Icon from '@/components/basic/Icon.vue';
  126. import Touchable from '@/components/feedback/Touchable.vue';
  127. import Image from '@/components/basic/Image.vue';
  128. import Height from '@/components/layout/space/Height.vue';
  129. import Avatar from '@/components/display/Avatar.vue';
  130. import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
  131. import Progress from '@/components/display/Progress.vue';
  132. import TreeApi, { type BlessPackageItem, type GrowthLogFeedItem } from '@/api/light/TreeApi';
  133. import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
  134. import BlessBuyDialog from '../dialogs/BlessBuyDialog.vue';
  135. const GROWTH_FEED_COUNT = 6;
  136. const DEFAULT_AVATAR = 'https://xy.wenlvti.net/app_static/images/village/PlaceholderVolunteer.png';
  137. const villageStore = useVillageStore();
  138. const blessBuyDialogRef = ref<InstanceType<typeof BlessBuyDialog>>();
  139. const currentBless = ref<BlessPackageItem>();
  140. const infoLoader = useSimpleDataLoader(async () => {
  141. const villageId = villageStore.currentVillage?.id;
  142. if (!villageId) return [];
  143. function mapGrowthFeedToInfoItem(feed: GrowthLogFeedItem) {
  144. const { item, logType } = feed;
  145. let content = item.remark?.trim() || '';
  146. let levelText = '';
  147. if (logType === 'task') {
  148. levelText = item.taskName || '任务';
  149. if (!content) {
  150. content = item.taskName ? `完成任务「${item.taskName}」` : '任务动态';
  151. }
  152. } else if (logType === 'fruit') {
  153. levelText = item.typeText || item.type || '乡源果';
  154. if (!content) {
  155. const delta = item.fruit > 0 ? `+${item.fruit}` : `${item.fruit}`;
  156. content = `${levelText} ${delta} 乡源果`;
  157. }
  158. } else {
  159. levelText = item.typeText || item.type || '乡源光';
  160. if (!content) {
  161. const delta = item.light > 0 ? `+${item.light}` : `${item.light}`;
  162. content = `${levelText} ${delta} 乡源光`;
  163. }
  164. }
  165. return {
  166. id: `${logType}-${item.id}`,
  167. head: DEFAULT_AVATAR,
  168. content,
  169. levelText,
  170. };
  171. }
  172. const { list } = await TreeApi.getRandomGrowthLogFeed(GROWTH_FEED_COUNT, { villageId });
  173. return list.map(mapGrowthFeedToInfoItem);
  174. });
  175. watch(() => villageStore.currentVillage?.id, () => {
  176. infoLoader.reload();
  177. });
  178. const blessingInfoLoader = useSimpleDataLoader(async () => {
  179. const res = await TreeApi.getBlessList({ page: 1, pageSize: 18 });
  180. return res.list;
  181. });
  182. function handleBuyBless(bless: BlessPackageItem) {
  183. currentBless.value = bless;
  184. blessBuyDialogRef.value?.show();
  185. }
  186. function handleGoBless() {
  187. uni.pageScrollTo({
  188. scrollTop: 1000,
  189. duration: 300,
  190. });
  191. }
  192. </script>