增加评论样式
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 2m9s

This commit is contained in:
speakeloudest 2026-03-23 12:09:21 +02:00
parent 73afc3c435
commit 784cabaddc
7 changed files with 326 additions and 18 deletions

View File

@ -4,8 +4,15 @@
<div
class="mx-auto h-[60px] w-[210px] rounded-full bg-[#ADFF5B] md:-ml-2 md:h-[100px] md:w-[360px]"
>
<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
v-if="mainButton?.link"
v-else-if="mainButton?.link"
:href="mainButton.link"
target="_blank"
:aria-label="mainButton.label"
@ -31,8 +38,15 @@
<div class="flex items-center justify-center gap-4 md:justify-start">
<template v-for="(item, index) in otherButtons" :key="index">
<router-link
v-if="item.link && !item.link.startsWith('http')"
:to="item.link"
class="transition-transform hover:brightness-110 active:scale-95"
>
<component :is="item.secondaryIcon" class="h-[24px] text-white md:h-[34px]" />
</router-link>
<a
v-if="item.link"
v-else-if="item.link"
:href="item.link"
target="_blank"
:aria-label="item.label"
@ -68,8 +82,6 @@ import request from '@/utils/request'
import { computed, ref, onMounted } from 'vue'
import { getAllQueryString } from '@/utils/url-utils.ts'
const downLoadWin = ref('')
const downLoadMac = ref('')
const currentPlatform = ref('win')
onMounted(() => {
@ -109,29 +121,36 @@ onMounted(() => {
// downLoadMac.value = res.url
// })
request
.get('/api/v1/common/client/download', {
invite_code: getAllQueryString('ic'),
platform: 'windows',
})
.then((res: any) => {
downLoadWin.value = res.url
})
const ADJ_BASE_URL = 'https://hifastvpn.go.link/?adj_t=1xf6e7ru'
const getTrackedUrl = (target: string) => {
if (!target) return ''
return `${ADJ_BASE_URL}&adj_redirect=${encodeURIComponent(target)}`
}
const allDownloadOptions = computed(() => [
{
key: 'win',
mainIcon: Icon1,
secondaryIcon: WinIcon,
link: downLoadWin.value,
link: getTrackedUrl(
'https://api.hifast.biz/v1/common/client/download/file/Hi快VPN-windows-1.0.0.exe',
),
label: 'Windows',
id: 'downloadButton_win',
},
{ key: 'mac', mainIcon: Icon3, secondaryIcon: MacIcon, label: 'macOS', id: 'downloadButton_mac' },
{
key: 'mac',
mainIcon: Icon3,
secondaryIcon: MacIcon,
link: getTrackedUrl('https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167'),
label: 'macOS',
id: 'downloadButton_mac',
},
{
key: 'ios',
mainIcon: Icon2,
secondaryIcon: AppleIcon,
link: '/help',
label: 'iOS',
id: 'downloadButton_apple',
},
@ -139,6 +158,9 @@ const allDownloadOptions = computed(() => [
key: 'android',
mainIcon: Icon4,
secondaryIcon: AndroidIcon,
link: getTrackedUrl(
'https://api.hifast.biz/v1/common/client/download/file/Hi%E5%BF%ABVPN-android-1.0.0.apk',
),
label: 'Android',
id: 'downloadButton_android',
},

View File

@ -20,13 +20,12 @@
<div class="flex-grow min-w-0">
<div class="flex justify-between items-start mb-1">
<h3 class="text-base md:text-xl font-bold truncate pr-2">{{ currentReview.username }}</h3>
<a
href="https://hifastvpn.com"
target="_blank"
<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
</a>
</router-link>
</div>
<!-- Stars and Rating -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

279
src/pages/Reviews/index.vue Normal file
View File

@ -0,0 +1,279 @@
<template>
<div class="reviews-page min-h-screen overflow-x-hidden bg-black font-sans text-white">
<!-- Header -->
<div class="h-[80px] md:h-[114px]">
<div class="fixed z-50 w-full bg-black pt-[20px] pb-[20px] md:pt-[34px]">
<div class="container">
<header
class="flex h-[40px] items-center justify-between rounded-full bg-[#ADFF5B] pr-[30px] pl-5 md:h-[60px] md:pr-[58px] md:pl-[41px]"
>
<router-link to="/" class="flex items-center gap-2">
<!-- Desktop Logo -->
<!-- <Logo :src="Logo" alt="Hi快VPN" class="hidden h-10 w-auto text-black md:block" />-->
<!-- Mobile Logo -->
<MobileLogo alt="Hi快VPN" class="block h-[22px] text-black md:h-[36px]" />
</router-link>
<RightText class="block h-[12px] text-black md:h-[24px]" />
</header>
</div>
</div>
</div>
<!-- Main Content -->
<main class="container mx-auto max-w-2xl px-4 py-8">
<img src="./image2.png" class="hidden md:block" />
<img src="./image1.png" class="md:hidden" />
<div class="my-[40px] h-[1px] w-full bg-[#757575]" />
<div class="space-y-8">
<div
v-for="(review, index) in displayReviews"
:key="index"
class="review-card"
:style="{ '--index': index % 10 }"
>
<div class="mb-3 flex items-start justify-between">
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1">
<h2 class="text-lg leading-tight font-bold">{{ review.username }}</h2>
<span class="text-sm text-white/40">{{ review.date }}</span>
</div>
<!-- Stars -->
<div class="mt-1 flex shrink-0 gap-0.5">
<svg
v-for="i in 5"
:key="i"
class="h-4 w-4"
:class="i <= (review.stars || 5) ? 'text-[#ADFF5B]' : 'text-white/10'"
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>
</div>
<p class="mb-8 text-[15px] leading-relaxed text-white/80 md:text-base">
{{ review.comment }}
</p>
<div class="w-full border-b border-[#757575]"></div>
</div>
<!-- Loading state -->
<div v-if="isLoading" class="flex justify-center py-10">
<div
class="h-6 w-6 animate-spin rounded-full border-2 border-[#ADFF5B]/30 border-t-[#ADFF5B]"
></div>
</div>
<!-- No more data -->
<div v-if="!hasMore && !isLoading" class="py-10 text-center text-sm text-white/30">
暂无更多
</div>
</div>
</main>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useInfiniteScroll } from '@vueuse/core'
import MobileLogo from '@/pages/Home/mobile-logo.svg?component'
import RightText from './right-text.svg?component'
const router = useRouter()
const isLoading = ref(false)
const hasMore = ref(true)
// Fixed 20 random reviews based on the provided design
const allReviews = [
{
username: 'Alex Chen',
date: 'Oct.12',
stars: 5,
comment:
'真的是极简主义的胜利。没有多余的按钮打开软件的瞬间就已经连接成功了。抛弃了传统VPN繁琐的线路选择这种“无感”的体验让人非常舒服。Netflix 4K 拖拽完全没有缓冲。',
},
{
username: 'Fjafw****@gmail.com',
date: 'Feb. 2',
stars: 5,
comment:
'IEPL专线稳定性确实不是普通机场能比的。晚高峰打竞技游戏延迟依然很低几乎感觉不到身在海外。UI设计长在我的审美上黑绿配色极其克制且高级。',
},
{
username: 'Sarah Lin',
date: 'Sep. 19',
stars: 4,
comment:
'速度和稳定性都没得说,是目前用过最省心的软件。唯一扣掉的一星是希望能在未来加入一些特定地区冷门节点的备选方案,虽然目前的智能分配已经足够好用。总体强烈推荐。',
},
{
username: 'Michael W.',
date: 'Jan. 15',
stars: 5,
comment:
'I have tried many VPNs, but HiFast is by far the fastest. The connection is instantaneous and the bandwidth is impressive.',
},
{
username: '张晓明',
date: 'Dec. 5',
stars: 5,
comment: '非常好用连接速度快看YouTube 4K一点都不卡。',
},
{
username: 'David K.',
date: 'Nov. 22',
stars: 5,
comment:
'The UI is clean and the performance is top-notch. Highly recommended for professionals.',
},
{
username: 'Emily Chen',
date: 'Mar. 10',
stars: 5,
comment: 'Best VPN for gaming! Low ping and no packet loss. Love it.',
},
{
username: '李华',
date: 'Feb. 28',
stars: 5,
comment: '客服态度很好,遇到问题解决得很快。软件本身也非常稳定。',
},
{
username: 'Robert J.',
date: 'May. 14',
stars: 5,
comment: 'Solid performance. I use it for my remote work and it never fails me.',
},
{
username: '王大力',
date: 'Jun. 20',
stars: 4,
comment: '很不错的VPN虽然价格稍微贵一点但物有所值。',
},
{
username: 'Jessica S.',
date: 'Aug. 3',
stars: 5,
comment: 'So easy to use. Just one click and I am protected. Great job!',
},
{
username: '陈伟',
date: 'Jul. 12',
stars: 5,
comment: '在国外用这个看国内视频非常流畅,没有任何限制。',
},
{
username: 'Kevin L.',
date: 'Sep. 30',
stars: 5,
comment: 'The encryption makes me feel safe. High speed is a bonus.',
},
{
username: '周杰',
date: 'Apr. 18',
stars: 5,
comment: '支持多设备同时在线,非常方便。家里几个人共用一个账号。',
},
{
username: 'Anna B.',
date: 'Oct. 5',
stars: 5,
comment: 'Love the dark mode UI. It looks so modern and sleek.',
},
{
username: '赵三',
date: 'Dec. 25',
stars: 4,
comment: '整体感觉不错,连接速度挺快的,偶尔会断线。',
},
{
username: 'Thomas M.',
date: 'Nov. 8',
stars: 5,
comment: 'Great service. I have recommended it to all my friends.',
},
{
username: '刘红',
date: 'Jan. 22',
stars: 5,
comment: '非常感谢Hi快VPN让我能方便地学习国外的课程。',
},
{
username: 'Steven H.',
date: 'Feb. 14',
stars: 5,
comment: 'Excellent bandwidth. Streaming 4K is like watching local videos.',
},
{
username: '吴优',
date: 'Mar. 25',
stars: 5,
comment: '用过最简单的VPN即使是不懂技术的人也能轻松上手。',
},
]
const displayReviews = ref(allReviews.slice(0, 5))
const currentIndex = ref(5)
const loadMore = () => {
if (isLoading.value || !hasMore.value) return
isLoading.value = true
// Simulate network delay
setTimeout(() => {
const nextBatch = allReviews.slice(currentIndex.value, currentIndex.value + 3)
if (nextBatch.length > 0) {
displayReviews.value.push(...nextBatch)
currentIndex.value += nextBatch.length
}
if (currentIndex.value >= allReviews.length) {
hasMore.value = false
}
isLoading.value = false
}, 300)
}
useInfiniteScroll(
window,
() => {
loadMore()
},
{ distance: 200 },
)
const goBack = () => {
router.push('/')
}
</script>
<style scoped>
.reviews-page {
background-color: #000;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.review-card {
animation: slideUp 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Staggered animation for initial items */
.review-card {
animation-delay: calc(var(--index, 0) * 0.05s);
}
</style>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -8,6 +8,11 @@ const router = createRouter({
name: 'home',
component: () => import('../pages/Home/index.vue'),
},
{
path: '/reviews',
name: 'reviews',
component: () => import('../pages/Reviews/index.vue'),
},
{
path: '/help',
name: 'help',