样式处理
This commit is contained in:
parent
f7a28c1c86
commit
a9cbd2b921
@ -3,9 +3,10 @@
|
||||
<div
|
||||
v-for="device in devices"
|
||||
:key="device.id"
|
||||
class="h-[76px] rounded-3xl border-2 p-4 text-[10px]"
|
||||
@click="delDevice(device)"
|
||||
class="relative h-[76px] rounded-[25px] border-2 p-4 text-[10px]"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex h-full items-center justify-center gap-3">
|
||||
<component
|
||||
:is="getDeviceTypeInfo(device.user_agent)?.iconComponent"
|
||||
class="h-6 w-6 text-white"
|
||||
@ -17,12 +18,13 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<X :size="16" class="absolute top-[5px] right-[10px] text-[12px]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Laptop, Smartphone, Tablet, Monitor, Cpu, HelpCircle } from 'lucide-vue-next'
|
||||
import { Laptop, Smartphone, Tablet, Monitor, Cpu, HelpCircle, X } from 'lucide-vue-next'
|
||||
|
||||
interface Device {
|
||||
id: string
|
||||
@ -35,6 +37,10 @@ defineProps<{
|
||||
devices: Device[]
|
||||
}>()
|
||||
|
||||
function delDevice(item) {
|
||||
console.log('Device removed', item)
|
||||
}
|
||||
|
||||
interface DeviceTypeInfo {
|
||||
type: string
|
||||
icon: string
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="bg-[#A8FF53] px-6 pt-7 font-sans text-black">
|
||||
<div class="bg-[#A8FF53] px-6 font-sans text-black">
|
||||
<h2 class="mb-1 text-center text-2xl font-bold">选择付款方式</h2>
|
||||
|
||||
<div class="flex flex-col gap-4 pt-[43px]">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="px-6 pt-7 font-sans">
|
||||
<div class="px-6 font-sans">
|
||||
<h2 class="mb-1 text-center text-2xl font-bold">套餐选择</h2>
|
||||
<p class="mb-4 text-center text-sm font-[100] text-gray-600">*所有套餐均不限流量不限速度</p>
|
||||
|
||||
|
||||
BIN
src/pages/UserCenter/DesktopLayout/Line-8.png
Normal file
BIN
src/pages/UserCenter/DesktopLayout/Line-8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 335 B |
141
src/pages/UserCenter/DesktopLayout/index.vue
Normal file
141
src/pages/UserCenter/DesktopLayout/index.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<!-- Main Neon Green Card -->
|
||||
<div class="flex h-[678px]">
|
||||
<div
|
||||
class="flex w-[345px] flex-col justify-between rounded-4xl border-5 border-white py-[32px] pb-[22px]"
|
||||
>
|
||||
<div>
|
||||
<div class="mb-3 flex flex-col items-center">
|
||||
<img src="../avatar.png" class="size-[60px]" alt="" />
|
||||
<div class="flex flex-col justify-center text-white">
|
||||
<div class="text-xl font-semibold">{{ userInfo.email }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-5 px-[20px] text-white">
|
||||
<DeviceList :devices="devices" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="px-6 pt-8 pb-9">
|
||||
<!-- <Button
|
||||
variant="outline"
|
||||
class="mb-[10px] h-[50px] w-full rounded-[32px] border-2 border-[#FF00B7] bg-transparent text-xl font-bold text-[#FF00B7] transition-all hover:bg-[#FF00FF]/90 active:scale-[0.98]"
|
||||
>
|
||||
注销账户
|
||||
</Button>-->
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
@click="logout"
|
||||
class="h-[50px] w-full rounded-[32px] border-2 border-white bg-transparent text-xl font-bold text-white transition-all hover:bg-white/90 active:scale-[0.98]"
|
||||
>
|
||||
退出登录
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="text-center text-xs" :class="{ 'text-[#FF00B7]': expireDateInfo.highlight }">
|
||||
{{ expireDateInfo.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ml-2.5 flex items-center overflow-hidden rounded-4xl bg-[#A8FF53] pt-[32px] pb-[22px]"
|
||||
>
|
||||
<div class="h-full w-[345px]">
|
||||
<PlanCard :plans="plans" :currentPlanIndex="currentPlanIndex" @select="handlePlanSelect" />
|
||||
</div>
|
||||
<div
|
||||
class="mx-[5px] h-[624px] w-[1px] bg-[url(@/pages/userCenter/DesktopLayout/Line-8.png)]"
|
||||
></div>
|
||||
<div class="h-full w-[345px]">
|
||||
<PaymentMethod
|
||||
:methods="payments"
|
||||
:selectedPlan="selectedPlan"
|
||||
@pay="(id: number | string) => $emit('pay', id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import PlanCard from '@/components/user-center/PlanCard.vue'
|
||||
import DeviceList from '@/components/user-center/DeviceList.vue'
|
||||
import PaymentMethod from '@/components/user-center/PaymentMethod.vue'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
const props = defineProps<{
|
||||
devices: any[]
|
||||
plans: any[]
|
||||
payments: any[]
|
||||
alreadySubscribed: any[]
|
||||
userInfo: { email: string }
|
||||
selectedPlanId: string
|
||||
selectedPlan: any
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['select-plan', 'pay'])
|
||||
|
||||
// --- Handlers ---
|
||||
const handlePlanSelect = (id: string) => {
|
||||
emit('select-plan', id)
|
||||
}
|
||||
const currentPlanIndex = computed(() => {
|
||||
return props.plans.findIndex((p) => p.id === props.selectedPlanId)
|
||||
})
|
||||
|
||||
const expireDateInfo = computed(() => {
|
||||
const first = props.alreadySubscribed[0]
|
||||
let text = ''
|
||||
let highlight = false
|
||||
|
||||
if (!first || !first.expireDate) {
|
||||
text = '尚未购买套餐'
|
||||
highlight = true
|
||||
} else {
|
||||
// 尝试解析日期,兼容多种格式
|
||||
const dateStr = first.expireDate.replace(/ /g, 'T')
|
||||
const expireDateTime = new Date(dateStr)
|
||||
|
||||
if (isNaN(expireDateTime.getTime())) {
|
||||
text = '套餐信息无效'
|
||||
} else if (expireDateTime < new Date()) {
|
||||
const year = expireDateTime.getFullYear()
|
||||
const month = String(expireDateTime.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(expireDateTime.getDate()).padStart(2, '0')
|
||||
text = `已于 ${year}/${month}/${day} 到期`
|
||||
highlight = true
|
||||
} else {
|
||||
const year = expireDateTime.getFullYear()
|
||||
const month = String(expireDateTime.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(expireDateTime.getDate()).padStart(2, '0')
|
||||
const hour = String(expireDateTime.getHours()).padStart(2, '0')
|
||||
const minute = String(expireDateTime.getMinutes()).padStart(2, '0')
|
||||
const second = String(expireDateTime.getSeconds()).padStart(2, '0')
|
||||
text = `到期时间:${year}/${month}/${day} ${hour}:${minute}:${second}`
|
||||
highlight = false
|
||||
}
|
||||
}
|
||||
|
||||
return { text, highlight }
|
||||
})
|
||||
|
||||
function logout() {
|
||||
router.push('/')
|
||||
localStorage.removeItem('Authorization')
|
||||
toast.success('退出成功')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Simplified layout font */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&display=swap');
|
||||
|
||||
.tracking-tight {
|
||||
font-family: 'Inter', 'PingFang SC', sans-serif;
|
||||
}
|
||||
</style>
|
||||
@ -15,8 +15,10 @@
|
||||
<DeviceList :devices="devices" />
|
||||
</div>
|
||||
<div class="overflow-hidden rounded-4xl bg-[#A8FF53]">
|
||||
<PlanCard :plans="plans" :currentPlanIndex="currentPlanIndex" @select="handlePlanSelect" />
|
||||
<div class="pt-2">
|
||||
<div class="pt-7">
|
||||
<PlanCard :plans="plans" :currentPlanIndex="currentPlanIndex" @select="handlePlanSelect" />
|
||||
</div>
|
||||
<div class="pt-7">
|
||||
<PaymentMethod
|
||||
:methods="payments"
|
||||
:selectedPlan="selectedPlan"
|
||||
|
||||
@ -1,25 +1,29 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-black text-black">
|
||||
<div class="flex min-h-screen flex-col bg-black text-black">
|
||||
<!-- Full Width Header -->
|
||||
<div class="h-[88px]">
|
||||
<header
|
||||
class="fixed top-[20px] right-[18px] left-[18px] z-50 flex h-[68px] items-center justify-between rounded-[90px] bg-[#ADFF5B] pr-[30px] pl-6"
|
||||
>
|
||||
<div 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
|
||||
:src="MobileLogo"
|
||||
alt="Hi快VPN"
|
||||
class="block h-[28px] w-[67px] text-black md:hidden"
|
||||
/>
|
||||
<div class="h-[88px] md:h-[125px]">
|
||||
<div class="fixed top-[20px] z-50 w-full md:top-[45px]">
|
||||
<div class="container">
|
||||
<header
|
||||
class="flex h-[68px] items-center justify-between rounded-full bg-[#ADFF5B] pr-[30px] pl-6 md:h-[80px]"
|
||||
>
|
||||
<div 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
|
||||
:src="MobileLogo"
|
||||
alt="Hi快VPN"
|
||||
class="block h-[28px] text-black md:h-[50px]"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xl font-[600] text-black md:text-3xl">个人账户</div>
|
||||
</header>
|
||||
</div>
|
||||
<div class="text-xl font-[600]">个人账户</div>
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Main Neon Green Card -->
|
||||
<div class="px-[18px]">
|
||||
<div class="container md:hidden">
|
||||
<MobileLayout
|
||||
:already-subscribed="alreadySubscribed"
|
||||
:devices="devices"
|
||||
@ -32,12 +36,26 @@
|
||||
@pay="handlePay"
|
||||
/>
|
||||
</div>
|
||||
<div class="container mx-auto hidden flex-1 items-center justify-center md:flex">
|
||||
<DesktopLayout
|
||||
:already-subscribed="alreadySubscribed"
|
||||
:devices="devices"
|
||||
:plans="plans"
|
||||
:payments="payments"
|
||||
:user-info="userSubInfo"
|
||||
:selected-plan-id="selectedPlanId"
|
||||
:selected-plan="activePlan"
|
||||
@select-plan="handlePlanSelect"
|
||||
@pay="handlePay"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import MobileLayout from './MobileLayout/index.vue'
|
||||
import DesktopLayout from './DesktopLayout/index.vue'
|
||||
import Logo from '@/pages/Home/logo.svg?component'
|
||||
import MobileLogo from '@/pages/Home/mobile-logo.svg?component'
|
||||
import request from '@/utils/request'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user