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-header">
|
||||||
<view class="c-user-info">
|
<view class="c-user-info">
|
||||||
<text class="c-name">{{ comment.name }}</text>
|
<text class="c-name">{{ comment.name }}</text>
|
||||||
|
<!-- 用户态度徽章 -->
|
||||||
|
<ActionBadge v-if="comment.userAction" :action="comment.userAction" />
|
||||||
<view class="c-badge" v-if="comment.badge">
|
<view class="c-badge" v-if="comment.badge">
|
||||||
<text class="b-icon">{{ comment.badgeIcon }}</text>
|
<text class="b-icon">{{ comment.badgeIcon }}</text>
|
||||||
<text class="b-text">{{ comment.badge }}</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 { onLoad, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
|
||||||
import AttitudePanel from "@/components/AttitudePanel/AttitudePanel.vue";
|
import AttitudePanel from "@/components/AttitudePanel/AttitudePanel.vue";
|
||||||
import SuccessPopup from "@/components/SuccessPopup/SuccessPopup.vue";
|
import SuccessPopup from "@/components/SuccessPopup/SuccessPopup.vue";
|
||||||
|
import ActionBadge from "@/components/ActionBadge/ActionBadge.vue";
|
||||||
import { FILE_BASE_URL } from "@/utils/constants";
|
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 statusBarHeight = ref(getStatusBarHeight() || 44);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const hasMore = ref(true);
|
const hasMore = ref(true);
|
||||||
|
const currentPage = ref(1);
|
||||||
const currentAction = ref('');
|
const currentAction = ref('');
|
||||||
const successPopupRef = ref(null);
|
const successPopupRef = ref(null);
|
||||||
|
|
||||||
@@ -201,7 +208,10 @@ const handleSendComment = async (payload) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 刷新页面数据以获取最新评论
|
// 刷新页面数据以获取最新评论
|
||||||
getDetailData();
|
currentPage.value = 1;
|
||||||
|
hasMore.value = true;
|
||||||
|
comments.value = [];
|
||||||
|
getCommentsData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
uni.showToast({
|
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 () => {
|
const getDetailData = async () => {
|
||||||
if (!itemId.value) return;
|
if (!itemId.value) return;
|
||||||
try {
|
try {
|
||||||
@@ -235,11 +280,15 @@ const getDetailData = async () => {
|
|||||||
currentAction.value = data.userAction;
|
currentAction.value = data.userAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有评论数据,更新评论
|
// 如果有评论数据,更新评论 (兼容老接口一并返回的情况,但推荐通过 getCommentsData 单独获取)
|
||||||
if (data.comments && Array.isArray(data.comments)) {
|
if (data.comments && Array.isArray(data.comments) && currentPage.value === 1) {
|
||||||
comments.value = data.comments;
|
// 如果后端在详情里依然返回了一部分评论
|
||||||
} else {
|
// comments.value = data.comments;
|
||||||
comments.value = [];
|
}
|
||||||
|
|
||||||
|
// 拉取真实的评论列表
|
||||||
|
if (currentPage.value === 1) {
|
||||||
|
getCommentsData();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取详情失败:', error);
|
console.error('获取详情失败:', error);
|
||||||
@@ -261,12 +310,16 @@ onLoad((options) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onPullDownRefresh(() => {
|
onPullDownRefresh(() => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMore.value = true;
|
||||||
|
comments.value = [];
|
||||||
getDetailData();
|
getDetailData();
|
||||||
});
|
});
|
||||||
|
|
||||||
onReachBottom(() => {
|
onReachBottom(() => {
|
||||||
if (!hasMore.value || loading.value) return;
|
if (!hasMore.value || loading.value) return;
|
||||||
// TODO: 评论分页加载逻辑
|
currentPage.value += 1;
|
||||||
|
getCommentsData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user