fix: rating
This commit is contained in:
96
components/ActionBadge/ActionBadge.vue
Normal file
96
components/ActionBadge/ActionBadge.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<view class="action-badge" :class="badgeClass" v-if="action">
|
||||
<text class="badge-icon">{{ badgeIcon }}</text>
|
||||
<text class="badge-text">{{ action }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
const badgeClass = computed(() => {
|
||||
switch (props.action) {
|
||||
case '夯': return 'badge-god';
|
||||
case '顶级': return 'badge-good';
|
||||
case '人上人': return 'badge-ok';
|
||||
case 'NPC': return 'badge-bad';
|
||||
case '拉': return 'badge-terrible';
|
||||
default: return 'badge-default';
|
||||
}
|
||||
});
|
||||
|
||||
const badgeIcon = computed(() => {
|
||||
switch (props.action) {
|
||||
case '夯': return '👑';
|
||||
case '顶级': return '🔥';
|
||||
case '人上人': return '🙂';
|
||||
case 'NPC': return '😐';
|
||||
case '拉': return '👎';
|
||||
default: return '';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.action-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: bold;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.badge-icon {
|
||||
margin-right: 6rpx;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
/* 夯 - 金色/黄色 */
|
||||
.badge-god {
|
||||
background: linear-gradient(135deg, #fff8e1, #ffe082);
|
||||
color: #b07d00;
|
||||
border: 1rpx solid #ffecb3;
|
||||
}
|
||||
|
||||
/* 顶级 - 红色/橙色 */
|
||||
.badge-good {
|
||||
background: linear-gradient(135deg, #ffebee, #ffcdd2);
|
||||
color: #c62828;
|
||||
border: 1rpx solid #ffcdd2;
|
||||
}
|
||||
|
||||
/* 人上人 - 蓝色/绿色 */
|
||||
.badge-ok {
|
||||
background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
|
||||
color: #2e7d32;
|
||||
border: 1rpx solid #c8e6c9;
|
||||
}
|
||||
|
||||
/* NPC - 灰色 */
|
||||
.badge-bad {
|
||||
background: linear-gradient(135deg, #f5f5f5, #e0e0e0);
|
||||
color: #616161;
|
||||
border: 1rpx solid #e0e0e0;
|
||||
}
|
||||
|
||||
/* 拉 - 深灰/暗红 */
|
||||
.badge-terrible {
|
||||
background: linear-gradient(135deg, #eceff1, #cfd8dc);
|
||||
color: #455a64;
|
||||
border: 1rpx solid #cfd8dc;
|
||||
}
|
||||
|
||||
.badge-default {
|
||||
background-color: #f5f6fa;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
@@ -93,6 +93,8 @@
|
||||
<view class="c-header">
|
||||
<view class="c-user-info">
|
||||
<text class="c-name">{{ comment.name }}</text>
|
||||
<!-- 用户态度徽章 -->
|
||||
<ActionBadge v-if="comment.userAction" :action="comment.userAction" />
|
||||
<view class="c-badge" v-if="comment.badge">
|
||||
<text class="b-icon">{{ comment.badgeIcon }}</text>
|
||||
<text class="b-text">{{ comment.badge }}</text>
|
||||
@@ -127,12 +129,17 @@ import { getStatusBarHeight } from "@/utils/system";
|
||||
import { onLoad, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
|
||||
import AttitudePanel from "@/components/AttitudePanel/AttitudePanel.vue";
|
||||
import SuccessPopup from "@/components/SuccessPopup/SuccessPopup.vue";
|
||||
import ActionBadge from "@/components/ActionBadge/ActionBadge.vue";
|
||||
import { FILE_BASE_URL } from "@/utils/constants";
|
||||
import { fetchTopicRatingItems, topicItemScore, topicItemComment } from "@/api/topicItem";
|
||||
import { fetchTopicRatingItems, topicItemScore, topicItemComment, topicItemCommentList } from "@/api/topicItem";
|
||||
import { formatDate } from "@/utils/date";
|
||||
|
||||
|
||||
|
||||
const statusBarHeight = ref(getStatusBarHeight() || 44);
|
||||
const loading = ref(false);
|
||||
const hasMore = ref(true);
|
||||
const currentPage = ref(1);
|
||||
const currentAction = ref('');
|
||||
const successPopupRef = ref(null);
|
||||
|
||||
@@ -201,7 +208,10 @@ const handleSendComment = async (payload) => {
|
||||
}
|
||||
|
||||
// 刷新页面数据以获取最新评论
|
||||
getDetailData();
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
comments.value = [];
|
||||
getCommentsData();
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
@@ -211,6 +221,41 @@ const handleSendComment = async (payload) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getCommentsData = async () => {
|
||||
if (!detailData.value.topicId || !itemId.value || loading.value) return;
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await topicItemCommentList(detailData.value.topicId, itemId.value, currentPage.value);
|
||||
const list = res?.list || [];
|
||||
|
||||
const formattedList = list.map(item => ({
|
||||
id: item.id,
|
||||
name: item.user?.nickname || '匿名用户',
|
||||
avatar: item.user?.avatar ? item.user.avatar : 'https://api.dicebear.com/7.x/avataaars/svg?seed=fallback',
|
||||
time: formatDate(item.createdAt) || '刚刚', // 如果后端返回了时间字段可以替换
|
||||
content: item.content,
|
||||
likes: item.likeCount || 0,
|
||||
badge: '', // 预留徽章字段
|
||||
badgeIcon: '',
|
||||
userAction: item.userAction || "" // 夯/顶级/人上人/NPC/拉
|
||||
}));
|
||||
|
||||
if (currentPage.value === 1) {
|
||||
comments.value = formattedList;
|
||||
} else {
|
||||
comments.value = [...comments.value, ...formattedList];
|
||||
}
|
||||
|
||||
// 假设每页10条,如果返回的少于10条则没有更多了
|
||||
hasMore.value = list.length >= 10;
|
||||
} catch (error) {
|
||||
console.error('获取评论列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const getDetailData = async () => {
|
||||
if (!itemId.value) return;
|
||||
try {
|
||||
@@ -235,11 +280,15 @@ const getDetailData = async () => {
|
||||
currentAction.value = data.userAction;
|
||||
}
|
||||
|
||||
// 如果有评论数据,更新评论
|
||||
if (data.comments && Array.isArray(data.comments)) {
|
||||
comments.value = data.comments;
|
||||
} else {
|
||||
comments.value = [];
|
||||
// 如果有评论数据,更新评论 (兼容老接口一并返回的情况,但推荐通过 getCommentsData 单独获取)
|
||||
if (data.comments && Array.isArray(data.comments) && currentPage.value === 1) {
|
||||
// 如果后端在详情里依然返回了一部分评论
|
||||
// comments.value = data.comments;
|
||||
}
|
||||
|
||||
// 拉取真实的评论列表
|
||||
if (currentPage.value === 1) {
|
||||
getCommentsData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取详情失败:', error);
|
||||
@@ -261,12 +310,16 @@ onLoad((options) => {
|
||||
});
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
comments.value = [];
|
||||
getDetailData();
|
||||
});
|
||||
|
||||
onReachBottom(() => {
|
||||
if (!hasMore.value || loading.value) return;
|
||||
// TODO: 评论分页加载逻辑
|
||||
currentPage.value += 1;
|
||||
getCommentsData();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user