Files
site-10584/components/Index/Category.vue
2026-01-29 10:43:43 +08:00

648 lines
16 KiB
Vue
Raw Permalink 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 setup lang="ts">
import {treeNavigation} from '~/api/cms/cmsNavigation';
import type {CmsNavigation} from '~/api/cms/cmsNavigation/model';
import NewsList from '~/components/Index/NewsList.vue';
import NewsListSimple from '~/components/Index/NewsListSimple.vue';
import NewsCard from '~/components/Index/NewsCard.vue';
import {pageCmsArticle} from "~/api/cms/cmsArticle";
import type {CmsArticle} from "~/api/cms/cmsArticle/model";
import {getCmsAd} from "~/api/cms/cmsAd";
import type {CmsAd} from "~/api/cms/cmsAd/model";
const categoryList = ref<CmsNavigation[]>([]);
const hotNews = ref<CmsArticle[]>([]);
// 当前激活的分类ID
const activeCategoryId = ref<number>(4264);
// 其他栏目数据
const memberNews = ref<CmsArticle[]>([]); // 会员之家
const brandNews = ref<CmsArticle[]>([]); // 品牌建设
const industryNews = ref<CmsArticle[]>([]); // 行业自律
const partyNews = ref<CmsArticle[]>([]); // 协会党建
const productNews = ref<CmsArticle[]>([]); // 名优产品
const bannerAd = ref<any>(); // 广告位441
// 产品轮播相关
const productCarousel = ref<HTMLElement>();
let carouselTimer: NodeJS.Timeout | null = null;
// 分类选项
const categoryTabs = [
{id: 4266, name: '行业新闻'},
{id: 4267, name: '工作动态'}
];
// 切换分类
const switchCategory = (categoryId: number) => {
activeCategoryId.value = categoryId;
};
// 格式化日期
const formatDate = (dateStr: string | undefined) => {
if (!dateStr) return '';
const date = new Date(dateStr);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${month}-${day}`;
};
// 启动产品轮播
const startProductCarousel = () => {
if (!productCarousel.value || productNews.value.length <= 4) return;
carouselTimer = setInterval(() => {
const container = productCarousel.value;
if (!container) return;
const itemWidth = 200; // 每个产品项的宽度
const currentScroll = container.scrollLeft;
const maxScroll = container.scrollWidth - container.clientWidth;
if (currentScroll >= maxScroll) {
// 滚动到末尾,重置到开始
container.scrollTo({left: 0, behavior: 'smooth'});
} else {
// 继续向右滚动
container.scrollTo({left: currentScroll + itemWidth, behavior: 'smooth'});
}
}, 3000); // 每3秒滚动一次
};
// 停止产品轮播
const stopProductCarousel = () => {
if (carouselTimer) {
clearInterval(carouselTimer);
carouselTimer = null;
}
};
const reload = async () => {
treeNavigation({
recommend: true
}).then(data => {
categoryList.value = data || [];
console.log(data, '123132');
});
// 获取热门新闻
const hot_news = await pageCmsArticle({
limit: 5,
recommend: 1
});
if (hot_news) {
hotNews.value = hot_news?.list || [];
}
// 获取会员之家数据
const memberData = await pageCmsArticle({
limit: 4,
parentId: 4297
});
if (memberData) {
memberNews.value = memberData?.list || [];
}
// 获取品牌建设数据
const brandData = await pageCmsArticle({
limit: 4,
parentId: 4301
});
if (brandData) {
brandNews.value = brandData?.list || [];
}
// 获取行业自律数据
const industryData = await pageCmsArticle({
limit: 4,
parentId: 4300
});
if (industryData) {
industryNews.value = industryData?.list || [];
}
// 获取协会党建数据
const partyData = await pageCmsArticle({
limit: 4,
categoryId: 4310
});
if (partyData) {
partyNews.value = partyData?.list || [];
}
// 获取名优产品数据
const productData = await pageCmsArticle({
limit: 8,
categoryId: 4299
});
if (productData) {
productNews.value = productData?.list || [];
}
// 获取广告位441数据
try {
const adData = await getCmsAd(441);
if (adData && adData.status == 0) {
bannerAd.value = adData.imageList[0];
}
} catch (error) {
console.log('获取广告位441失败:', error);
}
};
onMounted(() => {
reload();
// 延迟启动轮播确保DOM已渲染
nextTick(() => {
setTimeout(() => {
startProductCarousel();
}, 1000);
});
});
onUnmounted(() => {
stopProductCarousel();
});
</script>
<template>
<!-- 通知公告样式的新闻专区 -->
<div class="news-section-wrapper">
<div class="xl:w-screen-xl m-auto">
<el-row :gutter="20">
<el-col :span="8">
<el-carousel height="324px" class="bg-white rounded-lg overflow-hidden">
<el-carousel-item v-for="(item,index) in hotNews" :key="index">
<el-image :src="item.image" fit="cover" class="w-full h-full"
@click="navigateTo(`/detail/${item.articleId}.html`, { target: '_blank' })"/>
</el-carousel-item>
</el-carousel>
</el-col>
<el-col :span="16">
<div
class="w-full h-[324px] bg-white border-1 border-solid border-gray-200 rounded-lg overflow-hidden flex flex-col">
<div
class="title flex justify-between items-center bg-green-50 py-3 px-4 text-lg border-b-1 border-b-solid border-gray-200 flex-shrink-0"
>
<a-space class="flex items-center gap-1">
<span
class="cursor-pointer transition-colors duration-200"
:class="{ 'active': activeCategoryId === 4264 }"
@click="switchCategory(4264)"
>
通知公告
</span>
<el-divider direction="vertical"/>
<span
class="cursor-pointer transition-colors duration-200"
:class="{ 'active': activeCategoryId === 4266 }"
@click="switchCategory(4266)"
>
行业新闻
</span>
<el-divider direction="vertical"/>
<span
class="cursor-pointer transition-colors duration-200"
:class="{ 'active': activeCategoryId === 4267 }"
@click="switchCategory(4267)"
>
工作动态
</span>
</a-space>
<a :href="`/article/${activeCategoryId}`" class="text-sm hover:text-green-600 transition-colors">更多</a>
</div>
<div class="flex-1 overflow-hidden">
<NewsListSimple :categoryId="activeCategoryId" :row="6" :key="activeCategoryId"/>
</div>
</div>
</el-col>
</el-row>
</div>
</div>
<!-- 其他栏目内容 -->
<div class="other-sections-wrapper">
<div class="xl:w-screen-xl m-auto">
<!-- 会员之家单独一排 -->
<el-row :gutter="20" class="mb-8">
<!-- 名优产品(带封面图) -->
<el-col :span="16">
<div class="section-card product-card">
<div class="section-header">
<h3 class="section-title">名优产品</h3>
<a href="/article/4299" class="more-link">更多</a>
</div>
<div class="section-content">
<div class="product-carousel-container">
<div class="product-carousel" ref="productCarousel">
<div v-for="(item, index) in productNews" :key="index" class="product-item">
<a :href="`/detail/${item.articleId}`" class="product-link">
<div class="product-image">
<el-image
:src="item.image || '/default-product.jpg'"
fit="cover"
class="w-full h-full"
:alt="item.title"
/>
</div>
<div class="product-info">
<h4 class="product-title">{{ item.title }}</h4>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</el-col>
<!-- 协会党建 -->
<el-col :span="8">
<div class="section-card">
<div class="section-header">
<h3 class="section-title">协会党建</h3>
<a href="/article/4310" class="more-link">更多</a>
</div>
<div class="section-content">
<div class="news-list">
<div v-for="(item, index) in partyNews" :key="index" class="news-item">
<a :href="`/detail/${item.articleId}`" class="news-link">
<span class="news-title">{{ item.title }}</span>
<span class="news-date">{{ formatDate(item.createTime) }}</span>
</a>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
<!-- 广告位1000x125 -->
<div v-if="bannerAd" class="ad-banner-wrapper">
<div class="xl:w-screen-xl m-auto">
<div class="ad-banner-container">
<a
:href="bannerAd.url || '#'"
:target="bannerAd.url ? '_blank' : '_self'"
class="ad-banner-link"
>
<el-image
:src="bannerAd.url"
:alt="bannerAd.url"
fit="cover"
class="ad-banner-image"
/>
</a>
</div>
</div>
</div>
<!-- 其他三个栏目一排 -->
<el-row :gutter="20" class="mb-8">
<!-- 会员之家文本列表 -->
<el-col :span="8">
<div class="section-card">
<div class="section-header">
<h3 class="section-title">会员之家</h3>
<a href="/article/4297" class="more-link">更多</a>
</div>
<div class="section-content">
<div class="news-list">
<div v-for="(item, index) in memberNews" :key="index" class="news-item">
<a :href="`/detail/${item.articleId}`" class="news-link">
<span class="news-title">{{ item.title }}</span>
<span class="news-date">{{ formatDate(item.createTime) }}</span>
</a>
</div>
</div>
</div>
</div>
</el-col>
<!-- 品牌建设 -->
<el-col :span="8">
<div class="section-card">
<div class="section-header">
<h3 class="section-title">品牌建设</h3>
<a href="/article/4301" class="more-link">更多</a>
</div>
<div class="section-content">
<div class="news-list">
<div v-for="(item, index) in brandNews" :key="index" class="news-item">
<a :href="`/detail/${item.articleId}`" class="news-link">
<span class="news-title">{{ item.title }}</span>
<span class="news-date">{{ formatDate(item.createTime) }}</span>
</a>
</div>
</div>
</div>
</div>
</el-col>
<!-- 行业自律 -->
<el-col :span="8">
<div class="section-card">
<div class="section-header">
<h3 class="section-title">政策法规</h3>
<a href="/article/4419" class="more-link">更多</a>
</div>
<div class="section-content">
<div class="news-list">
<div v-for="(item, index) in industryNews" :key="index" class="news-item">
<a :href="`/detail/${item.articleId}`" class="news-link">
<span class="news-title">{{ item.title }}</span>
<span class="news-date">{{ formatDate(item.createTime) }}</span>
</a>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<style scoped lang="scss">
.news-section-wrapper {
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
padding: 40px 0;
margin: 0;
}
.active {
font-weight: bold;
color: #1b850c;
position: relative;
&::after {
content: '';
position: absolute;
bottom: -8px;
left: 0;
right: 0;
height: 2px;
border-radius: 1px;
}
}
.cursor-pointer {
padding: 4px 8px;
border-radius: 4px;
position: relative;
&:hover {
background-color: rgba(27, 133, 12, 0.1);
color: #1b850c;
}
&:not(.active):hover {
font-weight: 500;
}
}
// 轮播图样式优化
.el-carousel {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
// 新闻区域卡片样式
.bg-white {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
// 其他栏目样式
.other-sections-wrapper {
background: #f8fafc;
padding: 40px 0;
}
.section-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
height: 280px;
display: flex;
flex-direction: column;
transition: all 0.3s ease;
&:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
background: linear-gradient(135deg, #1b850c 0%, #22c55e 100%);
color: white;
}
.section-title {
font-size: 16px;
font-weight: 600;
margin: 0;
}
.more-link {
color: white;
text-decoration: none;
font-size: 14px;
opacity: 0.9;
transition: opacity 0.3s ease;
&:hover {
opacity: 1;
text-decoration: underline;
}
}
.section-content {
flex: 1;
padding: 16px 20px;
overflow: hidden;
}
.news-list {
height: 100%;
overflow: hidden;
}
.news-item {
margin-bottom: 12px;
&:last-child {
margin-bottom: 0;
}
}
.news-link {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
text-decoration: none;
color: #333;
border-bottom: 1px solid #f0f0f0;
transition: all 0.3s ease;
&:hover {
color: #1b850c;
background-color: rgba(27, 133, 12, 0.05);
padding-left: 8px;
border-radius: 4px;
border-bottom-color: transparent;
}
}
.news-title {
flex: 1;
font-size: 14px;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 12px;
}
.news-date {
font-size: 12px;
color: #999;
white-space: nowrap;
}
// 产品轮播样式
.product-card {
height: 280px;
}
.product-carousel-container {
height: 100%;
overflow: hidden;
position: relative;
}
.product-carousel {
display: flex;
gap: 16px;
height: 100%;
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE and Edge */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari and Opera */
}
}
.product-item {
flex: 0 0 180px; /* 固定宽度,不收缩不扩展 */
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
}
.product-link {
display: block;
height: 100%;
text-decoration: none;
color: inherit;
}
.product-image {
height: 135px; /* 4:3 比例宽度180px对应高度135px */
width: 100%;
background: #f5f5f5;
overflow: hidden;
position: relative;
}
.product-info {
padding: 12px;
height: calc(100% - 135px);
display: flex;
align-items: center;
justify-content: center;
}
.product-title {
font-size: 14px;
font-weight: 500;
color: #333;
margin: 0;
line-height: 1.4;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
// 广告位样式
.ad-banner-wrapper {
padding-bottom: 30px;
}
.ad-banner-container {
display: flex;
justify-content: center;
align-items: center;
}
.ad-banner-link {
display: block;
width: 1000px;
height: 125px;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
&:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
}
.ad-banner-image {
width: 100%;
height: 100%;
object-fit: cover;
}
// 响应式设计
@media (max-width: 1200px) {
.ad-banner-link {
width: 100%;
max-width: 1000px;
}
}
@media (max-width: 768px) {
.ad-banner-link {
height: 80px;
}
.ad-banner-wrapper {
padding: 15px 0;
}
}
</style>