feat: 修改文案大小

This commit is contained in:
speakeloudest 2025-08-16 09:38:50 -07:00
parent 9cde4cb0a1
commit bf8c01048c
32 changed files with 218 additions and 243 deletions

View File

@ -5,7 +5,7 @@
### 熟练部署命令
```shell
APP_NAME="ppanel-admin-web-dev"
APP_NAME="ppanel-admin-web"
tar -xzvf ${APP_NAME}.tar.gz && pm2 start ${APP_NAME} && pm2 list
unset APP_NAME # 显式销毁变量
```

View File

@ -19,7 +19,7 @@ export function Header() {
const items = useMemo(() => findNavByUrl(pathname), [pathname]);
return (
<header className='flex h-[84px] w-full items-center justify-end gap-2 px-4 pt-4 md:hidden'>
<SidebarTrigger className={'fixed left-4'} />
<SidebarTrigger className={'fixed left-4 z-50'} />
<Breadcrumb>
<BreadcrumbList className={'text-[36px] font-semibold'}>
{items.map((item, index) => {

View File

@ -51,8 +51,8 @@ export const AnnouncementDialog = ({ ref }: AnnouncementDialogProps) => {
const response = await queryAnnouncement({
...pagination,
...filter,
pinned: false,
popup: false,
// pinned: false,
// popup: false,
});
return {
list: response.data.data?.announcements || [],
@ -62,7 +62,7 @@ export const AnnouncementDialog = ({ ref }: AnnouncementDialogProps) => {
renderItem={(item) => {
return (
<div
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2 shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)]`}
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-1.5 shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)]`}
>
<p
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}

View File

@ -1,7 +1,6 @@
import { Display } from '@/components/display';
import Renewal from '@/components/subscribe/renewal';
import { resetUserSubscribeToken } from '@/services/user/user';
import { Button } from '@workspace/airo-ui/components/button';
import {
Select,
SelectContent,
@ -14,6 +13,7 @@ import { toast } from 'sonner';
import SvgIcon from '@/components/SvgIcon';
import useGlobalStore from '@/config/use-global';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import {
AlertDialog,
AlertDialogAction,
@ -62,13 +62,13 @@ const SubscribeCard = (props: SubscribeCardProps) => {
</p>
{/* 统计信息 */}
<div className='rounded-[20px] bg-[#EAEAEA] p-4'>
<div className='rounded-[20px] bg-[#EAEAEA] py-4'>
<div className='grid grid-cols-3 gap-4 text-center'>
<div>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
{t('totalTraffic')}
</p>
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
<Display
type='traffic'
value={userSubscribeData.traffic}
@ -77,20 +77,20 @@ const SubscribeCard = (props: SubscribeCardProps) => {
</p>
</div>
<div>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
{t('nextResetDays')}
</p>
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
{userSubscribeData.reset_time
? differenceInDays(new Date(userSubscribeData.reset_time), new Date())
: t('noReset')}
</p>
</div>
<div>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
{t('expirationDays')}
</p>
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
{userSubscribeData.expire_time
? differenceInDays(new Date(userSubscribeData.expire_time), new Date()) ||
t('unknown')
@ -123,7 +123,7 @@ const SubscribeCard = (props: SubscribeCardProps) => {
</Tabs>
)}
</div>
<div className={'mb-3 flex items-center justify-center gap-1'}>
<div className={'mb-3 flex items-center justify-center gap-3'}>
<div
className={
'flex flex-1 items-center gap-1 rounded-full bg-[#BABABA] pl-1 sm:gap-2 sm:rounded-[16px] sm:pl-2'
@ -133,14 +133,14 @@ const SubscribeCard = (props: SubscribeCardProps) => {
value={userSubscribeProtocolCurrent}
onValueChange={setUserSubscribeProtocolCurrent}
>
<SelectTrigger className='h-auto w-auto flex-shrink-0 rounded-[16px] border-none bg-[#D9D9D9] px-2.5 py-0.5 text-[13px] text-sm font-medium text-white shadow-none hover:bg-[#848484] focus:ring-0 sm:h-[35px] sm:rounded-[8px] sm:p-2 [&>svg]:hidden'>
<SelectTrigger className='h-auto w-auto flex-shrink-0 rounded-[16px] border-none bg-[#D9D9D9] px-2.5 py-0.5 text-[13px] font-medium text-[#0F2C53] shadow-none hover:bg-[#848484] focus:ring-0 sm:h-[35px] sm:rounded-[8px] sm:px-2 sm:py-1.5 [&>svg]:hidden'>
<SelectValue>
<div className='flex flex-col items-center justify-center text-[10px] sm:text-sm'>
<div className='flex flex-col items-center justify-between text-[10px] sm:text-xs'>
<div>
{t('subscriptionUrl')}
{userSubscribeProtocolCurrent + 1}
</div>
<div className='-mt-0.5 h-0 w-0 scale-50 border-l-[5px] border-r-[5px] border-t-[5px] border-l-transparent border-r-transparent border-t-white sm:scale-100'></div>
<div className='-mt-0.5 h-0 w-0 scale-50 border-l-[3px] border-r-[3px] border-t-[3px] border-l-transparent border-r-transparent border-t-[#0F2C53] sm:scale-100'></div>
</div>
</SelectValue>
</SelectTrigger>
@ -158,8 +158,8 @@ const SubscribeCard = (props: SubscribeCardProps) => {
</SelectContent>
</Select>
<div className='flex-1 rounded-full bg-white px-3 py-1 text-[10px] leading-tight text-[#225BA9] shadow-[inset_0px_0px_7.6px_0px_rgba(0,0,0,0.25)] sm:rounded-[16px] sm:text-xs'>
<div className={'flex items-center gap-4 py-1 text-[10px] sm:text-[16px]'}>
<div className='flex-1 rounded-full bg-white px-3 py-2 text-[10px] leading-tight text-[#225BA9] shadow-[inset_0px_0px_7.6px_0px_rgba(0,0,0,0.25)] sm:rounded-[16px]'>
<div className={'flex items-center gap-4 py-1'}>
<div className={'line-clamp-2 flex-1 break-all'}>
{userSubscribeProtocol[userSubscribeProtocolCurrent]}
</div>
@ -203,15 +203,9 @@ const SubscribeCard = (props: SubscribeCardProps) => {
<div className='flex justify-between gap-2'>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
size='sm'
className={
'h-fit rounded-full bg-[#E22C2E] px-3 py-1 text-[10px] text-white sm:h-9 sm:text-xs'
}
variant='destructive'
>
<AiroButton variant='danger' className={'px-2 text-xs'}>
{t('resetSubscription')}
</Button>
</AiroButton>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
@ -235,7 +229,7 @@ const SubscribeCard = (props: SubscribeCardProps) => {
</AlertDialogContent>
</AlertDialog>
<Renewal
className='h-fit rounded-full bg-[#A8D4ED] px-3 py-1 text-[10px] text-white sm:h-9 sm:text-xs'
className='px-2 text-xs'
id={userSubscribeData.id}
subscribe={userSubscribeData.subscribe}
/>

View File

@ -64,9 +64,9 @@ export default function Content() {
queryFn: async () => {
const { data } = await queryAnnouncement({
page: 1,
size: 4,
pinned: false,
popup: false,
size: 5,
// pinned: false,
// popup: false,
});
return data.data?.announcements || [];
},
@ -96,7 +96,7 @@ export default function Content() {
<div className={'grid grid-cols-1 gap-[10px] sm:gap-6 lg:grid-cols-2'}>
{/* 账户概况 Card */}
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
<div className='mb-1 sm:mb-4'>
<div className='mb-1'>
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
{t('accountOverview')}
</h3>
@ -105,8 +105,8 @@ export default function Content() {
</p>
</div>
<div className='mb-3 sm:mb-6'>
<span className='text-2xl font-medium text-[#091B33] sm:text-3xl'>
<div className='mb-3 sm:mb-3.5'>
<span className='text-2xl font-medium text-[#091B33]'>
{userSubscribe?.length > 0 && userSubscribe[0]?.status === 1 && orderData
? orderData?.quantity === 1
? t('annualMonthPlanUser')
@ -115,7 +115,7 @@ export default function Content() {
</span>
</div>
<div className='rounded-[20px] bg-[#EAEAEA] px-4 py-[10px]'>
<div className='rounded-[20px] bg-[#EAEAEA] px-5 py-2.5'>
<div className='flex items-center justify-between'>
<span className='text-sm font-light text-[#666666]'>{t('accountBalance')}</span>
<Recharge
@ -124,7 +124,7 @@ export default function Content() {
}
/>
</div>
<div className='text-xl font-medium text-[#225BA9] sm:text-4xl'>
<div className='text-xl font-medium text-[#225BA9] sm:text-2xl'>
<Display type='currency' value={totalAssets} />
</div>
</div>
@ -132,7 +132,7 @@ export default function Content() {
{/* 套餐状态 Card */}
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 text-[#666666] shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
<div className='mb-4'>
<div className=''>
<h3 className='flex items-center justify-between text-[#666666]'>
<div className={'flex items-center justify-between'}>
<span className={'text-base font-medium sm:text-xl'}>{t('planStatus')}</span>
@ -153,12 +153,12 @@ export default function Content() {
</div>
{userSubscribe?.length ? (
<>
<div className='mb-2 text-sm text-[#666666] sm:mb-[22px] sm:mt-1'>
<div className='mt-1 text-xs text-[#666666] sm:text-sm'>
{t('planExpirationTime')}
{formatDate(userSubscribe?.[0]?.expire_time, false)}
</div>
<div className='mb-3 sm:mb-6'>
<span className='text-2xl font-medium text-[#091B33] sm:text-3xl'>
<div className='mb-3 sm:mb-5'>
<span className='text-2xl font-medium text-[#091B33]'>
{userSubscribe?.[0]?.subscribe.name}
</span>
</div>
@ -226,7 +226,7 @@ export default function Content() {
</Card>
{/* 网站公告 Card */}
<Card className='relative order-4 rounded-[20px] border border-[#EAEAEA] bg-gradient-to-b from-white to-[#EAEAEA] p-6 pb-0 sm:order-none'>
<div className='mb-3 flex items-center justify-between sm:mb-4'>
<div className='mb-3 flex items-center justify-between sm:mb-1'>
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
{t('siteAnnouncements')}
</h3>
@ -248,7 +248,7 @@ export default function Content() {
return (
<div
key={item.id}
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2`}
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-1.5`}
>
<p
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
@ -285,7 +285,7 @@ export default function Content() {
{/* 我的订阅 Card */}
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
<div className='flex items-center justify-between sm:mb-4'>
<div className='flex items-center justify-between'>
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
{t('mySubscription')}
</h3>

View File

@ -67,7 +67,7 @@ const OrderDetailDialog = forwardRef<OrderDetailDialogRef, OrderDetailDialogProp
<div className={'sr-only'}>order detail</div>
</DialogTitle>
<DialogContent className='sm:w-[675px]'>
<div className='text-4xl font-bold text-[#0F2C53] sm:mb-8 sm:text-center sm:text-4xl'>
<div className='text-2xl font-bold text-[#0F2C53] sm:mb-8 sm:text-center'>
{t('orderDetail')}
</div>

View File

@ -77,7 +77,7 @@ export default function Page() {
</AiroButton>
</div>
</div>
<CardContent className='px-0 py-3 pb-0 text-sm sm:pb-6'>
<CardContent className='px-0 py-3 pb-0 text-sm'>
<ul className='grid grid-cols-2 gap-3 *:flex *:flex-col lg:grid-cols-4'>
<li>
<span className='text-[#225BA9]'>{t('name')}</span>

View File

@ -29,16 +29,12 @@ export default function Page() {
return (
<>
<LoginDialogProvider>
<div
className={
'hidden text-4xl font-bold text-[#0F2C53] sm:block md:mb-4 md:text-center md:text-5xl'
}
>
<div className={'hidden text-4xl font-bold text-[#0F2C53] sm:block md:mb-4 md:text-center'}>
{t('title')}
</div>
<div
className={
'mt-0 text-right text-lg font-bold text-[#666666] sm:mt-0 sm:text-center sm:font-medium'
'mt-0 text-right text-base font-bold text-[#666666] sm:mt-0 sm:text-center sm:font-medium'
}
>
{t('description')}

View File

@ -27,23 +27,23 @@ const Table: React.FC<{}> = () => {
<CardContent className='px-0 py-3 text-[10px] sm:p-3 sm:text-sm'>
<ul className='grid grid-cols-4 gap-3 *:flex *:flex-col'>
<li className='font-semibold'>
<span className='text-[#225BA9]'>{t('createdAt')}</span>
<time>{formatDate(item.created_at)}</time>
<span className='font-normal text-[#225BA9]'>{t('createdAt')}</span>
<time className={'text-base'}>{formatDate(item.created_at)}</time>
</li>
<li className='font-semibold'>
<span className='text-[#225BA9]'>{t('type.0')}</span>
<span>{t(`type.${item.type}`)}</span>
<span className='font-normal text-[#225BA9]'>{t('type.0')}</span>
<span className={'text-base'}>{t(`type.${item.type}`)}</span>
</li>
<li className='font-semibold'>
<span className='text-[#225BA9]'>{t('amount')}</span>
<span>
<span className='font-normal text-[#225BA9]'>{t('amount')}</span>
<span className={'text-base'}>
<Display type='currency' value={item.amount} />
</span>
</li>
<li className='font-semibold'>
<span className='text-[#225BA9]'>{t('balance')}</span>
<span>
<span className='font-normal text-[#225BA9]'>{t('balance')}</span>
<span className={'text-base'}>
<Display type='currency' value={item.balance} />
</span>
</li>

View File

@ -31,7 +31,7 @@ export default function Page() {
<div className='flex items-center justify-between'>
<div>
<p className='text-sm font-light text-[#666]'>{t('totalAssets')}</p>
<p className='text-2xl font-bold sm:text-[32px]'>
<p className='text-2xl font-bold'>
<Display type='currency' value={totalAssets} />
</p>
</div>
@ -39,37 +39,33 @@ export default function Page() {
</div>
<div className='grid grid-cols-2 gap-2 sm:grid-cols-2 sm:gap-6 md:grid-cols-4'>
<div className='col-span-2 rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
<p className='text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>
{t('accountBalance')}
</p>
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
<p className='text-xl font-medium text-[#225BA9]'>
<Display type='currency' value={user?.balance} />
</p>
</div>
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
<p className='t text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
{t('giftAmount')}
</p>
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>{t('giftAmount')}</p>
<p className='text-xl font-medium text-[#225BA9]'>
<Display type='currency' value={user?.gift_amount} />
</p>
</div>
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
<p className='t text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
{t('commission')}
</p>
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>{t('commission')}</p>
<p className='text-xl font-medium text-[#225BA9]'>
<Display type='currency' value={user?.commission} />
</p>
</div>
<div className='col-span-2 rounded-[20px] border-2 border-[#D9D9D9] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
<p className='mb-1 flex justify-between text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
<p className='mb-1 flex justify-between text-sm font-light text-[#666] sm:mb-3'>
<span>{t('referralCode')}</span>
<Link href='/affiliate' className={'text-[#225BA9]'}>
{t('referralDetails')}
</Link>
</p>
<p className='flex justify-between text-base font-bold text-[#225BA9] sm:text-2xl'>
<p className='flex justify-between text-base font-medium text-[#225BA9]'>
<span> {user?.refer_code}</span>
<CopyToClipboard
text={`${location?.origin}/?invite=${user?.refer_code}`}

View File

@ -66,7 +66,7 @@ const LoginDialog = forwardRef<LoginDialogRef>((props, ref) => {
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className='rounded-0 h-full w-full px-12 py-[4.5rem] sm:h-auto sm:w-[496px] sm:!rounded-[50px]'>
<DialogTitle className='sr-only'>Login</DialogTitle>
<div className='min-h-[524px]'>
<div className=''>
<EmailAuthForm hide={hide} isRedirect={isRedirect} />
</div>
</DialogContent>

View File

@ -1,5 +1,6 @@
import useGlobalStore from '@/config/use-global';
import { zodResolver } from '@hookform/resolvers/zod';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { Button } from '@workspace/airo-ui/components/button';
import {
Form,
@ -55,7 +56,7 @@ export default function LoginForm({
return (
<>
<div className={'pb-9 pt-16 text-4xl font-bold'}></div>
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}></div>
<Form {...form}>
<form onSubmit={handleSubmit} className=''>
<FormField
@ -65,9 +66,7 @@ export default function LoginForm({
<FormItem className={'mb-5'}>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Email'
type='email'
{...field}
@ -84,9 +83,7 @@ export default function LoginForm({
<FormItem className={'mb-2'}>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Password'
type='password'
{...field}
@ -133,14 +130,15 @@ export default function LoginForm({
</div>
<div className='mt-6 flex justify-center'>
<Button
<AiroButton
type='submit'
variant='default'
disabled={loading}
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
className='h-auto min-w-[157px] py-2 text-lg font-medium'
>
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
{t('title')}
</Button>
</AiroButton>
</div>
</form>
</Form>

View File

@ -1,6 +1,8 @@
import useGlobalStore from '@/config/use-global';
import { zodResolver } from '@hookform/resolvers/zod';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { Button } from '@workspace/airo-ui/components/button';
import {
Form,
FormControl,
@ -93,7 +95,7 @@ export default function RegisterForm({
return (
<>
<div className={'pb-9 text-4xl font-bold'}></div>
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}></div>
{auth.register.stop_register ? (
<Markdown>{t('message')}</Markdown>
@ -108,9 +110,7 @@ export default function RegisterForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Enter your email...'
type='email'
{...field}
@ -127,9 +127,7 @@ export default function RegisterForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Enter your password...'
type='password'
{...field}
@ -146,9 +144,7 @@ export default function RegisterForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
disabled={loading}
placeholder='Enter password again...'
type='password'
@ -169,9 +165,7 @@ export default function RegisterForm({
<div className='flex items-center gap-8'>
<Input
disabled={loading}
className={
'h-[60px] flex-1 rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Enter code...'
type='text'
{...field}
@ -198,9 +192,7 @@ export default function RegisterForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
disabled={loading || !!localStorage.getItem('invite')}
placeholder={t('invite')}
{...field}
@ -242,14 +234,14 @@ export default function RegisterForm({
</Button>
</div>
<div className='mt-6 flex justify-center'>
<Button
<AiroButton
type='submit'
disabled={loading}
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
className='h-auto min-w-[157px] py-2 text-lg font-medium'
>
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
{t('title')}
</Button>
</AiroButton>
</div>
</form>
</Form>

View File

@ -1,5 +1,6 @@
import useGlobalStore from '@/config/use-global';
import { zodResolver } from '@hookform/resolvers/zod';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { Button } from '@workspace/airo-ui/components/button';
import {
Form,
@ -60,7 +61,7 @@ export default function ResetForm({
return (
<>
<div className={'pb-9 pt-10 text-4xl font-bold'}></div>
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}></div>
<Form {...form}>
<form onSubmit={handleSubmit}>
<div className='grid gap-5'>
@ -71,9 +72,7 @@ export default function ResetForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Enter your email...'
type='email'
{...field}
@ -91,9 +90,7 @@ export default function ResetForm({
<FormControl>
<div className='flex items-center gap-8'>
<Input
className={
'h-[60px] flex-1 rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
disabled={loading}
placeholder='Enter code...'
type='text'
@ -120,9 +117,7 @@ export default function ResetForm({
<FormItem>
<FormControl>
<Input
className={
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
}
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
placeholder='Enter your new password...'
type='password'
{...field}
@ -162,14 +157,14 @@ export default function ResetForm({
</Button>
</div>
<div className='mt-6 flex justify-center'>
<Button
<AiroButton
type='submit'
disabled={loading}
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
className='h-auto min-w-[157px] py-2 text-lg font-medium'
>
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
{t('title')}
</Button>
</AiroButton>
</div>
</form>
</Form>

View File

@ -84,7 +84,7 @@ export default function SendCode({ type, params }: SendCodeProps) {
<Button
type='button'
className={
'h-[60px] w-[109px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-xl hover:bg-[#225BA9] hover:text-white'
'h-[30px] w-[109px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-base hover:bg-[#225BA9] hover:text-white'
}
onClick={handleSendCode}
disabled={disabled}

View File

@ -1,8 +1,8 @@
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="10" fill="#D9D9D9"/>
<rect x="1" y="1" width="38" height="38" rx="9" stroke="#848484" stroke-opacity="0.28" stroke-width="2"/>
<rect x="1" y="1" width="38" height="38" rx="9" stroke="#225BA9" stroke-width="2"/>
<g clip-path="url(#clip0_795_3268)">
<path d="M8.75 8C8.3375 8 8 8.3375 8 8.75V17.75C8 18.1625 8.3375 18.5 8.75 18.5H17.75C18.1625 18.5 18.5 18.1625 18.5 17.75V8.75C18.5 8.3375 18.1625 8 17.75 8H8.75ZM22.25 8C21.8375 8 21.5 8.3375 21.5 8.75V17.75C21.5 18.1625 21.8375 18.5 22.25 18.5H31.25C31.6625 18.5 32 18.1625 32 17.75V8.75C32 8.3375 31.6625 8 31.25 8H22.25ZM9.5 9.5H17V17H9.5V9.5ZM23 9.5H30.5V17H23V9.5ZM11 11V15.5H15.5V11H11ZM24.5 11V15.5H29V11H24.5ZM8.75 21.5C8.3375 21.5 8 21.8375 8 22.25V31.25C8 31.6625 8.3375 32 8.75 32H17.75C18.1625 32 18.5 31.6625 18.5 31.25V22.25C18.5 21.8375 18.1625 21.5 17.75 21.5H8.75ZM22.25 21.5C21.8375 21.5 21.5 21.8375 21.5 22.25V26H23V23H26V21.5H22.25ZM28.25 21.5C27.8375 21.5 27.5 21.8375 27.5 22.25V26H29V23H32V21.5H28.25ZM9.5 23H17V30.5H9.5V23ZM11 24.5V29H15.5V24.5H11ZM24.5 26V27.5H23.75C23.3375 27.5 23 27.8375 23 28.25V32H24.5V29H26V32H27.5V28.25C27.5 27.8375 27.1625 27.5 26.75 27.5H26V26H24.5ZM30.5 26V32H32V26H30.5Z" fill="#848484"/>
<path d="M8.75 8C8.3375 8 8 8.3375 8 8.75V17.75C8 18.1625 8.3375 18.5 8.75 18.5H17.75C18.1625 18.5 18.5 18.1625 18.5 17.75V8.75C18.5 8.3375 18.1625 8 17.75 8H8.75ZM22.25 8C21.8375 8 21.5 8.3375 21.5 8.75V17.75C21.5 18.1625 21.8375 18.5 22.25 18.5H31.25C31.6625 18.5 32 18.1625 32 17.75V8.75C32 8.3375 31.6625 8 31.25 8H22.25ZM9.5 9.5H17V17H9.5V9.5ZM23 9.5H30.5V17H23V9.5ZM11 11V15.5H15.5V11H11ZM24.5 11V15.5H29V11H24.5ZM8.75 21.5C8.3375 21.5 8 21.8375 8 22.25V31.25C8 31.6625 8.3375 32 8.75 32H17.75C18.1625 32 18.5 31.6625 18.5 31.25V22.25C18.5 21.8375 18.1625 21.5 17.75 21.5H8.75ZM22.25 21.5C21.8375 21.5 21.5 21.8375 21.5 22.25V26H23V23H26V21.5H22.25ZM28.25 21.5C27.8375 21.5 27.5 21.8375 27.5 22.25V26H29V23H32V21.5H28.25ZM9.5 23H17V30.5H9.5V23ZM11 24.5V29H15.5V24.5H11ZM24.5 26V27.5H23.75C23.3375 27.5 23 27.8375 23 28.25V32H24.5V29H26V32H27.5V28.25C27.5 27.8375 27.1625 27.5 26.75 27.5H26V26H24.5ZM30.5 26V32H32V26H30.5Z" fill="#225BA9"/>
</g>
<defs>
<clipPath id="clip0_795_3268">

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -26,11 +26,11 @@ export default function Header() {
<>
<header className='fixed top-10 z-50 w-full'>
<div className={'container'}>
<div className='flex h-[60px] items-center justify-between rounded-[50px] bg-white pl-4 pr-1 sm:h-[73px] md:pl-7'>
<div className='flex h-[60px] items-center justify-between rounded-[50px] bg-white pl-4 pr-3 md:pl-6'>
<nav className='flex-col gap-6 font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6'>
{Logo}
</nav>
<div className='flex h-full flex-1 items-center justify-end gap-2 py-1'>
<div className='flex h-full flex-1 items-center justify-end gap-2 py-2'>
<LanguageSwitch />
{/*<ThemeSwitch />*/}
<UserNav />
@ -43,7 +43,7 @@ export default function Header() {
size: 'lg',
variant: 'outline',
}),
'h-full rounded-[50px] border-0 border-[#0F2C53] bg-[#0F2C53] px-5 text-[16px] font-bold text-white transition hover:bg-[#225BA9] hover:text-white sm:px-14 sm:text-2xl',
'h-full rounded-[50px] border-0 border-[#0F2C53] bg-[#0F2C53] px-5 text-base font-bold text-white transition hover:bg-[#225BA9] hover:text-white sm:px-10 sm:text-lg',
)}
>
{t('login')}

View File

@ -65,9 +65,7 @@ const PriceDisplay: React.FC<PriceDisplayProps> = ({ plan }) => {
{common?.currency?.currency_symbol}
{plan.discount_price}
</span>
<span className='text-sm font-normal leading-[1.8em] text-[#4D4D4D] sm:text-[15px]'>
{t('perYear')}
</span>
<span className='text-sm font-normal text-[#4D4D4D] sm:text-base'>{t('perYear')}</span>
</div>
<div className={'h-[15px]'}>
{plan.origin_price && (
@ -86,12 +84,13 @@ import Modal, { AlertDialogRef } from '@/components/Modal';
import Purchase from '@/components/subscribe/purchase';
import useGlobalStore from '@/config/use-global';
import { queryUserSubscribe } from '@/services/user/user';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { useTranslations } from 'next-intl';
import React from 'react';
// 星级评分组件
const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: number }) => (
<div className='text-right text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
<div className='text-right text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
{Array.from({ length: Math.min(rating, maxRating) }, (_, i) => (
<span key={i} className='text-black'>
@ -103,13 +102,13 @@ const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: num
// 功能列表组件
const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
const t = useTranslations('subscribe.detail');
const tSubscribe = useTranslations('subscribe');
const tOffer = useTranslations('components.offerDialog');
const features = [{ label: tOffer('availableNodes'), value: plan?.server_count }];
return (
<div className='mt-6 space-y-0 sm:mt-6'>
<ul className='list-disc space-y-1 pl-5'>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
<ul className='list-disc space-y-0 pl-5'>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
<div className={'flex items-start justify-between'}>
<span className=''>{t('availableTraffic')}</span>
<span>
@ -117,7 +116,16 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
</span>
</div>
</li>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
<div className={'flex items-start justify-between'}>
<span className=''>{tSubscribe('billing.duration')}</span>
<span>
{plan.origin_price ? '365' : '30'}
{tSubscribe('Day')}
</span>
</div>
</li>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
<div className={'flex items-start justify-between'}>
<span className=''>{t('connectionSpeed')}</span>
<span>
@ -125,7 +133,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
</span>
</div>
</li>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
<div className={'flex items-start justify-between'}>
<span className=''>{t('connectedDevices')}</span>
<span>
@ -136,7 +144,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
{features.map((feature) => (
<li
key={feature.label}
className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'
className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'
>
<div className={'flex items-start justify-between'}>
<span className=''>{feature.label}</span>
@ -146,7 +154,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
))}
<li className='py-1'>
<div className={'flex items-start justify-between'}>
<span className='text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
<span className='text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
{tOffer('networkStabilityIndex')}
</span>
<StarRating rating={5} />
@ -186,23 +194,24 @@ const PlanCard: React.FC<{
}
return (
<div className='relative w-full min-w-[300px] cursor-pointer rounded-[20px] border border-[#D9D9D9] bg-white p-8 shadow-[0_0_52.6px_1px_rgba(15,44,83,0.05)] transition-all duration-300 sm:w-[345px] sm:p-10'>
{/* 套餐名称 */}
<h3 className='mb-4 text-left text-xl font-normal sm:mb-6 sm:text-base'>{plan.name}</h3>
<div className='relative w-full min-w-[300px] cursor-pointer rounded-[20px] border border-[#D9D9D9] bg-white p-8 shadow-[0_0_52.6px_1px_rgba(15,44,83,0.05)] transition-all duration-300 sm:w-[345px]'>
<div className={'ml-4'}>
{/* 套餐名称 */}
<h3 className='mb-3 text-left text-xl font-normal sm:text-base'>{plan.name}</h3>
{/* 价格区域 */}
<PriceDisplay plan={plan} />
{/* 价格区域 */}
<PriceDisplay plan={plan} />
</div>
{/* 订阅按钮 */}
<button
onClick={handleSubscribe}
className='h-10 w-full rounded-full bg-[#0F2C53] text-sm font-medium text-white shadow-md transition-all duration-300 hover:bg-[#225BA9] sm:h-10 sm:text-sm md:h-[40px] md:text-[14px]'
>
<AiroButton onClick={handleSubscribe} className='h-10 w-full text-sm font-medium'>
{t('subscribe')}
</button>
</AiroButton>
{/* 功能列表 */}
<FeatureList plan={plan} />
<div className={'mx-4'}>
{/* 功能列表 */}
<FeatureList plan={plan} />
</div>
<Modal
ref={ModalRef}

View File

@ -28,13 +28,13 @@ const PlanTabs: React.FC<PlanTabProps> = (props) => {
return (
<Tabs
defaultValue='year'
className={cn('mt-8 w-full text-center md:mt-16', className)}
className={cn('mt-8 w-full text-center md:mt-8', className)}
value={tabValue}
onValueChange={(value) => props.setTabValue(value as 'year' | 'month')}
>
<TabsList className='relative mb-8 grid h-[74px] grid-cols-2 flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
<TabsList className='relative mb-8 grid h-auto grid-cols-2 flex-wrap rounded-full bg-[#EAEAEA] px-2.5 py-2'>
{tabValue === 'year' ? (
<span className='absolute -top-8 left-16 z-10 rounded-sm bg-[#E22C2E] px-2 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
<span className='absolute -top-7 left-16 z-10 rounded-sm bg-[#E22C2E] px-3 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
-{props.discount}%{/* 小三角箭头 */}
<span
className='absolute right-0 top-[75%] h-10 w-2 bg-[#E22C2E]'
@ -46,7 +46,7 @@ const PlanTabs: React.FC<PlanTabProps> = (props) => {
<TabsTrigger
key={val.value}
className={
'rounded-full py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
'rounded-full py-2 text-base text-[#0F2C53] data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
}
value={val.value}
>

View File

@ -57,11 +57,11 @@ export const AffiliateDialog = ({ ref }: AffiliateDialogProps) => {
return (
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)] sm:text-base'>
<div>
<div className={'text-[#225BA9]'}>{t('userIdentifier')}</div>
<div className={'text-sm text-[#225BA9]'}>{t('userIdentifier')}</div>
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
</div>
<div>
<div className={'text-[#225BA9]'}>{t('time')}</div>
<div className={'text-sm text-[#225BA9]'}>{t('time')}</div>
<div className={'font-bold text-[#091B33]'}>
{formatDate(invite.registered_at)}
</div>

View File

@ -66,24 +66,22 @@ export default function Affiliate() {
<div className={'text-xs font-light sm:text-[15px]'}>{t('commissionInfo')}</div>
</div>
<div
className={
'mb-3 text-xl font-bold leading-tight text-[#091B33] sm:text-[32px] sm:leading-[1.5]'
}
className={'mb-3 text-xl font-bold leading-tight text-[#091B33] sm:mb-4 sm:text-2xl'}
>
{t('historicalRecommendedUsers')}
{inviteListData?.total}
</div>
<div className={'grid grid-cols-2 gap-[10px] sm:grid-cols-1 sm:gap-5 lg:grid-cols-2'}>
<div className='rounded-[20px] border-2 border-[#EAEAEA] bg-[#EAEAEA] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:py-4'>
<p className='flex justify-between font-medium text-[#666] opacity-80 sm:mb-3 sm:text-sm'>
<div className='rounded-[20px] border-2 border-[#EAEAEA] bg-[#EAEAEA] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:px-5 sm:pb-2 sm:pt-4'>
<p className='flex justify-between font-light text-[#666] sm:mb-3 sm:text-sm'>
{t('totalCommission')}
</p>
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
<p className='text-xl font-semibold text-[#225BA9]'>
<Display type='currency' value={data?.total_commission} />
</p>
</div>
<div className='rounded-[20px] border-2 border-[#D9D9D9] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:py-4'>
<p className='flex justify-between font-medium text-[#666] opacity-80 sm:mb-3 sm:text-sm'>
<div className='rounded-[20px] border-2 border-[#D9D9D9] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:px-5 sm:pb-2 sm:pt-4'>
<p className='flex justify-between font-light text-[#666] sm:mb-3 sm:text-sm'>
{t('commissionInviteCode')}
<CopyToClipboard
text={`${location?.origin}/?invite=${user?.refer_code}`}
@ -102,7 +100,7 @@ export default function Affiliate() {
</Button>
</CopyToClipboard>
</p>
<p className='flex justify-between text-xl font-bold text-[#225BA9] sm:text-2xl'>
<p className='flex justify-between text-xl font-bold text-[#225BA9]'>
<span> {user?.refer_code}</span>
<CopyToClipboard
text={`${location?.origin}/?invite=${user?.refer_code}`}
@ -148,11 +146,11 @@ export default function Affiliate() {
return (
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] sm:text-base'>
<div>
<div className={'text-[#225BA9]'}>{t('userIdentifier')}</div>
<div className={'text-sm text-[#225BA9]'}>{t('userIdentifier')}</div>
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
</div>
<div>
<div className={'text-[#225BA9]'}>{t('time')}</div>
<div className={'text-sm text-[#225BA9]'}>{t('time')}</div>
<div className={'font-bold text-[#091B33]'}>
{formatDate(invite.registered_at)}
</div>
@ -172,7 +170,9 @@ export default function Affiliate() {
{t('commissionCalculation')}
</h3>
</div>
<div className={'mb-4 text-[10px] font-light text-[#0F2C53] sm:text-base'}>
<div
className={'mb-4 whitespace-pre-line text-[10px] font-light text-[#0F2C53] sm:text-sm'}
>
{t('commissionCalculationInfo')}
</div>

View File

@ -11,7 +11,7 @@ export default function FooterCopyright() {
const t = useTranslations('auth');
return (
<footer className={'fixed bottom-6 z-50 w-full text-xs sm:text-lg'}>
<footer className={'fixed bottom-6 z-[1] w-full text-xs sm:text-sm'}>
<div className={'container relative flex items-center justify-center text-right sm:block'}>
<Image
src={'./logo.png'}

View File

@ -1,18 +1,15 @@
'use client';
import { Button } from '@workspace/airo-ui/components/button';
import { useTranslations } from 'next-intl';
import { useRef } from 'react';
import OfferDialog, { OfferDialogRef } from './OfferDialog/index';
import OfferDialog from './OfferDialog/index';
export default function HomeContent() {
const dialogRef = useRef<OfferDialogRef>(null);
const t = useTranslations('components.home');
return (
<div className='flex min-h-[calc(100vh-73px)] flex-col items-center justify-center pt-8'>
{/* 大标题 */}
<h1 className='mb-6 self-start text-4xl font-bold !leading-tight text-white sm:mb-10 sm:self-center sm:text-6xl'>
<h1 className='mb-6 self-start text-4xl font-bold !leading-tight text-white sm:mb-10 sm:self-center sm:text-6xl sm:text-[64px]'>
{t('connect')}
<br />
{t('anytime')}
@ -30,14 +27,7 @@ export default function HomeContent() {
<p className={'mt-1 w-[255px] sm:mt-0 sm:w-full'}>{t('getSubscription')}</p>
</div>
{/* 按钮 */}
<Button
onClick={() => dialogRef.current?.show()}
className='mb-8 h-auto rounded-full border-2 border-white bg-white/10 px-8 py-2 text-lg font-bold text-white transition hover:bg-white/25 sm:py-4 sm:text-2xl'
>
{t('viewSubscriptionPlans')}
</Button>
<OfferDialog ref={dialogRef} />
<OfferDialog />
</div>
);
}

View File

@ -1,19 +1,22 @@
import { getSubscription } from '@/services/user/portal';
import { useQuery } from '@tanstack/react-query';
import { Dialog, DialogContent, DialogTitle } from '@workspace/airo-ui/components/dialog';
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import {
Dialog,
DialogContent,
DialogTitle,
DialogTrigger,
} from '@workspace/airo-ui/components/dialog';
import { useRef, useState } from 'react';
import TabContent from '@/components/SubscribePlan/PlanContent/index';
import PlanTabs from '@/components/SubscribePlan/PlanTabs/PlanTabs';
import { Button } from '@workspace/airo-ui/components/button';
import { useTranslations } from 'next-intl';
export interface OfferDialogRef {
show: () => void;
hide: () => void;
}
const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
const OfferDialog = () => {
const t = useTranslations('components.offerDialog');
const tHome = useTranslations('components.home');
const [open, setOpen] = useState(false);
const [tabValue, setTabValue] = useState<'year' | 'month'>('year');
const dialogRef = useRef<HTMLDivElement>(null);
@ -40,28 +43,26 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
},
enabled: true, // 初始不执行,手动控制
retry: 1, // 失败时重试1次
refetchOnWindowFocus: true,
});
useImperativeHandle(ref, () => ({
show: () => {
refetch();
setOpen(true);
},
hide: () => setOpen(false),
}));
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className='mb-8 h-auto rounded-full border-[3px] border-white bg-white/10 px-8 py-2 text-lg font-bold text-white transition hover:bg-white/25 sm:px-6 sm:py-1.5'>
{tHome('viewSubscriptionPlans')}
</Button>
</DialogTrigger>
<DialogContent
ref={dialogRef}
className='rounded-0 h-full gap-0 px-4 py-8 sm:max-h-[95%] sm:!rounded-[32px] sm:px-8 sm:py-12 md:max-w-[1280px]'
>
<DialogTitle className={'sr-only'}></DialogTitle>
<div className={'ml-6 sm:ml-0'}>
<div className={'text-4xl font-bold text-[#0F2C53] md:mb-4 md:text-center md:text-5xl'}>
<div className={'text-4xl font-bold text-[#0F2C53] md:mb-1 md:text-center'}>
{t('selectPlan')}
</div>
<div className={'text-lg font-medium text-[#666666] md:text-center'}>
<div className={'text-base font-medium text-[#666666] md:text-center'}>
{t('selectYourPlan')}
</div>
</div>
@ -80,6 +81,6 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
</DialogContent>
</Dialog>
);
});
};
export default OfferDialog;

View File

@ -5,7 +5,7 @@ import PlanTabs, { TabValueType } from '@/components/SubscribePlan/PlanTabs/Plan
import useGlobalStore from '@/config/use-global';
import { preCreateOrder, purchase } from '@/services/user/order';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/airo-ui/components/button';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import {
Dialog,
DialogContent,
@ -164,14 +164,10 @@ const Purchase = forwardRef<PurchaseDialogRef, PurchaseProps>((props, ref) => {
/>
</div>
<div className='mt-8 flex items-center justify-center'>
<Button
className='w-[150px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-xl hover:bg-[#225BA9] hover:text-white'
disabled={loading}
onClick={handleSubmit}
>
<AiroButton variant={'primary'} disabled={loading} onClick={handleSubmit}>
{loading && <LoaderCircle className='mr-2 animate-spin' />}
{t('buyNow')}
</Button>
</AiroButton>
</div>
</div>
</DialogContent>

View File

@ -6,7 +6,6 @@ import useGlobalStore from '@/config/use-global';
import { preCreateOrder, renewal } from '@/services/user/order';
import { useQuery } from '@tanstack/react-query';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { Button } from '@workspace/airo-ui/components/button';
import {
Dialog,
DialogContent,
@ -103,9 +102,9 @@ export default function Renewal({ id, subscribe, className }: Readonly<RenewalPr
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button size='sm' className={className}>
<AiroButton variant={'primaryBlue'} className={'px-2 text-xs'}>
{t('renewPlan')}
</Button>
</AiroButton>
</DialogTrigger>
<DialogContent className='flex h-full flex-col md:h-auto'>
<DialogHeader>

View File

@ -1,7 +1,7 @@
{
"annualPackage": "Annual Package",
"commissionCalculation": "Commission Calculation",
"commissionCalculationInfo": "Fill in the corresponding number of invited users below to calculate the commission amount at different ratios. *This table is calculated based on the Pro Plan. The ratios for other plans remain unchanged, and the calculation is based on the actual amount.",
"commissionCalculationInfo": "Fill in the corresponding number of invited users below to calculate the commission amount at different ratios. \n *This table is calculated based on the Pro Plan. The ratios for other plans remain unchanged, and the calculation is based on the actual amount.",
"commissionInfo": "Commission amount, which is automatically transferred to the wallet balance after a successful invitation.",
"commissionInviteCode": "Commission Invite Code",
"commissionRate": "Commission Rate",

View File

@ -1,7 +1,7 @@
{
"annualPackage": "年付套餐",
"commissionCalculation": "佣金计算",
"commissionCalculationInfo": "在下方填入对应邀请用户数量,即可计算不同比例返佣金额 *该表以Pro Plan计算其它套餐比例不变以实际金额计算为准",
"commissionCalculationInfo": "在下方填入对应邀请用户数量,即可计算不同比例返佣金额 \n *该表以Pro Plan计算其它套餐比例不变以实际金额计算为准",
"commissionInfo": "佣金金额,邀请成功后自动转入钱包余额",
"commissionInviteCode": "返佣邀请码",
"commissionRate": "佣金比例",

View File

@ -1,5 +1,11 @@
import baseConfig from '@workspace/airo-ui/tailwind.config';
baseConfig.theme.extend.boxShadow = {
...baseConfig.theme.extend.boxShadow,
...{
input: 'inset 0 0 7.6px 0 rgba(0, 0, 0, 0.25) ',
},
};
const config = {
...baseConfig,
darkMode: false, // 或 'media' 或 'class',根据你的需求覆盖

View File

@ -13,6 +13,7 @@ const buttonVariants = cva(
primary: 'bg-[#225BA9] text-primary-foreground shadow hover:bg-[#0F2C53] ',
danger: 'bg-[#FF4248] text-primary-foreground shadow hover:bg-[#E22C2E]',
dangerLink: 'text-[#E22C2E] ',
primaryBlue: 'bg-[#A8D4ED] text-primary-foreground hover:bg-[#225BA9]',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',

View File

@ -5,7 +5,7 @@ import * as React from 'react';
import { cn } from '@workspace/airo-ui/lib/utils';
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer',
{
variants: {
variant: {

View File

@ -133,42 +133,44 @@ export function ProList<TData, TValue extends Record<string, unknown>>({
return (
<div className='flex max-w-full flex-col gap-2 sm:gap-4'>
<div className='flex flex-wrap-reverse items-center justify-between gap-4'>
<div className={'w-full'}>
{params ? (
<div className='flex w-full justify-between'>
<ColumnFilter
table={table}
params={params}
filters={Object.fromEntries(columnFilters.map((item) => [item.id, item.value]))}
/>
<Button
variant='outline'
className='h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:hidden'
onClick={fetchData}
>
<RefreshCcw className='h-4 w-4 text-[#848484]' />
</Button>
</div>
) : (
header?.title
)}
{params || header ? (
<div className='flex flex-wrap-reverse items-center justify-between gap-4'>
<div className={'w-full'}>
{params ? (
<div className='flex w-full justify-between'>
<ColumnFilter
table={table}
params={params}
filters={Object.fromEntries(columnFilters.map((item) => [item.id, item.value]))}
/>
<Button
variant='outline'
className='h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:hidden'
onClick={fetchData}
>
<RefreshCcw className='h-4 w-4 text-[#848484]' />
</Button>
</div>
) : (
header?.title
)}
</div>
<div className='flex flex-1 items-center justify-end gap-2'>
{params && params?.length > 0 && (
<>
<Button
variant='outline'
className='hidden h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:block'
onClick={fetchData}
>
<RefreshCcw className='h-4 w-4 text-[#848484]' />
</Button>
</>
)}
{header?.toolbar}
</div>
</div>
<div className='flex flex-1 items-center justify-end gap-2'>
{params && params?.length > 0 && (
<>
<Button
variant='outline'
className='hidden h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:block'
onClick={fetchData}
>
<RefreshCcw className='h-4 w-4 text-[#848484]' />
</Button>
</>
)}
{header?.toolbar}
</div>
</div>
) : null}
{selectedCount > 0 && batchRender && (
<Alert className='flex items-center justify-between'>