xlqx/app/components/DevelopNews.vue
2025-10-31 17:09:26 +08:00

176 lines
5.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.

<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { getArticleList, type Article } from '~/config/api'
// 类型定义
interface NewsCategory {
name: string
code: string
articleList: Article[]
}
// 响应式数据
const newsData = ref<NewsCategory[]>([])
const loading = ref(false)
const error = ref('')
// 文章类型配置
const articleTypes = [
{ name: '解决方案', code: 'solution' },
{ name: '开发知识', code: 'developKnowledge' },
{ name: '行业动态', code: 'industryTrend' }
]
// 格式化时间
const formatTime = (timeString: string): string => {
if (!timeString) return ''
const date = new Date(timeString)
if (isNaN(date.getTime())) return timeString
const Y = date.getFullYear()
const M = String(date.getMonth() + 1).padStart(2, '0')
const D = String(date.getDate()).padStart(2, '0')
const h = String(date.getHours()).padStart(2, '0')
const m = String(date.getMinutes()).padStart(2, '0')
return `${Y}-${M}-${D} ${h}:${m}`
}
// 获取文章链接
const getArticleLink = (articleId: string): string => {
return `/article/${articleId}`
}
// 获取显示的文章列表每个分类显示前2篇文章
const getDisplayArticles = (articles: Article[]): Article[] => {
return articles.slice(0, 2)
}
// 获取新闻数据
const fetchNewsData = async (): Promise<void> => {
loading.value = true
error.value = ''
try {
// 并发获取所有类型的文章数据
const promises = articleTypes.map(async (type) => {
try {
const response = await getArticleList({
code: type.code,
pageNum: 1,
pageSize: 10
})
return {
name: type.name,
code: type.code,
articleList: response.rows || []
}
} catch (err) {
console.error(`获取 ${type.name} 文章失败:`, err)
return {
name: type.name,
code: type.code,
articleList: []
}
}
})
newsData.value = await Promise.all(promises)
} catch (err) {
error.value = err instanceof Error ? err.message : '获取新闻数据失败'
console.error('获取新闻数据时发生错误:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
fetchNewsData()
})
</script>
<template>
<!--box3 新闻-->
<div class="container mx-auto px-4">
<!-- 标题区域 -->
<div class="text-center ">
<div
class="text-black text-4xl leading-tight mb-3 wow fadeInDown animated"
style="visibility: visible; animation-name: fadeInDown;">
开发资讯
</div>
<div class="text-gray-600 text-lg wow fadeInUp animated" style="visibility: visible; animation-name: fadeInUp;">
NEWS
</div>
<div class="py-5"/>
</div>
<!-- 加载状态 -->
<div v-if="loading" class="text-center py-12">
<div class="text-gray-600 text-lg animate-pulse">正在加载新闻...</div>
<div class="py-12"/>
</div>
<!-- 错误状态 -->
<div v-else-if="error" class="text-center py-12">
<div class="text-red-600 text-lg mb-5">加载失败: {{ error }}</div>
<button
class="inline-block px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-base font-normal rounded transition-all duration-150 ease-in-out cursor-pointer border border-transparent"
@click="fetchNewsData">
重新加载
</button>
<div class="py-12"/>
</div>
<!-- 新闻分类列表 -->
<div v-else class="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
<div
v-for="(category, index) in newsData"
:key="category.name"
:data-wow-delay="`${300 + index * 200}ms`"
:style="`visibility: visible; animation-delay: ${300 + index * 200}ms; animation-name: fadeInDown;`"
class="wow fadeInDown animated active mb-8 lg:mb-12">
<!-- 分类标题 -->
<div :title="category.name" class="text-xl lg:text-2xl text-blue-600 text-center cursor-pointer mb-5">
{{ category.name }}
</div>
<hr class="border-gray-300 mb-5"/>
<div class="py-5"/>
<!-- 文章列表 -->
<template v-if="category.articleList.length > 0">
<ul class="list-none p-0 m-0">
<li v-for="article in getDisplayArticles(category.articleList)" :key="article.id" class="mb-2.5">
<a
:href="getArticleLink(article.id)"
:title="article.title"
class="text-gray-600 text-sm block py-1.5 no-underline hover:underline transition-all"
target="_blank">
<div class="flex items-center justify-between gap-3">
<span class="truncate flex-1 pr-2">{{ article.title }}</span>
<span class="text-gray-500 text-xs whitespace-nowrap flex-shrink-0">{{ formatTime(article.createTime) }}</span>
</div>
<div class="py-5"/>
</a>
</li>
</ul>
</template>
<div v-else class="text-center text-gray-600 text-sm py-5">
暂无文章
</div>
</div>
</div>
<!-- 空状态 -->
<div v-if="!loading && !error && newsData.length === 0" class="text-center py-12">
<div class="text-gray-600 text-lg">暂无新闻数据</div>
<div class="py-12"/>
</div>
</div>
</template>