| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- <template>
- <div class="image-feed-wrap">
- <SlideVertical
- v-model:index="farmIndex"
- class="farm-feed"
- :name="`${slideName}-farm`"
- >
- <SlideItem
- v-for="(farm, farmIdx) in farms"
- :key="farm.id"
- class="feed-item"
- >
- <SlideHorizontal
- v-model:index="imageIndexes[farmIdx]"
- class="image-feed"
- :name="`${slideName}-img-${farm.id}`"
- >
- <SlideItem
- v-for="item in farm.images"
- :key="item.aweme_id"
- class="feed-item"
- >
- <BaseImage :item="item" />
- <GuardImageOverlay :level="farm.level" />
- <GuardInfoBoard :badge-icon="badgeIcon" class="info-board-layer" />
- </SlideItem>
- </SlideHorizontal>
- </SlideItem>
- </SlideVertical>
- <button
- type="button"
- class="nav-btn prev"
- :disabled="currentImageIndex <= 0"
- aria-label="上一张"
- @click="prevImage"
- >
- <Icon icon="eva:arrow-ios-back-fill" />
- </button>
- <button
- type="button"
- class="nav-btn next"
- :disabled="currentImageIndex >= currentFarmImages.length - 1"
- aria-label="下一张"
- @click="nextImage"
- >
- <Icon icon="eva:arrow-ios-forward-fill" />
- </button>
- </div>
- </template>
- <script setup lang="ts">
- import { Icon } from '@iconify/vue'
- import { computed, ref } from 'vue'
- import SlideVertical from '@/components/slide/SlideVertical.vue'
- import SlideHorizontal from '@/components/slide/SlideHorizontal.vue'
- import SlideItem from '@/components/slide/SlideItem.vue'
- import BaseImage from '@/components/image/BaseImage.vue'
- import GuardImageOverlay from './GuardImageOverlay.vue'
- import GuardInfoBoard from './GuardInfoBoard.vue'
- import type { GuardFarm } from '@/mock/homeData'
- const props = defineProps({
- feedId: { type: String, required: true },
- farms: { type: Array as () => GuardFarm[], required: true },
- /** 第四张卡片顶部徽章图,路径由外部传入 */
- badgeIcon: { type: String, default: '' },
- })
- const slideName = computed(() => `guard-feed-${props.feedId}`)
- const farms = computed(() => props.farms)
- const farmIndex = ref(0)
- const imageIndexes = ref(props.farms.map(() => 0))
- const currentFarmImages = computed(() => farms.value[farmIndex.value]?.images ?? [])
- const currentImageIndex = computed(() => imageIndexes.value[farmIndex.value] ?? 0)
- function prevImage() {
- const idx = farmIndex.value
- if (imageIndexes.value[idx] > 0) imageIndexes.value[idx] -= 1
- }
- function nextImage() {
- const idx = farmIndex.value
- const max = (farms.value[idx]?.images.length ?? 1) - 1
- if (imageIndexes.value[idx] < max) imageIndexes.value[idx] += 1
- }
- </script>
- <style scoped lang="less">
- .image-feed-wrap {
- position: relative;
- height: 100%;
- width: 100%;
- }
- .farm-feed,
- .image-feed {
- height: 100%;
- width: 100%;
- background: #000;
- }
- .farm-feed {
- :deep(.feed-item) {
- position: relative;
- height: 100%;
- width: 100%;
- }
- }
- .image-feed {
- :deep(.feed-item) {
- position: relative;
- height: 100%;
- width: 100%;
- }
- }
- .info-board-layer {
- position: absolute;
- bottom: 0;
- z-index: 2;
- pointer-events: none;
- }
- .nav-btn {
- position: absolute;
- top: 50%;
- z-index: 4;
- transform: translateY(-50%);
- width: 40rem;
- height: 40rem;
- border: none;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(0, 0, 0, 0.6);
- color: #fff;
- pointer-events: auto;
- svg {
- font-size: 32rem;
- }
- &.prev {
- left: 12rem;
- }
- &.next {
- right: 12rem;
- }
- &:disabled {
- opacity: 0.5;
- }
- }
- </style>
|