|
|
|
|
@@ -37,38 +37,38 @@
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 领奖台 (Top 3) -->
|
|
|
|
|
<view class="podium-section">
|
|
|
|
|
<view class="podium-section" v-if="ratingItems && ratingItems.length >= 3">
|
|
|
|
|
<!-- 第二名 -->
|
|
|
|
|
<view class="podium-item rank-2">
|
|
|
|
|
<view class="avatar-wrap">
|
|
|
|
|
<image class="avatar" :src="topicData.top3[1].avatar" mode="aspectFill" />
|
|
|
|
|
<image class="avatar" :src="FILE_BASE_URL + ratingItems[1].avatarUrl" mode="aspectFill" />
|
|
|
|
|
<text class="rank-badge badge-2">2</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-box box-2">
|
|
|
|
|
<text class="name">{{ topicData.top3[1].name }}</text>
|
|
|
|
|
<text class="score">分数 {{ topicData.top3[1].score }}</text>
|
|
|
|
|
<text class="name">{{ ratingItems[1].name }}</text>
|
|
|
|
|
<text class="score">分数 {{ ratingItems[1].score }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- 第一名 -->
|
|
|
|
|
<view class="podium-item rank-1">
|
|
|
|
|
<view class="avatar-wrap">
|
|
|
|
|
<image class="avatar avatar-1" :src="topicData.top3[0].avatar" mode="aspectFill" />
|
|
|
|
|
<image class="avatar avatar-1" :src="FILE_BASE_URL + ratingItems[0].avatarUrl" mode="aspectFill" />
|
|
|
|
|
<text class="rank-badge badge-1">1</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-box box-1">
|
|
|
|
|
<text class="name name-1">{{ topicData.top3[0].name }}</text>
|
|
|
|
|
<text class="score score-1">分数 {{ topicData.top3[0].score }}</text>
|
|
|
|
|
<text class="name name-1">{{ ratingItems[0].name }}</text>
|
|
|
|
|
<text class="score score-1">分数 {{ ratingItems[0].score }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- 第三名 -->
|
|
|
|
|
<view class="podium-item rank-3">
|
|
|
|
|
<view class="avatar-wrap">
|
|
|
|
|
<image class="avatar" :src="topicData.top3[2].avatar" mode="aspectFill" />
|
|
|
|
|
<image class="avatar" :src="FILE_BASE_URL + ratingItems[2].avatarUrl" mode="aspectFill" />
|
|
|
|
|
<text class="rank-badge badge-3">3</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-box box-3">
|
|
|
|
|
<text class="name">{{ topicData.top3[2].name }}</text>
|
|
|
|
|
<text class="score">分数 {{ topicData.top3[2].score }}</text>
|
|
|
|
|
<text class="name">{{ ratingItems[2].name }}</text>
|
|
|
|
|
<text class="score">分数 {{ ratingItems[2].score }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@@ -82,7 +82,7 @@
|
|
|
|
|
@tap="goToDetail(item.id)"
|
|
|
|
|
>
|
|
|
|
|
<view class="card-header">
|
|
|
|
|
<image class="item-avatar" :src="item.avatar" mode="aspectFill" />
|
|
|
|
|
<image class="item-avatar" :src="FILE_BASE_URL + item.avatarUrl" mode="aspectFill" />
|
|
|
|
|
<text class="item-name">{{ item.name }}</text>
|
|
|
|
|
<view class="rank-tag" v-if="item.rank <= 3">NO.{{ item.rank }}</view>
|
|
|
|
|
<view class="flex-spacer"></view>
|
|
|
|
|
@@ -179,12 +179,16 @@
|
|
|
|
|
import { ref } from 'vue';
|
|
|
|
|
import { getStatusBarHeight } from "@/utils/system";
|
|
|
|
|
import { onPullDownRefresh, onReachBottom, onLoad } from "@dcloudio/uni-app";
|
|
|
|
|
import { fetchTopicDetail, fetchTopicRatingItems } from "@/api/topic";
|
|
|
|
|
import { FILE_BASE_URL } from "@/utils/constants";
|
|
|
|
|
|
|
|
|
|
// 状态栏高度处理
|
|
|
|
|
const statusBarHeight = ref(getStatusBarHeight() || 44);
|
|
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
const hasMore = ref(true);
|
|
|
|
|
const currentPage = ref(1);
|
|
|
|
|
const currentTopicId = ref(null);
|
|
|
|
|
|
|
|
|
|
const goBack = () => {
|
|
|
|
|
uni.navigateBack({
|
|
|
|
|
@@ -192,19 +196,28 @@ const goBack = () => {
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 模拟页面数据
|
|
|
|
|
const topicData = ref({
|
|
|
|
|
title: '你心中的千古一帝',
|
|
|
|
|
heat: '98.2w',
|
|
|
|
|
participants: '23万',
|
|
|
|
|
aiSummary: '当前讨论聚焦于"开疆拓土"与"民生治理"的权重对比。唐太宗凭借高频的"六合一统"评价暂时领跑,而秦始皇的"制度基石"标签正在快速攀升。',
|
|
|
|
|
top3: [
|
|
|
|
|
{ id: 1, name: '李世民', score: '9.8', avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=11' },
|
|
|
|
|
{ id: 2, name: '秦始皇', score: '9.5', avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=12' },
|
|
|
|
|
{ id: 3, name: '康熙', score: '9.2', avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=13' }
|
|
|
|
|
]
|
|
|
|
|
title: '',
|
|
|
|
|
heat: '0',
|
|
|
|
|
participants: '0',
|
|
|
|
|
aiSummary: ''
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const loadDetail = async (topicId) => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await fetchTopicDetail(topicId);
|
|
|
|
|
const data = res?.data || res || {};
|
|
|
|
|
topicData.value = {
|
|
|
|
|
title: data.title || '',
|
|
|
|
|
heat: data.heat || '0',
|
|
|
|
|
participants: data.participants || '0',
|
|
|
|
|
aiSummary: data.aiSummary || '暂无总结'
|
|
|
|
|
};
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("获取主题详情失败:", e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const showAddPopup = ref(false);
|
|
|
|
|
const newItem = ref({
|
|
|
|
|
name: '',
|
|
|
|
|
@@ -254,28 +267,34 @@ const actions = [
|
|
|
|
|
{ label: '封神', value: 'god', emoji: '👑' }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const mockRatingItems = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
rank: 1,
|
|
|
|
|
name: '李世民',
|
|
|
|
|
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=11',
|
|
|
|
|
score: '9.8',
|
|
|
|
|
quote: '六合一统,文治武功,除了儿子不行没毛病。',
|
|
|
|
|
userAction: 'god'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
rank: 2,
|
|
|
|
|
name: '秦始皇',
|
|
|
|
|
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=12',
|
|
|
|
|
score: '9.5',
|
|
|
|
|
quote: '两千年来,我们都还在用他设计的制度版本。',
|
|
|
|
|
userAction: ''
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
const ratingItems = ref([]);
|
|
|
|
|
|
|
|
|
|
const ratingItems = ref([...mockRatingItems]);
|
|
|
|
|
const loadItems = async (topicId, page = 1) => {
|
|
|
|
|
if (page === 1) {
|
|
|
|
|
ratingItems.value = [];
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
const res = await fetchTopicRatingItems(topicId, page);
|
|
|
|
|
const list = res?.data?.records || res?.records || res?.list || [];
|
|
|
|
|
|
|
|
|
|
ratingItems.value = [...ratingItems.value, ...list];
|
|
|
|
|
hasMore.value = list.length >= 10; // 假设 pageSize 是 10
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("获取评分项列表失败:", error);
|
|
|
|
|
hasMore.value = false;
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onLoad((options) => {
|
|
|
|
|
if (options.topicId) {
|
|
|
|
|
currentTopicId.value = options.topicId;
|
|
|
|
|
loadDetail(options.topicId);
|
|
|
|
|
loadItems(options.topicId, 1);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const mockComments = [
|
|
|
|
|
{
|
|
|
|
|
@@ -307,11 +326,18 @@ const goToDetail = (itemId) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 下拉刷新
|
|
|
|
|
onPullDownRefresh(() => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
ratingItems.value = [...mockRatingItems];
|
|
|
|
|
comments.value = [...mockComments];
|
|
|
|
|
onPullDownRefresh(async () => {
|
|
|
|
|
if (currentTopicId.value) {
|
|
|
|
|
currentPage.value = 1;
|
|
|
|
|
hasMore.value = true;
|
|
|
|
|
await Promise.all([
|
|
|
|
|
loadDetail(currentTopicId.value),
|
|
|
|
|
loadItems(currentTopicId.value, currentPage.value)
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
// 模拟评论刷新(此处未接接口,暂时保留原有模拟刷新逻辑,去掉 mockRatingItems 的重置)
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
comments.value = [...mockComments];
|
|
|
|
|
uni.stopPullDownRefresh();
|
|
|
|
|
}, 1000);
|
|
|
|
|
});
|
|
|
|
|
@@ -319,14 +345,15 @@ onPullDownRefresh(() => {
|
|
|
|
|
// 上拉加载更多
|
|
|
|
|
onReachBottom(() => {
|
|
|
|
|
if (!hasMore.value || loading.value) return;
|
|
|
|
|
loading.value = true;
|
|
|
|
|
if (currentTopicId.value) {
|
|
|
|
|
currentPage.value += 1;
|
|
|
|
|
loadItems(currentTopicId.value, currentPage.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 原有的评论模拟加载(根据需要决定是否保留)
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
const moreComments = mockComments.map(c => ({...c, id: c.id + comments.value.length}));
|
|
|
|
|
comments.value.push(...moreComments);
|
|
|
|
|
loading.value = false;
|
|
|
|
|
if (comments.value.length >= 10) {
|
|
|
|
|
hasMore.value = false;
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|