123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- <!-- 使用 type="home" 属性设置首页,其他页面不需要设置,默认为page;推荐使用json5,更强大,且允许注释 -->
- <route lang="json5" type="home">
- {
- layout: 'tabbar',
- style: {
- navigationStyle: 'custom',
- navigationBarTitleText: '首页',
- },
- }
- </route>
- <script lang="ts" setup>
- import Card from '@/components/card.vue'
- import HotActivity from '@/components/hot-activity.vue'
- import MomentItem from '@/components/moment-item.vue'
- import HomeBanner from './components/home-banner.vue'
- import useRequest from '../../hooks/useRequest'
- import Menus from './components/menus.vue'
- import {
- getActivities,
- getBadges,
- getCertificates,
- getCircles,
- getMyStudyTours,
- getSetIndexConfigs,
- getStudyTours,
- updateHonorPopUp,
- updateSetIndexConfig,
- } from '../../core/libs/requests'
- import { logo } from '../../core/libs/svgs'
- import { ComponentExposed } from 'vue-component-type-helpers'
- import { usePermissions } from '../../composables/permissions'
- import { storeToRefs } from 'pinia'
- import { handleUpvoteClick } from '../../core/libs/actions'
- import { useUserStore } from '../../store'
- import ScheduleCard from './components/schedule-card.vue'
- import dayjs from 'dayjs'
- import { pick, sort } from 'radash'
- import { Activity, StudyTour } from '../../core/libs/models'
- import PageHelperEvo from '@/components/page-helper-evo.vue'
- import { useMessage } from 'wot-design-uni'
- import ShareActionSheet from './components/share-action-sheet.vue'
- import { useShare } from '@/composables/share'
- import { useHonorDialog, HonorDialogType } from './components/honor-dialog/index'
- import { getByDictType } from '../../core/libs/requests'
- import { DictType } from '../../core/libs/models'
- defineOptions({
- name: 'Home',
- })
- useMessage()
- const { show } = useHonorDialog()
- const userStore = useUserStore()
- const { userInfo } = storeToRefs(userStore)
- const { features, isLogined } = usePermissions()
- const { shareAppMessage } = useShare()
- const pageHelperRef = ref<ComponentExposed<typeof PageHelperEvo>>()
- const { data: indexConfigsData, run: setIndexConfigsData } = useRequest(
- () => getSetIndexConfigs(),
- { initialData: { list: [] } },
- )
- const { data: studyTours, run: setStudyTours } = useRequest(() => getMyStudyTours(), {
- initialData: [],
- })
- const swiperData = ref<{ data: any }[]>()
- const swiperCurrent = ref(0)
- const autoplay = ref(true)
- const homeBannerRef = ref<ComponentExposed<typeof HomeBanner>[]>()
- const hotActivities =
- ref<{ type: 'studyTour' | 'activity'; data: StudyTour & Activity; startAt: string | number }[]>()
- const shareActionState = ref(false)
- // const shareRef = ref<Comp>()
- const shareOptions = ref()
- const currentStudyTour = computed(() =>
- studyTours.value.find(
- (it) => dayjs(it.studyStartTime).isBefore(dayjs()) && dayjs(it.studyEndTime).isAfter(dayjs()),
- ),
- )
- const toAbout = () => {
- uni.navigateTo({ url: '/pages-sub/home/about/index' })
- }
- const currentBanner = ref(0)
- const handleSwiperChange = ({ detail: { current, source } }) => {
- // console.log('current', current)
- console.log(current, source, swiperCurrent.value)
- homeBannerRef.value?.[swiperCurrent.value]?.videoContext.pause()
- swiperCurrent.value = current
- currentBanner.value = current
- }
- const handleLike = async (options) => {
- await handleUpvoteClick({
- ...options,
- userId: userInfo.value.userId,
- userName: userInfo.value.nickname,
- })
- await pageHelperRef.value?.refresh()
- }
- const setHotActivities = async () => {
- const res = await Promise.all([
- getStudyTours({ headRecommend: 1 }).then((res) =>
- res.data.list.map((it) => ({ type: 'studyTour', data: it, startAt: it.applyStartTime })),
- ),
- getActivities({ headRecommend: 1 }).then((res) =>
- res.data.list.map((it) => ({ type: 'activity', data: it, startAt: it.applyStartTime })),
- ),
- ])
- hotActivities.value = sort(res.flat(), (it) => it.startAt) as any
- }
- const handlePlay = async (id) => {
- const body = pick(swiperData.value?.find((it) => it.data.id === id).data, ['id', 'status'])
- autoplay.value = false
- await updateSetIndexConfig(body)
- }
- const handleShare = (options: any) => {
- shareOptions.value = options
- shareActionState.value = true
- }
- const dictMemberDesignStyle = ref<[]>()
- const dictCircleSpaceType = ref<[]>()
- const offLoad = (e) => {
- console.log(e)
- }
- const offError = (err) => {
- console.log(err)
- }
- onShow(async () => {
- await pageHelperRef.value?.reload()
- const reqs = [setHotActivities()]
- if (isLogined.value) {
- reqs.push(setStudyTours())
- }
- await Promise.all(reqs)
- if (userInfo.value.level != null) {
- const { data: badgeData } = await getBadges({})
- const { data: certificates } = await getCertificates()
- const badges = Object.values(badgeData)
- .flat()
- .filter((it) => !it.popUp && it.quantity)
- const honors = [
- ...badges.map((it) => ({
- type: HonorDialogType.Badge,
- id: it.id,
- title: it.badgeName,
- content: it.badgeDescription,
- image: it.badgeYesObtainedImage,
- })),
- ...certificates
- .filter((it) => !it.popUp)
- .map((it) => ({
- type: HonorDialogType.Certificate,
- id: it.id,
- title: it.certificateName,
- content: it.certificateDescription,
- image: it.certificateImage,
- })),
- ]
- if (honors.length) {
- const honor = honors[0]
- console.log(honor)
- await show({
- title: honor.title ?? ' ',
- content: honor.content ?? ' ',
- image: honor.image,
- type: honor.type,
- onLoad: async () => {
- await updateHonorPopUp({
- bizId: String(honor.id),
- bizType: honor.type === HonorDialogType.Badge ? '1' : '2',
- })
- },
- })
- }
- }
- })
- onLoad(async () => {
- await Promise.all([setIndexConfigsData()])
- swiperData.value = indexConfigsData.value.list.map((it) => ({
- data: it,
- }))
- let value1 = await getByDictType(DictType.circleSpaceType)
- dictCircleSpaceType.value = value1.data
- let value2 = await getByDictType(DictType.memberDesignStyle)
- dictMemberDesignStyle.value = value2.data
- })
- onHide(() => {
- // autoplay.value = true
- homeBannerRef.value?.[swiperCurrent.value]?.videoContext.pause()
- })
- onShareAppMessage(shareAppMessage)
- // onShareTimeline(async ({from, target}) => {
- // const res: Page.ShareTimelineContent = {}
- // if (from === 'button') {
- // // await shareCircle(target.dataset.options.id)
- // // res.path = `/pages-sub/home/moment/index?id=${target.dataset.options.id}&isShared=true`
- // }
- // return res
- // })
- </script>
- <template>
- <view class="">
- <!-- <view class="official">
- <official-account @load="offLoad" @error="offError"></official-account>
- </view> -->
- <view class="bg-black w-full relative aspect-[1.26/1]">
- <swiper :autoplay="autoplay" @change="handleSwiperChange">
- <template
- v-for="{ data: { id, coverVideoImage, indexPromotionalVideoImage } } of swiperData"
- :key="id"
- >
- <swiper-item>
- <HomeBanner
- ref="homeBannerRef"
- :id="id"
- :url="indexPromotionalVideoImage"
- :cover="coverVideoImage"
- @play="handlePlay"
- @ended="autoplay = true"
- />
- </swiper-item>
- </template>
- </swiper>
- <div class="absolute flex gap-1 dots">
- <template v-for="(it, i) in swiperData" :key="i">
- <div
- class="w-1 h-1 rounded-full"
- :class="`${currentBanner === i ? 'bg-white bg-active' : 'bg-white/40'}`"
- ></div>
- </template>
- </div>
- </view>
- <view class="bg-[#f6f6f6] relative bottom-4 rounded-t-2xl py-1">
- <template v-if="currentStudyTour">
- <ScheduleCard
- custom-class="my-6 mx-3.5"
- :items="currentStudyTour.studyTravelDOList"
- ></ScheduleCard>
- </template>
- <menus></menus>
- <view v-if="hotActivities?.length" class="my-6 mx-3.5">
- <HotActivity :items="hotActivities"></HotActivity>
- </view>
- <view v-if="features.about" class="my-6 mx-3.5" @click="toAbout()">
- <Card>
- <div class="flex items-center gap-2">
- <wd-img width="28" height="28" :src="logo"></wd-img>
- <div class="text-black/90 text-base font-normal font-['PingFang_SC'] leading-[10.18px]">
- 1分钟快速了解筑巢荟
- </div>
- <div class="flex-1"></div>
- <wd-icon name="help-circle" size="22px" custom-class="text-black/60"></wd-icon>
- </div>
- </Card>
- </view>
- <view class="mx-3.5 text-5 font-bold">设计圈</view>
- <view class="mx-3.5">
- <PageHelperEvo ref="pageHelperRef" :request="getCircles" class="">
- <template #default="{ source }">
- <template v-for="it of source.list" :key="it.id">
- <view class="my-3">
- <MomentItem
- :dict="{ spaceType: dictCircleSpaceType, designStyle: dictMemberDesignStyle }"
- :options="it"
- @like="handleLike"
- @share="handleShare"
- ></MomentItem>
- </view>
- </template>
- </template>
- </PageHelperEvo>
- </view>
- </view>
- <ShareActionSheet
- ref="shareRef"
- v-model="shareActionState"
- :options="shareOptions"
- ></ShareActionSheet>
- </view>
- </template>
- <style scoped>
- .dots {
- bottom: 60rpx;
- left: 50%;
- transform: translateX(-50%);
- }
- .bg-active {
- width: 40rpx;
- }
- .official {
- position: fixed;
- top: 100rpx;
- left: 0;
- width: 100%;
- z-index: 9999;
- }
- :deep(.level-circle) {
- top: -10rpx;
- left: -5rpx;
- }
- </style>
|