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

265 lines
6.3 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">
<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>
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;
}
.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-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;
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>