fix: rating
This commit is contained in:
@@ -9,7 +9,7 @@ export const topicItemScore = async (data) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取主题下的评分项
|
// 获取评分项详情
|
||||||
export const fetchTopicRatingItems = async (itemId) => {
|
export const fetchTopicRatingItems = async (itemId) => {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/rating/topic/item/detail/${itemId}`,
|
url: `/api/rating/topic/item/detail/${itemId}`,
|
||||||
|
|||||||
168
components/AttitudePanel/AttitudePanel.vue
Normal file
168
components/AttitudePanel/AttitudePanel.vue
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<template>
|
||||||
|
<view class="attitude-panel card">
|
||||||
|
<text class="section-title">你的态度</text>
|
||||||
|
<view class="action-group">
|
||||||
|
<view
|
||||||
|
class="action-item"
|
||||||
|
v-for="(action, index) in actions"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: currentAction === action.label }"
|
||||||
|
@tap="handleAction(action)"
|
||||||
|
>
|
||||||
|
<view class="emoji-wrap">
|
||||||
|
<text class="emoji">{{ action.emoji }}</text>
|
||||||
|
</view>
|
||||||
|
<text class="action-name">{{ action.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="quick-comment">
|
||||||
|
<input
|
||||||
|
class="comment-input"
|
||||||
|
type="text"
|
||||||
|
v-model="commentText"
|
||||||
|
placeholder="说点什么吧..."
|
||||||
|
placeholder-class="input-placeholder"
|
||||||
|
/>
|
||||||
|
<button class="send-btn" @tap="handleSend">发送</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
initialAction: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['action-change', 'send-comment']);
|
||||||
|
|
||||||
|
const currentAction = ref(props.initialAction);
|
||||||
|
|
||||||
|
// 监听父组件传入的 initialAction 的变化
|
||||||
|
watch(() => props.initialAction, (newVal) => {
|
||||||
|
currentAction.value = newVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
const commentText = ref('');
|
||||||
|
|
||||||
|
const actions = [
|
||||||
|
{ label: '拉', value: 'terrible', emoji: '👎', score: 2, scoreType:1 },
|
||||||
|
{ label: 'NPC', value: 'bad', emoji: '😐', score: 4, scoreType: 2},
|
||||||
|
{ label: '人上人', value: 'ok', emoji: '🙂', score: 6, scoreType: 3},
|
||||||
|
{ label: '顶级', value: 'good', emoji: '🔥', score: 8, scoreType: 4},
|
||||||
|
{ label: '夯', value: 'god', emoji: '👑', score: 10, scoreType: 5 }
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleAction = (action) => {
|
||||||
|
emit('action-change', action);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSend = () => {
|
||||||
|
if (!commentText.value.trim()) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入评论内容',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('send-comment', {
|
||||||
|
action: currentAction.value,
|
||||||
|
content: commentText.value
|
||||||
|
});
|
||||||
|
commentText.value = ''; // 发送后清空
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
display: block;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-wrap {
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
font-size: 56rpx;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-name {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item.active .emoji {
|
||||||
|
filter: grayscale(0%);
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-item.active .action-name {
|
||||||
|
color: #2953ff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-comment {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f0f2f7;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 8rpx 8rpx 8rpx 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-input {
|
||||||
|
flex: 1;
|
||||||
|
height: 72rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-placeholder {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-btn {
|
||||||
|
background-color: #4d44f1;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 26rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 0 40rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
line-height: 64rpx;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-btn::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -27,7 +27,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="hero-meta">
|
<view class="hero-meta">
|
||||||
<text class="meta-rank">🥇 No.1</text>
|
<text class="meta-rank">🥇 No.1</text>
|
||||||
<text class="meta-heat">🔥 98.2w 热度</text>
|
<text class="meta-heat">🔥 {{ detailData.hotScore }} 热度</text>
|
||||||
|
<text class="meta-count" style="margin-left: 20rpx; color: #999;">{{ detailData.ratingCount }} 人评分</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -42,27 +43,11 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 你的态度 -->
|
<!-- 你的态度 -->
|
||||||
<view class="attitude-panel card">
|
<AttitudePanel
|
||||||
<text class="section-title">你的态度</text>
|
:initial-action="currentAction"
|
||||||
<view class="action-group">
|
@action-change="handleActionChange"
|
||||||
<view
|
@send-comment="handleSendComment"
|
||||||
class="action-item"
|
/>
|
||||||
v-for="(action, index) in actions"
|
|
||||||
:key="index"
|
|
||||||
:class="{ active: currentAction === action.value }"
|
|
||||||
@tap="handleAction(action.value)"
|
|
||||||
>
|
|
||||||
<view class="emoji-wrap">
|
|
||||||
<text class="emoji">{{ action.emoji }}</text>
|
|
||||||
</view>
|
|
||||||
<text class="action-name">{{ action.label }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="quick-comment">
|
|
||||||
<input class="comment-input" type="text" placeholder="说点什么吧..." placeholder-class="input-placeholder" />
|
|
||||||
<button class="send-btn">发送</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 大家都在 PK -->
|
<!-- 大家都在 PK -->
|
||||||
<view class="pk-panel card">
|
<view class="pk-panel card">
|
||||||
@@ -137,82 +122,122 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { getStatusBarHeight } from "@/utils/system";
|
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 { fetchTopicRatingItems } from "@/api/topicItem";
|
||||||
|
import { FILE_BASE_URL } from "@/utils/constants";
|
||||||
|
import { topicItemScore } from "@/api/topicItem";
|
||||||
|
|
||||||
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 currentAction = ref('god');
|
const currentAction = ref('');
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
};
|
};
|
||||||
|
|
||||||
const detailData = ref({
|
const detailData = ref({
|
||||||
id: 1,
|
id: '',
|
||||||
name: '李世民',
|
name: '',
|
||||||
score: '9.8',
|
score: '0.0',
|
||||||
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=11',
|
avatar: '',
|
||||||
aiSummary: '多数用户认为李世民综合能力最强,尤其在文治武功方面优势明显。关于玄武门事件的争议依然存在。'
|
aiSummary: '加载中...',
|
||||||
|
userAction: "",
|
||||||
|
topicId: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const actions = [
|
const comments = ref([]);
|
||||||
{ label: '离谱', value: 'terrible', emoji: '👎' },
|
const itemId = ref('');
|
||||||
{ label: '一般', value: 'bad', emoji: '😐' },
|
|
||||||
{ label: '不错', value: 'ok', emoji: '🙂' },
|
|
||||||
{ label: '很强', value: 'good', emoji: '🔥' },
|
|
||||||
{ label: '封神', value: 'god', emoji: '👑' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const mockComments = [
|
const handleActionChange = async (action) => {
|
||||||
{
|
const originAction = detailData.value.userAction;
|
||||||
id: 1,
|
const originScore = detailData.value.score;
|
||||||
name: '历史课代表',
|
try {
|
||||||
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=u1',
|
detailData.value.userAction = detailData.value.userAction === action.label ? '' : action.label;
|
||||||
time: '2小时前',
|
currentAction.value = action.label;
|
||||||
content: '李世民唯一缺点是儿子太抽象。',
|
|
||||||
likes: '2.3k',
|
const res = await topicItemScore({
|
||||||
badge: '封神',
|
topicId: detailData.value.topicId,
|
||||||
badgeIcon: '👑'
|
itemId: itemId.value,
|
||||||
},
|
scoreType: action.scoreType
|
||||||
{
|
});
|
||||||
id: 2,
|
detailData.value.score = res?.scoreAvg || originScore;
|
||||||
name: '贞观长歌',
|
} catch (error) {
|
||||||
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=u2',
|
uni.showToast({
|
||||||
time: '5小时前',
|
title: '评分失败',
|
||||||
content: '不管怎么说,六边形战士在历史上是真罕见。',
|
icon: 'none'
|
||||||
likes: '856',
|
});
|
||||||
badge: '很强',
|
detailData.value.userAction = originAction;
|
||||||
badgeIcon: '🔥'
|
detailData.value.score = originScore;
|
||||||
|
currentAction.value = originAction;
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
|
|
||||||
const comments = ref([...mockComments]);
|
const handleSendComment = (payload) => {
|
||||||
|
console.log('发送评论:', payload);
|
||||||
|
uni.showToast({
|
||||||
|
title: '发送成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
// TODO: 调用接口发送评论,然后更新评论列表
|
||||||
|
};
|
||||||
|
|
||||||
const handleAction = (val) => {
|
const getDetailData = async () => {
|
||||||
currentAction.value = val;
|
if (!itemId.value) return;
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '加载中' });
|
||||||
|
const res = await fetchTopicRatingItems(itemId.value);
|
||||||
|
const data = res?.data || res || {};
|
||||||
|
|
||||||
|
detailData.value = {
|
||||||
|
id: itemId.value,
|
||||||
|
name: data.name || '未知',
|
||||||
|
score: data.scoreAvg ? Number(data.scoreAvg).toFixed(1) : '0.0',
|
||||||
|
avatar: data.avatarUrl ? `${FILE_BASE_URL}${data.avatarUrl}` : '',
|
||||||
|
aiSummary: data.description || '暂无总结',
|
||||||
|
hotScore: data.hotScore || '0.00',
|
||||||
|
topicId: data.topicId || '',
|
||||||
|
ratingCount: data.scoreCount || 0,
|
||||||
|
userAction: data.userAction || ""
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果接口返回了当前用户的态度,初始化它
|
||||||
|
if (data.userAction) {
|
||||||
|
currentAction.value = data.userAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有评论数据,更新评论
|
||||||
|
if (data.comments && Array.isArray(data.comments)) {
|
||||||
|
comments.value = data.comments;
|
||||||
|
} else {
|
||||||
|
comments.value = [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取详情失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取详情失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
console.log('Received itemId:', options.itemId);
|
if (options.itemId) {
|
||||||
|
itemId.value = options.itemId;
|
||||||
|
getDetailData();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onPullDownRefresh(() => {
|
onPullDownRefresh(() => {
|
||||||
setTimeout(() => {
|
getDetailData();
|
||||||
comments.value = [...mockComments];
|
|
||||||
hasMore.value = true;
|
|
||||||
uni.stopPullDownRefresh();
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onReachBottom(() => {
|
onReachBottom(() => {
|
||||||
if (!hasMore.value || loading.value) return;
|
if (!hasMore.value || loading.value) return;
|
||||||
loading.value = true;
|
// TODO: 评论分页加载逻辑
|
||||||
setTimeout(() => {
|
|
||||||
const more = mockComments.map(c => ({...c, id: c.id + comments.value.length}));
|
|
||||||
comments.value.push(...more);
|
|
||||||
loading.value = false;
|
|
||||||
if (comments.value.length >= 10) hasMore.value = false;
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -384,6 +409,8 @@ onReachBottom(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 你的态度面板 */
|
/* 你的态度面板 */
|
||||||
|
|
||||||
|
/* 大家都在 PK */
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 34rpx;
|
font-size: 34rpx;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -393,79 +420,6 @@ onReachBottom(() => {
|
|||||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-group {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-wrap {
|
|
||||||
margin-bottom: 12rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji {
|
|
||||||
font-size: 56rpx;
|
|
||||||
filter: grayscale(100%);
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-name {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-item.active .emoji {
|
|
||||||
filter: grayscale(0%);
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-item.active .action-name {
|
|
||||||
color: #2953ff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-comment {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #f0f2f7;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
padding: 8rpx 8rpx 8rpx 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment-input {
|
|
||||||
flex: 1;
|
|
||||||
height: 72rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-placeholder {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.send-btn {
|
|
||||||
background-color: #4d44f1;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 26rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
padding: 0 40rpx;
|
|
||||||
height: 64rpx;
|
|
||||||
line-height: 64rpx;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.send-btn::after {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 大家都在 PK */
|
|
||||||
.pk-header {
|
.pk-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user