130 lines
3.8 KiB
Vue
130 lines
3.8 KiB
Vue
<!-- 热门新闻列表组件 -->
|
||
<template>
|
||
<div class="trending-news">
|
||
<div class="trending-news-header">
|
||
<h3 class="font-semibold text-lg mb-3 dark:text-white">
|
||
<i class="fas fa-fire text-red-500 dark:text-red-400 mr-2"></i>
|
||
{{ $t('news.trendingNews') }}
|
||
</h3>
|
||
</div>
|
||
<div class="trending-news-list">
|
||
<NuxtLink
|
||
v-for="(article, index) in trendingNews"
|
||
:key="index"
|
||
:to="`/awsnews/${getArticleSlug(article)}`"
|
||
class="trending-news-item"
|
||
>
|
||
<div class="trending-news-rank">{{ index + 1 }}</div>
|
||
<div class="trending-news-content">
|
||
<h4 class="trending-news-title">{{ article.title }}</h4>
|
||
<div class="trending-news-meta">
|
||
<span class="trending-news-category" :class="getCategoryClass(article.category || article.meta?.category || 'other')">
|
||
{{ $t(`news.categories.${article.category || article.meta?.category || 'other'}`) }}
|
||
</span>
|
||
<!-- <span class="trending-news-views">
|
||
<i class="fas fa-eye text-gray-400 mr-1"></i> {{ article.views }}
|
||
</span> -->
|
||
</div>
|
||
</div>
|
||
</NuxtLink>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { PropType } from 'vue';
|
||
import { useI18n } from 'vue-i18n';
|
||
|
||
const { t } = useI18n();
|
||
|
||
// 定义组件属性
|
||
const props = defineProps({
|
||
trendingNews: {
|
||
type: Array as PropType<any[]>,
|
||
required: true
|
||
}
|
||
});
|
||
|
||
// 安全获取文章路径最后部分(slug)
|
||
const getArticleSlug = (article: any) => {
|
||
if (!article) return '';
|
||
|
||
// 优先使用path,如果没有则尝试使用_path
|
||
const path = article.path || article._path || '';
|
||
|
||
// 移除开头的斜杠
|
||
const cleanPath = path.startsWith('/') ? path.substring(1) : path;
|
||
|
||
// 如果路径中包含斜杠,取最后一段;否则使用整个路径
|
||
return cleanPath.includes('/') ? cleanPath.split('/').pop() : cleanPath;
|
||
};
|
||
|
||
// 获取分类样式
|
||
const getCategoryClass = (category: string) => {
|
||
const categoryColors: Record<string, string> = {
|
||
'cloud-computing': 'text-blue-600',
|
||
'security': 'text-red-600',
|
||
'serverless': 'text-purple-600',
|
||
'ai': 'text-green-600',
|
||
'database': 'text-yellow-600',
|
||
'quantum-computing': 'text-blue-700',
|
||
'networking': 'text-blue-500',
|
||
'containers': 'text-blue-600',
|
||
'machine-learning': 'text-blue-500',
|
||
'sustainability': 'text-blue-600',
|
||
'other': 'text-gray-600'
|
||
};
|
||
|
||
return categoryColors[category] || categoryColors.other;
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.trending-news {
|
||
@apply bg-white dark:bg-gray-800 rounded-lg shadow p-4 mt-6 sticky top-24;
|
||
}
|
||
|
||
.trending-news-list {
|
||
@apply space-y-4;
|
||
}
|
||
|
||
.trending-news-item {
|
||
@apply flex items-start py-2 border-b border-gray-100 dark:border-gray-700 last:border-0 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors;
|
||
}
|
||
|
||
.trending-news-rank {
|
||
@apply flex-shrink-0 w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center text-sm font-bold text-gray-700 dark:text-gray-300 mr-3;
|
||
}
|
||
|
||
.trending-news-item:nth-child(1) .trending-news-rank {
|
||
@apply bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-400;
|
||
}
|
||
|
||
.trending-news-item:nth-child(2) .trending-news-rank {
|
||
@apply bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-400;
|
||
}
|
||
|
||
.trending-news-item:nth-child(3) .trending-news-rank {
|
||
@apply bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-400;
|
||
}
|
||
|
||
.trending-news-content {
|
||
@apply flex-grow;
|
||
}
|
||
|
||
.trending-news-title {
|
||
@apply text-sm font-medium mb-1 line-clamp-2 dark:text-white;
|
||
}
|
||
|
||
.trending-news-meta {
|
||
@apply flex justify-between items-center text-xs;
|
||
}
|
||
|
||
.trending-news-category {
|
||
@apply font-medium;
|
||
}
|
||
|
||
.trending-news-views {
|
||
@apply text-gray-500 dark:text-gray-400;
|
||
}
|
||
</style> |