调整细节
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m51s

This commit is contained in:
speakeloudest 2026-03-25 09:42:52 +02:00
parent 784cabaddc
commit b6caf1c38b
7 changed files with 110 additions and 91 deletions

View File

@ -2,31 +2,30 @@
<div class="flex w-full flex-col items-center justify-center md:justify-start"> <div class="flex w-full flex-col items-center justify-center md:justify-start">
<!-- 主下载按钮 --> <!-- 主下载按钮 -->
<div <div
class="mx-auto h-[60px] w-[210px] rounded-full bg-[#ADFF5B] md:-ml-2 md:h-[100px] md:w-[360px]" class="relative mx-auto flex h-[60px] w-[210px] items-center justify-center overflow-hidden rounded-full bg-[#ADFF5B] px-[16px] md:mb-4 md:ml-0 md:h-[83px] md:w-[300px] md:px-[24px]"
> >
<router-link
v-if="mainButton?.link && !mainButton.link.startsWith('http')"
:to="mainButton.link"
class="block transition-transform hover:brightness-110 active:scale-95"
>
<component :is="mainButton.mainIcon" class="h-full text-black" />
</router-link>
<a <a
v-else-if="mainButton?.link" v-if="mainButton?.link"
:href="mainButton.link" :href="mainButton.link"
target="_blank" target="_blank"
:aria-label="mainButton.label" :aria-label="mainButton.label"
class="block transition-transform hover:brightness-110 active:scale-95" class="flex h-full w-full items-center justify-center transition-transform hover:brightness-110 active:scale-95"
> >
<component :is="mainButton.mainIcon" class="h-full text-black" /> <component
:is="mainButton.mainIcon"
class="h-auto w-full text-black transition-transform"
/>
</a> </a>
<div <div
v-else v-else
:id="mainButton?.id" :id="mainButton?.id"
:aria-label="mainButton?.label" :aria-label="mainButton?.label"
class="cursor-pointer transition-transform hover:brightness-110 active:scale-95" class="flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:brightness-110 active:scale-95"
> >
<component :is="mainButton?.mainIcon" class="h-full text-black" /> <component
:is="mainButton?.mainIcon"
class="h-auto w-full text-black transition-transform"
/>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<svg viewBox="0 0 140 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="17 0 99 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="17" y="11" width="8.57529" height="8.60876" fill="currentColor"/> <rect x="17" y="11" width="8.57529" height="8.60876" fill="currentColor"/>
<rect x="26.3549" y="11" width="8.57529" height="8.60876" fill="currentColor"/> <rect x="26.3549" y="11" width="8.57529" height="8.60876" fill="currentColor"/>
<rect x="17" y="20.3914" width="8.57529" height="8.60876" fill="currentColor"/> <rect x="17" y="20.3914" width="8.57529" height="8.60876" fill="currentColor"/>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -1,4 +1,4 @@
<svg viewBox="0 0 140 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="15 0 96 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1511_3352)"> <g clip-path="url(#clip0_1511_3352)">
<path d="M28.2965 31C29.0321 31 29.6736 30.3585 29.6736 29.623V26.4069H30.5931C31.1448 26.4069 31.5126 26.0391 31.5126 25.4874V16.302H20.4875V25.4875C20.4875 26.0392 20.8553 26.407 21.407 26.407H22.3265V29.623C22.3265 30.3586 22.9679 31.0001 23.7036 31.0001C24.4391 31.0001 25.0805 30.3586 25.0805 29.623V26.407H26.9195V29.623C26.9195 30.3585 27.5609 31 28.2965 31Z" fill="currentColor"/> <path d="M28.2965 31C29.0321 31 29.6736 30.3585 29.6736 29.623V26.4069H30.5931C31.1448 26.4069 31.5126 26.0391 31.5126 25.4874V16.302H20.4875V25.4875C20.4875 26.0392 20.8553 26.407 21.407 26.407H22.3265V29.623C22.3265 30.3586 22.9679 31.0001 23.7036 31.0001C24.4391 31.0001 25.0805 30.3586 25.0805 29.623V26.407H26.9195V29.623C26.9195 30.3585 27.5609 31 28.2965 31Z" fill="currentColor"/>
<path d="M33.8092 25.4875C34.5448 25.4875 35.1861 24.8461 35.1861 24.1105V17.6785C35.1861 16.9468 34.5448 16.302 33.8092 16.302C33.0735 16.302 32.4321 16.9468 32.4321 17.6785V24.1105C32.4321 24.846 33.0735 25.4875 33.8092 25.4875Z" fill="currentColor"/> <path d="M33.8092 25.4875C34.5448 25.4875 35.1861 24.8461 35.1861 24.1105V17.6785C35.1861 16.9468 34.5448 16.302 33.8092 16.302C33.0735 16.302 32.4321 16.9468 32.4321 17.6785V24.1105C32.4321 24.846 33.0735 25.4875 33.8092 25.4875Z" fill="currentColor"/>

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -1,124 +1,138 @@
<template> <template>
<div class="review-carousel-container relative"> <div class="review-carousel-container relative">
<transition name="fade" mode="out-in"> <div
<div class="review-card lucid-glass-bar relative flex items-center overflow-hidden rounded-2xl p-4 text-white md:p-5"
v-if="currentReview" :style="{ height: isMobile ? '114px' : '130px' }"
:key="currentIndex" >
class="review-card flex items-center lucid-glass-bar text-white rounded-2xl overflow-hidden p-4 md:p-5 relative" <!-- Static More Reviews Button, 不受动画影响随时可点 -->
:style="{ height: isMobile ? '114px' : '130px' }" <router-link
to="/reviews"
class="absolute top-[18px] right-4 z-20 cursor-pointer text-[10px] text-white underline decoration-white underline-offset-4 transition-colors hover:text-[#ADFF5B] md:top-[24px] md:right-5 md:text-sm"
> >
<!-- Avatar --> More Reviews
<div class="flex-shrink-0 mr-4 md:mr-6"> </router-link>
<img <!-- 动画应用在卡片内部的内容上 -->
:src="currentReview.avatar" <transition name="fade" mode="out-in">
alt="User Avatar" <div v-if="currentReview" :key="currentIndex" class="flex h-full w-full items-center">
class="w-[70px] h-[70px] md:w-[84px] md:h-[84px] rounded-full object-cover border-2 border-pink-300/30" <!-- Avatar -->
/> <div class="mr-4 flex-shrink-0 md:mr-6">
</div> <img
:src="currentReview.avatar"
<!-- Content --> alt="User Avatar"
<div class="flex-grow min-w-0"> class="h-[70px] w-[70px] rounded-full border-2 border-pink-300/30 object-cover md:h-[84px] md:w-[84px]"
<div class="flex justify-between items-start mb-1"> />
<h3 class="text-base md:text-xl font-bold truncate pr-2">{{ currentReview.username }}</h3>
<router-link
to="/reviews"
class="more-reviews text-[10px] md:text-sm text-white hover:text-[#ADFF5B] transition-colors underline decoration-white underline-offset-4"
>
More Reviews
</router-link>
</div> </div>
<!-- Stars and Rating --> <!-- Content -->
<div class="flex items-center gap-1 mb-1 md:mb-2"> <div class="min-w-0 flex-grow">
<div class="flex gap-0.5"> <div class="mb-1 flex items-start justify-between">
<svg v-for="i in 5" :key="i" class="w-3 h-3 md:w-4 md:h-4 text-[#ADFF5B]" fill="currentColor" viewBox="0 0 20 20"> <h3 class="truncate pr-20 text-base font-bold md:pr-28 md:text-xl">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" /> {{ currentReview.username }}
</svg> </h3>
</div> </div>
<span class="text-xs md:text-sm text-white/50 font-medium ml-1">4.9</span>
<span class="text-xs md:text-sm text-white/30 ml-2">{{ currentReview.reviewCount }}k reviews</span>
</div>
<!-- Comment Text --> <!-- Stars and Rating -->
<p class="text-xs md:text-sm text-white/90 leading-[1.4] line-clamp-2 md:pr-4"> <div class="mb-1 flex items-center gap-1 md:mb-2">
{{ currentReview.comment }} <div class="flex gap-0.5">
</p> <svg
v-for="i in 5"
:key="i"
class="h-3 w-3 text-[#ADFF5B] md:h-4 md:w-4"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
/>
</svg>
</div>
<span class="ml-1 text-xs font-medium text-white/50 md:text-sm">4.9</span>
<span class="ml-2 text-xs text-white/30 md:text-sm"
>{{ currentReview.reviewCount }}k reviews</span
>
</div>
<!-- Comment Text -->
<p class="line-clamp-2 text-xs leading-[1.4] text-white/90 md:pr-4 md:text-sm">
{{ currentReview.comment }}
</p>
</div>
</div> </div>
</div> </transition>
</transition> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'; import { ref, onMounted, onUnmounted, computed } from 'vue'
// Import avatars // Import avatars
import avatar1 from './avatars/avatar1.png'; import avatar1 from './avatars/avatar1.png'
import avatar2 from './avatars/avatar2.png'; import avatar2 from './avatars/avatar2.png'
import avatar3 from './avatars/avatar3.png'; import avatar3 from './avatars/avatar3.png'
import avatar4 from './avatars/avatar4.png'; import avatar4 from './avatars/avatar4.png'
import avatar6 from './avatars/avatar6.png'; import avatar6 from './avatars/avatar6.png'
const isMobile = ref(false); const isMobile = ref(false)
const reviews = [ const reviews = [
{ {
username: '庄子不给', username: '庄子不给',
avatar: avatar1, avatar: avatar1,
comment: '真心不错,比我只前买的那个好用多了。网宿很给力。', comment: '真心不错,比我只前买的那个好用多了。网宿很给力。',
reviewCount: '5.7' reviewCount: '5.7',
}, },
{ {
username: 'TechEnthusiast', username: 'TechEnthusiast',
avatar: avatar6, avatar: avatar6,
comment: 'Speed is incredible! The best VPN I have used in years for international streaming.', comment: 'Speed is incredible! The best VPN I have used in years for international streaming.',
reviewCount: '12.4' reviewCount: '12.4',
}, },
{ {
username: '阿杰', username: '阿杰',
avatar: avatar2, avatar: avatar2,
comment: '非常稳定的连接在高峰时段也没掉过线。UI设计很现代用着很舒服。', comment: '非常稳定的连接在高峰时段也没掉过线。UI设计很现代用着很舒服。',
reviewCount: '3.2' reviewCount: '3.2',
}, },
{ {
username: 'Lina_Zhang', username: 'Lina_Zhang',
avatar: avatar3, avatar: avatar3,
comment: '客服响应速度很快,配置简单。推荐给需要长期稳定翻墙的朋友们。', comment: '客服响应速度很快,配置简单。推荐给需要长期稳定翻墙的朋友们。',
reviewCount: '8.9' reviewCount: '8.9',
}, },
{ {
username: 'GlobalNomad', username: 'GlobalNomad',
avatar: avatar4, avatar: avatar4,
comment: 'Perfect for my travels. Low latency and high security. A must-have for privacy.', comment: 'Perfect for my travels. Low latency and high security. A must-have for privacy.',
reviewCount: '6.1' reviewCount: '6.1',
} },
]; ]
const currentIndex = ref(0); const currentIndex = ref(0)
const currentReview = computed(() => reviews[currentIndex.value]); const currentReview = computed(() => reviews[currentIndex.value])
let timer: any = null; let timer: any = null
const startCarousel = () => { const startCarousel = () => {
timer = setInterval(() => { timer = setInterval(() => {
currentIndex.value = (currentIndex.value + 1) % reviews.length; currentIndex.value = (currentIndex.value + 1) % reviews.length
}, 5000); }, 5000)
}; }
const handleResize = () => { const handleResize = () => {
isMobile.value = window.innerWidth < 768; isMobile.value = window.innerWidth < 768
}; }
onMounted(() => { onMounted(() => {
handleResize(); handleResize()
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize)
startCarousel(); startCarousel()
}); })
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', handleResize); window.removeEventListener('resize', handleResize)
if (timer) clearInterval(timer); if (timer) clearInterval(timer)
}); })
</script> </script>
<style scoped> <style scoped>
@ -134,7 +148,9 @@ onUnmounted(() => {
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1), transform 0.8s cubic-bezier(0.4, 0, 0.2, 1); transition:
opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
} }
.fade-enter-from { .fade-enter-from {
@ -163,8 +179,12 @@ onUnmounted(() => {
border-radius: inherit; border-radius: inherit;
padding: 1px; padding: 1px;
background: linear-gradient(135deg, rgba(173, 255, 91, 0.1), transparent 50%); background: linear-gradient(135deg, rgba(173, 255, 91, 0.1), transparent 50%);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask:
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor; -webkit-mask-composite: xor;
mask-composite: exclude; mask-composite: exclude;
pointer-events: none; pointer-events: none;

View File

@ -69,7 +69,7 @@
<!-- No more data --> <!-- No more data -->
<div v-if="!hasMore && !isLoading" class="py-10 text-center text-sm text-white/30"> <div v-if="!hasMore && !isLoading" class="py-10 text-center text-sm text-white/30">
暂无更多 已经到底啦 ~
</div> </div>
</div> </div>
</main> </main>
@ -234,7 +234,7 @@ const loadMore = () => {
hasMore.value = false hasMore.value = false
} }
isLoading.value = false isLoading.value = false
}, 300) }, 800)
} }
useInfiniteScroll( useInfiniteScroll(