Ver código fonte

feat: home页面调整

BaiLuoYan 1 mês atrás
pai
commit
c1ec50d08a

+ 14 - 15
src/components/Footerbar/index.tsx

@@ -1,25 +1,24 @@
-import { memo } from 'react'
+import { memo } from 'react';
 
-import { Icon } from '@iconify/react'
-import { useTranslation } from 'react-i18next'
-import { useNavigate } from 'react-router-dom'
+import { Icon } from '@iconify/react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
 
-
-import logoUnion from '@/assets/iconify/multi-color/logo-union.svg'
+import logoUnion from '@/assets/iconify/multi-color/logo-union.svg';
 
 const Footerbar = memo(() => {
-    const { t } = useTranslation()
-    const navigate = useNavigate()
+    const { t } = useTranslation();
+    const navigate = useNavigate();
 
     const handleLinkClick = (path: string) => {
-        navigate(path)
-    }
+        navigate(path);
+    };
 
     const navLinks = [
         { path: '/privacy', labelKey: 'components.footerbar.privacyPolicy' },
         { path: '/terms-of-service', labelKey: 'components.footerbar.termsOfService' },
         { path: '/contact', labelKey: 'components.footerbar.contact' },
-    ] as const
+    ] as const;
 
     return (
         <footer className="bg-black border-t border-white/10">
@@ -54,9 +53,9 @@ const Footerbar = memo(() => {
                 </div>
             </div>
         </footer>
-    )
-})
+    );
+});
 
-Footerbar.displayName = 'Footerbar'
+Footerbar.displayName = 'Footerbar';
 
-export default Footerbar
+export default Footerbar;

+ 20 - 20
src/hooks/useLoginDialog.tsx

@@ -1,27 +1,27 @@
-import { useCallback } from 'react'
+import { useCallback } from 'react';
 
-import { Trans, useTranslation } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next';
 
-import LoginForm from '@/components/LoginForm'
-import { useAppUrls } from '@/hooks/useAppUrls'
-import { dialogModel } from '@/models/dialogModel'
+import LoginForm from '@/components/LoginForm';
+import { useAppUrls } from '@/hooks/useAppUrls';
+import { dialogModel } from '@/models/dialogModel';
 
 export interface LoginDialogOptions {
     /** 弹窗标题的 i18n key,默认 common.login.dialogTitle */
-    titleKey?: string
+    titleKey?: string;
     /** 提示文案的 i18n key(支持 <linkText> / <downloadLink> 插值),默认 common.login.dialogPrompt */
-    promptKey?: string
+    promptKey?: string;
 }
 
 export function useLoginDialog() {
-    const { t } = useTranslation()
-    const { openDialog, closeDialog } = dialogModel.useModel()
-    const { deeplinkUrl, downloadUrlByPlatform } = useAppUrls()
+    const { t } = useTranslation();
+    const { openDialog, closeDialog } = dialogModel.useModel();
+    const { deeplinkUrl, downloadUrlByPlatform } = useAppUrls();
 
     return useCallback(
         (options?: LoginDialogOptions) => {
-            const titleKey = options?.titleKey ?? 'common.login.dialogTitle'
-            const promptKey = options?.promptKey ?? 'common.login.dialogPrompt'
+            const titleKey = options?.titleKey ?? 'common.login.dialogTitle';
+            const promptKey = options?.promptKey ?? 'common.login.dialogPrompt';
 
             const id = openDialog({
                 title: t(titleKey),
@@ -35,7 +35,7 @@ export function useLoginDialog() {
                                         const Wrap = ({
                                             children,
                                         }: {
-                                            children?: React.ReactNode
+                                            children?: React.ReactNode;
                                         }) =>
                                             deeplinkUrl ? (
                                                 <a
@@ -48,14 +48,14 @@ export function useLoginDialog() {
                                                 </a>
                                             ) : (
                                                 <span>{children}</span>
-                                            )
-                                        return <Wrap />
+                                            );
+                                        return <Wrap />;
                                     })(),
                                     downloadLink: (() => {
                                         const Wrap = ({
                                             children,
                                         }: {
-                                            children?: React.ReactNode
+                                            children?: React.ReactNode;
                                         }) =>
                                             downloadUrlByPlatform ? (
                                                 <a
@@ -68,8 +68,8 @@ export function useLoginDialog() {
                                                 </a>
                                             ) : (
                                                 <span>{children}</span>
-                                            )
-                                        return <Wrap />
+                                            );
+                                        return <Wrap />;
                                     })(),
                                 }}
                             />
@@ -79,8 +79,8 @@ export function useLoginDialog() {
                 ),
                 maskClosable: false,
                 closeable: true,
-            })
+            });
         },
         [t, openDialog, closeDialog, deeplinkUrl, downloadUrlByPlatform]
-    )
+    );
 }

+ 1 - 3
src/hooks/useSize.ts

@@ -28,9 +28,7 @@ export const useScreenSize = () => {
  * @param ref 目标元素的 RefObject
  * @returns 当前元素的 { width, height }(contentRect)
  */
-export const useRefSize = <T extends HTMLElement = HTMLDivElement>(
-    ref: React.RefObject<T>
-) => {
+export const useRefSize = <T extends HTMLElement = HTMLDivElement>(ref: React.RefObject<T>) => {
     const [size, setSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });
 
     useEffect(() => {

+ 1 - 5
src/pages/home/components/AppAccess.tsx

@@ -23,11 +23,7 @@ export function AppAccess() {
 
                 {/* App wall background with NOMO branding */}
                 <div className="relative w-full max-w-[1280px] rounded-lg overflow-hidden">
-                    <img
-                        src={appAccessSection}
-                        alt=""
-                        className="w-full h-auto object-cover"
-                    />
+                    <img src={appAccessSection} alt="" className="w-full h-auto object-cover" />
                 </div>
 
                 {/* Logo strip with fade edges */}

+ 38 - 23
src/pages/home/components/ChoosePlatform.tsx

@@ -1,35 +1,35 @@
-import { useTranslation } from 'react-i18next'
+import { useTranslation } from 'react-i18next';
 
-import btnAndroid from '@/assets/images/home/btn-android.svg'
-import btnAppStore from '@/assets/images/home/btn-app-store.svg'
-import btnGooglePlay from '@/assets/images/home/btn-google-play.svg'
-import btnMacos from '@/assets/images/home/btn-macos.svg'
-import btnWindows from '@/assets/images/home/btn-windows.svg'
-import devicesMockup from '@/assets/images/home/devices-mockup.png'
-import { useAppUrls } from '@/hooks/useAppUrls'
+import btnAndroid from '@/assets/images/home/btn-android.svg';
+import btnAppStore from '@/assets/images/home/btn-app-store.svg';
+import btnGooglePlay from '@/assets/images/home/btn-google-play.svg';
+import btnMacos from '@/assets/images/home/btn-macos.svg';
+import btnWindows from '@/assets/images/home/btn-windows.svg';
+import devicesMockup from '@/assets/images/home/devices-mockup.png';
+import { useAppUrls } from '@/hooks/useAppUrls';
 
-import Wrapper from './Wrapper'
+import Wrapper from './Wrapper';
 
 interface PlatformButton {
-    image: string
-    alt: string
-    urlKey: 'appleStoreUrl' | 'googleStoreUrl' | 'downloadUrlByPlatform'
+    image: string;
+    alt: string;
+    urlKey: 'appleStoreUrl' | 'googleStoreUrl' | 'downloadUrlByPlatform';
 }
 
 const STORE_BUTTONS: PlatformButton[] = [
     { image: btnAppStore, alt: 'App Store', urlKey: 'appleStoreUrl' },
     { image: btnGooglePlay, alt: 'Google Play', urlKey: 'googleStoreUrl' },
-]
+];
 
 const PLATFORM_ICONS = [
     { image: btnAndroid, alt: 'Android' },
     { image: btnWindows, alt: 'Windows' },
     { image: btnMacos, alt: 'Mac OS' },
-] as const
+] as const;
 
 export function ChoosePlatform() {
-    const { t } = useTranslation()
-    const urls = useAppUrls()
+    const { t } = useTranslation();
+    const urls = useAppUrls();
 
     return (
         <section className="w-full py-8 sm:py-10 lg:py-16">
@@ -46,16 +46,31 @@ export function ChoosePlatform() {
 
                     <div className="grid grid-cols-2 gap-6 px-4 w-full sm:flex sm:flex-wrap sm:items-center sm:justify-center">
                         {STORE_BUTTONS.map(({ image, alt, urlKey }) => {
-                            const url = urls[urlKey]
-                            if (!url) return null
+                            const url = urls[urlKey];
+                            if (!url) return null;
                             return (
-                                <a key={alt} href={url} target="_blank" rel="noopener noreferrer" className="h-[50px]">
-                                    <img src={image} alt={alt} className="h-full w-full object-contain sm:w-auto" />
+                                <a
+                                    key={alt}
+                                    href={url}
+                                    target="_blank"
+                                    rel="noopener noreferrer"
+                                    className="h-[50px]"
+                                >
+                                    <img
+                                        src={image}
+                                        alt={alt}
+                                        className="h-full w-full object-contain sm:w-auto"
+                                    />
                                 </a>
-                            )
+                            );
                         })}
                         {PLATFORM_ICONS.map(({ image, alt }) => (
-                            <img key={alt} src={image} alt={alt} className="h-[50px] w-full object-contain sm:w-auto" />
+                            <img
+                                key={alt}
+                                src={image}
+                                alt={alt}
+                                className="h-[50px] w-full object-contain sm:w-auto"
+                            />
                         ))}
                     </div>
                 </div>
@@ -67,5 +82,5 @@ export function ChoosePlatform() {
                 />
             </Wrapper>
         </section>
-    )
+    );
 }

+ 13 - 13
src/pages/home/components/FeatureDetails.tsx

@@ -1,17 +1,17 @@
-import { useTranslation } from 'react-i18next'
+import { useTranslation } from 'react-i18next';
 
-import featureDetailIp from '@/assets/images/home/feature-detail-ip.png'
-import featureDetailPrivacy from '@/assets/images/home/feature-detail-privacy.png'
-import featureDetailSpeed from '@/assets/images/home/feature-detail-speed.png'
+import featureDetailIp from '@/assets/images/home/feature-detail-ip.png';
+import featureDetailPrivacy from '@/assets/images/home/feature-detail-privacy.png';
+import featureDetailSpeed from '@/assets/images/home/feature-detail-speed.png';
 
-import Wrapper from './Wrapper'
+import Wrapper from './Wrapper';
 
 interface FeatureItem {
-    titleKey: string
-    descKey: string
-    image: string
-    imageAlt: string
-    reverse: boolean
+    titleKey: string;
+    descKey: string;
+    image: string;
+    imageAlt: string;
+    reverse: boolean;
 }
 
 const FEATURES: FeatureItem[] = [
@@ -36,10 +36,10 @@ const FEATURES: FeatureItem[] = [
         imageAlt: 'Fixed IP functionality',
         reverse: false,
     },
-]
+];
 
 export function FeatureDetails() {
-    const { t } = useTranslation()
+    const { t } = useTranslation();
 
     return (
         <section className="w-full py-10 lg:py-16">
@@ -68,5 +68,5 @@ export function FeatureDetails() {
                 ))}
             </Wrapper>
         </section>
-    )
+    );
 }

+ 8 - 8
src/pages/home/index.tsx

@@ -1,8 +1,8 @@
-import { AppAccess } from './components/AppAccess'
-import { ChoosePlatform } from './components/ChoosePlatform'
-import { FeatureDetails } from './components/FeatureDetails'
-import { Hero } from './components/Hero'
-import { SectionDivider } from './components/SectionDivider'
+import { AppAccess } from './components/AppAccess';
+import { ChoosePlatform } from './components/ChoosePlatform';
+import { FeatureDetails } from './components/FeatureDetails';
+import { Hero } from './components/Hero';
+import { SectionDivider } from './components/SectionDivider';
 
 const Home: React.FC = () => {
     return (
@@ -16,7 +16,7 @@ const Home: React.FC = () => {
             <FeatureDetails />
             <SectionDivider />
         </div>
-    )
-}
+    );
+};
 
-export default Home
+export default Home;