Files
rating/components/TopicCard/TopicCard.vue
2026-06-10 01:10:58 +08:00

260 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="topic-card">
<!-- 卡片头部标题与统计信息 -->
<view class="topic-header">
<text class="topic-title">{{ topic.title }}</text>
<view class="topic-stats">
<view class="stat-item">
<image class="stat-icon stat-icon-img" src="/static/images/icon/group.png" mode="aspectFit"></image>
<text>{{ topic.participantCount }}人参与</text>
</view>
<view class="stat-item heat">
<image class="stat-icon stat-icon-img" src="/static/images/icon/fire.png" mode="aspectFit"></image>
<text>热度 {{ topic.hotScore }} w</text>
</view>
</view>
</view>
<!-- 排行榜列表 -->
<view class="rank-list">
<view
class="rank-item"
v-for="(item, index) in topic.items"
:key="item.id"
@tap="handleItemTap(item.id)"
>
<image
v-if="index < 3"
class="rank-icon"
:src="`/static/images/icon/${index + 1}.png`"
mode="aspectFit"
/>
<text v-else class="rank-num" :class="'rank-' + (index + 1)">{{ index + 1 }}</text>
<image class="item-avatar" :src="FILE_BASE_URL + item.avatarUrl" mode="aspectFill"></image>
<text class="item-name">{{ item.name }}</text>
<text class="item-score" :class="'score-' + (index + 1)">{{ item.scoreAvg }}</text>
</view>
</view>
<!-- AI 总结 -->
<view class="ai-summary" v-if="topic.aiSummary">
<image class="ai-icon ai-icon-img" src="/static/images/icon/robot.png" mode="aspectFit"></image>
<view class="summary-text">
<text class="summary-label">AI总结</text>
<text class="summary-content">{{ topic.aiSummary }}</text>
</view>
</view>
<!-- 标签列表 -->
<view class="tag-list">
<view class="tag" v-for="(tag, tIndex) in topic.tags" :key="tIndex">
<text>#{{ tag }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { FILE_BASE_URL } from "@/utils/constants";
const props = defineProps({
topic: {
type: Object,
required: true,
default: () => ({})
}
});
const emit = defineEmits(['item-click']);
const handleItemTap = (itemId) => {
emit('item-click', props.topic.id, itemId);
};
</script>
<style lang="scss" scoped>
.topic-card {
background-color: #ffffff;
border-radius: 40rpx;
padding: 36rpx;
margin-bottom: 32rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.04);
transition: transform 0.2s ease;
}
.topic-card:active {
transform: scale(0.98);
}
.topic-header {
margin-bottom: 32rpx;
}
.topic-title {
font-size: 38rpx;
font-weight: 800;
color: #222;
margin-bottom: 20rpx;
display: block;
letter-spacing: 1rpx;
}
.topic-stats {
display: flex;
align-items: center;
}
.stat-item {
display: flex;
align-items: center;
font-size: 24rpx;
color: #666;
margin-right: 20rpx;
background-color: #f7f7f9;
padding: 6rpx 16rpx;
border-radius: 100rpx;
}
.stat-icon {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
display: inline-block;
background-size: cover;
}
.stat-icon-img {
flex-shrink: 0;
}
.rank-list {
margin-bottom: 24rpx;
background-color: #fcfcfd;
border-radius: 24rpx;
padding: 16rpx 24rpx;
}
.rank-item {
display: flex;
align-items: center;
padding: 16rpx 0;
border-bottom: 2rpx dashed #eee;
}
.rank-item:last-child {
border-bottom: none;
}
.rank-num {
width: 44rpx;
font-size: 34rpx;
font-weight: 900;
text-align: center;
margin-right: 16rpx;
font-style: italic;
}
.rank-icon {
width: 44rpx;
height: 44rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.rank-1 {
color: #2953ff;
font-size: 40rpx;
}
.rank-2, .rank-3 {
color: #333;
}
.item-avatar {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
margin-right: 24rpx;
background-color: #f0f0f0;
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.item-name {
flex: 1;
font-size: 30rpx;
color: #333;
font-weight: 500;
}
.item-score {
font-size: 36rpx;
font-weight: 900;
font-family: Arial, sans-serif;
}
.score-1 {
color: #2953ff;
}
.score-2, .score-3 {
color: #333;
}
.ai-summary {
display: flex;
align-items: flex-start;
padding: 20rpx 24rpx;
background: linear-gradient(135deg, #fbfaff, #f4efff);
border: 2rpx solid #e0d6ff;
border-radius: 20rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(123, 70, 241, 0.05);
}
.ai-icon {
width: 32rpx;
height: 32rpx;
margin-right: 12rpx;
margin-top: 4rpx;
flex-shrink: 0;
}
.ai-icon-img {
display: block;
}
.summary-text {
flex: 1;
font-size: 26rpx;
line-height: 1.6;
}
.summary-label {
color: #7b46f1;
font-weight: bold;
}
.summary-content {
color: #444;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.tag {
background-color: #f4eaff;
padding: 6rpx 24rpx;
border-radius: 100rpx;
}
.tag text {
color: #9d5bfe;
font-size: 22rpx;
font-weight: 500;
}
</style>