perf(listings): 首页仅展示单张纯币截图,去除悬停轮播以降低OSS并发请求
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { Listing } from '@/features/listings'
|
||||
import { formatCent, formatMoney } from '@/shared/utils/money'
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
formatHafCoinM,
|
||||
readAssetString,
|
||||
isTopTierInsurance,
|
||||
getCoinScreenshotURL,
|
||||
type ListingDisplayResource,
|
||||
} from '@/shared/utils/listingDisplay'
|
||||
|
||||
@@ -31,37 +32,8 @@ interface Props {
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// 多图悬浮轮播(Hover Carousel)
|
||||
const activeImageIndex = ref(0)
|
||||
const screenshotList = computed(() => {
|
||||
const urls = props.listing.screenshot_urls
|
||||
if (Array.isArray(urls) && urls.length > 0) {
|
||||
return urls.filter(Boolean)
|
||||
}
|
||||
if (props.listing.cover_url) {
|
||||
return [props.listing.cover_url]
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
const activeCoverURL = computed(() => {
|
||||
if (screenshotList.value.length === 0) return ''
|
||||
return screenshotList.value[activeImageIndex.value] || screenshotList.value[0] || ''
|
||||
})
|
||||
|
||||
function handleCoverMouseMove(e: MouseEvent) {
|
||||
const total = screenshotList.value.length
|
||||
if (total <= 1) return
|
||||
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()
|
||||
const offsetX = Math.max(0, Math.min(e.clientX - rect.left, rect.width))
|
||||
const ratio = offsetX / rect.width
|
||||
const nextIdx = Math.min(total - 1, Math.floor(ratio * total))
|
||||
activeImageIndex.value = nextIdx
|
||||
}
|
||||
|
||||
function handleCoverMouseLeave() {
|
||||
activeImageIndex.value = 0
|
||||
}
|
||||
// 封面图片:仅展示纯币截图单张,避免 OSS 爆发高频请求错误
|
||||
const coverURL = computed(() => getCoinScreenshotURL(props.listing))
|
||||
|
||||
// 基础元信息
|
||||
const listingCode = computed(() => formatListingCode(props.listing))
|
||||
@@ -129,11 +101,11 @@ function formatStatNumber(value: number) {
|
||||
|
||||
<template>
|
||||
<RouterLink class="hfb-listing-card" :to="`/listings/${listing.id}`">
|
||||
<!-- 左侧:4:3 黄金比例封面 + 悬浮多图轮播 -->
|
||||
<div class="card-media" @mousemove="handleCoverMouseMove" @mouseleave="handleCoverMouseLeave">
|
||||
<!-- 左侧:4:3 黄金比例单张封面(展示纯币截图) -->
|
||||
<div class="card-media">
|
||||
<img
|
||||
v-if="activeCoverURL"
|
||||
:src="activeCoverURL"
|
||||
v-if="coverURL"
|
||||
:src="coverURL"
|
||||
:alt="getListingTitle(listing)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
@@ -148,17 +120,6 @@ function formatStatNumber(value: number) {
|
||||
|
||||
<!-- 左下角黑金比例浮层 -->
|
||||
<div v-if="ratioValue > 0" class="media-ratio">比例 1:{{ ratioValue.toFixed(1) }}</div>
|
||||
|
||||
<!-- 多图小圆点指示器 -->
|
||||
<div v-if="screenshotList.length > 1" class="media-indicators">
|
||||
<span
|
||||
v-for="(_, index) in screenshotList"
|
||||
:key="index"
|
||||
class="indicator-dot"
|
||||
:class="{ active: index === activeImageIndex }"
|
||||
@mouseenter.stop="activeImageIndex = index"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间:双栏结构化信息区(左基础指标 + 右高光装备物资展台) -->
|
||||
|
||||
@@ -53,6 +53,7 @@ import {
|
||||
hasAcceleratedSaleRatio,
|
||||
hasGiftResources,
|
||||
isTopTierInsurance,
|
||||
getCoinScreenshotURL,
|
||||
getCoinWan,
|
||||
formatHafCoinM,
|
||||
readAssetString,
|
||||
@@ -1046,8 +1047,8 @@ syncMobileHomeQuery()
|
||||
<!-- 左侧封面 -->
|
||||
<div class="mobile-card-media">
|
||||
<img
|
||||
v-if="item.cover_url || item.screenshot_urls?.[0]"
|
||||
:src="item.cover_url || item.screenshot_urls?.[0]"
|
||||
v-if="getCoinScreenshotURL(item)"
|
||||
:src="getCoinScreenshotURL(item)"
|
||||
:alt="formatListingCode(item)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
|
||||
@@ -409,3 +409,18 @@ export function isTopTierInsurance(value: string | undefined | null): boolean {
|
||||
s.includes('3*3') || s.includes('3x3') || s.includes('3×3') || s === '9格' || s.includes('9格')
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取账号封面/纯币截图(仅展示一张,优先纯币截图,其次封面图,其次首张截图)
|
||||
*/
|
||||
export function getCoinScreenshotURL(item: Listing): string {
|
||||
const groups = item.asset_summary?.screenshot_groups
|
||||
if (typeof groups === 'object' && groups !== null) {
|
||||
const coinUrls = (groups as Record<string, unknown>)['coin']
|
||||
if (Array.isArray(coinUrls)) {
|
||||
const firstCoin = coinUrls.find(url => typeof url === 'string' && Boolean(url))
|
||||
if (firstCoin) return firstCoin
|
||||
}
|
||||
}
|
||||
return item.cover_url || item.screenshot_urls?.[0] || ''
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user