hi-partner/src/pages/Home/index.vue
speakeloudest e52ec9bd01
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m15s
增加视频播放
2026-02-02 10:13:49 +02:00

242 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="relative min-h-screen overflow-hidden bg-black bg-cover bg-center bg-no-repeat pb-[calc(4rem+env(safe-area-inset-bottom))] font-sans text-white md:flex md:flex-col"
>
<!-- Full Width Header -->
<div class="h-[60px] md:h-[125px]">
<div class="fixed top-[20px] z-50 w-full md:top-[45px]">
<div class="container">
<header
class="lucid-glass-bar flex h-[40px] items-center justify-between rounded-[90px] pr-[5px] pl-5 transition-all duration-300 md:h-[60px] md:pr-[10px]"
>
<router-link to="/" class="flex items-center gap-2">
<!-- Desktop Logo -->
<Logo alt="Hi快VPN" class="h-[18px] w-auto md:ml-8 md:h-[29px]" />
<span class="ml-3 text-2xl font-black">高能合伙人</span>
</router-link>
<div v-if="isLoggedIn" class="flex items-center">
<router-link
to="/user-center"
class="flex size-[30px] items-center justify-center rounded-full bg-[#78788029] text-xl font-bold text-white shadow-lg transition hover:scale-105 md:size-[40px] md:text-3xl"
>
{{ userLetter }}
</router-link>
</div>
<button
v-else
@click="openLoginModal"
class="flex h-[30px] cursor-pointer items-center justify-center rounded-full bg-[#78788029] px-6 text-sm font-bold backdrop-blur-md transition hover:brightness-110 md:h-[40px] md:w-[220px] md:text-xl"
>
代理后台登录/注册
</button>
</header>
</div>
</div>
</div>
<!-- Main Content Container -->
<div class="container mx-auto flex flex-col">
<main class="pt-10">
<!-- module0 -->
<div class="mb-[80px] flex justify-between">
<div class="flex flex-col items-center">
<div class="mb-[20px] ml-[42px] md:ml-[17px]">
<h2 class="mb-2 text-2xl font-black md:text-8xl">
<Logo class="h-[34px] md:h-[43px]" />
</h2>
<p class="font-600 text-3xl">网在我在, 网快我快</p>
</div>
<img src="./Group%20133.png" alt="" class="mt-[52px] h-[287px] w-[182px]" />
</div>
<!-- video -->
<div
class="max-w-[800px] flex-1 cursor-pointer overflow-hidden rounded-[40px] transition duration-300 hover:scale-[1.02]"
@click="openVideoModal"
>
<img
src="@/pages/Home/modules1/Group-236.png"
class="h-full w-full object-cover object-center"
alt="Video Cover"
/>
</div>
</div>
<!-- modules1 -->
<div class="mb-[80px] w-full">
<img src="./modules1/Group%20235.png" alt="邀请规则" class="mx-auto w-[1024px]" />
</div>
<!-- modules2 -->
<div class="mb-[80px] w-full rounded-[40px] bg-[#ADFF5B] p-8 pb-2 text-black">
<div class="text-center text-4xl font-black">“超强产品力全面秒杀同级app”</div>
<div class="mt-2 text-center">为高能合伙人提供强力的的产品背书,每个点拿出去都能打。</div>
<div class="el-style-scrollbar mt-8 flex gap-2 overflow-x-auto pb-4">
<img
:src="image"
alt=""
v-for="(image, index) in modules2Image"
class="h-[432px] w-[200px] shrink-0 rounded-[30px] md:h-[600px] md:w-[277.5px]"
:key="index"
/>
</div>
</div>
<!-- modules3 -->
<div class="mb-[40px] w-full rounded-[40px] pb-2 text-black">
<div class="text-center text-4xl font-black">
<Group215Icon class="mx-auto" />
</div>
<div class="text-center text-[#999999]">给您的客户提供专业视角的建议</div>
<div class="mt-[20px] flex justify-center">
<Carousel class="relative w-full max-w-[700px]" :opts="{ loop: true }">
<div class="size-[700px] overflow-hidden rounded-[40px]">
<CarouselContent>
<CarouselItem v-for="(img, index) in modules4Images" :key="index">
<img
:src="img"
alt=""
class="h-[700px] w-[700px] object-cover select-none"
draggable="false"
/>
</CarouselItem>
</CarouselContent>
</div>
<CarouselPrevious class="-left-[100px]" />
<CarouselNext class="-right-[100px]" />
</Carousel>
</div>
</div>
</main>
</div>
<div class="container flex flex-col items-center justify-center">
<div class="mb-1 h-[20px] w-[352px] md:ml-[17px]">
<img src="./image-1.png" alt="image" />
</div>
<div class="text-center text-[10px] leading-[14px] font-[300] md:ml-[17px] md:text-left">
<span class="font-[600]">Hi快VPN</span> &copy; All rights reserved.<br />
<router-link to="/terms" class="underline">Terms of Service</router-link>
<router-link to="/privacy" class="ml-2 underline">Privacy Policy</router-link>
</div>
</div>
<LoginFormModal ref="loginModalRef" />
<!-- Video Modal -->
<Dialog
v-model:open="videoModalVisible"
@update:open="(val) => !val && handleVideoModalClose()"
>
<DialogContent class="max-w-[60vw]! overflow-hidden rounded-2xl border-none bg-black/90 p-0">
<div class="relative w-full pt-[56.25%]">
<video
ref="videoRef"
src="/fast-video.MP4"
class="absolute inset-0 h-full w-full"
controls
autoplay
></video>
</div>
</DialogContent>
</Dialog>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useLocalStorage } from '@vueuse/core'
import LoginFormModal from './components/LoginFormModal.vue'
import Logo from './logo.svg?component'
import Group215Icon from './modules3/Group 215.svg?component'
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from '@/components/ui/carousel'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import request from '@/utils/request'
import Frame98 from './modules2/Frame 98.png'
import Frame99 from './modules2/Frame 99.png'
import Frame100 from './modules2/Frame 100.png'
import Frame101 from './modules2/Frame 101.png'
import Frame104 from './modules2/Frame 104.png'
import Frame105 from './modules2/Frame 105.png'
import image1 from './modules4/image1.png'
import image2 from './modules4/image2.png'
import image3 from './modules4/image3.png'
import image4 from './modules4/image4.png'
import image5 from './modules4/image5.png'
import image6 from './modules4/image6.png'
const modules2Image = [Frame98, Frame99, Frame100, Frame101, Frame104, Frame105]
const modules4Images = [image1, image2, image3, image4, image5, image6]
const videoModalVisible = ref(false)
const videoRef = ref<HTMLVideoElement | null>(null)
const openVideoModal = () => {
videoModalVisible.value = true
}
const handleVideoModalClose = () => {
if (videoRef.value) {
videoRef.value.pause()
videoRef.value.currentTime = 0
}
}
const route = useRoute()
const router = useRouter()
const token = useLocalStorage('Authorization', '')
const userEmail = useLocalStorage('UserEmail', '')
const isLoggedIn = computed(() => !!token.value)
const userLetter = computed(() => {
if (!userEmail.value) return '?'
return userEmail.value.charAt(0).toUpperCase()
})
const fetchUserInfo = async () => {
if (!token.value) return
try {
const res = (await request.get('/api/v1/public/user/info')) as any
const emailInfo = res.auth_methods?.find((item: any) => item.auth_type === 'email')
if (emailInfo) {
userEmail.value = emailInfo.auth_identifier
}
} catch (error: any) {
console.error('Failed to fetch user info:', error)
if (error?.code === 401 || error?.status === 401) {
token.value = ''
userEmail.value = ''
}
}
}
onMounted(() => {
fetchUserInfo()
if (route.query.login === 'true') {
openLoginModal()
router.replace({ query: { ...route.query, login: undefined } })
}
})
watch(
() => route.query.login,
(newVal) => {
if (newVal === 'true') {
openLoginModal()
router.replace({ query: { ...route.query, login: undefined } })
}
},
)
const loginModalRef = ref<InstanceType<typeof LoginFormModal> | null>(null)
const openLoginModal = () => {
loginModalRef.value?.show()
}
</script>
<style scoped></style>