feat:修改已知bug

This commit is contained in:
zerosaturation 2026-06-11 21:07:00 +08:00
parent 542b1bd4f0
commit a1bb302be8
3 changed files with 124 additions and 51 deletions

View File

@ -1,7 +1,7 @@
# 开发环境配置
# HBuilderX「运行」时自动加载;CLI 用 --mode development
# VITE_API_BASE_URL=http://192.168.110.60:8080
VITE_API_BASE_URL=https://api.topfans.online
VITE_API_BASE_URL=http://192.168.110.60:8080
# VITE_API_BASE_URL=https://api.topfans.online
# WebSocket 地址:如与 API 同源可省略(自动从 VITE_API_BASE_URL 推导 http→ws、https→wss
# 独立部署时直接覆盖例如ws://192.168.110.60:8081
VITE_WS_BASE_URL=ws://192.168.110.60:8080

View File

@ -215,7 +215,7 @@
<script setup>
import { ref, computed, onUnmounted } from 'vue';
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app';
import { getAssetDetailApi, getMintOrderDetailApi, likeAssetApi, unlikeAssetApi, getAssetMaterialsApi, getAssetLikersApi } from '@/utils/api.js';
import { getAssetCoverRealUrl } from '@/utils/assetImageHelper.js';
import LikeUsersModal from '@/pages/components/LikeUsersModal.vue';
@ -295,17 +295,20 @@ const isLiked = ref(false);
const likeCount = ref(0);
const liking = ref(false);
//
//
const userAvatarUrl = ref('');
const currentUserId = ref('');
const currentUserNickname = ref('');
//
const loadCurrentUser = () => {
try {
const userStr = uni.getStorageSync('user');
if (userStr) {
const userInfo = JSON.parse(userStr);
if (!userStr) return;
const userInfo = typeof userStr === 'string' ? JSON.parse(userStr) : userStr;
userAvatarUrl.value = userInfo?.avatar_url || '';
}
currentUserId.value = String(userInfo?.uid || userInfo?.user_id || '');
currentUserNickname.value = userInfo?.nickname || '';
} catch (e) {
console.error('解析用户信息失败:', e);
}
@ -325,15 +328,10 @@ const ellipseConfig = [
// API
const likedUsers = ref([]);
//
const loadLikedUsers = async (assetId) => {
try {
likedUsersLoading.value = true;
//
const res = await getAssetLikersApi(assetId, 20, 0);
if (res.code === 200 && res.data?.users) {
//
likedUsers.value = res.data?.users.slice(0, 6).map((user, index) => {
// API 6
const mapLikersToDisplay = (users) => {
if (!Array.isArray(users) || !users.length) return [];
return users.slice(0, 6).map((user, index) => {
const config = ellipseConfig[index] || { ellipseX: 0, ellipseY: 0, size: 1 };
return {
avatar: user.avatar || '/static/sucai/default-avatar.png',
@ -342,13 +340,29 @@ const loadLikedUsers = async (assetId) => {
size: config.size
};
});
//
allLikedUsers.value = res.data?.users.map(user => ({
};
// API
const mapLikersToModal = (users) => {
if (!Array.isArray(users)) return [];
return users.map(user => ({
userId: user.user_id,
nickname: user.nickname || '匿名用户',
avatar: user.avatar || '/static/sucai/default-avatar.png',
liked_at: user.liked_at || 0
}));
};
//
const loadLikedUsers = async (assetId) => {
if (!assetId) return;
try {
likedUsersLoading.value = true;
//
const res = await getAssetLikersApi(assetId, 20, 0);
if (res.code === 200 && res.data?.users) {
likedUsers.value = mapLikersToDisplay(res.data.users);
allLikedUsers.value = mapLikersToModal(res.data.users);
}
} catch (e) {
console.error('加载点赞用户失败:', e);
@ -540,21 +554,16 @@ const copyHash = () => {
//
const loadData = async () => {
console.log('loadData 开始执行');
loading.value = true;
loadError.value = '';
try {
let assetId = assetIdParam.value;
console.log('assetIdParam:', assetIdParam.value, 'orderIdParam:', orderIdParam.value);
if (!assetId && orderIdParam.value) {
console.log('通过 order_id 获取资产信息');
const mintRes = await getMintOrderDetailApi(orderIdParam.value);
console.log('getMintOrderDetailApi 响应:', mintRes);
if (mintRes.code === 200 && mintRes.data?.asset?.asset_id) {
assetId = mintRes.data.asset.asset_id;
console.log('获取到 assetId:', assetId);
} else {
throw new Error('获取铸造订单详情失败');
}
@ -562,9 +571,7 @@ const loadData = async () => {
if (!assetId) throw new Error('藏品信息不完整');
console.log('调用 getAssetDetailApiassetId:', assetId);
const res = await getAssetDetailApi(assetId);
console.log('getAssetDetailApi 响应:', res);
if (res.code === 200 && res.data?.asset) {
const asset = res.data.asset;
assetData.value = asset;
@ -579,12 +586,9 @@ const loadData = async () => {
if (asset.exhibition_expire_at) {
startCountdown();
}
console.log(res.data)
//
console.log('开始加载封面图片:', asset.cover_url);
getAssetCoverRealUrl(asset.cover_url).then(async (url) => {
console.log('封面图片加载成功:', url);
coverUrl.value = url;
if (isLenticularAsset.value) {
// success.vue bindAssetMaterialsApi
@ -593,7 +597,6 @@ const loadData = async () => {
//
try {
const materialsRes = await getAssetMaterialsApi(assetId)
console.log('getAssetMaterialsApi 响应:', materialsRes)
if (materialsRes.code === 200 && materialsRes.data) {
const materialsList = Array.isArray(materialsRes.data) ? materialsRes.data : materialsRes.data.materials || []
// bg main
@ -619,7 +622,6 @@ const loadData = async () => {
console.error('加载封面图片失败:', err);
coverUrl.value = ''; //
});
console.log('loadData 执行成功');
//
loadLikedUsers(assetId);
} else {
@ -630,7 +632,6 @@ const loadData = async () => {
loadError.value = err.message || '加载失败,请重试';
} finally {
loading.value = false;
console.log('loadData 执行完成loading:', loading.value);
}
};
@ -643,6 +644,29 @@ const startCountdown = () => {
}, 1000);
};
//
const prependCurrentUserToLikers = () => {
if (!userAvatarUrl.value) return;
const meAvatar = userAvatarUrl.value;
// 1)
const nextDisplay = [
{ avatar: meAvatar },
...likedUsers.value.filter(u => u.avatar !== meAvatar)
];
likedUsers.value = mapLikersToDisplay(nextDisplay);
// 2)
const meRow = {
userId: currentUserId.value,
nickname: currentUserNickname.value || '我',
avatar: meAvatar,
liked_at: Date.now()
};
allLikedUsers.value = [
meRow,
...allLikedUsers.value.filter(u => u.avatar !== meAvatar)
];
};
//
const handleLike = async () => {
if (liking.value || !assetData.value.asset_id) return;
@ -653,9 +677,15 @@ const handleLike = async () => {
// isLiked.value = false;
// likeCount.value = Math.max(0, likeCount.value - 1);
// } else {
await likeAssetApi(assetData.value.asset_id);
const res = await likeAssetApi(assetData.value.asset_id);
isLiked.value = true;
likeCount.value += 1;
// like_count +1
const serverCount = res?.data?.like_count;
likeCount.value = typeof serverCount === 'number' ? serverCount : likeCount.value + 1;
//
prependCurrentUserToLikers();
// avatar URL
loadLikedUsers(assetData.value.asset_id);
// }
//
uni.$emit('assetLikeChanged', {
@ -669,7 +699,7 @@ const handleLike = async () => {
//
const showMsg = errData || errMsg || '点赞失败';
uni.showToast({ title: showMsg, icon: 'none', duration: 2000 });
console.log('点赞错误:', err);
console.error('点赞失败:', err);
} finally {
liking.value = false;
}
@ -712,12 +742,6 @@ const handleCraftMint = async () => {
const bgImagePath = isCraftLenticular.value
? lenticularLayers.value.find((l) => l.id === 'base')?.src || ''
: undefined;
console.log('[asset-detail] handleCraftMint', {
isCraftLenticular: isCraftLenticular.value,
bgImagePath: bgImagePath,
lenticularLayers: lenticularLayers.value.map(l => ({ id: l.id, src: l.src ? l.src.substring(0, 30) : '' })),
craftFormDataKeys: Object.keys(craftFormData.value || {})
})
craftMinting.value = true;
uni.showLoading({ title: '铸造中…', mask: true });
try {
@ -749,32 +773,71 @@ const handleBack = () => {
}
};
// / WS
let likePollingTimer = null;
const LIKE_POLLING_INTERVAL = 30000; // 20s
//
const startLikePolling = () => {
stopLikePolling();
if (!assetData.value?.asset_id) return;
likePollingTimer = setInterval(() => {
// uni-app H5/App setInterval
// onHide onShow
if (assetData.value?.asset_id) {
loadLikedUsers(assetData.value.asset_id);
}
}, LIKE_POLLING_INTERVAL);
};
const stopLikePolling = () => {
if (likePollingTimer) {
clearInterval(likePollingTimer);
likePollingTimer = null;
}
};
//
const handleAssetLikeChangedExternal = (data) => {
if (!data || String(data.asset_id) !== String(assetData.value?.asset_id)) return;
if (typeof data.like_count === 'number') likeCount.value = data.like_count;
if (typeof data.is_liked === 'boolean') isLiked.value = data.is_liked;
//
if (assetData.value?.asset_id) {
loadLikedUsers(assetData.value.asset_id);
}
};
onLoad((options) => {
console.log('onLoad 触发,参数:', options);
assetIdParam.value = options?.asset_id || '';
orderIdParam.value = options?.order_id || '';
fromParam.value = options?.from || '';
studioKindParam.value = options?.studio_kind || '';
loadCurrentUser();
//
uni.$on('assetLikeChanged', handleAssetLikeChangedExternal);
// craft_confirm loadData
if (fromParam.value === 'craft_confirm') {
console.log('[asset-detail] craft_confirm 模式,加载本地数据');
craftConfirmMode.value = true;
loadCraftConfirm();
}
});
onShow(() => {
console.log('onShow 触发');
const currentKey = `${assetIdParam.value}_${orderIdParam.value}`;
console.log('当前key:', currentKey, '上次key:', lastLoadKey.value);
//
if ((assetIdParam.value || orderIdParam.value) && currentKey !== lastLoadKey.value) {
lastLoadKey.value = currentKey;
loadData();
}
//
if (assetData.value?.asset_id && !craftConfirmMode.value) {
loadLikedUsers(assetData.value.asset_id);
// startLikePolling();
}
});
onHide(() => {
@ -784,11 +847,20 @@ onHide(() => {
if (isLenticularDetail.value) {
stopTiltPreview()
}
stopLikePolling();
});
onUnload(() => {
// /
stopLikePolling();
uni.$off('assetLikeChanged', handleAssetLikeChangedExternal);
});
onUnmounted(() => {
if (countdownTimer) clearInterval(countdownTimer);
stopTiltPreview();
stopLikePolling();
uni.$off('assetLikeChanged', handleAssetLikeChangedExternal);
});
</script>

View File

@ -455,6 +455,7 @@ onUnmounted(() => {
.content-scroll {
flex: 1;
min-height: 0;
border-radius: 12px;
overflow: hidden;
}