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

311 lines
6.5 KiB
Vue
Raw Normal View History

2026-04-23 17:03:40 +08:00
<template>
<div class="industry-detail-page">
<HeaderComponent />
<main class="detail-content">
<section class="detail-banner">
<div class="banner-overlay">
<div class="banner-wrapper">
<h1 class="banner-title">{{ t('industry.detailTitle') }}</h1>
<p class="banner-subtitle">{{ t('industry.detailTitleSub') }}</p>
2026-04-23 17:03:40 +08:00
</div>
</div>
</section>
<section class="breadcrumb-section">
<div class="breadcrumb-wrapper">
<span class="breadcrumb-item" @click="goHome">{{ t('nav.home') }}</span>
2026-04-23 17:03:40 +08:00
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-item" @click="goBack">{{ t('industry.listBanner') }}</span>
2026-04-23 17:03:40 +08:00
<span class="breadcrumb-separator">/</span>
<span class="breadcrumb-item active">{{ t('industry.breadcrumbDetail') }}</span>
2026-04-23 17:03:40 +08:00
</div>
</section>
<section class="detail-section" v-loading="loading">
<div class="detail-wrapper">
<article class="article-content">
<h1 class="article-title">{{ locale === 'en-US' && industryDetail.titleEn ? industryDetail.titleEn : industryDetail.title }}</h1>
2026-04-23 17:03:40 +08:00
<div class="article-meta">
<span class="meta-item">
<el-icon><Calendar /></el-icon>
{{ t('industry.publicTime') }}{{ formatDate(industryDetail.publishDate) }}
2026-04-23 17:03:40 +08:00
</span>
<span class="meta-item">
<el-icon><View /></el-icon>
{{ t('common.viewsLabel') }}{{ industryDetail.views }}
2026-04-23 17:03:40 +08:00
</span>
</div>
<div class="article-body" v-html="locale === 'en-US' && industryDetail.contentEn ? industryDetail.contentEn : industryDetail.content"></div>
2026-04-23 17:03:40 +08:00
</article>
<div class="back-button">
<el-button type="primary" @click="goBack">
<el-icon><Back /></el-icon>
{{ t('industry.returnList') }}
2026-04-23 17:03:40 +08:00
</el-button>
</div>
</div>
</section>
</main>
<FooterComponent />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
2026-04-23 17:03:40 +08:00
import { Calendar, View, Back } from '@element-plus/icons-vue'
import HeaderComponent from '@/components/HeaderComponent.vue'
import FooterComponent from '@/components/FooterComponent.vue'
import { post } from '@/utils/request'
import { industryApi } from '@/api/industry-api.ts'
const router = useRouter()
const route = useRoute()
const { t, locale } = useI18n()
2026-04-23 17:03:40 +08:00
// 行业动态详情数据
const industryDetail = ref<any>({
title: '',
content: '',
views: 0,
publishDate: ''
})
// 加载状态
const loading = ref(false)
// 获取行业动态详情
const getIndustryDetail = async (id: any) => {
try {
loading.value = true
// 先增加访问量
await industryApi.increaseViews(id)
// 查询详情通过list接口查询单条
const response = await post('/industry/list?pagenum=1&pagesize=1', {
id: id
})
if (response.data.list && response.data.list.length > 0) {
industryDetail.value = response.data.list[0]
}
} catch (error: any) {
console.error(t('industry.fetchDetailFail'), error)
2026-04-23 17:03:40 +08:00
} finally {
loading.value = false
}
}
// 格式化日期
const formatDate = (date: string) => {
if (!date) return ''
const d = new Date(date)
const year = d.getFullYear()
const month = (d.getMonth() + 1).toString().padStart(2, '0')
const day = d.getDate().toString().padStart(2, '0')
return `${year}-${month}-${day}`
}
// 返回首页
const goHome = () => {
router.push('/')
}
// 返回列表
const goBack = () => {
router.push('/industry')
}
// 组件加载时获取数据
onMounted(() => {
const id = route.query.id
if (id) {
getIndustryDetail(id)
}
})
</script>
<style scoped lang="less">
.industry-detail-page {
width: 100%;
min-height: 100vh;
background: #f8f9fa;
}
.detail-content {
width: 100%;
background: #f8f9fa;
padding-top: 70px;
}
.detail-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;
display: flex;
align-items: center;
}
.breadcrumb-item {
font-size: 14px;
color: #666;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: #1890ff;
}
&.active {
color: #1a1a1a;
cursor: default;
}
}
.breadcrumb-separator {
margin: 0 8px;
color: #999;
}
}
.detail-section {
padding: 40px 0 80px;
.detail-wrapper {
max-width: 1000px;
margin: 0 auto;
padding: 0 100px;
}
}
.article-content {
background: #fff;
border-radius: 8px;
padding: 40px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.article-title {
font-size: 28px;
font-weight: 700;
color: #1a1a1a;
margin: 0 0 20px;
line-height: 1.4;
}
.article-meta {
display: flex;
gap: 24px;
padding-bottom: 20px;
border-bottom: 1px solid #e8e8e8;
margin-bottom: 30px;
.meta-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 14px;
color: #666;
.el-icon {
font-size: 16px;
}
}
}
.article-body {
font-size: 16px;
line-height: 1.8;
color: #333;
p {
margin-bottom: 16px;
}
img {
max-width: 100%;
height: auto;
margin: 20px 0;
}
}
}
.back-button {
margin-top: 30px;
text-align: center;
}
@media (max-width: 768px) {
.banner-wrapper,
.breadcrumb-wrapper,
.detail-wrapper {
padding: 0 24px;
}
.detail-banner {
padding: 60px 0 40px;
.banner-title {
font-size: 28px;
}
}
.article-content {
padding: 24px;
.article-title {
font-size: 22px;
}
}
}
</style>