diff --git a/frontend/pages/profile/hisWorks.vue b/frontend/pages/profile/hisWorks.vue index f6a3bd4..7d3018c 100644 --- a/frontend/pages/profile/hisWorks.vue +++ b/frontend/pages/profile/hisWorks.vue @@ -31,7 +31,7 @@ :skip-built-in-touch="true" :shimmer-mid-opacity="0.16" @simulate="(x, y) => onLenticularSimulate(exhibitionAtSlot[0].id, x, y)" /> + :src="exhibitionAtSlot[0].realCoverUrl || exhibitionAtSlot[0].cover_url || '/static/nft/placeholder.png'" mode="aspectFill"> @@ -67,7 +67,7 @@ :skip-built-in-touch="true" :shimmer-mid-opacity="0.16" @simulate="(x, y) => onLenticularSimulate(exhibitionAtSlot[1].id, x, y)" /> + :src="exhibitionAtSlot[1].realCoverUrl || exhibitionAtSlot[1].cover_url || '/static/nft/placeholder.png'" mode="aspectFill"> @@ -123,7 +123,7 @@ :transforms="getLikedLenticularTransforms(item.id)" :gyro-source="gyroSourceLabel" :skip-built-in-touch="true" :shimmer-mid-opacity="0.16" @simulate="(x, y) => onLikedLenticularSimulate(item.id, x, y)" /> - @@ -164,6 +164,7 @@ import { ref, onMounted, onUnmounted, computed } from 'vue'; import { onLoad } from '@dcloudio/uni-app'; import { getUserGalleriesApi, getUserLikedAssetsApi, getAssetMaterialsApi } from '@/utils/api.js'; +import { getAssetCoverRealUrl } from '@/utils/assetImageHelper.js'; import LenticularCard from '@/components/lenticular/LenticularCard.vue'; import { useLenticularCraftTiltPreview } from '@/composables/useLenticularCraftTiltPreview.js'; import { buildLenticularLayers, buildLenticularLayersTwo } from '@/utils/castloveMintForm.js'; @@ -549,7 +550,7 @@ const loadExhibitedAssets = async () => { try { const res = await getUserGalleriesApi(userId.value); if (res.data && res.data.slots) { - exhibitionWorks.value = res.data.slots + const mapped = res.data.slots .filter(slot => slot.status === 'OCCUPIED' && slot.asset) .map(slot => ({ id: slot.asset.asset_id, @@ -559,8 +560,12 @@ const loadExhibitedAssets = async () => { name: slot.asset.name, slot_index: slot.slot_index ?? 0, is_lenticular: slot.asset.is_lenticular ?? false, - })) - .sort((a, b) => (a.slot_index ?? 0) - (b.slot_index ?? 0)); + })); + // 把后端返回的相对 cover_url 解析成可访问的 URL(OSS 预签名 / 完整URL / 静态资源) + for (const item of mapped) { + item.realCoverUrl = await getAssetCoverRealUrl(item.cover_url); + } + exhibitionWorks.value = mapped.sort((a, b) => (a.slot_index ?? 0) - (b.slot_index ?? 0)); // 为每个光栅卡加载层级数据 for (const item of exhibitionWorks.value) { @@ -591,7 +596,7 @@ const loadLikedAssets = async () => { res = await getUserLikedAssetsApi(userId.value, 1, 20); } if (res.data && res.data.items) { - likedWorks.value = res.data.items.map((item, index) => ({ + const mapped = res.data.items.map((item, index) => ({ id: item.asset_id, cover_url: item.cover_url, like_count: item.like_count, @@ -602,6 +607,11 @@ const loadLikedAssets = async () => { score: item.like_count, reward: Math.floor(item.earnings || 0), })); + // 把后端返回的相对 cover_url 解析成可访问的 URL + for (const item of mapped) { + item.realCoverUrl = await getAssetCoverRealUrl(item.cover_url); + } + likedWorks.value = mapped; // 为每个光栅卡加载层级数据 for (const item of likedWorks.value) { @@ -908,6 +918,7 @@ onUnmounted(() => { z-index: 9; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.4); opacity: 0.95; + /* display: none; */ } /* 倒计时文字 */