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 # HBuilderX「运行」时自动加载;CLI 用 --mode development
# VITE_API_BASE_URL=http://192.168.110.60:8080 VITE_API_BASE_URL=http://192.168.110.60:8080
VITE_API_BASE_URL=https://api.topfans.online # VITE_API_BASE_URL=https://api.topfans.online
# WebSocket 地址:如与 API 同源可省略(自动从 VITE_API_BASE_URL 推导 http→ws、https→wss # WebSocket 地址:如与 API 同源可省略(自动从 VITE_API_BASE_URL 推导 http→ws、https→wss
# 独立部署时直接覆盖例如ws://192.168.110.60:8081 # 独立部署时直接覆盖例如ws://192.168.110.60:8081
VITE_WS_BASE_URL=ws://192.168.110.60:8080 VITE_WS_BASE_URL=ws://192.168.110.60:8080

View File

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

View File

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