Forráskód Böngészése

feat: 解决方案模板

Lee 2 napja
szülő
commit
aa5e91e4fb

+ 29 - 0
app/assets/icons/dzfs.svg

@@ -0,0 +1,29 @@
+<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="44" height="44" rx="8" fill="url(#paint0_linear_1234_3211)"/>
+<foreignObject x="-2" y="-2" width="72" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="backdrop-filter:blur(7px);clip-path:url(#bgblur_0_1234_3211_clip_path);height:100%;width:100%"></div></foreignObject><g filter="url(#filter0_ii_1234_3211)" data-figma-bg-blur-radius="14">
+<rect x="12" y="12" width="44" height="44" rx="8" fill="#CBDAFF" fill-opacity="0.4"/>
+</g>
+<path d="M29.75 20.875C28.875 20.875 28 21.575 28 22.45V24.025H41.3C42.175 24.025 43.05 24.725 43.05 25.6V42.75H44.8C45.675 42.75 46.55 42.05 46.55 41.175V22.45C46.55 21.575 45.85 20.875 44.8 20.875H29.75Z" fill="white"/>
+<path d="M40.2502 25.25H25.2002C24.3252 25.25 23.4502 25.95 23.4502 26.825V45.375C23.4502 46.25 24.1502 46.95 25.2002 46.95H40.2502C41.1252 46.95 42.0002 46.25 42.0002 45.375V26.825C42.0002 25.95 41.3002 25.25 40.2502 25.25ZM36.7502 37.5C37.2752 37.5 37.6252 37.85 37.6252 38.2C37.6252 38.55 37.2752 38.9 36.7502 38.9H33.2502V41C33.2502 41.35 32.9002 41.7 32.3752 41.7C31.8502 41.7 31.6752 41.35 31.6752 41V38.9H28.8752C28.3502 38.9 28.0002 38.55 28.0002 38.2C28.0002 37.85 28.3502 37.5 28.8752 37.5H31.6752V35.925H28.8752C28.3502 35.925 28.0002 35.75 28.0002 35.225C28.0002 34.875 28.3502 34.525 28.8752 34.525H31.1502L28.7002 31.9C28.3502 31.725 28.5252 31.2 28.8752 31.025C29.2252 30.675 29.7502 30.675 29.9252 31.025L32.5502 33.65L35.0002 30.85C35.1752 30.675 35.7002 30.675 36.0502 30.85C36.4002 31.2 36.4002 31.55 36.2252 31.725L33.7752 34.525H36.7502C37.2752 34.525 37.6252 34.875 37.6252 35.225C37.6252 35.75 37.1002 35.925 36.7502 35.925H33.2502V37.5H36.7502Z" fill="white"/>
+<defs>
+<filter id="filter0_ii_1234_3211" x="-2" y="-2" width="72" height="72" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="1" dy="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1234_3211"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="-1" dy="-1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.617412 0 0 0 0 0.688994 0 0 0 0 0.949294 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="effect1_innerShadow_1234_3211" result="effect2_innerShadow_1234_3211"/>
+</filter>
+<clipPath id="bgblur_0_1234_3211_clip_path" transform="translate(2 2)"><rect x="12" y="12" width="44" height="44" rx="8"/>
+</clipPath><linearGradient id="paint0_linear_1234_3211" x1="0" y1="0" x2="44" y2="47.5" gradientUnits="userSpaceOnUse">
+<stop stop-color="#7DA2FF"/>
+<stop offset="1" stop-color="#0049FF"/>
+</linearGradient>
+</defs>
+</svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 2 - 0
app/assets/icons/function.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 7 - 0
app/assets/icons/sfn.svg


+ 28 - 0
app/assets/icons/zypf.svg

@@ -0,0 +1,28 @@
+<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="44" height="44" rx="8" fill="url(#paint0_linear_1234_3217)"/>
+<foreignObject x="-2" y="-2" width="72" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="backdrop-filter:blur(7px);clip-path:url(#bgblur_0_1234_3217_clip_path);height:100%;width:100%"></div></foreignObject><g filter="url(#filter0_ii_1234_3217)" data-figma-bg-blur-radius="14">
+<rect x="12" y="12" width="44" height="44" rx="8" fill="#CBDAFF" fill-opacity="0.4"/>
+</g>
+<path d="M37.1679 38.1217C37.1679 37.2819 36.8343 36.4764 36.2405 35.8826C35.6466 35.2887 34.8411 34.9551 34.0013 34.9551C33.1614 34.9551 32.356 35.2887 31.7621 35.8826C31.1682 36.4764 30.8346 37.2819 30.8346 38.1217C30.8346 38.9616 31.1682 39.7671 31.7621 40.3609C32.356 40.9548 33.1614 41.2884 34.0013 41.2884C34.8411 41.2884 35.6466 40.9548 36.2405 40.3609C36.8343 39.7671 37.1679 38.9616 37.1679 38.1217ZM32.4179 25.1485V31.7897C32.4179 31.9976 32.4588 32.2035 32.5384 32.3957C32.618 32.5878 32.7346 32.7624 32.8816 32.9094C33.0286 33.0565 33.2032 33.1731 33.3953 33.2527C33.5874 33.3323 33.7933 33.3733 34.0013 33.3733C34.2092 33.3733 34.4151 33.3323 34.6073 33.2527C34.7994 33.1731 34.9739 33.0565 35.121 32.9094C35.268 32.7624 35.3846 32.5878 35.4642 32.3957C35.5437 32.2035 35.5846 31.9976 35.5846 31.7897V25.1574C35.5846 22.7203 38.2319 21.1851 40.3409 22.4062C42.368 23.5772 44.0307 25.2873 45.144 27.3466C46.2574 29.4059 46.7779 31.7336 46.6477 34.0709C46.3006 40.5449 40.8425 45.8535 34.361 46.0321C31.534 46.1131 28.7612 45.2455 26.4845 43.5676C24.2079 41.8896 22.5584 39.4978 21.799 36.7735C21.0396 34.0491 21.2141 31.149 22.2945 28.5353C23.3749 25.9216 25.2991 23.7448 27.7604 22.3517C29.8377 21.1699 32.4192 22.7571 32.4192 25.1485H32.4179Z" fill="white"/>
+<defs>
+<filter id="filter0_ii_1234_3217" x="-2" y="-2" width="72" height="72" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="1" dy="1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1234_3217"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="-1" dy="-1"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.617412 0 0 0 0 0.688994 0 0 0 0 0.949294 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="effect1_innerShadow_1234_3217" result="effect2_innerShadow_1234_3217"/>
+</filter>
+<clipPath id="bgblur_0_1234_3217_clip_path" transform="translate(2 2)"><rect x="12" y="12" width="44" height="44" rx="8"/>
+</clipPath><linearGradient id="paint0_linear_1234_3217" x1="0" y1="0" x2="44" y2="47.5" gradientUnits="userSpaceOnUse">
+<stop stop-color="#7DA2FF"/>
+<stop offset="1" stop-color="#0049FF"/>
+</linearGradient>
+</defs>
+</svg>

BIN
app/assets/images/case-bg.png


BIN
app/assets/images/solution-bg.png


BIN
app/assets/images/solution-mobile-bg.png


+ 9 - 0
app/assets/scss/common.scss

@@ -114,3 +114,12 @@ html:not(.zoom-ready) body {
 .d-din-pro-700-bold {
   font-family: 'D-DIN-PRO-700-Bold';
 }
+
+.btn-primary {
+  @apply bg-gradient-to-r from-[#779EFF] to-[#0A50FF];
+  border: none;
+  outline: none;
+  &:hover {
+    opacity: 0.8;
+  }
+}

+ 13 - 5
app/components/Header.vue

@@ -2,7 +2,7 @@
  * @Author: LiZhiWei
  * @Date: 2026-01-13 15:41:49
  * @LastEditors: LiZhiWei
- * @LastEditTime: 2026-01-22 10:51:05
+ * @LastEditTime: 2026-01-22 15:57:07
  * @Description: 
 -->
 <!--
@@ -85,10 +85,11 @@
               <!-- Right Content -->
               <div class="flex-1 pl-60px">
                 <div class="grid grid-cols-2 gap-x-60px gap-y-40px">
-                  <div
+                  <NuxtLink
                     v-for="(item, idx) in currentItems"
                     :key="idx"
                     class="flex gap-16px group/item cursor-pointer"
+                    :to="`/solution/${item.id}`"
                   >
                     <!-- Icon -->
                     <i :class="[item.icon, 'wh-48px']"></i>
@@ -102,7 +103,7 @@
                       </div>
                       <div class="text-12px text-#64748b lh-20px line-clamp-2">{{ item.desc }}</div>
                     </div>
-                  </div>
+                  </NuxtLink>
                 </div>
               </div>
             </div>
@@ -210,8 +211,14 @@
               </div>
               <div class="pl-4px grid grid-cols-2 gap-x-10px gap-y-10px">
                 <div v-for="(item, i) in abilities[tab.id]" :key="i" class="mobile-solution-card">
-                  <i :class="[item.icon, 'mobile-solution-icon']"></i>
-                  {{ item.title }}
+                  <NuxtLink
+                    :to="`/solution/${item.id}`"
+                    class="flex items-center gap-8px w-full"
+                    @click="isMobileMenuOpen = false"
+                  >
+                    <i :class="[item.icon, 'mobile-solution-icon']"></i>
+                    {{ item.title }}
+                  </NuxtLink>
                 </div>
               </div>
             </div>
@@ -291,6 +298,7 @@
 <style scoped lang="scss">
   .landing-header {
     @apply fixed top-0 left-0 z-100 w-full bg-transparent transition-all duration-300 ease;
+    @apply lt-sm:sticky;
 
     &:hover,
     &.is-scrolled {

+ 2 - 2
app/components/section/Ability.vue

@@ -40,12 +40,12 @@
               <div class="ability-card-desc pf-sc-regular">
                 {{ ability.desc }}
               </div>
-              <div class="ability-card-link">
+              <NuxtLink class="ability-card-link" :to="`/solution/${ability.id}`">
                 查看详情
                 <i
                   class="i-custom-arrow-right-c color-#0F67F8 wh-18px lt-sm:wh-28px transition-transform group-hover:translate-x-4px"
                 ></i>
-              </div>
+              </NuxtLink>
             </div>
           </div>
         </Transition>

+ 130 - 0
app/constants/common.ts

@@ -1,3 +1,7 @@
+import { id } from 'element-plus/es/locales.mjs'
+import { functions } from 'lodash-es'
+import { title } from 'process'
+
 export const solutions = [
   {
     id: 'sys-sf',
@@ -118,31 +122,37 @@ export const abilityTabs = [
 export const abilities: Record<string, Card[]> = {
   system: [
     {
+      id: 'SFS-001',
       title: '智能收费系统',
       desc: '自动生成账单、线上多渠道支付、实时对账、智能催缴,收缴率显著提升,财务效率提高80%',
       icon: 'i-custom-sf',
     },
     {
+      id: 'CTD-002',
       title: '综合工单调度',
       desc: '报修、投诉线上提交、智能派单、全程跟踪、业主评价,形成服务闭环,提升响应速度与满意度',
       icon: 'i-custom-gd',
     },
     {
+      id: 'MPI-003',
       title: '移动巡检巡更',
       desc: '扫码打卡、规范流程、问题实时上报,确保服务质量可追溯,降低管理盲区,提升巡检效率',
       icon: 'i-custom-ydxj',
     },
     {
+      id: 'SPLM-004',
       title: '智慧车场管理',
       desc: '无人值守、自动识别、线上缴费,降低人工成本70%,杜绝收费漏洞,提升车场运营效率',
       icon: 'i-custom-zhcc',
     },
     {
+      id: 'DDC-005',
       title: '数据决策中心',
       desc: '多维度经营报表、收缴率分析、业主满意度洞察,数据可视化呈现,助力科学决策与精细运营',
       icon: 'i-custom-sjjc',
     },
     {
+      id: 'ALM-006',
       title: '资产与租赁管理',
       desc: '房屋、车位、客户档案数字化管理,合同、费用一目了然,提升资产利用率与租赁管理效率。',
       icon: 'i-custom-zczl',
@@ -150,31 +160,37 @@ export const abilities: Record<string, Card[]> = {
   ],
   service: [
     {
+      id: 'OPAR-007',
       title: '在线缴费查账',
       desc: '物业费、车位费、水电煤一键缴纳,账单历史随时可查,缴费凭证电子化保存,便捷又透明。',
       icon: 'i-custom-zxjf',
     },
     {
+      id: 'OCRR-008',
       title: '一键报事报修',
       desc: '手机拍照上传问题,实时跟踪处理进度,服务完成后进行评价,让报修过程全程可视化。',
       icon: 'i-custom-bsbx',
     },
     {
+      id: 'IAC-009',
       title: '智能门禁通行',
       desc: '手机蓝牙、动态二维码、人脸识别多种方式开门,访客可远程邀请,提升社区安全与便利性。',
       icon: 'i-custom-znmj',
     },
     {
+      id: 'CID-010',
       title: '社区信息直达',
       desc: '停水停电、小区通知、政务公告精准推送,重要信息不再错过,提升信息传达效率。',
       icon: 'i-custom-sqxx',
     },
     {
+      id: 'NSAM-011',
       title: '邻里服务与商城',
       desc: '物业发布家政、维修等增值服务,业主可在线预约支付,打造社区生活服务生态圈。',
       icon: 'i-custom-llfw',
     },
     {
+      id: 'OVAD-012',
       title: '线上投票与议事',
       desc: '重要事项在线投票,议事结果公开透明,提升社区治理效率与业主参与度。',
       icon: 'i-custom-xstp',
@@ -182,31 +198,37 @@ export const abilities: Record<string, Card[]> = {
   ],
   hardware: [
     {
+      id: 'PEE-013',
       title: '人行出入口',
       desc: '人脸识别门禁机、门禁闸机、智能门锁,实现人员进出智能化管理,提升社区安全等级。',
       icon: 'i-custom-rxcrk',
     },
     {
+      id: 'VEE-014',
       title: '车行出入口',
       desc: '车牌识别摄像机、智能道闸、车位引导系统,实现车辆无人化值守,提升通行效率。',
       icon: 'i-custom-cxcrk',
     },
     {
+      id: 'CSM-015',
       title: '社区安防监控',
       desc: '高清监控摄像机、周界报警、电梯电动车禁入系统、高空抛物监测,打造立体安防体系。',
       icon: 'i-custom-sqaf',
     },
     {
+      id: 'SECM-016',
       title: '智慧能耗管理',
       desc: '远程智能水电表、节能控制设备,实现能耗数据实时采集与分析,助力节能降耗。',
       icon: 'i-custom-zhnh',
     },
     {
+      id: 'CCF-017',
       title: '便民充电设施',
       desc: '电动汽车充电桩、两轮车智能充电桩,支持多种支付方式,安全可靠,解决社区充电难题。',
       icon: 'i-custom-bmcd',
     },
     {
+      id: 'IOT-018',
       title: '物联网平台',
       desc: '统一设备接入与管理平台,打破硬件信息孤岛,实现设备联动与智能场景化控制。',
       icon: 'i-custom-iot',
@@ -407,3 +429,111 @@ export const historyYears: HistoryYear[] = [
     ],
   },
 ]
+
+export const solutionPoints = [
+  {
+    id: 'SFS-001',
+    title: '智慧收费系统',
+    subTitle: '破解物业收费难、对账烦的核心方案',
+    description:
+      '覆盖物业费、停车费、水电费等全品类收费场景,支持线上多渠道缴费+自动催缴+财务智能对账,收费率提升至95%+',
+    corePoints: {
+      title: '传统物业收费的核心痛点',
+      points: [
+        {
+          point: '收费率低',
+          pointDesc: '人工催费效率低,业主缴费意愿差,物业费收缴率普遍低于70%,现金流紧张',
+          icon: 'i-custom-sfn',
+        },
+        {
+          point: '对账繁琐',
+          pointDesc: '人工统计缴费数据,易出错、耗时长,财务对账周期长达3-5天,且需反复核对流水',
+          icon: 'i-custom-dzfs',
+        },
+        {
+          point: '争议频发',
+          pointDesc: '收费标准不透明,业主对公摊水电费、服务费等明细有异议,沟通成本高,易引发矛盾',
+          icon: 'i-custom-zypf',
+        },
+      ],
+    },
+    coreFunctions: {
+      title: '智慧收费系统核心功能',
+      function: [
+        {
+          name: '多渠道线上缴费',
+          funcDesc:
+            '支持物业费、停车费、公摊水电费等全品类费用收缴,集成微信、支付宝等多种缴费渠道,业主无需下载APP即可轻松缴费。',
+          funcPoints: ['全渠道覆盖', '免APP', '自动代扣'],
+        },
+        {
+          name: '智能分级催缴',
+          funcDesc:
+            '通过微信、短信等方式智能催缴,按欠费时长自动触发不同催缴动作,支持自定义催缴模板,有效提升催缴效率。',
+          funcPoints: ['分级规则', '模板定制', '人工提醒'],
+        },
+        {
+          name: '电子票据自动生成',
+          funcDesc:
+            '业主缴费后自动生成电子票据,直接推送到微信/邮箱,支持随时查询、下载、打印,满足财务合规要求。',
+          funcPoints: ['实时生成', '税务对接', '永久留存'],
+        },
+        {
+          name: '财务智能对账',
+          funcDesc:
+            '系统自动抓取各支付渠道交易流水,与内部收费数据精准匹配,对异常情况自动标记并预警,大幅提升财务对账效率。/邮箱,支持随时查询、下载、打印,满足财务合规要求。',
+          funcPoints: ['自动匹配', '异常预警', '多维度报表'],
+        },
+        {
+          name: '收费标准透明化',
+          funcDesc: '业主可在业主端查看每笔费用明细,系统首页公示收费标准,费用透明化,减少争议。',
+          funcPoints: ['明细可查', '标准公示', '异议反馈'],
+        },
+        {
+          name: '权限分级管理',
+          funcDesc:
+            '支持自定义角色,精准分配权限,所有操作记录留痕,不同项目数据相互隔离,保障数据安全。',
+          funcPoints: ['角色定制', '操作留痕', '数据隔离'],
+        },
+      ],
+    },
+    coreEffects: {
+      title: '方案落地核心效果',
+      effect: [
+        {
+          name: '物业收费率',
+          percent: '95%+',
+        },
+        {
+          name: '催缴效率提升',
+          percent: '80%',
+        },
+        {
+          name: '对账时间缩短',
+          percent: '90%',
+        },
+        {
+          name: '费用争议减少',
+          percent: '70%',
+        },
+      ],
+    },
+    typicalCases: {
+      title: '典型客户案例',
+      cases: [
+        {
+          caseName: '海口置地花园',
+          caseCover: 'https://huijia-website.oss-cn-beijing.aliyuncs.com/haikou-cover.png',
+          casePainPoint:
+            '人工收费率仅65%,财务对账需3人/天,业主对公摊水电费明细异议多,每月投诉超20起;临时停车费现金收取,易出现漏收、错收问题。',
+          caseEffect: [
+            '1. 收费率从65%提升至93%,其中自动代扣占比达45%;',
+            '2. 财务对账时间从3天缩短至10分钟,减少2名财务人员工作量;',
+            '3. 业主费用争议投诉率下降85%,满意度调研提升至92分;',
+            '4. 临时停车费漏收率从15%降至0,每月增收约2万元。',
+          ],
+        },
+      ],
+    },
+  },
+]

+ 2 - 1
app/models/common.ts

@@ -2,11 +2,12 @@
  * @Author: LiZhiWei
  * @Date: 2026-01-13 15:01:49
  * @LastEditors: LiZhiWei
- * @LastEditTime: 2026-01-15 17:51:48
+ * @LastEditTime: 2026-01-22 14:57:52
  * @Description:
  */
 declare global {
   type Card = {
+    id?: string
     title: string
     desc: string
     icon: string

+ 6 - 15
app/pages/about/index.vue

@@ -2,16 +2,14 @@
  * @Author: LiZhiWei
  * @Date: 2026-01-21 08:34:10
  * @LastEditors: LiZhiWei
- * @LastEditTime: 2026-01-21 09:09:48
+ * @LastEditTime: 2026-01-22 17:20:07
  * @Description: 
 -->
 <template>
-  <div class="landing">
-    <banner />
-    <about />
-    <section-history />
-    <section-cta />
-  </div>
+  <banner />
+  <about />
+  <section-history />
+  <section-cta />
 </template>
 
 <script setup lang="ts">
@@ -19,16 +17,9 @@
   import About from './components/about.vue'
 
   useSeoMeta({
-    title: '关于我们 - 绘家科技 | 专业的智慧社区解决方案提供商',
+    title: '关于绘家 - 绘家科技 | 专业的智慧社区解决方案提供商',
     description:
       '了解绘家科技的发展历程与企业愿景。我们专注通过科技赋能物业,构建美好的智慧社区生活。',
     keywords: '绘家科技简介,企业文化,发展历程,智慧社区愿景',
   })
 </script>
-<style scoped lang="scss">
-  .landing {
-    @apply lt-sm:pt-120px;
-    color: var(--hj-text);
-    background: var(--hj-bg);
-  }
-</style>

+ 8 - 18
app/pages/index/index.vue

@@ -1,19 +1,17 @@
 <!--
  * @Author: LiZhiWei
  * @LastEditors: LiZhiWei
- * @LastEditTime: 2026-01-22 10:19:40
+ * @LastEditTime: 2026-01-22 17:20:43
  * @Description: 
 -->
 <template>
-  <div class="landing">
-    <section-hero />
-    <section-solution />
-    <section-ability />
-    <section-cases />
-    <section-partnership />
-    <section-history />
-    <section-cta />
-  </div>
+  <section-hero />
+  <section-solution />
+  <section-ability />
+  <section-cases />
+  <section-partnership />
+  <section-history />
+  <section-cta />
 </template>
 
 <script setup lang="ts">
@@ -24,11 +22,3 @@
     keywords: '智慧物业,物业管理系统,社区数字化,绘管家,绘家科技',
   })
 </script>
-
-<style scoped lang="scss">
-  .landing {
-    @apply lt-sm:pt-120px;
-    color: var(--hj-text);
-    background: var(--hj-bg);
-  }
-</style>

+ 352 - 0
app/pages/solution/[id].vue

@@ -0,0 +1,352 @@
+<!--
+ * @Author: LiZhiWei
+ * @Date: 2026-01-22 14:08:24
+ * @LastEditors: LiZhiWei
+ * @LastEditTime: 2026-01-22 17:24:03
+ * @Description: 解决方案详情页
+-->
+<template>
+  <div v-if="solution" class="solution-page">
+    <!-- Hero Section -->
+    <section class="solution-hero">
+      <div
+        class="landing-container flex flex-col items-center justify-center h-full text-center lt-sm:px-32px"
+      >
+        <div class="hero-title pf-sc-semibold">{{ solution.title }}</div>
+        <div class="hero-subtitle pf-sc-semibold">{{ solution.subTitle }}</div>
+        <div class="hero-desc pf-sc-regular">{{ solution.description }}</div>
+        <button class="hero-btn btn-primary pf-sc-semibold" @click="openConsultation">
+          立即免费咨询
+        </button>
+      </div>
+    </section>
+
+    <!-- Core Pain Points -->
+    <section class="section-container bg-white">
+      <div class="landing-container lt-sm:px-32px">
+        <div class="section-title pf-sc-semibold">{{ solution.corePoints.title }}</div>
+        <div class="grid grid-cols-3 gap-25px lt-sm:grid-cols-1">
+          <div
+            v-for="(item, index) in solution.corePoints.points"
+            :key="index"
+            class="pain-card group"
+          >
+            <i :class="[item.icon, 'pain-icon']"></i>
+            <div class="pain-title pf-sc-semibold">{{ item.point }}</div>
+            <div class="pain-desc pf-sc-regular">{{ item.pointDesc }}</div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- Core Functions -->
+    <section class="section-container bg-#F6F8FD">
+      <div class="landing-container lt-sm:px-32px">
+        <div class="section-title pf-sc-semibold">{{ solution.coreFunctions.title }}</div>
+        <div class="grid grid-cols-1 md:grid-cols-2 gap-24px mt-60px">
+          <div
+            v-for="(item, index) in solution.coreFunctions.function"
+            :key="index"
+            class="function-card"
+          >
+            <div class="function-card-header">
+              <img src="~/assets/icons/function.svg" class="function-icon" alt="icon" />
+              <div class="function-title pf-sc-semibold">{{ item.name }}</div>
+            </div>
+            <div class="function-desc pf-sc-regular">{{ item.funcDesc }}</div>
+            <div class="function-tags">
+              <span
+                v-for="(tag, tIndex) in item.funcPoints"
+                :key="tIndex"
+                class="function-tag pf-sc-medium"
+              >
+                <i class="i-custom-check-one wh-15px lt-sm:wh-24px"></i>
+                {{ tag }}
+              </span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- Core Effects -->
+    <section class="section-container bg-white">
+      <div class="landing-container">
+        <div class="section-title pf-sc-semibold">{{ solution.coreEffects.title }}</div>
+        <div
+          class="flex justify-between mt-80px gap-y-40px lt-sm:mt-72px lt-sm:grid lt-sm:grid-cols-2!"
+        >
+          <div
+            v-for="(item, index) in solution.coreEffects.effect"
+            :key="index"
+            class="effect-item flex-1 text-center"
+          >
+            <div class="effect-percent d-din-pro-700-bold">{{ item.percent }}</div>
+            <div class="effect-name pf-sc-regular">{{ item.name }}</div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- Typical Cases -->
+    <section v-if="currentCase" class="section-container solution-case">
+      <div class="landing-container lt-sm:px-32px">
+        <div class="section-title pf-sc-semibold">{{ solution.typicalCases.title }}</div>
+        <div class="mt-60px lt-sm:mt-48px">
+          <div class="case-card">
+            <div class="case-img-wrapper">
+              <img :src="currentCase.caseCover" class="case-img" :alt="currentCase.caseName" />
+            </div>
+            <div class="case-content">
+              <div class="case-header">
+                <div class="case-name pf-sc-semibold">{{ currentCase.caseName }}</div>
+                <div v-if="(solution.typicalCases.cases?.length ?? 0) > 1" class="case-nav-btns">
+                  <!-- PC Prev -->
+                  <i
+                    class="i-custom-arrow-circle-left wh-32px transition-colors lt-sm:hidden"
+                    :class="
+                      activeCaseIndex === 0
+                        ? 'cursor-not-allowed opacity-50'
+                        : 'cursor-pointer hover:i-custom-arrow-circle-left-active'
+                    "
+                    @click="prevCase"
+                  ></i>
+                  <!-- Mobile Prev -->
+                  <i
+                    class="i-custom-button-previous-mobile wh-32px transition-all shrink-0 hidden lt-sm:block"
+                    :class="[
+                      activeCaseIndex === 0
+                        ? 'cursor-not-allowed i-custom-button-previous-mobile-disabled'
+                        : 'cursor-pointer active:i-custom-button-previous-mobile-active',
+                    ]"
+                    @click="prevCase"
+                  ></i>
+
+                  <!-- PC Next -->
+                  <i
+                    class="i-custom-arrow-circle-right wh-32px ml-12px transition-colors lt-sm:hidden"
+                    :class="
+                      activeCaseIndex === solution.typicalCases.cases.length - 1
+                        ? 'cursor-not-allowed opacity-50'
+                        : 'cursor-pointer hover:i-custom-arrow-circle-right-active'
+                    "
+                    @click="nextCase"
+                  ></i>
+                  <!-- Mobile Next -->
+                  <i
+                    class="i-custom-button-next-mobile wh-32px ml-12px transition-all shrink-0 hidden lt-sm:block"
+                    :class="[
+                      activeCaseIndex === solution.typicalCases.cases.length - 1
+                        ? 'cursor-not-allowed i-custom-button-next-mobile-disabled'
+                        : 'cursor-pointer active:i-custom-button-next-mobile-active',
+                    ]"
+                    @click="nextCase"
+                  ></i>
+                </div>
+              </div>
+
+              <div class="case-section">
+                <div class="case-subtitle pf-sc-semibold">客户痛点</div>
+                <div class="case-text pf-sc-regular">{{ currentCase.casePainPoint }}</div>
+              </div>
+              <div
+                class="case-section mt-24px bg-#F6F8FD p-16px rounded-8px lt-sm:mt-24px lt-sm:p-24px lt-sm:rounded-8px"
+              >
+                <div class="case-subtitle pf-sc-semibold">落地效果</div>
+                <div class="case-text pf-sc-regular">
+                  <div v-for="(effect, eIndex) in currentCase.caseEffect" :key="eIndex">
+                    {{ effect }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- CTA -->
+    <SectionCta />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { solutionPoints } from '@/constants/common'
+
+  const route = useRoute()
+  const { openConsultation } = useConsultation()
+
+  const solution = computed(() => solutionPoints.find((item) => item.id === route.params.id))
+
+  const activeCaseIndex = ref(0)
+  const currentCase = computed(() => {
+    if (!solution.value?.typicalCases?.cases?.length) return null
+    return solution.value.typicalCases.cases[activeCaseIndex.value]
+  })
+
+  const nextCase = () => {
+    if (!solution.value?.typicalCases?.cases) return
+    if (activeCaseIndex.value < solution.value.typicalCases.cases.length - 1) {
+      activeCaseIndex.value++
+    }
+  }
+
+  const prevCase = () => {
+    if (activeCaseIndex.value > 0) {
+      activeCaseIndex.value--
+    }
+  }
+</script>
+
+<style scoped lang="scss">
+  .section-container {
+    @apply py-120px lt-sm:py-120px;
+  }
+
+  .section-title {
+    @apply font-s-36px text-#000000 text-center lh-60px mb-40px lt-sm:font-s-48px lt-sm:mb-40px;
+  }
+
+  /* Hero */
+  .solution-hero {
+    @apply w-full h-600px relative bg-cover bg-center bg-no-repeat;
+    @apply lt-sm:h-auto lt-sm:py-160px;
+    background-image: url('~/assets/images/solution-bg.png');
+    @screen lt-sm {
+      background-image: url('~/assets/images/solution-mobile-bg.png');
+    }
+  }
+
+  .hero-title {
+    @apply font-s-48px text-#000000;
+    @apply lt-sm:font-s-56px lt-sm:px-20px;
+  }
+
+  .hero-subtitle {
+    @apply font-s-38px text-#000000 mb-16px;
+    @apply lt-sm:font-s-38px lt-sm:px-20px;
+  }
+
+  .hero-desc {
+    @apply font-s-18px text-#091221/70;
+    @apply lt-sm:font-s-26px lt-sm:px-32px;
+  }
+
+  .hero-btn {
+    @apply w-162px h-56px rounded-8px mt-36px font-s-18px text-white hover:opacity-80 transition-colors cursor-pointer;
+    @apply lt-sm:w-224px lt-sm:h-71px lt-sm:rounded-8px lt-sm:font-s-28px;
+  }
+
+  /* Pain Points */
+  .pain-card {
+    @apply bg-white rounded-16px p-40px border border-#E2E8F0 hover:shadow-md transition-all duration-300 text-center flex flex-col items-center;
+    @apply lt-sm:rounded-16px lt-sm:p-40px;
+  }
+
+  .pain-icon {
+    @apply wh-64px mb-16px;
+    @apply lt-sm:wh-69px;
+  }
+
+  .pain-title {
+    @apply font-s-18px text-#091221 mb-16px;
+    @apply lt-sm:font-s-32px;
+  }
+
+  .pain-desc {
+    @apply font-s-14px text-#091221/70 text-center;
+    @apply font-s-24px;
+  }
+
+  /* Functions */
+  .function-card {
+    @apply bg-gradient-to-b from-[#E5E9F5] to-[#EFF2FB] rounded-16px p-40px transition-all duration-300;
+    @apply lt-sm:rounded-16px lt-sm:p-40px;
+  }
+
+  .function-card-header {
+    @apply flex items-start flex-col gap-12px mb-12px;
+    @apply lt-sm:gap-24px lt-sm:mb-24px;
+  }
+
+  .function-icon {
+    @apply wh-44px;
+    @apply lt-sm:wh-78px;
+  }
+
+  .function-title {
+    @apply font-s-18px text-#091221;
+    @apply lt-sm:font-s-32px;
+  }
+
+  .function-desc {
+    @apply font-s-14px text-#091221/70 mb-12px lh-24px;
+    @apply lt-sm:font-s-24px lt-sm:lh-normal lt-sm:mb-24px;
+  }
+
+  .function-tags {
+    @apply flex flex-wrap gap-26px;
+    @apply lt-sm:gap-24px;
+  }
+
+  .function-tag {
+    @apply flex items-center font-s-14px text-#091221 gap-8px;
+    @apply lt-sm:font-s-24px lt-sm:gap-8px;
+  }
+
+  /* Effects */
+  .effect-percent {
+    @apply font-s-48px text-#0F67F8 lt-sm:font-s-56px;
+  }
+
+  .effect-name {
+    @apply font-s-16px text-#384146;
+  }
+
+  .solution-case {
+    @apply bg-cover bg-center bg-no-repeat;
+    background-image: url('~/assets/images/case-bg.png');
+  }
+
+  /* Typical Cases */
+  .case-card {
+    @apply bg-white rounded-16px p-24px flex gap-40px items-stretch shadow-sm;
+    @apply lt-sm:flex-col lt-sm:p-32px lt-sm:gap-42px lt-sm:rounded-16px;
+  }
+
+  .case-img-wrapper {
+    @apply w-542px h-342px rounded-8px overflow-hidden flex-shrink-0;
+    @apply lt-sm:w-full lt-sm:h-320px lt-sm:rounded-12px;
+  }
+
+  .case-img {
+    @apply w-full h-full object-fill;
+  }
+
+  .case-content {
+    @apply flex-1 py-10px flex flex-col justify-center;
+  }
+
+  .case-header {
+    @apply flex justify-between items-center mb-30px;
+    @apply lt-sm:mb-24px;
+  }
+
+  .case-name {
+    @apply font-s-22px text-#091221;
+  }
+
+  .case-nav-btns {
+    @apply flex items-center;
+  }
+
+  .case-subtitle {
+    @apply font-s-18px text-#091221 mb-12px;
+    @apply lt-sm:mb-12px;
+  }
+
+  .case-text {
+    @apply font-s-14px text-#091221/70 lh-24px;
+    @apply lt-sm:font-s-24px lt-sm:lh-normal;
+  }
+</style>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott