Files
.shoudate/demo-vue/src/views/industry/IndustryPage.vue

425 lines
9.3 KiB
Vue
Raw Normal View History

2026-04-23 17:03:40 +08:00
<template>
<div class="industry-page">
<HeaderComponent />
<main class="industry-content">
<section class="industry-banner">
<div class="banner-overlay">
<div class="banner-wrapper">
<h1 class="banner-title">{{ t('industry.listBanner') }}</h1>
<p class="banner-subtitle">{{ t('industry.listBannerSub') }}</p>
2026-04-23 17:03:40 +08:00
</div>
</div>
</section>
<section class="breadcrumb-section">
<div class="breadcrumb-wrapper">
<span class="breadcrumb-item">{{ t('nav.home') }}</span>
2026-04-23 17:03:40 +08:00
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-item active">{{ t('nav.industryNews') }}</span>
2026-04-23 17:03:40 +08:00
</div>
</section>
<section class="industry-list-section">
<div class="industry-list-wrapper">
<div class="industry-item" v-for="(item, index) in industryList" :key="index" @click="goToDetail(item.id)">
<div class="industry-item-main">
<h3 class="industry-title">{{ item.title }}</h3>
<div class="industry-meta">
<span class="meta-item">
<el-icon><View /></el-icon>
{{ t('common.viewsLabel') }}{{ item.views }}
2026-04-23 17:03:40 +08:00
</span>
</div>
</div>
<div class="industry-item-date">
<span class="date-year">{{ item.year }}</span>
<span class="date-day">{{ item.day }}</span>
</div>
</div>
<div class="pagination-section">
<div class="pagination-controls">
<button class="page-btn" :disabled="currentPage === 1" @click="prevPage">
<el-icon><ArrowLeft /></el-icon>
</button>
<button class="page-btn active">{{ currentPage }}</button>
<button class="page-btn" :disabled="currentPage === totalPages" @click="nextPage">
<el-icon><ArrowRight /></el-icon>
</button>
<span class="jump-text">{{ t('common.goTo') }}</span>
2026-04-23 17:03:40 +08:00
<input type="number" class="page-input" v-model.number="jumpPage" @keyup.enter="jumpToPage" min="1" :max="totalPages" />
<span class="jump-text">{{ t('common.toPage') }}</span>
<span class="page-info">{{ t('common.pageUnit') }}</span>
2026-04-23 17:03:40 +08:00
</div>
</div>
</div>
</section>
</main>
<FooterComponent />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
2026-04-23 17:03:40 +08:00
import { View, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import HeaderComponent from '@/components/HeaderComponent.vue'
import FooterComponent from '@/components/FooterComponent.vue'
import { post } from '@/utils/request'
const router = useRouter()
const { t } = useI18n()
2026-04-23 17:03:40 +08:00
// 行业动态列表数据
const industryList = ref<any[]>([])
// 分页相关
const currentPage = ref(1)
const totalPages = ref(1)
const jumpPage = ref(1)
const pageSize = 10
// 从数据库获取行业动态列表
const getIndustryList = async (page: number = 1) => {
try {
// 调用后端分页查询接口
const response = await post(`/industry/list?pagenum=${page}&pagesize=${pageSize}`, {
status: 1 // 只查询启用的动态
})
// 处理返回数据,格式化日期
const list = response.data.list || []
industryList.value = list.map((item: any) => {
// 解析发布日期
let year = '2026'
let day = '01-01'
if (item.publishDate) {
const date = new Date(item.publishDate)
year = date.getFullYear().toString()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const dayNum = date.getDate().toString().padStart(2, '0')
day = `${month}-${dayNum}`
} else if (item.createTime) {
const date = new Date(item.createTime)
year = date.getFullYear().toString()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const dayNum = date.getDate().toString().padStart(2, '0')
day = `${month}-${dayNum}`
}
return {
id: item.id,
title: item.title,
views: item.views || 0,
year: year,
day: day,
publishDate: item.publishDate
}
})
// 设置总页数
totalPages.value = Math.ceil(response.data.total / pageSize)
} catch (error: any) {
console.error(t('industry.fetchFail'), error)
2026-04-23 17:03:40 +08:00
industryList.value = []
}
}
// 跳转到行业动态详情
const goToDetail = (id: any) => {
router.push({
path: '/industry-detail',
query: { id: id }
})
}
// 跳转到指定页
const jumpToPage = () => {
if (jumpPage.value >= 1 && jumpPage.value <= totalPages.value) {
currentPage.value = jumpPage.value
getIndustryList(currentPage.value)
}
}
// 上一页
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--
getIndustryList(currentPage.value)
}
}
// 下一页
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++
getIndustryList(currentPage.value)
}
}
// 组件加载时获取数据
onMounted(() => {
getIndustryList(1)
})
</script>
<style scoped lang="less">
.industry-page {
width: 100%;
min-height: 100vh;
background: #f8f9fa;
}
.industry-content {
width: 100%;
background: #f8f9fa;
padding-top: 70px;
}
.industry-banner {
position: relative;
background: url(../../assets/images/bg2.jpg) center center / cover no-repeat;
padding: 80px 0 60px;
text-align: center;
min-height: 350px;
.banner-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
}
.banner-wrapper {
position: relative;
z-index: 1;
max-width: 1400px;
margin: 0 auto;
padding: 0 100px;
}
.banner-title {
font-size: 36px;
font-weight: 700;
color: #fff;
margin: 0 0 8px;
}
.banner-subtitle {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin: 0;
}
}
.breadcrumb-section {
background: #fff;
padding: 20px 0;
border-bottom: 1px solid #e8e8e8;
.breadcrumb-wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 0 100px;
}
.breadcrumb-item {
font-size: 14px;
color: #666;
&.active {
color: #1a1a1a;
}
}
.breadcrumb-separator {
margin: 0 8px;
color: #999;
}
}
.industry-list-section {
padding: 40px 0 80px;
.industry-list-wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 0 100px;
}
}
.industry-item {
background: #fff;
border-radius: 8px;
padding: 24px 32px;
margin-bottom: 16px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s;
cursor: pointer;
&:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
.industry-title {
color: #1890ff;
}
}
.industry-item-main {
flex: 1;
.industry-title {
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 12px;
transition: color 0.3s;
}
.industry-meta {
.meta-item {
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
color: #666;
.el-icon {
font-size: 16px;
}
}
}
}
.industry-item-date {
text-align: right;
margin-left: 20px;
.date-year {
display: block;
font-size: 12px;
color: #999;
margin-bottom: 4px;
}
.date-day {
display: block;
font-size: 24px;
font-weight: 700;
color: #1a1a1a;
}
}
}
.pagination-section {
margin-top: 40px;
text-align: center;
.pagination-controls {
display: inline-flex;
align-items: center;
gap: 8px;
.page-btn {
width: 32px;
height: 32px;
border: 1px solid #e8e8e8;
background: #fff;
color: #666;
border-radius: 4px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
&:hover:not(:disabled) {
border-color: #1890ff;
color: #1890ff;
}
&.active {
background: #1890ff;
border-color: #1890ff;
color: #fff;
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
.el-icon {
font-size: 16px;
}
}
.jump-text {
font-size: 14px;
color: #666;
}
.page-input {
width: 50px;
height: 32px;
border: 1px solid #e8e8e8;
border-radius: 4px;
text-align: center;
font-size: 14px;
color: #1a1a1a;
&:focus {
outline: none;
border-color: #1890ff;
}
}
.page-info {
font-size: 14px;
color: #666;
}
}
}
@media (max-width: 768px) {
.banner-wrapper,
.breadcrumb-wrapper,
.industry-list-wrapper {
padding: 0 24px;
}
.industry-banner {
padding: 60px 0 40px;
.banner-title {
font-size: 28px;
}
}
.industry-item {
flex-direction: column;
align-items: flex-start;
padding: 20px;
.industry-item-date {
text-align: left;
margin-left: 0;
margin-top: 12px;
}
}
}
</style>