完成社会服务的web界面
This commit is contained in:
@@ -1,5 +1,20 @@
|
||||
<template>
|
||||
<!-- 用ElConfigProvider包裹整个组件,配置中文语言 -->
|
||||
<el-config-provider :locale="zhCn">
|
||||
<div class="workstation-page">
|
||||
|
||||
<!-- 顶部横幅(背景图从后端接口获取) -->
|
||||
<div
|
||||
class="top-banner"
|
||||
:style="{
|
||||
backgroundImage: `url(${bannerUrl || 'https://picsum.photos/id/180/1920/400'})`
|
||||
}"
|
||||
>
|
||||
<div class="banner-container">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
@@ -7,21 +22,21 @@
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="currentTab = 'schoolEnterprise'"
|
||||
@click.prevent="switchTab('schoolEnterprise')"
|
||||
:class="{ active: currentTab === 'schoolEnterprise' && !showAllList }"
|
||||
>校企合作</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="currentTab = 'researchInternship'"
|
||||
@click.prevent="switchTab('researchInternship')"
|
||||
:class="{ active: currentTab === 'researchInternship' && !showAllList }"
|
||||
>研究实习项目</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="currentTab = 'ruralGovernment'"
|
||||
@click.prevent="switchTab('ruralGovernment')"
|
||||
:class="{ active: currentTab === 'ruralGovernment' && !showAllList }"
|
||||
>乡村政府项目</a>
|
||||
</li>
|
||||
@@ -31,14 +46,7 @@
|
||||
|
||||
<!-- 主要内容区 -->
|
||||
<main class="container main-content" v-loading="loading">
|
||||
<!-- 通用标题 -->
|
||||
<div class="header-section">
|
||||
<h1 class="main-title">良品优生省级研究生工作站</h1>
|
||||
<p class="sub-title">湖北省省级研究生工作站</p>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
|
||||
<!-- 全部文章列表页面 -->
|
||||
<!-- 全部文章列表页面(带分页) -->
|
||||
<div v-if="showAllList" class="all-articles-page">
|
||||
<!-- 面包屑导航 -->
|
||||
<div class="breadcrumbs">
|
||||
@@ -53,7 +61,7 @@
|
||||
<div class="all-articles-header">
|
||||
<h2>{{ getTabName(currentTab) }} - 全部项目</h2>
|
||||
<button class="back-btn" @click="showAllList = false">
|
||||
<i class="icon-arrow-left"></i> 返回
|
||||
返回
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -65,19 +73,40 @@
|
||||
class="article-item"
|
||||
@click="selectMainArticle(item)"
|
||||
>
|
||||
<img :src="item.cover_url" :alt="item.title" class="item-img" />
|
||||
<!-- 封面图添加默认占位图 -->
|
||||
<img
|
||||
:src="item.cover_url || 'https://picsum.photos/id/237/120/120'"
|
||||
:alt="item.title"
|
||||
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.create_time) }}</p>
|
||||
<p class="item-date">{{ formatDate(item.publish_time) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-if="allArticles.length === 0" class="empty-state">
|
||||
<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>
|
||||
|
||||
<!-- 原首页内容 -->
|
||||
@@ -87,23 +116,28 @@
|
||||
<article class="main-article">
|
||||
<!-- 封面图 -->
|
||||
<div class="article-cover">
|
||||
<img :src="currentArticle.cover_url" :alt="currentArticle.title" class="cover-img" />
|
||||
<img
|
||||
:src="currentArticle.cover_url || 'https://picsum.photos/id/237/1200/600'"
|
||||
:alt="currentArticle.title"
|
||||
class="cover-img"
|
||||
:onerror="defaultImg"
|
||||
/>
|
||||
</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>
|
||||
<p class="article-date">{{ formatDate(currentArticle.publish_time) }}</p>
|
||||
<div class="article-content" v-html="currentArticle.content || '<p>暂无详细内容</p>'"></div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- 相关文章标题 + 更多按钮 -->
|
||||
<div class="related-title">
|
||||
<h3>更多相关项目</h3>
|
||||
<button class="view-all-btn" @click="showAllList = true">
|
||||
查看全部 <i class="icon-arrow-right"></i>
|
||||
<button class="view-all-btn" @click="handleViewAll">
|
||||
查看全部
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -115,18 +149,23 @@
|
||||
class="related-card"
|
||||
@click="selectMainArticle(item)"
|
||||
>
|
||||
<img :src="item.cover_url" :alt="item.title" class="card-img" />
|
||||
<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.create_time) }}</p>
|
||||
<p class="card-date">{{ formatDate(item.publish_time) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div v-else class="empty-state">
|
||||
<div v-else-if="!loading" class="empty-state">
|
||||
<p>暂无内容</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,72 +178,247 @@
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<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 {
|
||||
name: 'WorkstationPage',
|
||||
components: {
|
||||
ElPagination,
|
||||
ElConfigProvider
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
zhCn, // 中文语言包
|
||||
currentTab: 'schoolEnterprise',
|
||||
articles: {},
|
||||
// 存储各分类的完整数据
|
||||
articles: {
|
||||
schoolEnterprise: [],
|
||||
researchInternship: [],
|
||||
ruralGovernment: []
|
||||
},
|
||||
currentArticle: null,
|
||||
relatedArticles: [],
|
||||
allArticles: [], // 用于全部文章列表
|
||||
allArticles: [], // 分页当前页数据
|
||||
total: 0, // 分页总条数
|
||||
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: {
|
||||
currentArticles() {
|
||||
return this.articles[this.currentTab] || [];
|
||||
},
|
||||
// 当前分类的分页配置
|
||||
currentPagination() {
|
||||
return this.pagination[this.currentTab];
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentTab: {
|
||||
immediate: true,
|
||||
handler(newTab) {
|
||||
this.fetchArticles(newTab);
|
||||
// 切换标签时隐藏全部列表页面
|
||||
// 切换分类时,加载首页数据
|
||||
this.fetchHomeData(newTab);
|
||||
this.showAllList = false;
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// 组件创建时获取横幅图片
|
||||
this.fetchBannerImage();
|
||||
},
|
||||
methods: {
|
||||
async fetchArticles(category) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const mockData = this.getMockData(category);
|
||||
this.articles[category] = mockData;
|
||||
switchTab(tab) {
|
||||
this.currentTab = tab;
|
||||
},
|
||||
|
||||
const list = this.articles[category];
|
||||
if (list.length > 0) {
|
||||
this.currentArticle = list[0];
|
||||
this.relatedArticles = list.slice(1, 4);
|
||||
this.allArticles = list; // 全部文章数据
|
||||
/**
|
||||
* 获取横幅图片(使用POST请求)
|
||||
*/
|
||||
async fetchBannerImage() {
|
||||
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 {
|
||||
this.currentArticle = null;
|
||||
this.relatedArticles = [];
|
||||
this.allArticles = [];
|
||||
ElMessage.warning('未找到横幅图片数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取文章失败:', error);
|
||||
this.$message?.error?.('加载失败') || alert('加载失败');
|
||||
console.error('获取横幅图片失败:', error);
|
||||
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 {
|
||||
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) {
|
||||
this.currentArticle = article;
|
||||
// 重新筛选相关文章(排除当前选中项,取前3条)
|
||||
this.relatedArticles = this.currentArticles
|
||||
.filter(a => a.id !== article.id)
|
||||
.sort((a, b) => new Date(b.publish_time) - new Date(a.publish_time))
|
||||
.slice(0, 3);
|
||||
this.showAllList = false; // 选中文章后返回首页
|
||||
this.showAllList = false;
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
},
|
||||
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString('zh-CN', {
|
||||
year: 'numeric',
|
||||
@@ -221,109 +435,14 @@ export default {
|
||||
};
|
||||
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>
|
||||
|
||||
<style scoped>
|
||||
/* 基础样式保持不变 */
|
||||
* { 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; }
|
||||
|
||||
/* 导航栏 */
|
||||
.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 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:hover:not(.active) { color: #4080FF; }
|
||||
|
||||
/* 主要内容 */
|
||||
.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; }
|
||||
.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; }
|
||||
@@ -349,38 +462,13 @@ export default {
|
||||
.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 >>> 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; }
|
||||
.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;
|
||||
}
|
||||
.view-all-btn:hover {
|
||||
background: #0E42D2;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.icon-arrow-right::after { content: '→'; font-size: 1.1rem; }
|
||||
.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; }
|
||||
.view-all-btn:hover { background: #0E42D2; transform: translateY(-2px); }
|
||||
|
||||
/* 相关卡片 */
|
||||
.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: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-date { color: #9CA3AF; font-size: 0.9rem; }
|
||||
|
||||
/* 空状态 */
|
||||
.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; }
|
||||
.copyright { text-align: center; color: #86909C; font-size: 0.95rem; }
|
||||
|
||||
/* 全部文章列表页面样式 */
|
||||
.all-articles-page { max-width: 1000px; margin: 0 auto; }
|
||||
.breadcrumbs { margin-bottom: 2rem; font-size: 0.95rem; color: #6B7280; }
|
||||
.breadcrumbs a { color: #165DFF; text-decoration: none; margin-right: 0.5rem; }
|
||||
.breadcrumbs span { margin: 0 0.5rem; }
|
||||
.all-articles-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid #E5E6EB;
|
||||
}
|
||||
.all-articles-header { 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; }
|
||||
.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;
|
||||
}
|
||||
.back-btn:hover {
|
||||
background: #F0F7FF;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.icon-arrow-left::before { content: '←'; font-size: 1.1rem; }
|
||||
.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; }
|
||||
.back-btn:hover { background: #F0F7FF; transform: translateY(-2px); }
|
||||
.all-articles-list { margin-top: 2rem; }
|
||||
.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);
|
||||
}
|
||||
.article-item:hover {
|
||||
background: #F7F8FA;
|
||||
transform: translateX(4px);
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
|
||||
}
|
||||
.item-img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.item-info {
|
||||
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;
|
||||
.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); }
|
||||
.article-item:hover { background: #F7F8FA; transform: translateX(4px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||
.item-img { width: 120px; height: 120px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
|
||||
.item-info { 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; }
|
||||
.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; }
|
||||
.item-date { color: #9CA3AF; font-size: 0.9rem; }
|
||||
|
||||
/* 分页容器样式 */
|
||||
.pagination-container { margin-top: 3rem; display: flex; justify-content: center; padding-bottom: 2rem; }
|
||||
|
||||
/* 适配Element Plus分页组件样式 */
|
||||
::v-deep .el-pagination { --el-pagination-color: #6B7280; --el-pagination-hover-color: #165DFF; --el-pagination-active-color: #fff; --el-pagination-active-bg-color: #165DFF; }
|
||||
::v-deep .el-pagination__sizes .el-input__wrapper { width: 100px; }
|
||||
|
||||
/* 顶部横幅样式 */
|
||||
.top-banner {
|
||||
width: 100%;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
padding: 3.5rem 0;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 300px;
|
||||
}
|
||||
.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;
|
||||
.top-banner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
z-index: 1;
|
||||
}
|
||||
.item-date {
|
||||
color: #9CA3AF;
|
||||
font-size: 0.9rem;
|
||||
.banner-container {
|
||||
position: relative;
|
||||
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) {
|
||||
.related-title { flex-direction: column; gap: 1rem; }
|
||||
.related-articles { grid-template-columns: 1fr; }
|
||||
|
||||
/* 全部文章列表响应式 */
|
||||
.all-articles-header { flex-direction: column; gap: 1.5rem; align-items: flex-start; }
|
||||
.article-item { flex-direction: column; }
|
||||
.item-img { width: 100%; height: 180px; }
|
||||
.pagination-container { padding-bottom: 1rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.main-title { font-size: 2rem; }
|
||||
.article-title { font-size: 1.8rem; }
|
||||
.all-articles-header h2 { font-size: 1.6rem; }
|
||||
.nav-links { gap: 1.5rem; }
|
||||
.el-pagination { font-size: 0.85rem; }
|
||||
::v-deep .el-pagination__sizes, ::v-deep .el-pagination__jumper { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user