feat:页面优化
This commit is contained in:
parent
17cb1efcd0
commit
c5c9cb5cee
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@ -60,7 +60,10 @@ const handleCategoryKeydown = (event, index) => {
|
||||
</aside>
|
||||
<div id="case-panel" class="case-grid" role="tabpanel" :aria-label="active">
|
||||
<article v-for="item in filteredCases" :key="`${active}-${item.name}`" class="case-card">
|
||||
<div :class="['case-logo', `case-logo--${item.tone}`]">{{ item.short }}</div>
|
||||
<div :class="['case-logo-slot', { 'case-logo-slot--placeholder': !item.logo }]">
|
||||
<img v-if="item.logo" :src="item.logo" :alt="`${item.name.replace(/\n/g, '')} logo`" />
|
||||
<span v-else :class="['case-logo-fallback', `case-logo--${item.tone}`]">{{ item.short }}</span>
|
||||
</div>
|
||||
<p>{{ item.name }}</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<script setup>
|
||||
import IconMark from './IconMark.vue'
|
||||
import QrPlaceholder from './QrPlaceholder.vue'
|
||||
import SectionTitle from './SectionTitle.vue'
|
||||
</script>
|
||||
@ -15,21 +16,27 @@ import SectionTitle from './SectionTitle.vue'
|
||||
rel="noopener noreferrer"
|
||||
aria-label="在地图中打开办公地址"
|
||||
>
|
||||
<span class="address-icon">📍</span>
|
||||
<span class="address-icon">
|
||||
<IconMark name="map-pin" :size="22" />
|
||||
</span>
|
||||
<strong>办公地址:</strong>
|
||||
<span>杭州市西湖区翠苑街道塘苗路1号4号楼2楼</span>
|
||||
</a>
|
||||
<div class="contact-manager-grid">
|
||||
<article class="manager-card">
|
||||
<div class="manager-copy">
|
||||
<span class="manager-icon">👤</span>
|
||||
<span class="manager-icon">
|
||||
<IconMark name="user" :size="22" />
|
||||
</span>
|
||||
<p><strong>客户成功经理:王经理</strong><br /></p>
|
||||
</div>
|
||||
<QrPlaceholder label="王经理个人码" small />
|
||||
</article>
|
||||
<article class="manager-card">
|
||||
<div class="manager-copy">
|
||||
<span class="manager-icon">👤</span>
|
||||
<span class="manager-icon">
|
||||
<IconMark name="user" :size="22" />
|
||||
</span>
|
||||
<p><strong>客户成功经理:罗经理</strong><br /></p>
|
||||
</div>
|
||||
<QrPlaceholder label="罗经理个人码" small />
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { navItems } from '../data/homepage'
|
||||
import IconMark from './IconMark.vue'
|
||||
|
||||
const activeTarget = ref(navItems[0]?.target ?? '')
|
||||
const isMenuOpen = ref(false)
|
||||
@ -99,9 +100,7 @@ onBeforeUnmount(() => {
|
||||
:aria-label="isMenuOpen ? '收起主导航' : '展开主导航'"
|
||||
@click="toggleMenu"
|
||||
>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<IconMark :name="isMenuOpen ? 'x' : 'menu'" :size="24" />
|
||||
</button>
|
||||
<nav
|
||||
id="main-navigation"
|
||||
|
||||
@ -4,8 +4,7 @@
|
||||
<div class="hero-bg-orb hero-bg-orb--right"></div>
|
||||
<div class="container hero-grid">
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow">医疗服务数智化升级服务商</p>
|
||||
<h1>医疗行业患者全周期<br />管理服务数智化升级服务</h1>
|
||||
<h1><span class="hero-title-nowrap">医疗行业患者全周期管理服务</span><br />数智化升级服务商</h1>
|
||||
<div class="hero-badge">专注于医疗服务提质提效增收</div>
|
||||
<article id="company" class="intro-card glass-card">
|
||||
<p>
|
||||
|
||||
@ -6,27 +6,68 @@ defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<svg class="icon-mark" :width="size" :height="size" viewBox="0 0 48 48" fill="none" aria-hidden="true">
|
||||
<svg
|
||||
class="icon-mark"
|
||||
:width="size"
|
||||
:height="size"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<template v-if="name === 'user-flow'">
|
||||
<circle cx="24" cy="16" r="7" stroke="currentColor" stroke-width="3" />
|
||||
<path d="M12 37c2.4-8.2 7-12 12-12s9.6 3.8 12 12" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<path d="M9 24h5m20 0h5" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<path d="M18 21a8 8 0 0 0-16 0" />
|
||||
<circle cx="10" cy="8" r="5" />
|
||||
<path d="M22 20c0-3.37-2-6.5-4.5-8" />
|
||||
<path d="M17 3.13a5 5 0 0 1 0 9.74" />
|
||||
</template>
|
||||
<template v-else-if="name === 'clipboard'">
|
||||
<rect x="12" y="10" width="24" height="30" rx="5" stroke="currentColor" stroke-width="3" />
|
||||
<path d="M18 8h12l2 5H16l2-5Z" fill="currentColor" />
|
||||
<path d="M18 23h12M18 31h8" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<rect width="8" height="4" x="8" y="2" rx="1" ry="1" />
|
||||
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" />
|
||||
<path d="M9 12h6" />
|
||||
<path d="M9 16h6" />
|
||||
</template>
|
||||
<template v-else-if="name === 'chart'">
|
||||
<path d="M12 38h26" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<rect x="15" y="25" width="5" height="10" rx="2" fill="currentColor" />
|
||||
<rect x="24" y="17" width="5" height="18" rx="2" fill="currentColor" opacity="0.76" />
|
||||
<rect x="33" y="10" width="5" height="25" rx="2" fill="currentColor" opacity="0.52" />
|
||||
<path d="M3 3v18h18" />
|
||||
<path d="M18 17V9" />
|
||||
<path d="M13 17V5" />
|
||||
<path d="M8 17v-3" />
|
||||
</template>
|
||||
<template v-else-if="name === 'ai'">
|
||||
<path d="M12 8V4H8" />
|
||||
<rect width="16" height="12" x="4" y="8" rx="2" />
|
||||
<path d="M2 14h2" />
|
||||
<path d="M20 14h2" />
|
||||
<path d="M15 13v2" />
|
||||
<path d="M9 13v2" />
|
||||
</template>
|
||||
<template v-else-if="name === 'check'">
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</template>
|
||||
<template v-else-if="name === 'map-pin'">
|
||||
<path d="M20 10c0 4.99-5.54 10.19-7.4 11.8a1 1 0 0 1-1.2 0C9.54 20.19 4 14.99 4 10a8 8 0 0 1 16 0" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</template>
|
||||
<template v-else-if="name === 'user'">
|
||||
<path d="M18 20a6 6 0 0 0-12 0" />
|
||||
<circle cx="12" cy="10" r="4" />
|
||||
</template>
|
||||
<template v-else-if="name === 'menu'">
|
||||
<path d="M4 6h16" />
|
||||
<path d="M4 12h16" />
|
||||
<path d="M4 18h16" />
|
||||
</template>
|
||||
<template v-else-if="name === 'x'">
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="m6 6 12 12" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<path d="M15 32c-4-3-6-8-4-13 2-7 8-11 15-10 8 1 13 7 13 15 0 6-3 11-8 14" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<path d="M19 25h4l3-8 3 16 3-8h4" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M18 39h13" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M12 8v4" />
|
||||
<path d="M12 16h.01" />
|
||||
</template>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
@ -18,7 +18,9 @@ import SectionTitle from './SectionTitle.vue'
|
||||
</div>
|
||||
<ul class="feature-list">
|
||||
<li v-for="item in feature.items" :key="item">
|
||||
<span class="check-dot">✓</span>
|
||||
<span class="check-dot">
|
||||
<IconMark name="check" :size="11" />
|
||||
</span>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -40,7 +40,7 @@ const handleTabKeydown = (event, index) => {
|
||||
<template>
|
||||
<section class="solution-section page-section page-section--compact">
|
||||
<div class="container">
|
||||
<div class="solution-tabs" role="tablist" aria-label="版本切换">
|
||||
<div class="solution-tabs solution-tabs--mobile" role="tablist" aria-label="版本切换">
|
||||
<button
|
||||
v-for="(solution, index) in solutions"
|
||||
:key="solution.key"
|
||||
@ -59,7 +59,28 @@ const handleTabKeydown = (event, index) => {
|
||||
<span class="tab-indicator" :style="{ transform: `translateX(${activeIndex * 100}%)` }"></span>
|
||||
</div>
|
||||
|
||||
<div class="solution-grid">
|
||||
<div class="solution-grid solution-grid--desktop">
|
||||
<article
|
||||
v-for="solution in solutions"
|
||||
:key="solution.key"
|
||||
class="solution-card"
|
||||
>
|
||||
<div class="solution-card-top">
|
||||
<span class="solution-kicker">{{ solution.tab }}</span>
|
||||
<h3>{{ solution.title }}</h3>
|
||||
</div>
|
||||
<ol v-if="solution.key !== 'personal'" class="solution-points">
|
||||
<li v-for="point in solution.points" :key="point">{{ point }}</li>
|
||||
</ol>
|
||||
<p v-else class="solution-personal-text">{{ solution.points[0] }}</p>
|
||||
<div class="solution-qr-row">
|
||||
<span>具体咨询:</span>
|
||||
<QrPlaceholder :label="solution.qrLabel" :title="`${solution.tab}咨询二维码`" />
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="solution-panel solution-panel--mobile">
|
||||
<article
|
||||
id="solution-panel"
|
||||
:key="activeSolution.key"
|
||||
|
||||
@ -53,17 +53,17 @@ export const solutions = [
|
||||
}
|
||||
]
|
||||
|
||||
export const caseCategories = ['国家医学中心', '公立医院', '妇幼保健宫', '医疗集团客户']
|
||||
export const caseCategories = ['国家医学中心', '公立医院', '妇幼保健客户', '医疗集团客户']
|
||||
|
||||
export const cases = [
|
||||
{ short: '骨', name: '国家骨科医学中心\n上海市第六人民医院', tone: 'blue', category: '国家医学中心' },
|
||||
{ short: '呼', name: '国家呼吸医学中心\n广州医科大学附属第一医院', tone: 'orange', category: '国家医学中心' },
|
||||
{ short: '广', name: '广医口腔', tone: 'blue', category: '公立医院' },
|
||||
{ short: '广', name: '广医口腔', tone: 'blue', category: '公立医院' },
|
||||
{ short: '丹', name: '丹红互联网医院', tone: 'red', category: '公立医院' },
|
||||
{ short: '十', name: '圣德', tone: 'green', category: '妇幼保健宫' },
|
||||
{ short: '中', name: '中信医疗', tone: 'red', category: '医疗集团客户' },
|
||||
{ short: 'Z', name: '浙江震元', tone: 'cyan', category: '医疗集团客户' },
|
||||
{ short: '合', name: '合禾', tone: 'green', category: '医疗集团客户' },
|
||||
{ short: '…', name: '更多案例\n……', tone: 'gray', category: '医疗集团客户' }
|
||||
{ short: '骨', logo: '', name: '国家骨科医学中心\n上海市第六人民医院', tone: 'blue', category: '国家医学中心' },
|
||||
{ short: '呼', logo: '', name: '国家呼吸医学中心\n广州医科大学附属第一医院', tone: 'orange', category: '国家医学中心' },
|
||||
{ short: '广', logo: '', name: '广医口腔', tone: 'blue', category: '公立医院' },
|
||||
{ short: '广', logo: '', name: '广医口腔', tone: 'blue', category: '公立医院' },
|
||||
{ short: '丹', logo: '', name: '中丹红互联网医院', tone: 'red', category: '公立医院' },
|
||||
{ short: '十', logo: '', name: '圣德', tone: 'green', category: '妇幼保健客户' },
|
||||
{ short: '中', logo: '', name: '中信医疗', tone: 'red', category: '医疗集团客户' },
|
||||
{ short: 'Z', logo: '', name: '浙江震元', tone: 'cyan', category: '医疗集团客户' },
|
||||
{ short: '合', logo: '', name: '合禾', tone: 'green', category: '医疗集团客户' },
|
||||
{ short: '…', logo: '', name: '更多案例\n……', tone: 'gray', category: '医疗集团客户' }
|
||||
]
|
||||
|
||||
@ -130,14 +130,6 @@ button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-toggle span {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
border-radius: 999px;
|
||||
background: var(--brand);
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
position: relative;
|
||||
padding: 31px 0 28px;
|
||||
@ -244,6 +236,10 @@ button {
|
||||
color: #171b23;
|
||||
}
|
||||
|
||||
.hero-title-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hero-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@ -444,12 +440,12 @@ button {
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
min-height: 36px;
|
||||
padding: 8px 13px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, #fff, #fff5ec);
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
background: #fff7ec;
|
||||
color: #535b68;
|
||||
font-size: 14px;
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 138, 0, 0.10);
|
||||
border: 1px solid rgba(255, 138, 0, 0.12);
|
||||
}
|
||||
|
||||
.check-dot {
|
||||
@ -471,9 +467,9 @@ button {
|
||||
|
||||
.solution-tabs {
|
||||
position: relative;
|
||||
display: grid;
|
||||
display: none;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
width: min(760px, 100%);
|
||||
width: 100%;
|
||||
min-height: 58px;
|
||||
margin: 0 auto 28px;
|
||||
padding: 6px;
|
||||
@ -514,9 +510,13 @@ button {
|
||||
|
||||
.solution-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
width: min(760px, 100%);
|
||||
margin: 0 auto;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.solution-panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.solution-card {
|
||||
@ -683,12 +683,26 @@ button {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.case-logo {
|
||||
.case-logo-slot {
|
||||
flex: 0 0 auto;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.case-logo-slot img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.case-logo-fallback {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 14px;
|
||||
color: #fff;
|
||||
font-weight: 900;
|
||||
@ -715,7 +729,7 @@ button {
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
width: min(960px, 100%);
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 34px 40px;
|
||||
border-radius: 24px;
|
||||
@ -830,6 +844,9 @@ button {
|
||||
.feature-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.solution-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.case-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
@ -901,7 +918,14 @@ button {
|
||||
.contact-manager-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.solution-grid--desktop {
|
||||
display: none;
|
||||
}
|
||||
.solution-panel--mobile {
|
||||
display: block;
|
||||
}
|
||||
.solution-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
min-height: 50px;
|
||||
padding: 5px;
|
||||
@ -954,6 +978,7 @@ button {
|
||||
}
|
||||
.hero-copy h1 {
|
||||
font-size: 31px;
|
||||
letter-spacing: -0.05em;
|
||||
}
|
||||
.section-title {
|
||||
gap: 12px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user