fix(listings): 首页卡片统一接入 AuthImage 解决私有对象存储鉴权加载失败问题
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { Listing } from '@/features/listings'
|
||||
import AuthImage from '@/shared/components/business/AuthImage.vue'
|
||||
import { formatCent, formatMoney } from '@/shared/utils/money'
|
||||
import {
|
||||
formatEstimatedRentalDuration,
|
||||
@@ -103,12 +104,13 @@ function formatStatNumber(value: number) {
|
||||
<RouterLink class="hfb-listing-card" :to="`/listings/${listing.id}`">
|
||||
<!-- 左侧:4:3 黄金比例单张封面(展示纯币截图) -->
|
||||
<div class="card-media">
|
||||
<img
|
||||
<AuthImage
|
||||
v-if="coverURL"
|
||||
:src="coverURL"
|
||||
:source="coverURL"
|
||||
:alt="getListingTitle(listing)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
image-class="media-img"
|
||||
fallback-class="media-fallback"
|
||||
fit="cover"
|
||||
/>
|
||||
<div v-else class="media-empty">HFB</div>
|
||||
|
||||
@@ -297,6 +299,7 @@ function formatStatNumber(value: number) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-media :deep(img),
|
||||
.card-media img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -305,10 +308,25 @@ function formatStatNumber(value: number) {
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.hfb-listing-card:hover .card-media :deep(img),
|
||||
.hfb-listing-card:hover .card-media img {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.card-media :deep(.auth-image-fallback) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: #f1f5f9;
|
||||
color: #94a3b8;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.media-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
useListingCollections,
|
||||
type ListingCollectionItem,
|
||||
} from '@/features/listings/composables/useListingCollections'
|
||||
import AuthImage from '@/shared/components/business/AuthImage.vue'
|
||||
import { formatCent, formatMoney } from '@/shared/utils/money'
|
||||
import {
|
||||
formatHafCoinM,
|
||||
@@ -16,6 +17,7 @@ import {
|
||||
getCoinWan,
|
||||
getListingDisplayPrice,
|
||||
getListingTitle,
|
||||
getCoinScreenshotURL,
|
||||
} from '@/shared/utils/listingDisplay'
|
||||
|
||||
const route = useRoute()
|
||||
@@ -136,10 +138,11 @@ function timeText(item: ListingCollectionItem) {
|
||||
<section v-else class="mobile-list">
|
||||
<article v-for="item in activeItems" :key="item.listing.id" class="mobile-card">
|
||||
<RouterLink :to="detailPath(item)" class="mobile-card-main">
|
||||
<img
|
||||
v-if="item.listing.cover_url || item.listing.screenshot_urls?.[0]"
|
||||
:src="item.listing.cover_url || item.listing.screenshot_urls?.[0]"
|
||||
<AuthImage
|
||||
v-if="getCoinScreenshotURL(item.listing)"
|
||||
:source="getCoinScreenshotURL(item.listing)"
|
||||
:alt="getListingTitle(item.listing)"
|
||||
fit="cover"
|
||||
/>
|
||||
<div v-else class="mobile-cover-empty">HFB</div>
|
||||
<div class="mobile-info">
|
||||
|
||||
@@ -728,6 +728,20 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mobile-card-media .auth-image-fallback {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: #f1f5f9;
|
||||
color: #94a3b8;
|
||||
font-size: 11px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.media-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1046,12 +1046,13 @@ syncMobileHomeQuery()
|
||||
<div class="mobile-card-body">
|
||||
<!-- 左侧封面 -->
|
||||
<div class="mobile-card-media">
|
||||
<img
|
||||
<AuthImage
|
||||
v-if="getCoinScreenshotURL(item)"
|
||||
:src="getCoinScreenshotURL(item)"
|
||||
:source="getCoinScreenshotURL(item)"
|
||||
:alt="formatListingCode(item)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
image-class="mobile-media-img"
|
||||
fallback-class="mobile-media-fallback"
|
||||
fit="cover"
|
||||
/>
|
||||
<div v-else class="media-empty">HFB</div>
|
||||
|
||||
|
||||
@@ -47,7 +47,16 @@ export async function fetchAdminFileBlob(key: string) {
|
||||
}
|
||||
|
||||
export async function fetchFileBlobByURL(fileURL: string) {
|
||||
const apiPath = fileURL.startsWith('/api/') ? fileURL.slice(4) : fileURL
|
||||
let apiPath = fileURL
|
||||
try {
|
||||
const parsed = new URL(fileURL, window.location.origin)
|
||||
apiPath = parsed.pathname + parsed.search
|
||||
} catch {
|
||||
// keep as is
|
||||
}
|
||||
if (apiPath.startsWith('/api/')) {
|
||||
apiPath = apiPath.slice(4)
|
||||
}
|
||||
const { data } = await apiClient.get<Blob>(apiPath, {
|
||||
responseType: 'blob',
|
||||
})
|
||||
|
||||
@@ -416,10 +416,22 @@ export function isTopTierInsurance(value: string | undefined | null): boolean {
|
||||
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
|
||||
const groupRecord = groups as Record<string, unknown>
|
||||
const orderedKeys = ['coin', 'tencentSecurity', 'skin', 'gameId', 'totalAsset']
|
||||
for (const key of orderedKeys) {
|
||||
const urls = groupRecord[key]
|
||||
if (Array.isArray(urls)) {
|
||||
const found = urls.find(url => typeof url === 'string' && Boolean(url))
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(groupRecord)) {
|
||||
if (orderedKeys.includes(key)) continue
|
||||
const urls = groupRecord[key]
|
||||
if (Array.isArray(urls)) {
|
||||
const found = urls.find(url => typeof url === 'string' && Boolean(url))
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
}
|
||||
return item.cover_url || item.screenshot_urls?.[0] || ''
|
||||
|
||||
Reference in New Issue
Block a user