Files
rating/components/TopicCard/TopicCard.vue

247 lines
5.9 KiB
Vue
Raw Normal View History

2026-05-21 18:00:07 +08:00
<template>
<view class="topic-card">
<!-- 卡片头部标题与统计信息 -->
<view class="topic-header">
<text class="topic-title">{{ topic.title }}</text>
<view class="topic-stats">
<view class="stat-item">
<text class="stat-icon icon-group"></text>
<text>{{ topic.participants }}人参与</text>
</view>
<view class="stat-item heat">
<text class="stat-icon icon-fire"></text>
<text>热度 {{ topic.heat }}</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)"
>
<text 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.score }}</text>
</view>
</view>
<!-- AI 总结 -->
<view class="ai-summary" v-if="topic.aiSummary">
<text class="ai-icon icon-robot"></text>
<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>
2026-05-21 23:00:54 +08:00
import { FILE_BASE_URL } from "@/utils/constants";
2026-05-21 18:00:07 +08:00
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;
}
.icon-group {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23999999'%3E%3Cpath d='M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z'/%3E%3C/svg%3E");
}
.icon-fire {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ff4d4f'%3E%3Cpath d='M19.48 13.03c-.02-.19-.13-.36-.29-.46-.17-.11-.38-.13-.56-.05-.98.42-2.12.3-2.92-.31-1.07-.81-1.55-2.22-1.28-3.75.12-.66.1-1.32-.06-1.97-.24-.95-1.1-1.6-2.09-1.58-1 .02-1.83.74-2 1.72-.25 1.55-.95 2.94-2 4.02-1.38 1.41-2.05 3.39-1.85 5.4.2 2.05 1.42 3.86 3.25 4.82 1.37.72 2.94 1.01 4.5.83 2.74-.32 5.06-2.28 5.86-4.95.23-.75.29-1.52.19-2.28-.06-.5-.21-.99-.41-1.45l-.34-.99zm-4.98 6.47c-1.37 0-2.5-1.13-2.5-2.5s1.13-2.5 2.5-2.5 2.5 1.13 2.5 2.5-1.13 2.5-2.5 2.5z'/%3E%3C/svg%3E");
}
.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-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;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%237b46f1'%3E%3Cpath d='M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h5a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h5V5.73A2 2 0 0 1 10 4a2 2 0 0 1 2-2zm-3 8a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm6 0a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z'/%3E%3C/svg%3E");
}
.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>