Files
2026-09-11 12:25:38 +08:00

248 lines
5.0 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.
<template>
<div class="member-detail-page">
<PortalHeader active-path="/membership" />
<main class="container member-detail-main">
<div class="breadcrumb-bar">
<NuxtLink to="/">首页</NuxtLink>
<span>/</span>
<NuxtLink to="/membership">会员服务</NuxtLink>
<span>/</span>
<span>{{ service.title || "会员服务详情" }}</span>
</div>
<div v-if="loading" class="state-wrap">
<a-skeleton active :paragraph="{ rows: 10 }" />
</div>
<div v-else-if="!service.serviceId" class="state-wrap">
<a-result status="404" title="会员服务不存在" sub-title="您查找的会员服务不存在或已下线">
<template #extra>
<a-button type="primary" @click="navigateTo('/membership')">返回会员服务</a-button>
</template>
</a-result>
</div>
<article v-else class="member-detail-card">
<div class="member-head">
<div>
<div class="service-badge">{{ service.categoryName }}</div>
<h1>{{ service.title }}</h1>
<p>{{ service.summary || "会员服务详情" }}</p>
</div>
<span v-if="service.publishTime" class="join-time">发布时间{{ service.publishTime }}</span>
</div>
<div v-if="service.tags?.length" class="tag-list">
<span v-for="tag in service.tags" :key="tag">{{ tag }}</span>
</div>
<section class="content-section">
<h2>服务介绍</h2>
<div v-if="service.content" class="content-body" v-html="service.content" />
<div v-else class="content-body">
<p>{{ service.summary || "暂无详情。" }}</p>
</div>
</section>
</article>
</main>
<footer class="site-footer">
<PortalFooter />
</footer>
</div>
</template>
<script setup lang="ts">
import { message } from "ant-design-vue"
import { getSiteMembershipService, type SiteMembershipService } from "@/api/site"
import { usePageSeo } from "@/composables/usePageSeo"
definePageMeta({
layout: "blank"
})
usePageSeo({
title: "会员服务详情",
description: "广西决策咨询网会员服务详情页"
})
const route = useRoute()
const memberId = computed(() => route.params.id as string)
const loading = ref(true)
const service = ref<Partial<SiteMembershipService>>({})
useHead({
title: computed(() => `${service.value.title || "会员服务详情"} - 广西决策咨询网`),
meta: [
{ name: "description", content: computed(() => service.value.summary || "广西决策咨询网会员服务详情页") }
]
})
async function loadMember() {
loading.value = true
try {
service.value = await getSiteMembershipService(memberId.value)
} catch (error) {
service.value = {}
if (!(error instanceof Error && /404/.test(error.message))) {
message.error(error instanceof Error ? error.message : "加载失败")
}
} finally {
loading.value = false
}
}
watch(memberId, () => {
loadMember()
})
onMounted(() => {
loadMember()
})
</script>
<style scoped>
.member-detail-page {
min-height: 100vh;
background: #f5f7fa;
}
.container {
width: min(1200px, calc(100% - 32px));
margin: 0 auto;
}
.member-detail-main {
padding: 28px 0 48px;
}
.breadcrumb-bar {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 24px;
color: #7d8a98;
font-size: 14px;
}
.breadcrumb-bar a {
color: #4a6fa1;
}
.member-detail-card {
padding: 32px;
background: #fff;
border: 1px solid #e5ebf2;
}
.member-head {
display: flex;
align-items: start;
justify-content: space-between;
gap: 24px;
padding-bottom: 24px;
border-bottom: 1px solid #edf1f5;
}
.service-badge {
display: inline-flex;
margin-bottom: 14px;
padding: 6px 14px;
border-radius: 999px;
background: #eef5ff;
color: #2d7af0;
font-size: 13px;
}
.member-head h1 {
margin: 0 0 10px;
color: #1f2d3d;
font-size: 34px;
line-height: 1.2;
}
.member-head p {
margin: 0;
color: #64707d;
font-size: 15px;
}
.join-time {
flex-shrink: 0;
color: #7d8a98;
font-size: 14px;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 12px;
padding: 24px 0 10px;
}
.tag-list span {
padding: 7px 14px;
border: 1px solid #9fc3ff;
border-radius: 12px;
color: #2d7af0;
font-size: 14px;
}
.content-section {
padding-top: 8px;
}
.content-section h2 {
margin: 0 0 16px;
color: #1f2d3d;
font-size: 22px;
}
.content-body {
color: #495463;
font-size: 15px;
line-height: 2;
}
.content-body :deep(p) {
margin: 0 0 16px;
}
.content-body :deep(*:last-child) {
margin-bottom: 0;
}
.state-wrap {
padding: 40px 0;
}
.site-footer {
margin-top: 24px;
}
.footer-nav {
background: #1f4fa3;
}
.footer-nav-inner {
display: flex;
align-items: center;
justify-content: center;
gap: 32px;
min-height: 58px;
}
.footer-nav-inner a {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
}
@media (max-width: 768px) {
.member-head {
flex-direction: column;
}
}
</style>