260 lines
4.9 KiB
Vue
260 lines
4.9 KiB
Vue
<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>
|