index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <!-- 使用 type="home" 属性设置首页,其他页面不需要设置,默认为page;推荐使用json5,更强大,且允许注释 -->
  2. <route lang="json5" type="home">
  3. {
  4. layout: 'tabbar',
  5. style: {
  6. navigationStyle: 'custom',
  7. navigationBarTitleText: '首页',
  8. },
  9. }
  10. </route>
  11. <script lang="ts" setup>
  12. import Card from '@/components/card.vue'
  13. import HotActivity from '@/components/hot-activity.vue'
  14. import MomentItem from '@/components/moment-item.vue'
  15. import useRequest from '../../hooks/useRequest'
  16. import Menus from './components/menus.vue'
  17. import { getCircles, getSetIndexConfigs, shareCircle } from '../../core/libs/requests'
  18. import { logo } from '../../core/libs/svgs'
  19. import PageHelper from '@/components/page-helper.vue'
  20. import { ComponentExposed } from 'vue-component-type-helpers'
  21. import { usePermissions } from '../../composables/permissions'
  22. import { storeToRefs } from 'pinia'
  23. import { messages } from '../../core/libs/messages'
  24. import { handleUpvoteClick } from '../../core/libs/actions'
  25. import { useUserStore } from '../../store'
  26. defineOptions({
  27. name: 'Home',
  28. })
  29. const instance = getCurrentInstance()
  30. const userStore = useUserStore()
  31. const { userInfo } = storeToRefs(userStore)
  32. const { isLogined, isDesigner } = usePermissions()
  33. const pageHelperRef = ref<ComponentExposed<typeof PageHelper>>()
  34. const { data: indexConfigsData, run: setIndexConfigsData } = useRequest(
  35. () => getSetIndexConfigs(),
  36. { initialData: { list: [] } },
  37. )
  38. const swiperData = ref<{ data: any; videoContext: UniNamespace.VideoContext; playing: boolean }[]>()
  39. const swiperCurrent = ref(0)
  40. onShow(async () => {
  41. pageHelperRef.value?.refresh()
  42. })
  43. onLoad(async () => {
  44. await setIndexConfigsData()
  45. swiperData.value = indexConfigsData.value.list.map((it) => ({
  46. data: it,
  47. videoContext: uni.createVideoContext(`video-${it.id}`, instance),
  48. playing: false,
  49. }))
  50. })
  51. const toAbout = () => {
  52. uni.navigateTo({ url: '/pages/home/about/index' })
  53. }
  54. const handleSwiperChange = ({ detail: { current } }) => {
  55. swiperCurrent.value = current
  56. }
  57. const handlePlay = () => {
  58. swiperData.value[swiperCurrent.value].videoContext.play()
  59. swiperData.value[swiperCurrent.value].playing = true
  60. }
  61. const handleLike = async (options) => {
  62. await handleUpvoteClick({
  63. ...options,
  64. userId: userInfo.value.userId,
  65. userName: userInfo.value.nickname,
  66. })
  67. pageHelperRef.value?.refresh()
  68. }
  69. onShareAppMessage(async ({ from, target }) => {
  70. const res: Page.CustomShareContent = {}
  71. if (from === 'button') {
  72. await shareCircle(target.id)
  73. res.path = `/pages/home/moment/index?id=${target.id}`
  74. res.imageUrl = target.dataset.options.bannerUrls[0]
  75. res.title = `${target.dataset.options.stylistName}: ${target.dataset.options.circleDesc}`
  76. }
  77. if (from === 'menu') {
  78. res.title = messages.home.shareTitle
  79. }
  80. return res
  81. })
  82. </script>
  83. <template>
  84. <view class="">
  85. <view class="bg-black w-full relative aspect-[1.26/1]">
  86. <swiper @change="handleSwiperChange">
  87. <template
  88. v-for="{
  89. data: { id, coverVideoImage, indexPromotionalVideoImage },
  90. playing,
  91. } of swiperData"
  92. :key="id"
  93. >
  94. <swiper-item>
  95. <div class="w-full h-full relative">
  96. <video
  97. class="w-full h-full"
  98. :id="`video-${id}`"
  99. :src="indexPromotionalVideoImage"
  100. ></video>
  101. <div v-if="!playing" class="absolute left-0 top-0 w-full h-full bg-black">
  102. <wd-img width="100%" height="100%" :src="coverVideoImage" />
  103. </div>
  104. <div
  105. v-if="!playing"
  106. class="w-[375px] h-[90px] bg-gradient-to-t from-black to-black/0 absolute left-0 bottom-0 w-full flex items-center"
  107. >
  108. <view class="mx-7">
  109. <wd-button
  110. plain
  111. custom-class="bg-transparent! border-white! text-white!"
  112. icon="play"
  113. @click="handlePlay"
  114. >
  115. 02:30
  116. </wd-button>
  117. </view>
  118. </div>
  119. </div>
  120. </swiper-item>
  121. </template>
  122. </swiper>
  123. </view>
  124. <view class="bg-[#f6f6f6] relative bottom-4 rounded-t-2xl py-1">
  125. <!-- <ScheduleCard custom-class="my-6 mx-3.5"></ScheduleCard> -->
  126. <menus></menus>
  127. <!-- <view class="my-6 mx-3.5">
  128. <HotActivity></HotActivity>
  129. </view> -->
  130. <view v-if="isDesigner" class="my-6 mx-3.5" @click="toAbout()">
  131. <Card>
  132. <div class="flex items-center gap-2">
  133. <wd-img width="28" height="28" :src="logo"></wd-img>
  134. <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[10.18px]">
  135. 1分钟快速了解筑巢荟
  136. </div>
  137. <div class="flex-1"></div>
  138. <wd-icon name="help-circle" size="22px" custom-class="text-black/60"></wd-icon>
  139. </div>
  140. </Card>
  141. </view>
  142. <view class="mx-3.5 text-5 font-400">设计圈</view>
  143. <view class="mx-3.5">
  144. <PageHelper ref="pageHelperRef" :request="getCircles" :query="{}">
  145. <template #default="{ source }">
  146. <template v-for="it of source.list" :key="it.id">
  147. <view class="my-6">
  148. <MomentItem :options="it" @like="handleLike"></MomentItem>
  149. </view>
  150. </template>
  151. </template>
  152. </PageHelper>
  153. </view>
  154. </view>
  155. </view>
  156. </template>
  157. <style></style>