| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- <template>
- <section
- id="ability"
- ref="abilityRef"
- class="ability transition-all duration-1000 ease-out"
- :class="[isAbilityVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-50px']"
- >
- <div class="ability-title pf-sc-semibold">一体化智慧解决方案</div>
- <div class="ability-desc pf-sc-regular">
- 绘家科技提供从软件到硬件的完整解决方案,覆盖物业管理的全场景需求
- </div>
- <div class="ability-content">
- <div class="ability-tabs">
- <div class="ability-tab-indicator" :style="abilityTabIndicatorStyle"></div>
- <div
- v-for="tab in abilityTabs"
- :key="tab.title"
- class="ability-tab-item"
- :class="[
- activeAbilityTab.id === tab.id ? 'text-white' : 'text-#091221 hover:text-#0F67F8',
- ]"
- @click="handleAbilityTabClick(tab)"
- >
- {{ tab.title }}
- </div>
- </div>
- <div class="tab-content">
- <Transition name="tab-fade" mode="out-in">
- <div :key="activeAbilityTab.id" class="ability-grid">
- <div
- v-for="ability in abilities[activeAbilityTab.id]"
- :key="ability.title"
- class="ability-card"
- >
- <i :class="ability.icon" class="ability-card-icon"></i>
- <div class="ability-card-title pf-sc-semibold">
- {{ ability.title }}
- </div>
- <div class="ability-card-desc pf-sc-regular">
- {{ ability.desc }}
- </div>
- <div class="ability-card-link">
- 查看详情
- <i
- class="i-custom-arrow-right-c color-#0F67F8 wh-18px lt-sm:wh-28px transition-transform group-hover:translate-x-4px"
- ></i>
- </div>
- </div>
- </div>
- </Transition>
- </div>
- </div>
- </section>
- </template>
- <script setup lang="ts">
- import { abilityTabs, abilities } from '@/constants/common'
- const abilityRef = ref<HTMLElement | null>(null)
- const { isVisible: isAbilityVisible } = useScrollReveal(abilityRef)
- const activeAbilityTab = ref<AbilityTab>(abilityTabs[0] as AbilityTab)
- const abilityTabIndicatorStyle = computed(() => {
- const activeTabIndex = abilityTabs.findIndex((tab) => tab.id === activeAbilityTab.value.id)
- return {
- transform: `translateX(${activeTabIndex * 100}%)`,
- }
- })
- const handleAbilityTabClick = (tab: AbilityTab) => {
- activeAbilityTab.value = tab
- }
- </script>
- <style scoped lang="scss">
- .ability {
- @apply py-120px;
- @extend %landing-container;
- @apply lt-sm:py-120px lt-sm:px-32px;
- background-size: 100% 100%;
- background-image: url('@/assets/images/bg-ability.png');
- @screen lt-sm {
- background-size: 100% 100%;
- background-image: url('@/assets/images/bg-ability-mobile.png');
- }
- }
- .ability-title {
- @apply font-s-36px text-#000000 pf-sc-semibold flex-center lh-60px;
- @apply lt-sm:font-s-48px lt-sm:lh-60px;
- }
- .ability-desc {
- @apply font-s-16px text-#091221/70 pf-sc-regular lh-30px flex-center mt-4px;
- @apply lt-sm:font-s-24px lt-sm:lh-40px lt-sm:text-center lt-sm:px-60px;
- }
- .ability-content {
- @apply mt-24px flex-center flex-col;
- @apply lt-sm:mt-40px;
- }
- .ability-tabs {
- @apply relative flex items-center rounded-14px border border-#ECEFF6 bg-#F6F8FD p-6px;
- @apply lt-sm:rounded-16px lt-sm:p-8px lt-sm:w-[calc(100%-40px)];
- }
- .ability-tab-indicator {
- @apply absolute w-136px h-[calc(100%-12px)] transition-all duration-300 ease-out rounded-8px bg-#0F67F8;
- @apply lt-sm:w-[calc((100%-16px)/3)] lt-sm:h-[calc(100%-16px)] lt-sm:rounded-12px;
- }
- .ability-tab-item {
- @apply relative z-1 cursor-pointer py-14px px-20px text-center font-s-16px transition-colors duration-300 pf-sc-regular;
- @apply lt-sm:flex-1 lt-sm:px-0 lt-sm:py-20px lt-sm:font-s-24px;
- }
- .tab-content {
- @apply pt-45px;
- @apply lt-sm:pt-40px lt-sm:w-full;
- }
- .ability-grid {
- @apply grid grid-cols-3 gap-24px;
- @apply lt-sm:grid-cols-2 lt-sm:gap-25px;
- }
- .ability-card {
- @apply group relative flex flex-col rounded-16px border border-#ECEFF6 bg-[linear-gradient(0deg,_#FFFFFF_0%,_rgba(255,255,255,0.6)_100%)] p-24px transition-all duration-300 hover:border-#0F67F8/30 hover:shadow-[0_8px_24px_rgba(15,103,248,0.08)];
- @apply lt-sm:p-24px lt-sm:rounded-16px;
- }
- .ability-card-icon {
- @apply wh-48px;
- @apply lt-sm:wh-78px;
- }
- .ability-card-title {
- @apply mt-16px font-s-18px font-semibold text-#091221 pf-sc-semibold;
- @apply lt-sm:font-s-32px;
- }
- .ability-card-desc {
- @apply mt-8px flex-1 font-s-14px text-#091221/70 pf-sc-regular;
- @apply lt-sm:font-s-24px lt-sm:mt-16px;
- }
- .ability-card-link {
- @apply mt-24px flex items-center gap-8px font-s-16px pf-sc-regular text-#0F67F8 transition-colors hover:text-#0A50FF cursor-pointer;
- @apply lt-sm:mt-48px lt-sm:font-s-28px;
- }
- .tab-fade-enter-active {
- transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
- }
- .tab-fade-leave-active {
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
- }
- .tab-fade-enter-from {
- opacity: 0;
- transform: translateX(30px);
- }
- .tab-fade-leave-to {
- opacity: 0;
- transform: translateX(-30px);
- }
- .grid > div {
- animation: card-slide-up 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
- }
- .grid > div:nth-child(1) {
- animation-delay: 0.05s;
- }
- .grid > div:nth-child(2) {
- animation-delay: 0.1s;
- }
- .grid > div:nth-child(3) {
- animation-delay: 0.15s;
- }
- .grid > div:nth-child(4) {
- animation-delay: 0.2s;
- }
- .grid > div:nth-child(5) {
- animation-delay: 0.25s;
- }
- .grid > div:nth-child(6) {
- animation-delay: 0.3s;
- }
- .grid > div:nth-child(7) {
- animation-delay: 0.35s;
- }
- .grid > div:nth-child(8) {
- animation-delay: 0.4s;
- }
- @keyframes card-slide-up {
- from {
- opacity: 0;
- transform: translateY(20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
- }
- </style>
|