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; */
}
/* 倒计时文字 */