完成社会服务的web界面

This commit is contained in:
2025-10-30 17:25:07 +08:00
parent 2033278329
commit cca83a0eb7

View File

@@ -1,210 +1,424 @@
<template> <template>
<div class="workstation-page"> <!-- 用ElConfigProvider包裹整个组件配置中文语言 -->
<!-- 导航栏 --> <el-config-provider :locale="zhCn">
<nav class="navbar"> <div class="workstation-page">
<div class="container">
<ul class="nav-links">
<li>
<a
href="#"
@click.prevent="currentTab = 'schoolEnterprise'"
:class="{ active: currentTab === 'schoolEnterprise' && !showAllList }"
>校企合作</a>
</li>
<li>
<a
href="#"
@click.prevent="currentTab = 'researchInternship'"
:class="{ active: currentTab === 'researchInternship' && !showAllList }"
>研究实习项目</a>
</li>
<li>
<a
href="#"
@click.prevent="currentTab = 'ruralGovernment'"
:class="{ active: currentTab === 'ruralGovernment' && !showAllList }"
>乡村政府项目</a>
</li>
</ul>
</div>
</nav>
<!-- 主要内容区 --> <!-- 顶部横幅背景图从后端接口获取 -->
<main class="container main-content" v-loading="loading"> <div
<!-- 通用标题 --> class="top-banner"
<div class="header-section"> :style="{
<h1 class="main-title">良品优生省级研究生工作站</h1> backgroundImage: `url(${bannerUrl || 'https://picsum.photos/id/180/1920/400'})`
<p class="sub-title">湖北省省级研究生工作站</p> }"
<div class="divider"></div> >
<div class="banner-container">
</div>
</div> </div>
<!-- 全部文章列表页面 --> <!-- 导航栏 -->
<div v-if="showAllList" class="all-articles-page"> <nav class="navbar">
<!-- 面包屑导航 --> <div class="container">
<div class="breadcrumbs"> <ul class="nav-links">
<a href="#" @click.prevent="showAllList = false">首页</a> <li>
<span>/</span> <a
<span>{{ getTabName(currentTab) }}</span> href="#"
<span>/</span> @click.prevent="switchTab('schoolEnterprise')"
<span>全部项目</span> :class="{ active: currentTab === 'schoolEnterprise' && !showAllList }"
>校企合作</a>
</li>
<li>
<a
href="#"
@click.prevent="switchTab('researchInternship')"
:class="{ active: currentTab === 'researchInternship' && !showAllList }"
>研究实习项目</a>
</li>
<li>
<a
href="#"
@click.prevent="switchTab('ruralGovernment')"
:class="{ active: currentTab === 'ruralGovernment' && !showAllList }"
>乡村政府项目</a>
</li>
</ul>
</div> </div>
</nav>
<!-- 列表标题 --> <!-- 主要内容区 -->
<div class="all-articles-header"> <main class="container main-content" v-loading="loading">
<h2>{{ getTabName(currentTab) }} - 全部项目</h2> <!-- 全部文章列表页面带分页 -->
<button class="back-btn" @click="showAllList = false"> <div v-if="showAllList" class="all-articles-page">
<i class="icon-arrow-left"></i> 返回 <!-- 面包屑导航 -->
</button> <div class="breadcrumbs">
</div> <a href="#" @click.prevent="showAllList = false">首页</a>
<span>/</span>
<!-- 文章列表 --> <span>{{ getTabName(currentTab) }}</span>
<div class="all-articles-list"> <span>/</span>
<div <span>全部项目</span>
v-for="item in allArticles"
:key="item.id"
class="article-item"
@click="selectMainArticle(item)"
>
<img :src="item.cover_url" :alt="item.title" class="item-img" />
<div class="item-info">
<h4 class="item-title">{{ item.title }}</h4>
<p class="item-subtitle" v-if="item.subtitle">{{ item.subtitle }}</p>
<p class="item-date">{{ formatDate(item.create_time) }}</p>
</div>
</div> </div>
</div>
<!-- 空状态 --> <!-- 列表标题 -->
<div v-if="allArticles.length === 0" class="empty-state"> <div class="all-articles-header">
<p>暂无相关项目</p> <h2>{{ getTabName(currentTab) }} - 全部项目</h2>
</div> <button class="back-btn" @click="showAllList = false">
</div> 返回
<!-- 原首页内容 -->
<div v-else>
<!-- 主文章内容区 -->
<div class="content-section" v-if="currentArticle">
<article class="main-article">
<!-- 封面图 -->
<div class="article-cover">
<img :src="currentArticle.cover_url" :alt="currentArticle.title" class="cover-img" />
</div>
<!-- 文字内容 -->
<div class="article-body">
<h2 class="article-title">{{ currentArticle.title }}</h2>
<p class="article-subtitle" v-if="currentArticle.subtitle">{{ currentArticle.subtitle }}</p>
<p class="article-date">{{ formatDate(currentArticle.create_time) }}</p>
<div class="article-content" v-html="currentArticle.content"></div>
</div>
</article>
<!-- 相关文章标题 + 更多按钮 -->
<div class="related-title">
<h3>更多相关项目</h3>
<button class="view-all-btn" @click="showAllList = true">
查看全部 <i class="icon-arrow-right"></i>
</button> </button>
</div> </div>
<!-- 其他三篇文章卡片 --> <!-- 文章列表 -->
<div class="related-articles"> <div class="all-articles-list">
<div <div
v-for="item in relatedArticles" v-for="item in allArticles"
:key="item.id" :key="item.id"
class="related-card" class="article-item"
@click="selectMainArticle(item)" @click="selectMainArticle(item)"
> >
<img :src="item.cover_url" :alt="item.title" class="card-img" /> <!-- 封面图添加默认占位图 -->
<div class="card-content"> <img
<h4 class="card-title">{{ item.title }}</h4> :src="item.cover_url || 'https://picsum.photos/id/237/120/120'"
<p class="card-subtitle" v-if="item.subtitle">{{ item.subtitle }}</p> :alt="item.title"
<p class="card-date">{{ formatDate(item.create_time) }}</p> class="item-img"
:onerror="defaultImg"
/>
<div class="item-info">
<h4 class="item-title">{{ item.title }}</h4>
<p class="item-subtitle" v-if="item.subtitle">{{ item.subtitle }}</p>
<p class="item-date">{{ formatDate(item.publish_time) }}</p>
</div> </div>
</div> </div>
</div> </div>
<!-- 空状态 -->
<div v-if="allArticles.length === 0 && !loading" class="empty-state">
<p>暂无相关项目</p>
</div>
<!-- 分页组件已显示中文 -->
<div class="pagination-container" v-if="total > 0 && !loading">
<el-pagination
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
v-model:current-page="pagination[currentTab].currentPage"
v-model:page-size="pagination[currentTab].pageSize"
:page-sizes="[10, 20, 50]"
@size-change="handlePageSizeChange"
@current-change="handleCurrentPageChange"
:disabled="loading"
></el-pagination>
</div>
</div> </div>
<!-- 空状态 --> <!-- 原首页内容 -->
<div v-else class="empty-state"> <div v-else>
<p>暂无内容</p> <!-- 主文章内容区 -->
</div> <div class="content-section" v-if="currentArticle">
</div> <article class="main-article">
</main> <!-- 封面图 -->
<div class="article-cover">
<img
:src="currentArticle.cover_url || 'https://picsum.photos/id/237/1200/600'"
:alt="currentArticle.title"
class="cover-img"
:onerror="defaultImg"
/>
</div>
<!-- 页脚 --> <!-- 文字内容 -->
<footer class="footer"> <div class="article-body">
<div class="container"> <h2 class="article-title">{{ currentArticle.title }}</h2>
<p class="copyright">© 2025 良品优生省级研究生工作站 版权所有</p> <p class="article-subtitle" v-if="currentArticle.subtitle">{{ currentArticle.subtitle }}</p>
</div> <p class="article-date">{{ formatDate(currentArticle.publish_time) }}</p>
</footer> <div class="article-content" v-html="currentArticle.content || '<p>暂无详细内容</p>'"></div>
</div> </div>
</article>
<!-- 相关文章标题 + 更多按钮 -->
<div class="related-title">
<h3>更多相关项目</h3>
<button class="view-all-btn" @click="handleViewAll">
查看全部
</button>
</div>
<!-- 其他三篇文章卡片 -->
<div class="related-articles">
<div
v-for="item in relatedArticles"
:key="item.id"
class="related-card"
@click="selectMainArticle(item)"
>
<img
:src="item.cover_url || 'https://picsum.photos/id/237/300/180'"
:alt="item.title"
class="card-img"
:onerror="defaultImg"
/>
<div class="card-content">
<h4 class="card-title">{{ item.title }}</h4>
<p class="card-subtitle" v-if="item.subtitle">{{ item.subtitle }}</p>
<p class="card-date">{{ formatDate(item.publish_time) }}</p>
</div>
</div>
</div>
</div>
<!-- 空状态 -->
<div v-else-if="!loading" class="empty-state">
<p>暂无内容</p>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="footer">
<div class="container">
<p class="copyright">© 2025 良品优生省级研究生工作站 版权所有</p>
</div>
</footer>
</div>
</el-config-provider>
</template> </template>
<script> <script>
import axios from 'axios';
// 导入Element Plus组件和中文语言包
import { ElMessage, ElPagination, ElConfigProvider } from 'element-plus';
import zhCn from 'element-plus/es/locale/lang/zh-cn';
// 基础API地址
const base_url = 'http://localhost:8080/api';
export default { export default {
name: 'WorkstationPage', name: 'WorkstationPage',
components: {
ElPagination,
ElConfigProvider
},
data() { data() {
return { return {
zhCn, // 中文语言包
currentTab: 'schoolEnterprise', currentTab: 'schoolEnterprise',
articles: {}, // 存储各分类的完整数据
articles: {
schoolEnterprise: [],
researchInternship: [],
ruralGovernment: []
},
currentArticle: null, currentArticle: null,
relatedArticles: [], relatedArticles: [],
allArticles: [], // 用于全部文章列表 allArticles: [], // 分页当前页数据
total: 0, // 分页总条数
loading: false, loading: false,
showAllList: false, // 控制显示全部文章列表页面 showAllList: false,
// 每个分类独立的分页状态
pagination: {
schoolEnterprise: { currentPage: 1, pageSize: 10 },
researchInternship: { currentPage: 1, pageSize: 10 },
ruralGovernment: { currentPage: 1, pageSize: 10 }
},
// 封面图加载失败默认图
defaultImg: "this.src='https://picsum.photos/id/237/120/120'",
// 横幅图片地址
bannerUrl: ''
}; };
}, },
computed: { computed: {
currentArticles() { currentArticles() {
return this.articles[this.currentTab] || []; return this.articles[this.currentTab] || [];
}, },
// 当前分类的分页配置
currentPagination() {
return this.pagination[this.currentTab];
}
}, },
watch: { watch: {
currentTab: { currentTab: {
immediate: true, immediate: true,
handler(newTab) { handler(newTab) {
this.fetchArticles(newTab); // 切换分类时,加载首页数据
// 切换标签时隐藏全部列表页面 this.fetchHomeData(newTab);
this.showAllList = false; this.showAllList = false;
}, },
}, },
}, },
created() {
// 组件创建时获取横幅图片
this.fetchBannerImage();
},
methods: { methods: {
async fetchArticles(category) { switchTab(tab) {
this.loading = true; this.currentTab = tab;
try { },
const mockData = this.getMockData(category);
this.articles[category] = mockData;
const list = this.articles[category]; /**
if (list.length > 0) { * 获取横幅图片使用POST请求
this.currentArticle = list[0]; */
this.relatedArticles = list.slice(1, 4); async fetchBannerImage() {
this.allArticles = list; // 全部文章数据 try {
const response = await axios.post(
`${base_url}/page-image/get`,
{ page: 'SocialService' }, // 请求参数
{ headers: { 'Content-Type': 'application/json' } }
);
// 处理返回结果
if (response.data && Array.isArray(response.data.images) && response.data.images.length > 0) {
// 查找排序为1的图片如果有多个
const targetImage = response.data.images.find(img => img.sort === 1) || response.data.images[0];
this.bannerUrl = targetImage.image_url;
} else { } else {
this.currentArticle = null; ElMessage.warning('未找到横幅图片数据');
this.relatedArticles = [];
this.allArticles = [];
} }
} catch (error) { } catch (error) {
console.error('获取文章失败:', error); console.error('获取横幅图片失败:', error);
this.$message?.error?.('加载失败') || alert('加载失败'); ElMessage.error('获取横幅图片失败,请刷新页面重试');
}
},
// 首页数据加载只加载第一页取前4条用于首页展示
async fetchHomeData(category) {
this.loading = true;
try {
const url = this.getCategoryUrl(category);
const payload = { page: 1, page_size: 4 }; // 首页只查4条1条主文章+3条相关
const response = await axios.post(url, payload, {
headers: { 'Content-Type': 'application/json' },
});
this.handleResponseData(response, category, true);
} catch (error) {
this.handleFetchError(error, '首页数据');
} finally { } finally {
this.loading = false; this.loading = false;
} }
}, },
// 分页数据加载(全部项目页用)
async fetchPagedData(category, page = 1, pageSize = 10) {
this.loading = true;
try {
const url = this.getCategoryUrl(category);
const payload = { page, page_size: pageSize };
const response = await axios.post(url, payload, {
headers: { 'Content-Type': 'application/json' },
});
this.handleResponseData(response, category, false);
} catch (error) {
this.handleFetchError(error, '分页数据');
} finally {
this.loading = false;
}
},
// 处理接口响应数据
handleResponseData(response, category, isHome = true) {
const resData = response.data || {};
if (resData.code !== 0) throw new Error(resData.message || '接口返回错误');
const rawList = resData.data?.list || [];
if (!Array.isArray(rawList)) throw new Error('list 不是数组');
// 按发布时间倒序排序
const sortedList = rawList.sort((a, b) =>
new Date(b.publish_time) - new Date(a.publish_time)
);
// 存储总条数(分页用)
this.total = resData.data?.total || 0;
if (isHome) {
// 首页逻辑:存储完整数据,设置主文章和相关文章
this.articles[category] = sortedList;
this.currentArticle = sortedList[0] || null;
this.relatedArticles = sortedList.slice(1, 4) || [];
} else {
// 分页逻辑:存储当前页数据
this.allArticles = sortedList;
}
},
// 获取分类对应的接口URL
getCategoryUrl(category) {
switch (category) {
case 'schoolEnterprise':
return `${base_url}/social-service/list`;
case 'researchInternship':
return `${base_url}/social-service/internship/list`;
case 'ruralGovernment':
return `${base_url}/social-service/government-program/list`;
default:
return `${base_url}/social-service/list`;
}
},
// 错误处理
handleFetchError(error, type) {
console.error(`获取${type}失败:`, error);
const errMsg = error.message || '网络异常';
ElMessage?.error?.(`加载${type}失败:${errMsg}`) || alert(`加载失败:${errMsg}`);
// 重置数据状态
this.allArticles = [];
this.total = 0;
if (type === '首页数据') {
this.currentArticle = null;
this.relatedArticles = [];
this.articles[this.currentTab] = [];
}
},
// 查看全部:切换到分页页并加载第一页数据
handleViewAll() {
this.showAllList = true;
// 重置当前分类的分页状态为第一页
this.currentPagination.currentPage = 1;
// 加载分页第一页数据
this.fetchPagedData(
this.currentTab,
this.currentPagination.currentPage,
this.currentPagination.pageSize
);
},
// 页码切换
handleCurrentPageChange(val) {
this.currentPagination.currentPage = val;
this.fetchPagedData(
this.currentTab,
val,
this.currentPagination.pageSize
);
},
// 每页条数切换
handlePageSizeChange(val) {
this.currentPagination.pageSize = val;
this.currentPagination.currentPage = 1; // 切换条数时重置为第一页
this.fetchPagedData(
this.currentTab,
1,
val
);
},
selectMainArticle(article) { selectMainArticle(article) {
this.currentArticle = article; this.currentArticle = article;
// 重新筛选相关文章排除当前选中项取前3条
this.relatedArticles = this.currentArticles this.relatedArticles = this.currentArticles
.filter(a => a.id !== article.id) .filter(a => a.id !== article.id)
.sort((a, b) => new Date(b.publish_time) - new Date(a.publish_time))
.slice(0, 3); .slice(0, 3);
this.showAllList = false; // 选中文章后返回首页 this.showAllList = false;
window.scrollTo({ top: 0, behavior: 'smooth' }); window.scrollTo({ top: 0, behavior: 'smooth' });
}, },
formatDate(dateStr) { formatDate(dateStr) {
if (!dateStr) return '';
const date = new Date(dateStr); const date = new Date(dateStr);
return date.toLocaleDateString('zh-CN', { return date.toLocaleDateString('zh-CN', {
year: 'numeric', year: 'numeric',
@@ -221,109 +435,14 @@ export default {
}; };
return map[tab] || ''; return map[tab] || '';
}, },
// 模拟数据
getMockData(category) {
const base = [
{
id: 1,
title: '与良品铺子共建健康食品联合研发中心',
subtitle: '产学研深度融合5项专利获批',
cover_url: 'https://picsum.photos/id/180/1200/600',
content: `<p>2025年3月我校与良品铺子正式签署战略合作协议共建“健康食品联合研发中心”。中心聚焦功能性健康食品研发、食品质量安全检测、食品包装创新等三大方向配备专业研发设备20余台套组建由12名教授、20名企业技术骨干组成的研发团队。项目实施以来已成功研发益生菌零食、低糖糕点等3类新产品申请发明专利5项实用新型专利3项其中2项专利已实现成果转化产生直接经济效益800余万元。</p>`,
create_time: '2025-03-15 10:00:00',
},
{
id: 2,
title: '现代食品产业学院揭牌仪式',
subtitle: '校企共建人才培养新模式',
cover_url: 'https://picsum.photos/id/201/1200/600',
content: `<p>产业学院整合企业实训资源,为研究生提供“课堂+车间”双场景教学。学院建筑面积3000平方米设有食品研发实验室、品质控制中心、市场营销模拟实训室等6个功能区域。采用“3+1”培养模式研究生前3个学期在校学习理论知识最后1个学期进入企业开展顶岗实习。目前已开设食品科学与工程、食品质量与安全、市场营销等3个专业方向录取研究生120名其中85%的研究生在实习期间参与了企业实际项目研发。</p>`,
create_time: '2025-02-20 09:30:00',
},
{
id: 3,
title: '研究生双导师培养计划启动',
subtitle: '42位企业导师加入指导',
cover_url: 'https://picsum.photos/id/160/1200/600',
content: `<p>计划覆盖食品科学、营销管理、设计等3个专业方向。每位研究生配备1名校内导师和1名企业导师校内导师负责学术指导和理论教学企业导师负责实践指导和项目研发。企业导师均来自良品铺子、周黑鸭、劲牌等知名企业其中高级工程师25名企业技术总监8名具有丰富的行业实践经验。培养计划实施以来已组织校企导师联合授课36次开展企业实地教学18次研究生参与企业横向课题45项。</p>`,
create_time: '2025-01-10 14:00:00',
},
{
id: 4,
title: '功能性健康食品研发项目',
subtitle: '6个月科研津贴3000元/月',
cover_url: 'https://picsum.photos/id/96/1200/600',
content: `<p>项目聚焦益生菌零食开发研究生可申请参与。项目为期6个月面向食品科学、生物工程等相关专业研究生开放申请选拔20名优秀研究生组成研发团队。项目提供每月3000元科研津贴配备专项研发经费50万元以及专业的实验设备和场地支持。研发成果归校企双方共同所有研究生可参与专利申请和论文发表。目前已有15名研究生通过选拔项目已完成前期市场调研和配方设计工作。</p>`,
create_time: '2024-12-05 11:00:00',
},
{
id: 5,
title: '企业导师培训营',
subtitle: '提升指导能力,共建培养体系',
cover_url: 'https://picsum.photos/id/42/1200/600',
content: `<p>为企业导师提供教学方法与科研指导培训。培训营为期3天采用“理论授课+案例分析+分组研讨”的方式进行邀请高校教育学专家、资深导师进行授课。培训内容包括研究生培养政策解读、学术论文指导方法、科研项目管理、师生沟通技巧等方面。共有42位企业导师参加培训培训结束后组织考核考核合格者颁发企业导师资格证书。通过培训有效提升了企业导师的教学指导能力促进了校企培养体系的融合。</p>`,
create_time: '2024-11-20 15:00:00',
},
];
const maps = {
schoolEnterprise: base.slice(0, 5),
researchInternship: [
{ ...base[3], id: 6, title: '功能性健康食品研发实习', subtitle: '科研+实践双轨制', cover_url: 'https://picsum.photos/id/24/1200/600' },
{ ...base[1], id: 7, title: '健康食品消费行为调研', subtitle: '大数据分析方向', cover_url: 'https://picsum.photos/id/42/1200/600' },
{ ...base[2], id: 8, title: '品牌策划实习项目', subtitle: '市场部全流程参与', cover_url: 'https://picsum.photos/id/96/1200/600' },
{ ...base[0], id: 9, title: '联合实验室科研助理', subtitle: '设备操作与实验设计', cover_url: 'https://picsum.photos/id/180/1200/600' },
{ ...base[4], id: 10, title: '科研数据分析实训', subtitle: 'Python与SPSS实战', cover_url: 'https://picsum.photos/id/150/1200/600' },
],
ruralGovernment: [
{
id: 11,
title: '乡村特色农产品品牌打造',
subtitle: '覆盖10个乡镇品牌增值30%',
cover_url: 'https://picsum.photos/id/287/1200/600',
content: `<p>为当地蜂蜜、茶叶等农产品设计品牌形象。项目联合当地政府选取10个乡镇的特色农产品进行品牌化打造包括品牌定位、LOGO设计、包装创新、市场推广等全流程服务。组建由设计、营销、农学等专业研究生组成的服务团队深入乡村开展实地调研了解产品特点和市场需求。项目实施以来已成功打造“荆楚蜜语”蜂蜜、“云雾山茶”等5个区域品牌产品附加值提升30%以上带动农户户均增收8000元。</p>`,
create_time: '2025-03-01 08:00:00',
},
{
id: 12,
title: '乡村电商人才培育计划',
subtitle: '培训500+农户',
cover_url: 'https://picsum.photos/id/301/1200/600',
content: `<p>开设直播带货、短视频运营课程。计划面向农村地区开展电商技能培训覆盖500名农户和农村创业者。培训内容包括电商平台操作、直播带货技巧、短视频拍摄剪辑、产品包装设计、客户服务等方面采用“线上课程+线下实操+导师指导”的培训模式。配备20名研究生作为培训助教建立长期跟踪指导机制。目前已开展培训12期培训农户380名其中150名农户已成功开设电商店铺月销售额最高达5万元。</p>`,
create_time: '2025-02-15 10:00:00',
},
{
id: 13,
title: '"健康乡村"建设工程',
subtitle: '定期义诊 + 健康设施建设',
cover_url: 'https://picsum.photos/id/237/1200/600',
content: `<p>研究生医疗队下乡开展健康讲座与义诊活动。项目联合医学院、公共卫生学院组建研究生医疗队深入乡村开展健康服务。每月组织1次大型义诊活动提供常见病诊疗、健康体检、慢性病管理等服务每季度开展2次健康讲座内容包括健康教育、疾病预防、合理膳食等方面。同时协助乡村建设5个标准化卫生室配备基础医疗设备和常用药品。项目实施以来已开展义诊活动8次服务村民2000余人次健康讲座16场受益群众3000余人。</p>`,
create_time: '2025-01-20 09:00:00',
},
{
id: 14,
title: '农产品质量安全检测项目',
subtitle: '为乡村提供免费检测服务',
cover_url: 'https://picsum.photos/id/42/1200/600',
content: `<p>建立移动检测车覆盖周边5个乡镇。项目投入80万元购置移动检测车1辆配备农药残留检测仪、重金属检测仪、微生物检测仪等专业设备为乡村农产品提供免费质量安全检测服务。组建由食品质量与安全专业研究生组成的检测团队定期下乡开展检测服务同时为农户提供农产品质量安全咨询和技术指导。目前已开展检测服务20次检测农产品样本500余个合格率达98%,为农产品质量安全提供了有力保障。</p>`,
create_time: '2024-12-10 13:00:00',
},
],
};
return (maps[category] || []).sort((a, b) => new Date(b.create_time) - new Date(a.create_time));
},
}, },
}; };
</script> </script>
<style scoped> <style scoped>
/* 基础样式保持不变 */
* { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', system-ui, sans-serif; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', system-ui, sans-serif; }
.container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 20px; } .container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 20px; }
/* 导航栏 */
.navbar { background-color: #fff; box-shadow: 0 2px 12px rgba(0,0,0,0.06); padding: 1rem 0; position: sticky; top: 0; z-index: 100; } .navbar { background-color: #fff; box-shadow: 0 2px 12px rgba(0,0,0,0.06); padding: 1rem 0; position: sticky; top: 0; z-index: 100; }
.nav-links { display: flex; list-style: none; gap: 2.5rem; justify-content: center; } .nav-links { display: flex; list-style: none; gap: 2.5rem; justify-content: center; }
.nav-links a { text-decoration: none; color: #333; font-weight: 500; transition: all 0.3s ease; padding: 0.5rem 0; position: relative; cursor: pointer; } .nav-links a { text-decoration: none; color: #333; font-weight: 500; transition: all 0.3s ease; padding: 0.5rem 0; position: relative; cursor: pointer; }
@@ -331,14 +450,8 @@ export default {
.nav-links a.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 3px; background-color: #165DFF; border-radius: 3px; } .nav-links a.active::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 3px; background-color: #165DFF; border-radius: 3px; }
.nav-links a:hover:not(.active) { color: #4080FF; } .nav-links a:hover:not(.active) { color: #4080FF; }
/* 主要内容 */
.main-content { padding: 4rem 0; min-height: 80vh; } .main-content { padding: 4rem 0; min-height: 80vh; }
.header-section { text-align: center; margin-bottom: 3rem; }
.main-title { font-size: 2.5rem; color: #1D2129; margin-bottom: 0.5rem; font-weight: 700; }
.sub-title { color: #6B7280; font-size: 1.1rem; margin-bottom: 1.5rem; }
.divider { width: 80px; height: 3px; background-color: #165DFF; margin: 0 auto; border-radius: 3px; }
/* 主文章 */
.main-article { max-width: 900px; margin: 0 auto 5rem; text-align: center; } .main-article { max-width: 900px; margin: 0 auto 5rem; text-align: center; }
.article-cover { margin-bottom: 2.5rem; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(0,0,0,0.1); } .article-cover { margin-bottom: 2.5rem; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 32px rgba(0,0,0,0.1); }
.cover-img { width: 100%; height: auto; max-height: 500px; object-fit: cover; transition: transform 0.6s ease; } .cover-img { width: 100%; height: auto; max-height: 500px; object-fit: cover; transition: transform 0.6s ease; }
@@ -349,38 +462,13 @@ export default {
.article-date { color: #9CA3AF; font-size: 1rem; margin-bottom: 2.5rem; font-weight: 500; } .article-date { color: #9CA3AF; font-size: 1rem; margin-bottom: 2.5rem; font-weight: 500; }
.article-content { color: #4B5563; line-height: 1.95; font-size: 1.1rem; text-align: left; margin: 0 auto; } .article-content { color: #4B5563; line-height: 1.95; font-size: 1.1rem; text-align: left; margin: 0 auto; }
.article-content >>> p { margin-bottom: 1.5rem; } .article-content >>> p { margin-bottom: 1.5rem; }
.article-content >>> h1, .article-content >>> h2, .article-content >>> h3 { margin: 1.5rem 0 1rem; color: #1D2129; }
/* 相关文章标题 + 更多按钮 */ .related-title { display: flex; justify-content: space-between; align-items: center; text-align: center; margin: 4rem auto 2rem; max-width: 900px; }
.related-title {
display: flex;
justify-content: space-between;
align-items: center;
text-align: center;
margin: 4rem auto 2rem;
max-width: 900px;
}
.related-title h3 { font-size: 1.7rem; color: #1D2129; font-weight: 600; margin: 0; } .related-title h3 { font-size: 1.7rem; color: #1D2129; font-weight: 600; margin: 0; }
.view-all-btn { .view-all-btn { background: #165DFF; color: white; border: none; padding: 0.6rem 1.5rem; border-radius: 8px; font-size: 0.95rem; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; transition: all 0.3s ease; }
background: #165DFF; .view-all-btn:hover { background: #0E42D2; transform: translateY(-2px); }
color: white;
border: none;
padding: 0.6rem 1.5rem;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: all 0.3s ease;
}
.view-all-btn:hover {
background: #0E42D2;
transform: translateY(-2px);
}
.icon-arrow-right::after { content: '→'; font-size: 1.1rem; }
/* 相关卡片 */
.related-articles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 2rem; max-width: 1100px; margin: 0 auto 3rem; } .related-articles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 2rem; max-width: 1100px; margin: 0 auto 3rem; }
.related-card { background: #fff; border-radius: 14px; overflow: hidden; box-shadow: 0 6px 20px rgba(0,0,0,0.08); cursor: pointer; transition: all 0.4s ease; display: flex; flex-direction: column; } .related-card { background: #fff; border-radius: 14px; overflow: hidden; box-shadow: 0 6px 20px rgba(0,0,0,0.08); cursor: pointer; transition: all 0.4s ease; display: flex; flex-direction: column; }
.related-card:hover { transform: translateY(-8px); box-shadow: 0 16px 32px rgba(0,0,0,0.15); } .related-card:hover { transform: translateY(-8px); box-shadow: 0 16px 32px rgba(0,0,0,0.15); }
@@ -390,114 +478,102 @@ export default {
.card-subtitle { color: #4B5563; font-size: 0.95rem; margin-bottom: 0.75rem; font-weight: 500; font-style: italic; } .card-subtitle { color: #4B5563; font-size: 0.95rem; margin-bottom: 0.75rem; font-weight: 500; font-style: italic; }
.card-date { color: #9CA3AF; font-size: 0.9rem; } .card-date { color: #9CA3AF; font-size: 0.9rem; }
/* 空状态 */
.empty-state { text-align: center; padding: 4rem 0; color: #9CA3AF; font-size: 1.1rem; } .empty-state { text-align: center; padding: 4rem 0; color: #9CA3AF; font-size: 1.1rem; }
/* 页脚 */
.footer { background-color: #F7F8FA; padding: 2.5rem 0; margin-top: 5rem; border-top: 1px solid #E5E6EB; } .footer { background-color: #F7F8FA; padding: 2.5rem 0; margin-top: 5rem; border-top: 1px solid #E5E6EB; }
.copyright { text-align: center; color: #86909C; font-size: 0.95rem; } .copyright { text-align: center; color: #86909C; font-size: 0.95rem; }
/* 全部文章列表页面样式 */
.all-articles-page { max-width: 1000px; margin: 0 auto; } .all-articles-page { max-width: 1000px; margin: 0 auto; }
.breadcrumbs { margin-bottom: 2rem; font-size: 0.95rem; color: #6B7280; } .breadcrumbs { margin-bottom: 2rem; font-size: 0.95rem; color: #6B7280; }
.breadcrumbs a { color: #165DFF; text-decoration: none; margin-right: 0.5rem; } .breadcrumbs a { color: #165DFF; text-decoration: none; margin-right: 0.5rem; }
.breadcrumbs span { margin: 0 0.5rem; } .breadcrumbs span { margin: 0 0.5rem; }
.all-articles-header { .all-articles-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 3rem; padding-bottom: 1rem; border-bottom: 1px solid #E5E6EB; }
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3rem;
padding-bottom: 1rem;
border-bottom: 1px solid #E5E6EB;
}
.all-articles-header h2 { font-size: 2rem; color: #1D2129; font-weight: 700; margin: 0; } .all-articles-header h2 { font-size: 2rem; color: #1D2129; font-weight: 700; margin: 0; }
.back-btn { .back-btn { background: #fff; color: #165DFF; border: 1px solid #165DFF; padding: 0.6rem 1.5rem; border-radius: 8px; font-size: 0.95rem; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; transition: all 0.3s ease; }
background: #fff; .back-btn:hover { background: #F0F7FF; transform: translateY(-2px); }
color: #165DFF;
border: 1px solid #165DFF;
padding: 0.6rem 1.5rem;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: all 0.3s ease;
}
.back-btn:hover {
background: #F0F7FF;
transform: translateY(-2px);
}
.icon-arrow-left::before { content: '←'; font-size: 1.1rem; }
.all-articles-list { margin-top: 2rem; } .all-articles-list { margin-top: 2rem; }
.article-item { .article-item { display: flex; gap: 1.5rem; padding: 1.5rem; border-radius: 12px; cursor: pointer; transition: all 0.3s ease; margin-bottom: 1.5rem; background: #fff; box-shadow: 0 4px 16px rgba(0,0,0,0.05); }
display: flex; .article-item:hover { background: #F7F8FA; transform: translateX(4px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
gap: 1.5rem; .item-img { width: 120px; height: 120px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
padding: 1.5rem; .item-info { flex: 1; min-width: 0; }
border-radius: 12px; .item-title { font-size: 1.3rem; color: #1D2129; margin: 0 0 0.75rem; font-weight: 600; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
cursor: pointer; .item-subtitle { color: #4B5563; font-size: 1rem; margin: 0 0 0.75rem; font-style: italic; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
transition: all 0.3s ease; .item-date { color: #9CA3AF; font-size: 0.9rem; }
margin-bottom: 1.5rem;
background: #fff; /* 分页容器样式 */
box-shadow: 0 4px 16px rgba(0,0,0,0.05); .pagination-container { margin-top: 3rem; display: flex; justify-content: center; padding-bottom: 2rem; }
}
.article-item:hover { /* 适配Element Plus分页组件样式 */
background: #F7F8FA; ::v-deep .el-pagination { --el-pagination-color: #6B7280; --el-pagination-hover-color: #165DFF; --el-pagination-active-color: #fff; --el-pagination-active-bg-color: #165DFF; }
transform: translateX(4px); ::v-deep .el-pagination__sizes .el-input__wrapper { width: 100px; }
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
} /* 顶部横幅样式 */
.item-img { .top-banner {
width: 120px; width: 100%;
height: 120px; background-position: center center;
object-fit: cover; background-size: cover;
border-radius: 8px; padding: 3.5rem 0;
flex-shrink: 0; color: #fff;
} text-align: center;
.item-info { position: relative;
flex: 1;
min-width: 0;
}
.item-title {
font-size: 1.3rem;
color: #1D2129;
margin: 0 0 0.75rem;
font-weight: 600;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
height: 300px;
} }
.item-subtitle { .top-banner::before {
color: #4B5563; content: '';
font-size: 1rem; position: absolute;
margin: 0 0 0.75rem; top: 0;
font-style: italic; left: 0;
display: -webkit-box; width: 100%;
-webkit-line-clamp: 1; height: 100%;
-webkit-box-orient: vertical; background: rgba(0, 0, 0, 0.1);
overflow: hidden; z-index: 1;
} }
.item-date { .banner-container {
color: #9CA3AF; position: relative;
font-size: 0.9rem; z-index: 2;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.banner-content h3 {
font-size: 1.8rem;
margin-bottom: 1rem;
font-weight: 700;
letter-spacing: 0.5px;
}
/* 响应式适配 */
@media (max-width: 768px) {
.top-banner {
padding: 2.5rem 0;
}
.banner-content h3 {
font-size: 1.5rem;
}
}
@media (max-width: 480px) {
.top-banner {
padding: 2rem 0;
}
.banner-content h3 {
font-size: 1.3rem;
}
} }
/* 响应式 */
@media (max-width: 768px) { @media (max-width: 768px) {
.related-title { flex-direction: column; gap: 1rem; } .related-title { flex-direction: column; gap: 1rem; }
.related-articles { grid-template-columns: 1fr; } .related-articles { grid-template-columns: 1fr; }
/* 全部文章列表响应式 */
.all-articles-header { flex-direction: column; gap: 1.5rem; align-items: flex-start; } .all-articles-header { flex-direction: column; gap: 1.5rem; align-items: flex-start; }
.article-item { flex-direction: column; } .article-item { flex-direction: column; }
.item-img { width: 100%; height: 180px; } .item-img { width: 100%; height: 180px; }
.pagination-container { padding-bottom: 1rem; }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.main-title { font-size: 2rem; }
.article-title { font-size: 1.8rem; } .article-title { font-size: 1.8rem; }
.all-articles-header h2 { font-size: 1.6rem; } .all-articles-header h2 { font-size: 1.6rem; }
.nav-links { gap: 1.5rem; } .nav-links { gap: 1.5rem; }
.el-pagination { font-size: 0.85rem; }
::v-deep .el-pagination__sizes, ::v-deep .el-pagination__jumper { display: none; }
} }
</style> </style>