Header.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <!--
  2. * @Author: LiZhiWei
  3. * @Date: 2026-01-13 15:41:49
  4. * @LastEditors: LiZhiWei
  5. * @LastEditTime: 2026-01-20 14:00:24
  6. * @Description:
  7. -->
  8. <!--
  9. * @Author: LiZhiWei
  10. * @Description: AppHeader
  11. -->
  12. <template>
  13. <header class="landing-header" :class="{ 'is-scrolled': y > 0 }">
  14. <div
  15. class="landing-container h-80px flex items-center justify-between gap-16px lt-sm:h-128px lt-xs:px-15px"
  16. >
  17. <i class="i-custom-logo w-160px h-32px lt-sm:w-213px lt-sm:h-64px"></i>
  18. <nav class="hidden sm:flex items-center gap-52px text-16px text-#334155 h-full">
  19. <NuxtLink to="/" class="nav-link flex items-center">首页</NuxtLink>
  20. <NuxtLink to="/" class="nav-link flex items-center">产品中心</NuxtLink>
  21. <div class="group h-full flex items-center">
  22. <NuxtLink to="/" class="nav-link flex items-center">解决方案</NuxtLink>
  23. <!-- Mega Menu -->
  24. <div
  25. class="fixed left-0 top-60px sm:top-80px w-full bg-white shadow-lg border-t border-gray-100 hidden group-hover:block z-50 animate-fade-in-down"
  26. >
  27. <div class="landing-container py-40px flex">
  28. <!-- Left Sidebar -->
  29. <div class="w-240px border-r border-gray-100 pr-40px shrink-0">
  30. <div class="text-18px font-600 mb-20px text-#1e293b">解决方案分类</div>
  31. <div class="flex flex-col gap-4px">
  32. <div
  33. v-for="(cat, index) in solutionCategories"
  34. :key="index"
  35. class="px-16px py-12px rounded-4px cursor-pointer text-14px transition-colors"
  36. :class="
  37. activeCategory === index
  38. ? 'bg-#ECEFF6 text-#0F67F8 font-500'
  39. : 'text-#091221/70'
  40. "
  41. @mouseenter="activeCategory = index"
  42. >
  43. {{ cat.name }}
  44. </div>
  45. </div>
  46. </div>
  47. <!-- Right Content -->
  48. <div class="flex-1 pl-60px">
  49. <div class="grid grid-cols-2 gap-x-60px gap-y-40px">
  50. <div
  51. v-for="(item, idx) in currentItems"
  52. :key="idx"
  53. class="flex gap-16px group/item cursor-pointer"
  54. >
  55. <!-- Icon -->
  56. <i :class="[item.icon, 'wh-48px']"></i>
  57. <!-- Text -->
  58. <div>
  59. <div
  60. class="text-16px font-600 text-#1e293b mb-8px group-hover/item:text-#2563eb transition-colors"
  61. >
  62. {{ item.title }}
  63. </div>
  64. <div class="text-12px text-#64748b lh-20px line-clamp-2">{{ item.desc }}</div>
  65. </div>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </div>
  72. <NuxtLink to="/" class="nav-link flex items-center">客户案例</NuxtLink>
  73. <NuxtLink to="/" class="nav-link flex items-center">关于绘家</NuxtLink>
  74. <NuxtLink to="/" class="nav-link flex items-center">联系合作</NuxtLink>
  75. </nav>
  76. <div class="flex items-center gap-30px lt-sm:hidden">
  77. <span class="flex items-center gap-14px hidden sm:flex">
  78. <i class="i-custom-telephone wh-28px"></i>
  79. <span class="font-s-28px font-bold text-#28292E d-din-pro-600-semibold">
  80. 400-600-7709
  81. </span>
  82. </span>
  83. <button
  84. class="btn-primary text-white font-medium w-134px h-40px pf-sc-medium font-s-16px rounded-8px hidden sm:block"
  85. @click="openConsultation"
  86. >
  87. <span class="lh-20px">申请试用</span>
  88. </button>
  89. </div>
  90. <button class="sm:hidden text-#334155" @click="isMobileMenuOpen = !isMobileMenuOpen">
  91. <i v-if="!isMobileMenuOpen" class="i-custom-menu lt-sm:wh-48px"></i>
  92. <i v-else class="i-ep-close lt-sm:wh-48px"></i>
  93. </button>
  94. </div>
  95. </header>
  96. <!-- Mobile Menu Overlay -->
  97. <div
  98. v-if="isMobileMenuOpen"
  99. class="fixed inset-0 top-80px lt-sm:top-128px bg-white z-90 sm:hidden flex flex-col animate-fade-in-down overflow-hidden"
  100. >
  101. <nav class="flex-1 overflow-y-auto py-20px px-24px">
  102. <div class="flex flex-col gap-8px text-16px text-#334155 font-500">
  103. <NuxtLink
  104. to="/"
  105. class="mobile-nav-item flex items-center justify-between group"
  106. @click="isMobileMenuOpen = false"
  107. >
  108. <span>首页</span>
  109. </NuxtLink>
  110. <NuxtLink
  111. to="/"
  112. class="mobile-nav-item flex items-center justify-between group"
  113. @click="isMobileMenuOpen = false"
  114. >
  115. <span>产品中心</span>
  116. <i class="i-ep-arrow-right text-gray-300 text-12px group-active:text-#0F67F8"></i>
  117. </NuxtLink>
  118. <!-- Solutions Section -->
  119. <div class="border-b border-gray-100">
  120. <div
  121. class="mobile-nav-item flex items-center justify-between !border-none cursor-pointer"
  122. :class="{ 'text-#0F67F8': isMobileSolutionsOpen }"
  123. @click="isMobileSolutionsOpen = !isMobileSolutionsOpen"
  124. >
  125. <span>解决方案</span>
  126. <i
  127. class="i-ep-arrow-down transition-transform duration-300 text-gray-300"
  128. :class="{
  129. 'rotate-180': isMobileSolutionsOpen,
  130. 'text-#0F67F8': isMobileSolutionsOpen,
  131. }"
  132. ></i>
  133. </div>
  134. <div
  135. v-show="isMobileSolutionsOpen"
  136. class="pl-12px pb-16px flex flex-col gap-24px animate-fade-in"
  137. >
  138. <div v-for="(cat, idx) in solutionCategories" :key="idx">
  139. <div
  140. class="font-600 text-15px text-#1e293b mb-12px pl-10px border-l-3 border-#0F67F8 flex items-center h-16px"
  141. >
  142. {{ cat.name }}
  143. </div>
  144. <div class="pl-4px grid grid-cols-2 gap-x-10px gap-y-10px">
  145. <div
  146. v-for="(item, i) in cat.items"
  147. :key="i"
  148. class="text-13px text-#475569 bg-gray-50/80 border border-gray-100 rounded-8px py-10px px-8px flex items-center justify-center text-center active:bg-blue-50 active:border-blue-200 active:text-blue-600 transition-all duration-200"
  149. >
  150. {{ item.title }}
  151. </div>
  152. </div>
  153. </div>
  154. </div>
  155. </div>
  156. <NuxtLink
  157. to="/"
  158. class="mobile-nav-item flex items-center justify-between group"
  159. @click="isMobileMenuOpen = false"
  160. >
  161. <span>客户案例</span>
  162. <i class="i-ep-arrow-right text-gray-300 text-12px group-active:text-#0F67F8"></i>
  163. </NuxtLink>
  164. <NuxtLink
  165. to="/"
  166. class="mobile-nav-item flex items-center justify-between group"
  167. @click="isMobileMenuOpen = false"
  168. >
  169. <span>关于绘家</span>
  170. </NuxtLink>
  171. <NuxtLink
  172. to="/"
  173. class="mobile-nav-item flex items-center justify-between group"
  174. @click="isMobileMenuOpen = false"
  175. >
  176. <span>联系合作</span>
  177. </NuxtLink>
  178. </div>
  179. </nav>
  180. </div>
  181. </template>
  182. <script setup lang="ts">
  183. const { openConsultation } = useConsultation()
  184. const { y } = useWindowScroll()
  185. const isMobileMenuOpen = ref(false)
  186. const isMobileSolutionsOpen = ref(false)
  187. const activeCategory = ref(0)
  188. const solutionCategories = [
  189. {
  190. name: '物业管理系统',
  191. items: [
  192. {
  193. title: '智慧收费系统',
  194. desc: '自动生成账单、线上多渠道支付、实时对账、智能催缴,收缴率显著提升,财务效率提高80%',
  195. icon: 'i-custom-sf',
  196. },
  197. {
  198. title: '综合工单调度',
  199. desc: '报修、投诉线上提交、智能派单、全程跟踪、业主评价,形成服务闭环,提升响应速度与满意度',
  200. icon: 'i-custom-gd',
  201. },
  202. {
  203. title: '移动巡检巡更',
  204. desc: '扫码打卡、规范流程、问题实时上报,确保服务质量可追溯,降低管理盲区,提升巡检效率',
  205. icon: 'i-custom-ydxj',
  206. },
  207. {
  208. title: '智慧车场管理',
  209. desc: '无人值守、自动识别、线上缴费,降低人工成本70%,杜绝收费漏洞,提升车场运营效率',
  210. icon: 'i-custom-zhcc',
  211. },
  212. {
  213. title: '数据决策中心',
  214. desc: '多维度经营报表、收缴率分析、业主满意度洞察,数据可视化呈现,助力科学决策与精细运营',
  215. icon: 'i-custom-sjjc',
  216. },
  217. {
  218. title: '资产与租赁管理',
  219. desc: '房屋、车位、客户档案数字化管理,合同、费用一目了然,提升资产利用率与租赁管理效率',
  220. icon: 'i-custom-zczl',
  221. },
  222. ],
  223. },
  224. {
  225. name: '业主服务平台',
  226. items: [
  227. // Placeholder content for demo purposes
  228. {
  229. title: '业主移动端',
  230. desc: '提供便捷的线上服务入口,提升业主体验',
  231. icon: 'i-carbon-user-role',
  232. iconBg: 'bg-#3b82f6',
  233. },
  234. ],
  235. },
  236. {
  237. name: '智能硬件物联',
  238. items: [
  239. // Placeholder content for demo purposes
  240. {
  241. title: '智能门禁',
  242. desc: '安全便捷的通行体验,支持人脸识别',
  243. icon: 'i-carbon-gateway',
  244. iconBg: 'bg-#3b82f6',
  245. },
  246. ],
  247. },
  248. ]
  249. const currentItems = computed(() => solutionCategories[activeCategory.value]?.items || [])
  250. </script>
  251. <style scoped lang="scss">
  252. .landing-header {
  253. @apply fixed top-0 left-0 z-100 w-full bg-transparent transition-all duration-300 ease;
  254. &:hover,
  255. &.is-scrolled {
  256. @apply bg-white/80 backdrop-blur-12px shadow-[0_4px_20px_rgba(0,0,0,0.05)] border-b border-white/10;
  257. }
  258. @media (max-width: 767px) {
  259. @apply bg-white/80 backdrop-blur-12px shadow-[0_4px_20px_rgba(0,0,0,0.05)] border-b border-white/10;
  260. }
  261. }
  262. .nav-link {
  263. @apply relative py-8px text-[var(--hj-text-2)] transition-all duration-200 ease;
  264. &:hover,
  265. .group:hover & {
  266. @apply text-[var(--hj-primary)] font-600;
  267. }
  268. &::after {
  269. @apply content-[''] absolute bottom-0 left-1/2 w-0 h-3px bg-[var(--hj-primary)] transition-all duration-300 ease -translate-x-1/2;
  270. }
  271. &:hover::after,
  272. .group:hover &::after {
  273. @apply w-30px;
  274. }
  275. }
  276. .btn-primary {
  277. @apply bg-gradient-to-r from-[#779EFF] to-[#0A50FF] border-none outline-none hover:opacity-80;
  278. }
  279. @keyframes fadeInDown {
  280. from {
  281. opacity: 0;
  282. transform: translateY(-10px);
  283. }
  284. to {
  285. opacity: 1;
  286. transform: translateY(0);
  287. }
  288. }
  289. @keyframes fadeIn {
  290. from {
  291. opacity: 0;
  292. transform: translateY(-5px);
  293. }
  294. to {
  295. opacity: 1;
  296. transform: translateY(0);
  297. }
  298. }
  299. .animate-fade-in {
  300. animation: fadeIn 0.3s ease-out forwards;
  301. }
  302. .animate-fade-in-down {
  303. animation: fadeInDown 0.2s ease-out forwards;
  304. &::before {
  305. content: '';
  306. @apply absolute -top-10px left-0 w-full h-10px;
  307. }
  308. }
  309. .mobile-nav-item {
  310. @apply py-16px border-b border-gray-100 text-#334155 active:text-#0F67F8 transition-colors;
  311. }
  312. .safe-area-bottom {
  313. padding-bottom: calc(24px + env(safe-area-inset-bottom));
  314. }
  315. </style>