|
|
|
@ -1,5 +1,5 @@ |
|
|
|
<script setup> |
|
|
|
<script setup> |
|
|
|
import { ref, onMounted, onUnmounted, nextTick } from 'vue' |
|
|
|
import { ref, onMounted, onUnmounted, nextTick, computed } from 'vue' |
|
|
|
import { getHomeConfig } from '../services/api' |
|
|
|
import { getHomeConfig } from '../services/api' |
|
|
|
import { showToast } from 'vant' |
|
|
|
import { showToast } from 'vant' |
|
|
|
import SubmitAchievementForm from '../components/SubmitAchievementForm.vue' |
|
|
|
import SubmitAchievementForm from '../components/SubmitAchievementForm.vue' |
|
|
|
@ -13,10 +13,16 @@ const config = ref({ |
|
|
|
introduction: '', |
|
|
|
introduction: '', |
|
|
|
serviceHotline: [], |
|
|
|
serviceHotline: [], |
|
|
|
emails: [], |
|
|
|
emails: [], |
|
|
|
address: [] |
|
|
|
officialSite: [] |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const loading = ref(true) |
|
|
|
const loading = ref(true) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将简介文本按换行符分割成段落 |
|
|
|
|
|
|
|
const introductionParagraphs = computed(() => { |
|
|
|
|
|
|
|
if (!config.value.introduction) return [] |
|
|
|
|
|
|
|
return config.value.introduction.split(/\r\n|\r|\n/).filter(paragraph => paragraph.trim()) |
|
|
|
|
|
|
|
}) |
|
|
|
// 切换标签数据<van-icon name="balance-list" /><van-icon name="add-square" /> |
|
|
|
// 切换标签数据<van-icon name="balance-list" /><van-icon name="add-square" /> |
|
|
|
const tabs = [ |
|
|
|
const tabs = [ |
|
|
|
{ key: 'achievement', name: '成果清单', icon: 'balance-list', color: '#2196f3', activeColor: '#1976d2' }, |
|
|
|
{ key: 'achievement', name: '成果清单', icon: 'balance-list', color: '#2196f3', activeColor: '#1976d2' }, |
|
|
|
@ -83,6 +89,10 @@ onMounted(async () => { |
|
|
|
const response = await getHomeConfig() |
|
|
|
const response = await getHomeConfig() |
|
|
|
if (response.code === 1) { |
|
|
|
if (response.code === 1) { |
|
|
|
config.value = response.data |
|
|
|
config.value = response.data |
|
|
|
|
|
|
|
// 设置浏览器标题 |
|
|
|
|
|
|
|
if (response.data?.siteTitle) { |
|
|
|
|
|
|
|
document.title = response.data.siteTitle |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
showToast('获取数据失败') |
|
|
|
showToast('获取数据失败') |
|
|
|
} |
|
|
|
} |
|
|
|
@ -115,6 +125,7 @@ onUnmounted(() => { |
|
|
|
<!-- 顶部标题区域 --> |
|
|
|
<!-- 顶部标题区域 --> |
|
|
|
<div class="header"> |
|
|
|
<div class="header"> |
|
|
|
<h1 class="title">{{ config.title }}</h1> |
|
|
|
<h1 class="title">{{ config.title }}</h1> |
|
|
|
|
|
|
|
<p class="subtitle">{{ config.subTitle }}</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 内容区 --> |
|
|
|
<!-- 内容区 --> |
|
|
|
@ -125,7 +136,11 @@ onUnmounted(() => { |
|
|
|
<div v-if="loading" class="loading-container"> |
|
|
|
<div v-if="loading" class="loading-container"> |
|
|
|
<van-skeleton title :row="3" animated /> |
|
|
|
<van-skeleton title :row="3" animated /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-else class="intro-content">{{ config.introduction }}</div> |
|
|
|
<div v-else class="intro-content"> |
|
|
|
|
|
|
|
<p v-for="(paragraph, index) in introductionParagraphs" :key="index" class="intro-paragraph"> |
|
|
|
|
|
|
|
{{ paragraph }} |
|
|
|
|
|
|
|
</p> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 切换按钮区域 --> |
|
|
|
<!-- 切换按钮区域 --> |
|
|
|
@ -152,12 +167,12 @@ onUnmounted(() => { |
|
|
|
<div class="tab-content"> |
|
|
|
<div class="tab-content"> |
|
|
|
<!-- 成果清单 --> |
|
|
|
<!-- 成果清单 --> |
|
|
|
<div v-if="activeTab === 'achievement'" class="tab-panel"> |
|
|
|
<div v-if="activeTab === 'achievement'" class="tab-panel"> |
|
|
|
<AchievementList /> |
|
|
|
<AchievementList :config="config" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 需求清单 --> |
|
|
|
<!-- 需求清单 --> |
|
|
|
<div v-else-if="activeTab === 'demand'" class="tab-panel"> |
|
|
|
<div v-else-if="activeTab === 'demand'" class="tab-panel"> |
|
|
|
<DemandList /> |
|
|
|
<DemandList :config="config" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 成果填报 --> |
|
|
|
<!-- 成果填报 --> |
|
|
|
@ -183,13 +198,16 @@ onUnmounted(() => { |
|
|
|
<!-- 服务热线 --> |
|
|
|
<!-- 服务热线 --> |
|
|
|
<div class="contact-item-card phone-card"> |
|
|
|
<div class="contact-item-card phone-card"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<van-icon name="phone-o" size="18" color="#2196f3" /> |
|
|
|
<van-icon name="service-o" size="18" color="#2196f3" /> |
|
|
|
<span class="contact-item-label">服务热线</span> |
|
|
|
<span class="contact-item-label">服务热线</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="contact-item-content"> |
|
|
|
<div class="contact-item-content"> |
|
|
|
<div v-for="(item, index) in config.serviceHotline" :key="index" class="contact-person"> |
|
|
|
<div v-for="(item, index) in config.serviceHotline" :key="index" class="contact-person"> |
|
|
|
<span class="person-name">{{ item.name }}</span> |
|
|
|
<span class="person-name">{{ item.name }}</span> |
|
|
|
<a :href="`tel:${item.phone}`" class="person-phone">{{ item.phone }}</a> |
|
|
|
<a :href="`tel:${item.phone}`" class="person-phone"> |
|
|
|
|
|
|
|
<van-icon name="phone" size="14" color="#2196f3" /> |
|
|
|
|
|
|
|
<span>{{ item.phone }}</span> |
|
|
|
|
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@ -197,7 +215,7 @@ onUnmounted(() => { |
|
|
|
<!-- 邮箱咨询 --> |
|
|
|
<!-- 邮箱咨询 --> |
|
|
|
<div class="contact-item-card email-card"> |
|
|
|
<div class="contact-item-card email-card"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<van-icon name="email-o" size="18" color="#9c27b0" /> |
|
|
|
<van-icon name="envelop-o" size="18" color="#9c27b0" /> |
|
|
|
<span class="contact-item-label">邮箱咨询</span> |
|
|
|
<span class="contact-item-label">邮箱咨询</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="contact-item-content"> |
|
|
|
<div class="contact-item-content"> |
|
|
|
@ -207,16 +225,16 @@ onUnmounted(() => { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 办公地址 --> |
|
|
|
<!-- 协会官网 --> |
|
|
|
<div class="contact-item-card address-card"> |
|
|
|
<div class="contact-item-card official-site-card"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<div class="contact-item-header"> |
|
|
|
<van-icon name="location-o" size="18" color="#4caf50" /> |
|
|
|
<van-icon name="link-o" size="18" color="#4caf50" /> |
|
|
|
<span class="contact-item-label">办公地址</span> |
|
|
|
<span class="contact-item-label">协会官网</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="contact-item-content"> |
|
|
|
<div class="contact-item-content"> |
|
|
|
<div v-for="(addr, index) in config.address" :key="index" class="contact-address"> |
|
|
|
<a v-for="(site, index) in config.officialSite" :key="index" :href="site" class="contact-official-site" target="_blank"> |
|
|
|
{{ addr }} |
|
|
|
{{ site }} |
|
|
|
</div> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@ -249,6 +267,16 @@ onUnmounted(() => { |
|
|
|
word-break: break-word; |
|
|
|
word-break: break-word; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 副标题样式 */ |
|
|
|
|
|
|
|
.subtitle { |
|
|
|
|
|
|
|
font-size: 16px; |
|
|
|
|
|
|
|
font-weight: 500; |
|
|
|
|
|
|
|
margin: 8px 0 0 0; |
|
|
|
|
|
|
|
line-height: 1.3; |
|
|
|
|
|
|
|
word-break: break-word; |
|
|
|
|
|
|
|
opacity: 0.9; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 内容区 */ |
|
|
|
/* 内容区 */ |
|
|
|
.content { |
|
|
|
.content { |
|
|
|
padding: 15px; |
|
|
|
padding: 15px; |
|
|
|
@ -284,12 +312,26 @@ onUnmounted(() => { |
|
|
|
padding: 10px 0; |
|
|
|
padding: 10px 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 简介内容 */ |
|
|
|
/* 简介内容容器 */ |
|
|
|
.intro-content { |
|
|
|
.intro-content { |
|
|
|
|
|
|
|
display: block; |
|
|
|
|
|
|
|
width: 100%; |
|
|
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 简介段落 */ |
|
|
|
|
|
|
|
.intro-paragraph { |
|
|
|
font-size: 14px; |
|
|
|
font-size: 14px; |
|
|
|
line-height: 1.7; |
|
|
|
line-height: 1.7; |
|
|
|
color: #555; |
|
|
|
color: #555; |
|
|
|
text-align: justify; |
|
|
|
text-align: justify; |
|
|
|
|
|
|
|
text-indent: 2em; |
|
|
|
|
|
|
|
margin: 0 0 12px 0; |
|
|
|
|
|
|
|
word-wrap: break-word; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.intro-paragraph:last-child { |
|
|
|
|
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 正文占位符 */ |
|
|
|
/* 正文占位符 */ |
|
|
|
@ -377,17 +419,17 @@ onUnmounted(() => { |
|
|
|
color: #9c27b0; |
|
|
|
color: #9c27b0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 办公地址卡片样式 */ |
|
|
|
/* 协会官网卡片样式 */ |
|
|
|
.address-card { |
|
|
|
.official-site-card { |
|
|
|
background-color: rgba(76, 175, 80, 0.05); |
|
|
|
background-color: rgba(76, 175, 80, 0.05); |
|
|
|
border-left: 4px solid #4caf50; |
|
|
|
border-left: 4px solid #4caf50; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.address-card .contact-item-label { |
|
|
|
.official-site-card .contact-item-label { |
|
|
|
color: #4caf50; |
|
|
|
color: #4caf50; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.address-card .contact-address { |
|
|
|
.official-site-card .contact-official-site { |
|
|
|
color: #4caf50; |
|
|
|
color: #4caf50; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -414,9 +456,9 @@ onUnmounted(() => { |
|
|
|
/* 联系人信息 */ |
|
|
|
/* 联系人信息 */ |
|
|
|
.contact-person { |
|
|
|
.contact-person { |
|
|
|
display: flex; |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
flex-direction: row; |
|
|
|
align-items: center; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 8px; |
|
|
|
margin-bottom: 12px; |
|
|
|
font-size: 14px; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -428,10 +470,14 @@ onUnmounted(() => { |
|
|
|
.person-name { |
|
|
|
.person-name { |
|
|
|
color: #666; |
|
|
|
color: #666; |
|
|
|
font-weight: 500; |
|
|
|
font-weight: 500; |
|
|
|
|
|
|
|
margin-right: 12px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 联系人电话 */ |
|
|
|
/* 联系人电话 */ |
|
|
|
.person-phone { |
|
|
|
.person-phone { |
|
|
|
|
|
|
|
display: flex; |
|
|
|
|
|
|
|
align-items: center; |
|
|
|
|
|
|
|
gap: 6px; |
|
|
|
font-weight: 500; |
|
|
|
font-weight: 500; |
|
|
|
text-decoration: none; |
|
|
|
text-decoration: none; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -444,12 +490,18 @@ onUnmounted(() => { |
|
|
|
font-weight: 500; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 联系地址 */ |
|
|
|
/* 协会官网链接 */ |
|
|
|
.contact-address { |
|
|
|
.contact-official-site { |
|
|
|
display: block; |
|
|
|
display: block; |
|
|
|
font-size: 14px; |
|
|
|
font-size: 14px; |
|
|
|
font-weight: 500; |
|
|
|
font-weight: 500; |
|
|
|
line-height: 1.6; |
|
|
|
line-height: 1.6; |
|
|
|
|
|
|
|
text-decoration: none; |
|
|
|
|
|
|
|
word-break: break-all; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.contact-official-site:hover { |
|
|
|
|
|
|
|
text-decoration: underline; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 切换按钮区域 */ |
|
|
|
/* 切换按钮区域 */ |
|
|
|
|