首页重构为 TokenDance 设计系统 + Contact 页面
- Home/index.jsx: 替换为 TokenDance 设计(紫色点缀、白色主题、TuringToken 品牌) - Contact/index.jsx: 新增联系销售页面 - EmptyState.jsx: 新增通用空状态组件 - i18n/locales: 中英文 i18n 资源同步新增 - i18n.js, utils.jsx: 配合新页面更新工具函数 - App.jsx, AdminInitialSetupModal.jsx, User context: 注册联系页路由及配套调整
This commit is contained in:
parent
6836012ab4
commit
b47ea0dd3a
|
|
@ -95,6 +95,11 @@ import LuckyBag from './pages/LuckyBag';
|
||||||
import Drawing from './pages/Drawing';
|
import Drawing from './pages/Drawing';
|
||||||
import ProfitDashboard from './pages/ProfitDashboard';
|
import ProfitDashboard from './pages/ProfitDashboard';
|
||||||
import SettingsAntiAbuse from './pages/Setting/Operation/SettingsAntiAbuse';
|
import SettingsAntiAbuse from './pages/Setting/Operation/SettingsAntiAbuse';
|
||||||
|
import Contact from './pages/Contact';
|
||||||
|
import About from './pages/About';
|
||||||
|
import UserAgreement from './pages/UserAgreement';
|
||||||
|
import PrivacyPolicy from './pages/PrivacyPolicy';
|
||||||
|
import Docs from './pages/Docs';
|
||||||
|
|
||||||
const Home = lazy(() => import('./pages/Home'));
|
const Home = lazy(() => import('./pages/Home'));
|
||||||
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
||||||
|
|
@ -102,10 +107,6 @@ const DistributorApply = lazy(() => import('./pages/DistributorApply'));
|
||||||
const DistributorCenter = lazy(() => import('./pages/DistributorCenter'));
|
const DistributorCenter = lazy(() => import('./pages/DistributorCenter'));
|
||||||
const DistributorAdmin = lazy(() => import('./pages/DistributorAdmin'));
|
const DistributorAdmin = lazy(() => import('./pages/DistributorAdmin'));
|
||||||
const InviteRedirect = lazy(() => import('./pages/InviteRedirect'));
|
const InviteRedirect = lazy(() => import('./pages/InviteRedirect'));
|
||||||
const About = lazy(() => import('./pages/About'));
|
|
||||||
const UserAgreement = lazy(() => import('./pages/UserAgreement'));
|
|
||||||
const PrivacyPolicy = lazy(() => import('./pages/PrivacyPolicy'));
|
|
||||||
const Docs = lazy(() => import('./pages/Docs'));
|
|
||||||
|
|
||||||
function DynamicOAuth2Callback() {
|
function DynamicOAuth2Callback() {
|
||||||
const { provider } = useParams();
|
const { provider } = useParams();
|
||||||
|
|
@ -545,6 +546,14 @@ function App() {
|
||||||
</Suspense>
|
</Suspense>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path='/contact'
|
||||||
|
element={
|
||||||
|
<Suspense fallback={<Loading></Loading>} key={location.pathname}>
|
||||||
|
<Contact />
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path='/docs'
|
path='/docs'
|
||||||
element={
|
element={
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,16 @@ import React, {
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { Modal, Form, Typography, Space, Button } from '@douyinfe/semi-ui';
|
|
||||||
import { IconLock } from '@douyinfe/semi-icons';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { UserContext } from '../../context/User';
|
import { Lock as IconLock } from 'lucide-react';
|
||||||
|
import { Modal, Form, Typography, Space, Button } from '@douyinfe/semi-ui';
|
||||||
import {
|
import {
|
||||||
API,
|
API,
|
||||||
showError,
|
showError,
|
||||||
showSuccess,
|
showSuccess,
|
||||||
mergeSelfResponseIntoLocalUser,
|
mergeSelfResponseIntoLocalUser,
|
||||||
} from '../../helpers';
|
} from '../../helpers';
|
||||||
|
import { UserContext } from '../../context/User';
|
||||||
import { buildAdminUserPhoneFieldRules } from '../table/users/modals/userPhoneFormRules';
|
import { buildAdminUserPhoneFieldRules } from '../table/users/modals/userPhoneFormRules';
|
||||||
|
|
||||||
const { Text, Title } = Typography;
|
const { Text, Title } = Typography;
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button } from '@douyinfe/semi-ui';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button } from '@douyinfe/semi-ui';
|
||||||
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
import { useIsMobile } from '../../../hooks/common/useIsMobile';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2025 QuantumNous
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Inbox } from 'lucide-react';
|
||||||
|
|
||||||
|
const ACC = '#635BFF';
|
||||||
|
const ACC_SOFT = '#EEEBFF';
|
||||||
|
const INK = '#0A2540';
|
||||||
|
const SUB = '#425466';
|
||||||
|
const DIM = '#697386';
|
||||||
|
|
||||||
|
const toText = (v) =>
|
||||||
|
typeof v === 'string'
|
||||||
|
? v
|
||||||
|
: v?.props?.children || '';
|
||||||
|
|
||||||
|
const EmptyState = ({ icon, title, description, children, style }) => {
|
||||||
|
const Icon = icon || Inbox;
|
||||||
|
const titleText = toText(title);
|
||||||
|
const descText = toText(description);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className='flex flex-col items-center justify-center py-12 text-center'
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className='inline-flex h-12 w-12 items-center justify-center rounded-2xl'
|
||||||
|
style={{ background: ACC_SOFT, color: ACC }}
|
||||||
|
>
|
||||||
|
<Icon size={22} />
|
||||||
|
</div>
|
||||||
|
{titleText && (
|
||||||
|
<p className='mt-4 text-sm font-semibold' style={{ color: INK }}>
|
||||||
|
{titleText}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{descText && (
|
||||||
|
<p className='mt-1 text-sm' style={{ color: DIM }}>
|
||||||
|
{descText}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{!titleText && !descText && (
|
||||||
|
<p className='mt-4 text-sm' style={{ color: DIM }}>
|
||||||
|
暂无数据
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{children && <div className='mt-4'>{children}</div>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EmptyState;
|
||||||
|
|
@ -19,9 +19,10 @@ For commercial licensing, please contact support@quantumnous.com
|
||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { reducer, initialState } from './reducer';
|
import { API } from '../../helpers/api';
|
||||||
|
import { initialState, reducer } from './reducer';
|
||||||
|
import { mergeSelfResponseIntoLocalUser } from '../../helpers/data';
|
||||||
import { normalizeLanguage } from '../../i18n/language';
|
import { normalizeLanguage } from '../../i18n/language';
|
||||||
import { API, mergeSelfResponseIntoLocalUser } from '../../helpers';
|
|
||||||
import AdminInitialSetupModal from '../../components/auth/AdminInitialSetupModal';
|
import AdminInitialSetupModal from '../../components/auth/AdminInitialSetupModal';
|
||||||
|
|
||||||
export const UserContext = React.createContext({
|
export const UserContext = React.createContext({
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,12 @@ For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Toast, Pagination } from '@douyinfe/semi-ui';
|
import { Toast, Pagination } from '@douyinfe/semi-ui';
|
||||||
import { toastConstants } from '../constants';
|
|
||||||
import React from 'react';
|
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
import {
|
import {
|
||||||
THINK_TAG_REGEX,
|
THINK_TAG_REGEX,
|
||||||
MESSAGE_ROLES,
|
MESSAGE_ROLES,
|
||||||
} from '../constants/playground.constants';
|
} from '../constants/playground.constants';
|
||||||
import { TABLE_COMPACT_MODES_KEY } from '../constants';
|
import { TABLE_COMPACT_MODES_KEY } from '../constants';
|
||||||
import { USER_ROLES } from '../constants/user.constants';
|
import { toastConstants } from '../constants/toast.constants';
|
||||||
import { MOBILE_BREAKPOINT } from '../hooks/common/useIsMobile';
|
import { MOBILE_BREAKPOINT } from '../hooks/common/useIsMobile';
|
||||||
|
|
||||||
const HTMLToastContent = ({ htmlContent }) => {
|
const HTMLToastContent = ({ htmlContent }) => {
|
||||||
|
|
@ -144,6 +141,15 @@ export function parseCommissionPercentStringToBps(s) {
|
||||||
export function getSystemName() {
|
export function getSystemName() {
|
||||||
let system_name = localStorage.getItem('system_name');
|
let system_name = localStorage.getItem('system_name');
|
||||||
if (!system_name) return 'TuringToken';
|
if (!system_name) return 'TuringToken';
|
||||||
|
// 旧品牌名缓存迁移:清掉 TokenFactory / TokenFactoryOpen / 开放词元工厂 等历史默认,避免登录页/控制台标题闪烁。
|
||||||
|
if (
|
||||||
|
system_name === 'TokenFactory' ||
|
||||||
|
system_name === 'TokenFactoryOpen' ||
|
||||||
|
system_name === '开放词元工厂'
|
||||||
|
) {
|
||||||
|
localStorage.setItem('system_name', 'TuringToken');
|
||||||
|
return 'TuringToken';
|
||||||
|
}
|
||||||
return system_name;
|
return system_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,17 @@ i18n
|
||||||
load: 'currentOnly',
|
load: 'currentOnly',
|
||||||
supportedLngs: supportedLanguages,
|
supportedLngs: supportedLanguages,
|
||||||
resources: {
|
resources: {
|
||||||
en: enTranslation,
|
en: { translation: enTranslation },
|
||||||
'zh-CN': zhCNTranslation,
|
'zh-CN': { translation: zhCNTranslation },
|
||||||
'zh-TW': zhTWTranslation,
|
'zh-TW': { translation: zhTWTranslation },
|
||||||
fr: frTranslation,
|
fr: { translation: frTranslation },
|
||||||
ru: ruTranslation,
|
ru: { translation: ruTranslation },
|
||||||
ja: jaTranslation,
|
ja: { translation: jaTranslation },
|
||||||
vi: viTranslation,
|
vi: { translation: viTranslation },
|
||||||
id: idTranslation,
|
id: { translation: idTranslation },
|
||||||
ms: msTranslation,
|
ms: { translation: msTranslation },
|
||||||
th: thTranslation,
|
th: { translation: thTranslation },
|
||||||
sw: swTranslation,
|
sw: { translation: swTranslation },
|
||||||
},
|
},
|
||||||
fallbackLng: 'zh-CN',
|
fallbackLng: 'zh-CN',
|
||||||
lng: 'zh-CN',
|
lng: 'zh-CN',
|
||||||
|
|
|
||||||
|
|
@ -5695,6 +5695,21 @@
|
||||||
"主题切换": "Theme Toggle",
|
"主题切换": "Theme Toggle",
|
||||||
"顶栏显示主题切换按钮,允许用户切换亮色/暗色模式": "Show theme toggle in header bar, allowing users to switch between light/dark mode",
|
"顶栏显示主题切换按钮,允许用户切换亮色/暗色模式": "Show theme toggle in header bar, allowing users to switch between light/dark mode",
|
||||||
"语言选择器": "Language Selector",
|
"语言选择器": "Language Selector",
|
||||||
"顶栏显示语言选择器,允许用户切换界面语言": "Show language selector in header bar, allowing users to switch interface language"
|
"顶栏显示语言选择器,允许用户切换界面语言": "Show language selector in header bar, allowing users to switch interface language",
|
||||||
|
"All systems normal": "All systems normal",
|
||||||
|
"调用 AI 像调用函": "Call AI like calling a",
|
||||||
|
"函数": "function",
|
||||||
|
"一样轻。": "— that light.",
|
||||||
|
"把 OpenAI、Claude、Gemini、DeepSeek 等几十个模型收进同一个 base_url,切换模型、改价格、改延迟,不必动客户端。": "Bring OpenAI, Claude, Gemini, DeepSeek and dozens of other models behind a single base_url. Switch models, pricing, latency — no client changes.",
|
||||||
|
"免费注册": "Sign up free",
|
||||||
|
"联系销售": "Contact sales",
|
||||||
|
"注册即送 ¥10": "¥10 free credits on signup",
|
||||||
|
"无月费": "No monthly fee",
|
||||||
|
"比开放透明": "Transparent pricing",
|
||||||
|
"你的客户端只需一句": "Your client only needs one",
|
||||||
|
",其余的事——路由、价格、容灾——都替你做了。": ", and we handle routing, pricing, and failover for you.",
|
||||||
|
"立即接入。": "Integrate now.",
|
||||||
|
"注册送 ¥10 试用金,分键跑完一组 benchmark,一拍压测。": "Get ¥10 trial credit on signup. Run a benchmark, then a load test.",
|
||||||
|
"定价": "Pricing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5554,6 +5554,21 @@
|
||||||
"主题切换": "主题切换",
|
"主题切换": "主题切换",
|
||||||
"顶栏显示主题切换按钮,允许用户切换亮色/暗色模式": "顶栏显示主题切换按钮,允许用户切换亮色/暗色模式",
|
"顶栏显示主题切换按钮,允许用户切换亮色/暗色模式": "顶栏显示主题切换按钮,允许用户切换亮色/暗色模式",
|
||||||
"语言选择器": "语言选择器",
|
"语言选择器": "语言选择器",
|
||||||
"顶栏显示语言选择器,允许用户切换界面语言": "顶栏显示语言选择器,允许用户切换界面语言"
|
"顶栏显示语言选择器,允许用户切换界面语言": "顶栏显示语言选择器,允许用户切换界面语言",
|
||||||
|
"All systems normal": "All systems normal",
|
||||||
|
"调用 AI 像调用函": "调用 AI 像调用函",
|
||||||
|
"函数": "函数",
|
||||||
|
"一样轻。": "一样轻。",
|
||||||
|
"把 OpenAI、Claude、Gemini、DeepSeek 等几十个模型收进同一个 base_url,切换模型、改价格、改延迟,不必动客户端。": "把 OpenAI、Claude、Gemini、DeepSeek 等几十个模型收进同一个 base_url,切换模型、改价格、改延迟,不必动客户端。",
|
||||||
|
"免费注册": "免费注册",
|
||||||
|
"联系销售": "联系销售",
|
||||||
|
"注册即送 ¥10": "注册即送 ¥10",
|
||||||
|
"无月费": "无月费",
|
||||||
|
"比开放透明": "比开放透明",
|
||||||
|
"你的客户端只需一句": "你的客户端只需一句",
|
||||||
|
",其余的事——路由、价格、容灾——都替你做了。": ",其余的事——路由、价格、容灾——都替你做了。",
|
||||||
|
"立即接入。": "立即接入。",
|
||||||
|
"注册送 ¥10 试用金,分键跑完一组 benchmark,一拍压测。": "注册送 ¥10 试用金,分键跑完一组 benchmark,一拍压测。",
|
||||||
|
"定价": "定价"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2025 QuantumNous
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { ArrowRight, Mail, MessageSquare, Building2, ShieldCheck, Check } from 'lucide-react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const ACC = '#635BFF';
|
||||||
|
const ACC_SOFT = '#EEEBFF';
|
||||||
|
const BG = '#FFFFFF';
|
||||||
|
const SOFT = '#FBFAF7';
|
||||||
|
const TINT = '#F6F4FF';
|
||||||
|
const INK = '#0A2540';
|
||||||
|
const SUB = '#425466';
|
||||||
|
const DIM = '#697386';
|
||||||
|
const LINE = '#E3E8EE';
|
||||||
|
|
||||||
|
function Field({ label, value, onChange, type = 'text', required = false, placeholder = '' }) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="mb-2 text-xs" style={{ color: DIM }}>
|
||||||
|
{label}{required && <span style={{ color: ACC }}> *</span>}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
required={required}
|
||||||
|
placeholder={placeholder}
|
||||||
|
className="w-full rounded-lg border bg-white px-3.5 py-2.5 text-sm outline-none transition-colors focus:border-[#635BFF]"
|
||||||
|
style={{ borderColor: LINE, color: INK }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function InfoCard({ icon, title, primary, sub }) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="rounded-xl border bg-white p-5 transition-all hover:-translate-y-0.5 hover:shadow-sm"
|
||||||
|
style={{ borderColor: LINE }}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2.5">
|
||||||
|
<div
|
||||||
|
className="inline-flex h-8 w-8 items-center justify-center rounded-lg shrink-0"
|
||||||
|
style={{ background: ACC_SOFT, color: ACC }}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-semibold tracking-tight" style={{ color: INK }}>{title}</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-3.5 pl-[42px]">
|
||||||
|
<div className="text-[15px] font-medium" style={{ color: ACC }}>{primary}</div>
|
||||||
|
<div className="mt-1 text-xs leading-[1.6]" style={{ color: DIM }}>{sub}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MiniTopBar() {
|
||||||
|
return (
|
||||||
|
<header className="sticky top-0 z-50 border-b border-[#E3E8EE] bg-white/85 backdrop-blur-md">
|
||||||
|
<div className="flex h-16 items-center px-6 lg:px-10 max-w-[1200px] mx-auto">
|
||||||
|
<Link to="/" className="flex items-center gap-2.5">
|
||||||
|
<img src="/logo.jpg" alt="logo" className="h-7 w-7 rounded-full" />
|
||||||
|
<span className="font-heading text-[15px] font-semibold tracking-tight" style={{ color: INK }}>TuringToken</span>
|
||||||
|
</Link>
|
||||||
|
<div className="hidden md:flex items-center gap-2 ml-6 rounded-full px-2.5 py-1 text-[11px]" style={{ background: '#F6F9FC', color: DIM }}>
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />
|
||||||
|
<span>服务正常 · 99.95%</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1" />
|
||||||
|
<Link
|
||||||
|
to="/console"
|
||||||
|
className="inline-flex h-9 items-center rounded-full px-3.5 text-sm hover:bg-[#0A254006]"
|
||||||
|
style={{ color: SUB }}
|
||||||
|
>
|
||||||
|
控制台
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to="/register"
|
||||||
|
className="ml-2 inline-flex h-9 items-center gap-1.5 rounded-full px-4 text-sm font-medium text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
免费注册 <ArrowRight size={12} />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Contact() {
|
||||||
|
const [form, setForm] = useState({
|
||||||
|
company: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
volume: '',
|
||||||
|
message: '',
|
||||||
|
});
|
||||||
|
const update = (k) => (e) => setForm({ ...form, [k]: e.target.value });
|
||||||
|
const submit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
alert('已收到,我们会在 24 小时内联系你。');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen" style={{ background: BG, color: INK }}>
|
||||||
|
<MiniTopBar />
|
||||||
|
|
||||||
|
{/* Hero */}
|
||||||
|
<section className="relative overflow-hidden" style={{ background: BG }}>
|
||||||
|
<div
|
||||||
|
className="pointer-events-none absolute inset-x-0 top-0 h-[600px]"
|
||||||
|
style={{ background: 'radial-gradient(80% 60% at 50% 0%, #EEEBFF 0%, transparent 70%)' }}
|
||||||
|
/>
|
||||||
|
<div className="relative max-w-[1200px] mx-auto px-6 lg:px-10 pt-20 pb-14 lg:pt-28 lg:pb-20 text-center">
|
||||||
|
<div className="inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs" style={{ borderColor: LINE, color: DIM }}>
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full" style={{ background: ACC }} />
|
||||||
|
<span>contact sales</span>
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
className="mt-6 font-heading font-semibold leading-[1.04] tracking-[-0.025em]"
|
||||||
|
style={{ fontSize: 'clamp(40px, 5.4vw, 72px)', color: INK }}
|
||||||
|
>
|
||||||
|
告诉我们,<br />
|
||||||
|
你的 <span style={{ color: ACC }}>AI 场景</span>。
|
||||||
|
</h1>
|
||||||
|
<p className="mt-6 mx-auto max-w-2xl text-base leading-[1.65]" style={{ color: SUB }}>
|
||||||
|
大客户、定制路由、长期合约、技术对接 — 都从这里开始。
|
||||||
|
</p>
|
||||||
|
<div className="mt-8 flex flex-wrap items-center justify-center gap-6 text-xs" style={{ color: DIM }}>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<Check size={12} style={{ color: ACC }} /> 24 小时内回复
|
||||||
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<Check size={12} style={{ color: ACC }} /> 可签 NDA
|
||||||
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<Check size={12} style={{ color: ACC }} /> 无电销骚扰
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Form + Info */}
|
||||||
|
<section style={{ background: BG }}>
|
||||||
|
<div className="max-w-[1200px] mx-auto px-6 lg:px-10 pb-24">
|
||||||
|
<div className="grid gap-8 lg:grid-cols-[1.4fr_1fr]">
|
||||||
|
{/* Form */}
|
||||||
|
<form
|
||||||
|
onSubmit={submit}
|
||||||
|
className="rounded-2xl border bg-white p-8 lg:p-10 shadow-sm"
|
||||||
|
style={{ borderColor: LINE }}
|
||||||
|
>
|
||||||
|
<div className="font-mono text-[11px] uppercase tracking-[0.25em]" style={{ color: DIM }}>get in touch</div>
|
||||||
|
<h2
|
||||||
|
className="mt-4 font-heading text-2xl font-semibold leading-[1.2] tracking-tight lg:text-[32px]"
|
||||||
|
style={{ color: INK }}
|
||||||
|
>
|
||||||
|
填一下,<br />我们 24h 内联系你。
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="mt-8 grid gap-5 md:grid-cols-2">
|
||||||
|
<Field label="公司名" value={form.company} onChange={update('company')} required />
|
||||||
|
<Field label="你的姓名" value={form.name} onChange={update('name')} required />
|
||||||
|
</div>
|
||||||
|
<div className="mt-5">
|
||||||
|
<Field
|
||||||
|
label="工作邮箱"
|
||||||
|
type="email"
|
||||||
|
value={form.email}
|
||||||
|
onChange={update('email')}
|
||||||
|
required
|
||||||
|
placeholder="you@company.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="mb-2 text-xs" style={{ color: DIM }}>月调用量</div>
|
||||||
|
<div className="relative">
|
||||||
|
<select
|
||||||
|
value={form.volume}
|
||||||
|
onChange={update('volume')}
|
||||||
|
className="w-full appearance-none rounded-lg border bg-white pl-3.5 pr-9 py-2.5 text-sm outline-none transition-colors focus:border-[#635BFF]"
|
||||||
|
style={{ borderColor: LINE, color: form.volume ? INK : DIM }}
|
||||||
|
>
|
||||||
|
<option value="">选择大致量级</option>
|
||||||
|
<option>10 万以下</option>
|
||||||
|
<option>10 万 – 100 万</option>
|
||||||
|
<option>100 万 – 1000 万</option>
|
||||||
|
<option>1000 万以上</option>
|
||||||
|
<option>暂未确定</option>
|
||||||
|
</select>
|
||||||
|
<span className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-xs" style={{ color: DIM }}>▾</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="mb-2 text-xs" style={{ color: DIM }}>你的场景</div>
|
||||||
|
<textarea
|
||||||
|
value={form.message}
|
||||||
|
onChange={update('message')}
|
||||||
|
rows={4}
|
||||||
|
placeholder="例如:做企业知识库客服,需要稳定的 Claude + 国产模型双备援,月调用量约 300 万..."
|
||||||
|
className="w-full rounded-lg border bg-white px-3.5 py-2.5 text-sm outline-none transition-colors focus:border-[#635BFF] resize-y"
|
||||||
|
style={{ borderColor: LINE, color: INK }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-7 flex flex-wrap items-center gap-4">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="inline-flex h-11 items-center gap-2 rounded-full px-6 text-sm font-semibold text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
发送 <ArrowRight size={13} />
|
||||||
|
</button>
|
||||||
|
<span className="text-xs" style={{ color: DIM }}>
|
||||||
|
提交即同意我们通过邮箱回访,仅一次
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/* Info side */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<InfoCard
|
||||||
|
icon={<Mail size={16} />}
|
||||||
|
title="销售咨询"
|
||||||
|
primary="sales@turingtoken.ai"
|
||||||
|
sub="工作日 24h 内回复;加急请电话"
|
||||||
|
/>
|
||||||
|
<InfoCard
|
||||||
|
icon={<MessageSquare size={16} />}
|
||||||
|
title="技术支持"
|
||||||
|
primary="support@turingtoken.ai"
|
||||||
|
sub="已签合约客户优先;P0 故障 1h 响应"
|
||||||
|
/>
|
||||||
|
<InfoCard
|
||||||
|
icon={<ShieldCheck size={16} />}
|
||||||
|
title="法务 / NDA"
|
||||||
|
primary="legal@turingtoken.ai"
|
||||||
|
sub="签前可先发 NDA 模板,含双向保密"
|
||||||
|
/>
|
||||||
|
<InfoCard
|
||||||
|
icon={<Building2 size={16} />}
|
||||||
|
title="办公室"
|
||||||
|
primary="上海 · 北京 · 深圳"
|
||||||
|
sub="仅预约接待,不接受 walk-in"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* FAQ */}
|
||||||
|
<section style={{ background: SOFT }}>
|
||||||
|
<div className="max-w-[1100px] mx-auto px-6 lg:px-10 py-24 lg:py-32">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="font-mono text-[11px] uppercase tracking-[0.25em]" style={{ color: DIM }}>frequently asked</div>
|
||||||
|
<h2
|
||||||
|
className="mt-4 font-heading text-3xl font-semibold tracking-tight lg:text-4xl"
|
||||||
|
style={{ color: INK }}
|
||||||
|
>
|
||||||
|
常见问题。
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="mt-14 grid gap-5 md:grid-cols-2">
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
q: '支持私有化部署吗?',
|
||||||
|
a: '支持。签约后 2–4 周内完成,含多模型路由、监控面板、计费、权限管理、SSO。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
q: '大客户有专属价格吗?',
|
||||||
|
a: '月调用量 100 万以上可谈。多数客户能拿到比 OpenAI 直连便宜 30%+ 的合约价。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
q: '能签长期合约吗?',
|
||||||
|
a: '可以。年付 / 季付都支持,附 SLA 99.95% 兜底,故障按比例退款。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
q: '数据合规怎么做?',
|
||||||
|
a: '全链路 TLS 1.3;境内流量走国内供应商;日志 30 天滚动删除;支持 GDPR 与个保法。',
|
||||||
|
},
|
||||||
|
].map((f, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="rounded-xl border bg-white p-6"
|
||||||
|
style={{ borderColor: LINE }}
|
||||||
|
>
|
||||||
|
<h3 className="font-heading text-lg font-semibold tracking-tight" style={{ color: INK }}>{f.q}</h3>
|
||||||
|
<p className="mt-3 text-sm leading-[1.7]" style={{ color: SUB }}>{f.a}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Closing */}
|
||||||
|
<section className="relative overflow-hidden" style={{ background: BG }}>
|
||||||
|
<div
|
||||||
|
className="pointer-events-none absolute inset-x-0 bottom-0 h-[400px]"
|
||||||
|
style={{ background: 'radial-gradient(60% 60% at 50% 100%, #EEEBFF 0%, transparent 70%)' }}
|
||||||
|
/>
|
||||||
|
<div className="relative mx-auto max-w-3xl px-6 lg:px-10 py-24 lg:py-32 text-center">
|
||||||
|
<h2
|
||||||
|
className="font-heading text-3xl font-semibold leading-tight tracking-[-0.02em] lg:text-[44px]"
|
||||||
|
style={{ color: INK }}
|
||||||
|
>
|
||||||
|
先用起来,再聊。
|
||||||
|
</h2>
|
||||||
|
<p className="mt-5 text-base leading-[1.7]" style={{ color: SUB }}>
|
||||||
|
注册送 ¥10 试跑金,足够跑完一组 benchmark、一轮压测。聊完再决定也不迟。
|
||||||
|
</p>
|
||||||
|
<div className="mt-9 flex flex-wrap items-center justify-center gap-3">
|
||||||
|
<Link
|
||||||
|
to="/register"
|
||||||
|
className="inline-flex h-11 items-center gap-2 rounded-full px-6 text-sm font-semibold text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
免费注册 <ArrowRight size={13} />
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to="/"
|
||||||
|
className="inline-flex h-11 items-center gap-1.5 rounded-full border px-6 text-sm hover:bg-[#0A254006]"
|
||||||
|
style={{ borderColor: INK, color: INK }}
|
||||||
|
>
|
||||||
|
先看首页
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<footer className="border-t" style={{ borderColor: LINE, background: BG }}>
|
||||||
|
<div className="max-w-[1200px] mx-auto px-6 lg:px-10 py-12">
|
||||||
|
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
|
<Link to="/" className="inline-flex items-center gap-2.5">
|
||||||
|
<img src="/logo.jpg" alt="logo" className="h-7 w-7 rounded-full" />
|
||||||
|
<span className="font-heading text-base font-semibold tracking-tight" style={{ color: INK }}>TuringToken</span>
|
||||||
|
</Link>
|
||||||
|
<span className="text-xs" style={{ color: DIM }}>© 2026 TuringToken · Made for developers.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2025 QuantumNous
|
Copyright (C) 2025 QuantumNous
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -17,220 +17,186 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect, useCallback, useRef, useContext } from 'react';
|
import React, { useState, useContext, useCallback } from 'react';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Copy, Check, Code, Terminal, FileCode, Box, Grid3X3, Play, Trophy, PieChart, BookOpen, Search, Sun, Moon, Monitor, Languages } from 'lucide-react';
|
import { Copy, Check, ArrowRight, Terminal, Box, Trophy, BookOpen, Grid3X3 } from 'lucide-react';
|
||||||
import { UserContext } from '../../context/User';
|
import { UserContext } from '../../context/User';
|
||||||
import { StatusContext } from '../../context/Status';
|
import { StatusContext } from '../../context/Status';
|
||||||
import { stringToColor, getSystemName } from '../../helpers';
|
import { stringToColor, getSystemName } from '../../helpers';
|
||||||
|
|
||||||
|
|
||||||
/* ==================================================================
|
/* ==================================================================
|
||||||
TokenDance-style Home Page
|
Light-themed Home Page
|
||||||
Design: black/white minimal with serif headings
|
Design: clean white with purple accents
|
||||||
================================================================== */
|
================================================================== */
|
||||||
|
|
||||||
/* ─── Hero Marquee Carousel Texts ────────────────────────── */
|
const ACC = '#635BFF';
|
||||||
const CAROUSEL_TEXTS = [
|
const ACC_SOFT = '#EEEBFF';
|
||||||
'OpenAI 协议',
|
const BG = '#FFFFFF';
|
||||||
'Claude 协议',
|
const SOFT = '#FBFAF7';
|
||||||
'Gemini 协议',
|
const TINT = '#F6F4FF';
|
||||||
'智能路由',
|
const INK = '#0A2540';
|
||||||
'统一计费',
|
const SUB = '#425466';
|
||||||
'模型丰富',
|
const DIM = '#697386';
|
||||||
'安全可靠',
|
const LINE = '#E3E8EE';
|
||||||
'开箱即用',
|
|
||||||
];
|
|
||||||
|
|
||||||
/* ─── Hero Section ──────────────────────────────────────────── */
|
/* ─── NavBar ────────────────────────────────────────────────── */
|
||||||
|
|
||||||
/* --- Helper: Theme Toggle --- */
|
function HomeNavBar() {
|
||||||
function HomeThemeToggle() {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const ref = useRef(null);
|
|
||||||
useEffect(() => {
|
|
||||||
if (!open) return;
|
|
||||||
const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
|
|
||||||
document.addEventListener("mousedown", handler);
|
|
||||||
return () => document.removeEventListener("mousedown", handler);
|
|
||||||
}, [open]);
|
|
||||||
const theme = localStorage.getItem("theme-mode") || "auto";
|
|
||||||
const applyTheme = useCallback((val) => {
|
|
||||||
const actualTheme = val === 'auto'
|
|
||||||
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
||||||
: val;
|
|
||||||
if (actualTheme === 'dark') {
|
|
||||||
document.body.setAttribute('theme-mode', 'dark');
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
} else {
|
|
||||||
document.body.removeAttribute('theme-mode');
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
const setTheme = (val) => {
|
|
||||||
localStorage.setItem("theme-mode", val);
|
|
||||||
applyTheme(val);
|
|
||||||
setOpen(false);
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
applyTheme(theme);
|
|
||||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
||||||
const handleChange = () => {
|
|
||||||
const stored = localStorage.getItem("theme-mode") || "auto";
|
|
||||||
applyTheme(stored);
|
|
||||||
};
|
|
||||||
mediaQuery.addEventListener('change', handleChange);
|
|
||||||
return () => mediaQuery.removeEventListener('change', handleChange);
|
|
||||||
}, [applyTheme]);
|
|
||||||
const icons = { light: <Sun size={16} />, dark: <Moon size={16} />, auto: <Monitor size={16} /> };
|
|
||||||
return (
|
|
||||||
<div className="relative" ref={ref}>
|
|
||||||
<button type="button" onClick={() => setOpen(!open)} className="inline-flex items-center justify-center p-2 rounded-md text-white/60 hover:text-white hover:bg-white/10 transition-colors">
|
|
||||||
{icons[theme] || icons.auto}
|
|
||||||
</button>
|
|
||||||
{open && (
|
|
||||||
<div className="absolute right-0 top-full mt-1 z-50 min-w-[10rem] rounded-lg border border-white/10 bg-neutral-900 p-1 shadow-md">
|
|
||||||
{[
|
|
||||||
{ key: "light", icon: <Sun size={16} />, label: t("浅色模式") },
|
|
||||||
{ key: "dark", icon: <Moon size={16} />, label: t("深色模式") },
|
|
||||||
{ key: "auto", icon: <Monitor size={16} />, label: t("自动模式") },
|
|
||||||
].map((opt) => (
|
|
||||||
<button key={opt.key} type="button" onClick={() => setTheme(opt.key)} className={`flex w-full items-center gap-2 rounded-md px-2.5 py-2 text-sm transition-colors ${theme === opt.key ? "bg-white/10 text-white font-medium" : "text-white/50 hover:bg-white/10 hover:text-white"}`}>
|
|
||||||
{opt.icon}<span>{opt.label}</span>
|
|
||||||
{theme === opt.key && <span className="ml-auto flex h-3.5 w-3.5 items-center justify-center"><span className="h-1.5 w-1.5 rounded-full bg-white"></span></span>}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Helper: Language Selector --- */
|
|
||||||
function HomeLanguageSelector() {
|
|
||||||
const { t, i18n } = useTranslation();
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const ref = useRef(null);
|
|
||||||
useEffect(() => {
|
|
||||||
if (!open) return;
|
|
||||||
const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
|
|
||||||
document.addEventListener("mousedown", handler);
|
|
||||||
return () => document.removeEventListener("mousedown", handler);
|
|
||||||
}, [open]);
|
|
||||||
const current = (i18n.language || "").startsWith("zh") ? "zh-CN" : "en";
|
|
||||||
const switchLang = (code) => { i18n.changeLanguage(code); setOpen(false); };
|
|
||||||
const langLabels = { "zh-CN": "简体中文", "en": "English" };
|
|
||||||
return (
|
|
||||||
<div className="relative" ref={ref}>
|
|
||||||
<button type="button" onClick={() => setOpen(!open)} className="inline-flex items-center gap-1 rounded-md px-2 py-1.5 text-sm text-white/60 hover:text-white hover:bg-white/10 transition-colors">
|
|
||||||
<Languages size={16} /><span className="hidden sm:inline text-xs">{langLabels[current] || current}</span>
|
|
||||||
</button>
|
|
||||||
{open && (
|
|
||||||
<div className="absolute right-0 top-full mt-1 z-50 min-w-[8rem] rounded-lg border border-white/10 bg-neutral-900 p-1 shadow-md">
|
|
||||||
{Object.entries(langLabels).map(([code, label]) => (
|
|
||||||
<button key={code} type="button" onClick={() => switchLang(code)} className={`flex w-full items-center rounded-md px-2.5 py-1.5 text-sm transition-colors ${current === code ? "bg-white/10 text-white font-medium" : "text-white/50 hover:bg-white/10 hover:text-white"}`}>
|
|
||||||
{label}
|
|
||||||
{current === code && <span className="ml-auto flex h-3.5 w-3.5 items-center justify-center"><span className="h-1.5 w-1.5 rounded-full bg-white"></span></span>}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function HeroSection() {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [userState] = useContext(UserContext);
|
const [userState] = useContext(UserContext);
|
||||||
const [statusState] = useContext(StatusContext);
|
|
||||||
const [copied, setCopied] = useState(false);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
// 读取管理员开关:默认 true(未加载 status 前也显示)
|
|
||||||
const showThemeToggle = statusState?.status?.HeaderShowThemeToggle !== false;
|
|
||||||
const showLanguageSelector = statusState?.status?.HeaderShowLanguageSelector !== false;
|
|
||||||
const copyCmd = useCallback(() => {
|
|
||||||
navigator.clipboard.writeText("https://tokendance.space");
|
|
||||||
setCopied(true);
|
|
||||||
setTimeout(() => setCopied(false), 1500);
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<section className="relative bg-black text-white overflow-hidden">
|
<header className="sticky top-0 z-50 border-b bg-white/85 backdrop-blur-md" style={{ borderColor: LINE }}>
|
||||||
<div className="absolute inset-0 pointer-events-none opacity-[0.04]" style={{ backgroundImage: "radial-gradient(circle, white 1px, transparent 1px)", backgroundSize: "24px 24px" }} />
|
<div className="flex h-16 items-center px-6 lg:px-10 max-w-[1400px] mx-auto">
|
||||||
<div className="fixed top-0 z-50 w-full border-b border-white/10 bg-black">
|
<Link to="/" className="flex items-center gap-2.5">
|
||||||
<div className="flex h-14 items-center px-4 lg:px-6 max-w-[1400px] mx-auto">
|
<img src="/logo.jpg" alt="logo" className="h-7 w-7 rounded-full" />
|
||||||
<Link to="/" className="flex items-center gap-2 flex-shrink-0">
|
<span className="font-heading text-[15px] font-semibold tracking-tight" style={{ color: INK }}>TuringToken</span>
|
||||||
<img src="/logo.jpg" alt="logo" className="w-7 h-7 rounded-full object-cover" />
|
<span className="text-[10px] font-mono px-1.5 py-0.5 rounded border" style={{ borderColor: LINE, color: DIM }}>BETA</span>
|
||||||
<span className="font-heading text-lg font-bold tracking-tight text-white">TuringToken</span>
|
|
||||||
<span className="text-[10px] font-mono px-1.5 py-0.5 rounded border border-white/20 text-white/40">BETA</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
<div className="hidden md:block flex-1" />
|
<div className="hidden md:flex items-center gap-2 ml-6 rounded-full px-2.5 py-1 text-[11px]" style={{ background: '#F6F9FC', color: DIM }}>
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />
|
||||||
|
<span>{t('All systems normal')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1" />
|
||||||
<nav className="hidden md:flex items-center gap-0.5">
|
<nav className="hidden md:flex items-center gap-0.5">
|
||||||
{[
|
{[
|
||||||
{ key: "model", label: "模型", icon: <Box size={16} />, to: "/pricing" },
|
{ key: 'model', label: t('定价'), icon: <Box size={16} />, to: '/pricing' },
|
||||||
{ key: "benchmark", label: "评测", icon: <Trophy size={16} />, to: "/benchmarks" },
|
{ key: 'benchmark', label: t('评测'), icon: <Trophy size={16} />, to: '/benchmarks' },
|
||||||
{ key: "docs", label: "文档", icon: <BookOpen size={16} />, to: "/docs" },
|
{ key: 'docs', label: t('文档'), icon: <BookOpen size={16} />, to: '/docs' },
|
||||||
{ key: "console", label: "控制台", icon: <Grid3X3 size={16} />, to: "/console" },
|
{ key: 'console', label: t('控制台'), icon: <Grid3X3 size={16} />, to: '/console' },
|
||||||
].map((item) => (
|
].map((item) => (
|
||||||
<Link key={item.key} to={item.to} className="inline-flex items-center gap-1.5 px-3 py-1.5 text-[14px] rounded-md transition-colors duration-150 text-white/60 hover:text-white">{item.icon}<span className="hidden sm:inline">{t(item.label)}</span></Link>
|
<Link key={item.key} to={item.to} className="inline-flex items-center gap-1.5 px-3 py-1.5 text-[14px] rounded-md transition-colors duration-150 hover:bg-[#0A254008]" style={{ color: SUB }}>
|
||||||
|
{item.icon}<span className="hidden sm:inline">{item.label}</span>
|
||||||
|
</Link>
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center ml-4">
|
||||||
{showThemeToggle && <HomeThemeToggle />}
|
|
||||||
{showLanguageSelector && <HomeLanguageSelector />}
|
|
||||||
{userState.user ? (
|
{userState.user ? (
|
||||||
<Link to="/console" className="inline-flex items-center justify-center w-8 h-8 rounded-full hover:bg-white/20 border border-white/20 transition-colors duration-200 ml-2" title={userState.user.display_name || userState.user.username}>
|
<Link to="/console" className="inline-flex items-center justify-center w-8 h-8 rounded-full hover:bg-black/5 border transition-colors duration-200" style={{ borderColor: LINE }} title={userState.user.display_name || userState.user.username}>
|
||||||
<span className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold text-white" style={{ backgroundColor: stringToColor(userState.user.username) }}>
|
<span className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold text-white" style={{ backgroundColor: stringToColor(userState.user.username) }}>
|
||||||
{userState.user.username?.charAt(0).toUpperCase()}
|
{userState.user.username?.charAt(0).toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<Link to="/login" className="inline-flex items-center bg-white text-black px-4 py-1.5 text-sm font-mono font-medium uppercase tracking-widest rounded hover:bg-transparent hover:text-white border border-white transition-colors duration-200 ml-2">
|
<Link
|
||||||
{t("登录")}
|
to="/login"
|
||||||
|
className="inline-flex h-9 items-center rounded-full px-4 text-sm font-medium text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
{t('登录')}
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
<div className="relative flex-1 grid md:grid-cols-2 gap-8 px-6 md:px-12 pt-[88px] pb-12 items-center max-w-[1400px] mx-auto w-full" style={{ minHeight: "90vh" }}>
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Hero Section ──────────────────────────────────────────── */
|
||||||
|
|
||||||
|
function HeroSection() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [userState] = useContext(UserContext);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
const copyCmd = useCallback(() => {
|
||||||
|
navigator.clipboard.writeText('https://api.turingtoken.ai');
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 1500);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative overflow-hidden" style={{ background: BG }}>
|
||||||
|
{/* Subtle purple center glow */}
|
||||||
|
<div
|
||||||
|
className="pointer-events-none absolute inset-x-0 top-0 h-[700px]"
|
||||||
|
style={{ background: `radial-gradient(60% 60% at 50% 0%, ${ACC_SOFT} 0%, transparent 70%)` }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="relative max-w-[1400px] mx-auto px-6 lg:px-10 pt-20 pb-8 lg:pt-28 lg:pb-12">
|
||||||
|
<div className="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||||
|
{/* Left: Text */}
|
||||||
<div className="home-fade-in">
|
<div className="home-fade-in">
|
||||||
<p className="font-mono text-sm text-white/30 mb-6 tracking-wide font-body">
|
<div className="inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs mb-8" style={{ borderColor: LINE, color: DIM }}>
|
||||||
{"// unified model API gateway"}
|
<span className="h-1.5 w-1.5 rounded-full" style={{ background: ACC }} />
|
||||||
</p>
|
<span>{t('All systems normal')}</span>
|
||||||
<div className="w-[60px] h-[4px] bg-white mb-6" />
|
</div>
|
||||||
<h1 className="font-heading text-3xl sm:text-5xl md:text-6xl lg:text-7xl font-bold leading-[1.1] mb-6">
|
|
||||||
{t("更快、更稳、更省")}<br />{t("Token服务平台")}
|
<h1
|
||||||
|
className="font-heading font-semibold leading-[1.08] tracking-[-0.025em] mb-6"
|
||||||
|
style={{ fontSize: 'clamp(36px, 5vw, 64px)', color: INK }}
|
||||||
|
>
|
||||||
|
{t('调用 AI 像调用函')}
|
||||||
|
<span style={{ color: ACC }}>{t('函数')}</span>
|
||||||
|
{t('一样轻。')}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="font-body text-white/50 text-base md:text-lg leading-relaxed mb-10">
|
|
||||||
{t("兼容 OpenAI / Claude / Gemini 等协议,覆盖文本、图像、视频、语音,智能路由,统一计费。")}
|
<p className="text-base md:text-lg leading-[1.65] mb-8 max-w-xl" style={{ color: SUB }}>
|
||||||
|
{t('把 OpenAI、Claude、Gemini、DeepSeek 等几十个模型收进同一个 base_url,切换模型、改价格、改延迟,不必动客户端。')}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4 font-body">
|
|
||||||
<Link to="/console/token" className="inline-flex items-center bg-white text-black px-6 py-3 text-sm font-mono font-medium uppercase tracking-widest hover:bg-transparent hover:text-white border border-white transition-colors duration-200">
|
<div className="flex flex-wrap items-center gap-3 mb-8">
|
||||||
{t("开始使用")}
|
{userState.user ? (
|
||||||
|
<Link
|
||||||
|
to="/console/token"
|
||||||
|
className="inline-flex h-11 items-center gap-2 rounded-full px-6 text-sm font-semibold text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
{t('开始使用')} <ArrowRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/pricing" className="inline-flex items-center text-white/60 px-6 py-3 text-sm font-mono font-medium uppercase tracking-widest hover:text-white transition-colors duration-200">
|
) : (
|
||||||
{t("查看价格")} →
|
<Link
|
||||||
|
to="/register"
|
||||||
|
className="inline-flex h-11 items-center gap-2 rounded-full px-6 text-sm font-semibold text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
|
>
|
||||||
|
{t('免费注册')} <ArrowRight size={14} />
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
<Link
|
||||||
|
to="/contact"
|
||||||
|
className="inline-flex h-11 items-center gap-1.5 rounded-full border px-6 text-sm font-medium hover:bg-[#0A254006]"
|
||||||
|
style={{ borderColor: INK, color: INK }}
|
||||||
|
>
|
||||||
|
{t('联系销售')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap items-center gap-5 text-xs" style={{ color: DIM }}>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full" style={{ background: '#10b981' }} />
|
||||||
|
{t('注册即送 ¥10')}
|
||||||
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full" style={{ background: ACC }} />
|
||||||
|
{t('无月费')}
|
||||||
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
<span className="h-1.5 w-1.5 rounded-full" style={{ background: '#f59e0b' }} />
|
||||||
|
{t('比开放透明')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="home-fade-in-delay-1 font-body">
|
</div>
|
||||||
<div className="bg-neutral-900 border border-white/10 rounded-none overflow-hidden">
|
|
||||||
<div className="flex items-center justify-between px-4 py-2.5 border-b border-white/10 bg-neutral-800/50">
|
{/* Right: Code Example */}
|
||||||
|
<div className="home-fade-in-delay-1">
|
||||||
|
<div className="rounded-2xl border bg-white overflow-hidden shadow-sm" style={{ borderColor: LINE }}>
|
||||||
|
<div className="flex items-center justify-between px-4 py-2.5 border-b" style={{ borderColor: LINE, background: '#F9FAFB' }}>
|
||||||
<div className="flex gap-1.5">
|
<div className="flex gap-1.5">
|
||||||
<span className="w-3 h-3 rounded-full bg-red-500/60" />
|
<span className="w-3 h-3 rounded-full bg-red-400/60" />
|
||||||
<span className="w-3 h-3 rounded-full bg-yellow-500/60" />
|
<span className="w-3 h-3 rounded-full bg-yellow-400/60" />
|
||||||
<span className="w-3 h-3 rounded-full bg-green-500/60" />
|
<span className="w-3 h-3 rounded-full bg-green-400/60" />
|
||||||
</div>
|
</div>
|
||||||
<span className="font-mono text-[10px] text-white/20 tracking-wide">terminal</span>
|
<span className="font-mono text-[10px] tracking-wide" style={{ color: DIM }}>terminal</span>
|
||||||
<button type="button" onClick={copyCmd} className="text-white/30 hover:text-white/70 transition-colors" aria-label="Copy">
|
<button type="button" onClick={copyCmd} className="hover:opacity-70 transition-opacity" style={{ color: DIM }} aria-label="Copy">
|
||||||
{copied ? <Check size={14} /> : <Copy size={14} />}
|
{copied ? <Check size={14} /> : <Copy size={14} />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre className="p-5 text-sm font-mono leading-relaxed text-white/80 overflow-x-auto">
|
<pre className="p-5 text-sm font-mono leading-relaxed overflow-x-auto" style={{ color: INK, background: '#1e1e2e' }}>
|
||||||
<code>{`curl https://api.turingtoken.ai/v1/chat/completions \\
|
<code className="text-[#cdd6f4]">{`curl https://api.turingtoken.ai/v1/chat/completions \\
|
||||||
-H "Authorization: Bearer \$YOUR_API_KEY" \\
|
-H "Authorization: Bearer $YOUR_API_KEY" \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-d '{
|
-d '{
|
||||||
"model": "gpt-4o",
|
"model": "gpt-4o",
|
||||||
|
|
@ -238,70 +204,61 @@ function HeroSection() {
|
||||||
}'`}</code>
|
}'`}</code>
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p className="mt-5 text-sm leading-[1.6]" style={{ color: DIM }}>
|
||||||
|
{t('你的客户端只需一句')}
|
||||||
|
<code className="mx-1 px-1.5 py-0.5 rounded text-xs font-mono" style={{ background: TINT, color: ACC }}>base_url</code>
|
||||||
|
{t(',其余的事——路由、价格、容灾——都替你做了。')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Hero brand wordmark — TURINGTOKEN */}
|
{/* Dark brand wordmark strip */}
|
||||||
<div className="w-full overflow-hidden px-6 pb-2">
|
<div className="w-full overflow-hidden border-t" style={{ borderColor: LINE, background: INK }}>
|
||||||
<div
|
<div
|
||||||
className="inline-flex whitespace-nowrap origin-left font-mono font-bold uppercase leading-[0.85] select-none tracking-tight"
|
className="inline-flex whitespace-nowrap origin-left font-mono font-bold uppercase leading-[0.85] select-none tracking-tight py-8 px-6"
|
||||||
style={{ fontSize: 'clamp(4rem, 20vw, 12rem)', transform: 'scaleX(1.04)' }}
|
style={{ fontSize: 'clamp(3rem, 16vw, 10rem)', transform: 'scaleX(1.04)' }}
|
||||||
>
|
>
|
||||||
<span className="text-white">Turing</span>
|
<span className="text-white">Turing</span>
|
||||||
<span className="text-white/30" style={{ textShadow: '0 0 30px rgba(255,255,255,0.15), 4px 4px 12px rgba(0,0,0,0.5)' }}>Token</span>
|
<span className="text-white/30" style={{ textShadow: '0 0 30px rgba(255,255,255,0.15), 4px 4px 12px rgba(0,0,0,0.5)' }}>Token</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Feature marquee strip — 轮播: OpenAI 协议 / Claude 协议 / 智能路由 ... */}
|
|
||||||
<div className="w-full border-t border-white/10 py-5 px-6 overflow-hidden">
|
|
||||||
<div className="home-marquee flex gap-12 items-center">
|
|
||||||
{[...CAROUSEL_TEXTS, ...CAROUSEL_TEXTS].map((text, i) => (
|
|
||||||
<span
|
|
||||||
key={i}
|
|
||||||
className="font-mono text-sm text-white/40 whitespace-nowrap tracking-wider"
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}const FEATURES = [
|
}
|
||||||
|
|
||||||
|
/* ─── Features Section ──────────────────────────────────────── */
|
||||||
|
|
||||||
|
const FEATURES = [
|
||||||
{
|
{
|
||||||
titleKey: '多协议兼容',
|
titleKey: '多协议兼容',
|
||||||
descKey:
|
descKey: '原生支持 OpenAI、Claude、Gemini 文本协议,覆盖图像 / 视频 / 文本转语音生成。无需修改代码,切换 Base URL 即可接入。',
|
||||||
'原生支持 OpenAI、Claude、Gemini 文本协议,覆盖图像 / 视频 / 文本转语音生成。无需修改代码,切换 Base URL 即可接入。',
|
|
||||||
code: 'baseURL: "api.turingtoken.ai"',
|
code: 'baseURL: "api.turingtoken.ai"',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleKey: '智能路由',
|
titleKey: '智能路由',
|
||||||
descKey:
|
descKey: '根据模型名称自动路由至对应供应商。一个入口,无需关心底层调度。',
|
||||||
'根据模型名称自动路由至对应供应商。一个入口,无需关心底层调度。',
|
|
||||||
code: 'route(model) → provider',
|
code: 'route(model) → provider',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleKey: '统一计费',
|
titleKey: '统一计费',
|
||||||
descKey:
|
descKey: '跨供应商统一 Token 消耗统计与账单。告别多平台分别充值的混乱。',
|
||||||
'跨供应商统一 Token 消耗统计与账单。告别多平台分别充值的混乱。',
|
|
||||||
code: 'billing.unified()',
|
code: 'billing.unified()',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleKey: '容错降级',
|
titleKey: '容错降级',
|
||||||
descKey:
|
descKey: '同一模型支持多供应商端点自动切换;单次请求可指定多个候选模型,逐级降级,保障服务持续可用。',
|
||||||
'同一模型支持多供应商端点自动切换;单次请求可指定多个候选模型,逐级降级,保障服务持续可用。',
|
|
||||||
code: 'fallback: model[] → provider[]',
|
code: 'fallback: model[] → provider[]',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleKey: '模型丰富',
|
titleKey: '模型丰富',
|
||||||
descKey:
|
descKey: '接入 MiniMax、通义千问、Kimi、智谱、DeepSeek 等国内头部模型。持续扩展中。',
|
||||||
'接入 MiniMax、通义千问、Kimi、智谱、DeepSeek 等国内头部模型。持续扩展中。',
|
|
||||||
code: 'models.list() → 80+',
|
code: 'models.list() → 80+',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleKey: '开箱即用',
|
titleKey: '开箱即用',
|
||||||
descKey:
|
descKey: '一键登录,分钟级接入。兼容现有 SDK,零迁移成本。',
|
||||||
'一键登录,分钟级接入。兼容现有 SDK,零迁移成本。',
|
|
||||||
code: 'import OpenAI from "openai"',
|
code: 'import OpenAI from "openai"',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -309,27 +266,28 @@ function HeroSection() {
|
||||||
function FeaturesSection() {
|
function FeaturesSection() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<section id="features" className="py-24 px-6">
|
<section className="py-24 px-6 lg:px-10" style={{ background: BG }}>
|
||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-6xl mx-auto">
|
||||||
<p className="font-mono text-xs text-muted-foreground tracking-widest uppercase mb-3">
|
<div className="font-mono text-[11px] tracking-[0.25em] uppercase mb-3" style={{ color: DIM }}>
|
||||||
{/* features */}
|
{'// features'}
|
||||||
</p>
|
</div>
|
||||||
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight mb-16 text-foreground">
|
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight mb-16" style={{ color: INK }}>
|
||||||
{t('为接入 AI 模型的开发者而造。')}
|
{t('为接入 AI 模型的开发者而造。')}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{FEATURES.map((f, i) => (
|
{FEATURES.map((f, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className="group p-8 flex flex-col transition-all duration-200 hover:bg-foreground hover:text-background border-b sm:border-r border-border"
|
className="group p-8 flex flex-col transition-all duration-200 hover:bg-[#0A2540] border-b sm:border-r"
|
||||||
|
style={{ borderColor: LINE }}
|
||||||
>
|
>
|
||||||
<code className="inline-block text-xs mb-4 font-mono border border-foreground/10 px-2 py-1 w-fit group-hover:border-background/30 group-hover:text-background transition-all duration-200">
|
<code className="inline-block text-xs mb-4 font-mono border px-2 py-1 w-fit rounded group-hover:border-white/30 group-hover:text-white/80 transition-all duration-200" style={{ borderColor: LINE, color: DIM }}>
|
||||||
{f.code}
|
{f.code}
|
||||||
</code>
|
</code>
|
||||||
<h3 className="font-heading text-lg font-bold mb-2 text-foreground group-hover:text-background transition-all duration-200">
|
<h3 className="font-heading text-lg font-bold mb-2 group-hover:text-white transition-all duration-200" style={{ color: INK }}>
|
||||||
{t(f.titleKey)}
|
{t(f.titleKey)}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-muted-foreground leading-relaxed group-hover:text-background/70 transition-all duration-200">
|
<p className="text-sm leading-relaxed group-hover:text-white/60 transition-all duration-200" style={{ color: SUB }}>
|
||||||
{t(f.descKey)}
|
{t(f.descKey)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -340,422 +298,76 @@ function FeaturesSection() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── How It Works Section ──────────────────────────────────── */
|
/* ─── CTA Section ───────────────────────────────────────────── */
|
||||||
|
|
||||||
const STEPS = [
|
function CTASection() {
|
||||||
{
|
|
||||||
step: '01',
|
|
||||||
titleKey: '注册账号',
|
|
||||||
descKey: '通过邮箱一键注册,即刻开始使用。',
|
|
||||||
link: '/register',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
step: '02',
|
|
||||||
titleKey: '创建 API Key',
|
|
||||||
descKey: '在控制台创建密钥,支持多 Key 管理与权限控制。',
|
|
||||||
link: '/console/token',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
step: '03',
|
|
||||||
titleKey: '发起请求',
|
|
||||||
descKey: '使用你熟悉的 SDK 调用任意模型,完全兼容原生协议。',
|
|
||||||
link: '/pricing',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function HowItWorksSection() {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<section
|
<section className="relative overflow-hidden" style={{ background: BG }}>
|
||||||
id="how-it-works"
|
<div
|
||||||
className="border-y-4 border-border"
|
className="pointer-events-none absolute inset-x-0 bottom-0 h-[400px]"
|
||||||
|
style={{ background: `radial-gradient(60% 60% at 50% 100%, ${ACC_SOFT} 0%, transparent 70%)` }}
|
||||||
|
/>
|
||||||
|
<div className="relative mx-auto max-w-3xl px-6 lg:px-10 py-24 lg:py-32 text-center">
|
||||||
|
<h2
|
||||||
|
className="font-heading text-3xl font-semibold leading-tight tracking-[-0.02em] lg:text-[44px] mb-5"
|
||||||
|
style={{ color: INK }}
|
||||||
>
|
>
|
||||||
<div className="max-w-5xl mx-auto">
|
{t('立即接入。')}
|
||||||
<div className="px-6 md:px-12 pt-24 pb-12">
|
|
||||||
<div className="font-mono text-xs text-muted-foreground tracking-widest uppercase mb-3">
|
|
||||||
{'// how it works'}
|
|
||||||
</div>
|
|
||||||
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight text-foreground">
|
|
||||||
{t('三步接入,分钟级上线')}
|
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
<p className="text-base leading-[1.7] mb-9" style={{ color: SUB }}>
|
||||||
{STEPS.map((s, i) => (
|
{t('注册送 ¥10 试用金,分键跑完一组 benchmark,一拍压测。')}
|
||||||
<Link
|
|
||||||
key={i}
|
|
||||||
to={s.link}
|
|
||||||
className={`group block border-t border-border ${
|
|
||||||
i === STEPS.length - 1 ? 'border-b border-border' : ''
|
|
||||||
} hover:bg-foreground transition-all duration-200`}
|
|
||||||
>
|
|
||||||
<div className="grid md:grid-cols-[120px_1fr_auto] gap-0 items-center">
|
|
||||||
<div className="px-6 md:px-12 py-8 md:border-r border-border group-hover:border-background/10 flex items-baseline transition-all duration-200">
|
|
||||||
<span className="font-mono text-5xl md:text-6xl font-bold text-muted-foreground/30 group-hover:text-background leading-none transition-all duration-200">
|
|
||||||
{s.step}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="px-6 md:px-12 py-8">
|
|
||||||
<h3 className="font-mono text-lg font-bold uppercase tracking-wide mb-2 text-foreground group-hover:text-background transition-all duration-200">
|
|
||||||
{t(s.titleKey)}
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-muted-foreground group-hover:text-background/50 transition-all duration-200">
|
|
||||||
{t(s.descKey)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
<span className="hidden md:block pr-8 font-mono text-xl text-muted-foreground/30 group-hover:text-background transition-all duration-200">
|
|
||||||
→
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ─── Quick Start Section (Code Tabs) ───────────────────────── */
|
|
||||||
|
|
||||||
const PROVIDERS = ['openai', 'claude', 'gemini'];
|
|
||||||
const PROVIDER_LABELS = { openai: 'OpenAI', claude: 'Claude', gemini: 'Gemini' };
|
|
||||||
const LANGUAGES = ['curl', 'python', 'nodejs'];
|
|
||||||
const LANG_LABELS = { curl: 'cURL', python: 'Python', nodejs: 'Node.js' };
|
|
||||||
|
|
||||||
const CODE_SAMPLES = {
|
|
||||||
openai: {
|
|
||||||
curl: `curl https://api.turingtoken.ai/v1/chat/completions \\
|
|
||||||
-H "Authorization: Bearer $OPENAI_API_KEY" \\
|
|
||||||
-H "Content-Type: application/json" \\
|
|
||||||
-d '{
|
|
||||||
"model": "gpt-4o",
|
|
||||||
"messages": [{"role": "user", "content": "Hello!"}]
|
|
||||||
}'`,
|
|
||||||
python: `from openai import OpenAI
|
|
||||||
|
|
||||||
client = OpenAI(
|
|
||||||
base_url="https://api.turingtoken.ai",
|
|
||||||
api_key="sk-your-key"
|
|
||||||
)
|
|
||||||
|
|
||||||
response = client.chat.completions.create(
|
|
||||||
model="gpt-4o",
|
|
||||||
messages=[{"role": "user", "content": "Hello!"}]
|
|
||||||
)
|
|
||||||
print(response.choices[0].message.content)`,
|
|
||||||
nodejs: `import OpenAI from "openai";
|
|
||||||
|
|
||||||
const client = new OpenAI({
|
|
||||||
baseURL: "https://api.turingtoken.ai",
|
|
||||||
apiKey: "sk-your-key",
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await client.chat.completions.create({
|
|
||||||
model: "gpt-4o",
|
|
||||||
messages: [{ role: "user", content: "Hello!" }],
|
|
||||||
});
|
|
||||||
console.log(response.choices[0].message.content);`,
|
|
||||||
},
|
|
||||||
claude: {
|
|
||||||
curl: `curl https://api.turingtoken.ai/v1/messages \\
|
|
||||||
-H "x-api-key: sk-your-key" \\
|
|
||||||
-H "anthropic-version: 2023-06-01" \\
|
|
||||||
-H "Content-Type: application/json" \\
|
|
||||||
-d '{
|
|
||||||
"model": "claude-sonnet-4-20250514",
|
|
||||||
"max_tokens": 1024,
|
|
||||||
"messages": [{"role": "user", "content": "Hello!"}]
|
|
||||||
}'`,
|
|
||||||
python: `import anthropic
|
|
||||||
|
|
||||||
client = anthropic.Anthropic(
|
|
||||||
base_url="https://api.turingtoken.ai",
|
|
||||||
api_key="sk-your-key"
|
|
||||||
)
|
|
||||||
|
|
||||||
response = client.messages.create(
|
|
||||||
model="claude-sonnet-4-20250514",
|
|
||||||
max_tokens=1024,
|
|
||||||
messages=[{"role": "user", "content": "Hello!"}]
|
|
||||||
)
|
|
||||||
print(response.content[0].text)`,
|
|
||||||
nodejs: `import Anthropic from "@anthropic-ai/sdk";
|
|
||||||
|
|
||||||
const client = new Anthropic({
|
|
||||||
baseURL: "https://api.turingtoken.ai",
|
|
||||||
apiKey: "sk-your-key",
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await client.messages.create({
|
|
||||||
model: "claude-sonnet-4-20250514",
|
|
||||||
max_tokens: 1024,
|
|
||||||
messages: [{ role: "user", content: "Hello!" }],
|
|
||||||
});
|
|
||||||
console.log(response.content[0].text);`,
|
|
||||||
},
|
|
||||||
gemini: {
|
|
||||||
curl: `curl "https://api.turingtoken.ai/v1beta/models/gemini-2.0-flash:generateContent?key=sk-your-key" \\
|
|
||||||
-H "Content-Type: application/json" \\
|
|
||||||
-d '{
|
|
||||||
"contents": [{"parts":[{"text": "Hello!"}]}]
|
|
||||||
}'`,
|
|
||||||
python: `import google.generativeai as genai
|
|
||||||
|
|
||||||
genai.configure(api_key="sk-your-key")
|
|
||||||
|
|
||||||
model = genai.GenerativeModel("gemini-2.0-flash")
|
|
||||||
response = model.generate_content("Hello!")
|
|
||||||
print(response.text)`,
|
|
||||||
nodejs: `import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
||||||
|
|
||||||
const genAI = new GoogleGenerativeAI("sk-your-key");
|
|
||||||
const model = genAI.getGenerativeModel({
|
|
||||||
model: "gemini-2.0-flash",
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await model.generateContent("Hello!");
|
|
||||||
console.log(result.response.text());`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function QuickStartSection() {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [provider, setProvider] = useState('openai');
|
|
||||||
const [lang, setLang] = useState('curl');
|
|
||||||
const [copied, setCopied] = useState(false);
|
|
||||||
|
|
||||||
const code = CODE_SAMPLES[provider]?.[lang] || '';
|
|
||||||
|
|
||||||
const handleCopy = useCallback(() => {
|
|
||||||
navigator.clipboard.writeText(code);
|
|
||||||
setCopied(true);
|
|
||||||
setTimeout(() => setCopied(false), 1500);
|
|
||||||
}, [code]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section id="quick-start" className="px-6 py-16">
|
|
||||||
<div className="max-w-4xl mx-auto">
|
|
||||||
<p className="font-mono text-xs text-muted-foreground tracking-widest uppercase mb-2">
|
|
||||||
Quick Start
|
|
||||||
</p>
|
|
||||||
<h2 className="font-heading text-2xl font-bold mb-8 text-foreground">
|
|
||||||
{t('快速开始')}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Provider tabs */}
|
|
||||||
<div className="flex gap-0 mb-0">
|
|
||||||
{PROVIDERS.map((p) => (
|
|
||||||
<button
|
|
||||||
key={p}
|
|
||||||
type="button"
|
|
||||||
onClick={() => setProvider(p)}
|
|
||||||
className={`font-mono text-sm px-4 py-2 transition-all duration-200 ${
|
|
||||||
provider === p
|
|
||||||
? 'bg-foreground text-background'
|
|
||||||
: 'border-2 border-border bg-transparent hover:bg-foreground hover:text-background'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{PROVIDER_LABELS[p]}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Code block */}
|
|
||||||
<div className="border-2 border-border">
|
|
||||||
<div className="flex items-center justify-between px-4 py-2.5 border-b-2 border-border bg-muted">
|
|
||||||
<div className="flex gap-3">
|
|
||||||
{LANGUAGES.map((l) => (
|
|
||||||
<button
|
|
||||||
key={l}
|
|
||||||
type="button"
|
|
||||||
onClick={() => setLang(l)}
|
|
||||||
className={`font-mono text-xs transition-colors ${
|
|
||||||
lang === l
|
|
||||||
? 'text-foreground font-bold border-b-2 border-foreground'
|
|
||||||
: 'text-muted-foreground hover:text-foreground'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{LANG_LABELS[l]}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={handleCopy}
|
|
||||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
||||||
title="Copy"
|
|
||||||
>
|
|
||||||
{copied ? <Check size={16} className="text-green-600" /> : <Copy size={16} />}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="bg-foreground text-background">
|
|
||||||
<pre className="p-5 text-sm leading-relaxed overflow-x-auto font-mono">
|
|
||||||
<code>{code}</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Call to docs */}
|
|
||||||
<Link
|
|
||||||
to="/pricing"
|
|
||||||
className="group mt-6 flex items-center justify-between border-2 border-border p-5 hover:bg-foreground transition-all duration-200"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p className="font-mono text-xs text-muted-foreground group-hover:text-background/50 tracking-widest uppercase mb-1 transition-all duration-200">
|
|
||||||
Model Pricing
|
|
||||||
</p>
|
|
||||||
<p className="font-heading text-lg font-bold text-foreground group-hover:text-background transition-all duration-200">
|
|
||||||
{t('查看模型定价,了解完整列表')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span className="font-mono text-2xl text-foreground group-hover:text-background transition-all duration-200">
|
|
||||||
→
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ─── Pricing / CTA Section ──────────────────────────────────── */
|
|
||||||
|
|
||||||
function PricingSection() {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<section id="pricing" className="py-24 px-6">
|
|
||||||
<div className="max-w-4xl mx-auto">
|
|
||||||
<div className="text-xs font-mono text-muted-foreground mb-3 tracking-widest uppercase">
|
|
||||||
{'// pricing'}
|
|
||||||
</div>
|
|
||||||
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight mb-16 text-foreground">
|
|
||||||
{t('获取 Token 额度')}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{/* Token credit callout */}
|
|
||||||
<div className="bg-foreground text-background px-8 py-5 mb-6 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
|
|
||||||
<div className="flex items-center gap-4">
|
|
||||||
<span className="shrink-0 border border-background/30 px-2.5 py-0.5 text-xs font-mono tracking-widest uppercase">
|
|
||||||
{t('今日特惠')}
|
|
||||||
</span>
|
|
||||||
<span className="font-heading text-lg font-bold">
|
|
||||||
{t('注册即送 ¥10 额度')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span className="text-sm text-background/50">
|
|
||||||
{t('新用户注册即赠 ¥10 Token,7 天有效期')}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Call to action */}
|
|
||||||
<Link
|
<Link
|
||||||
to="/register"
|
to="/register"
|
||||||
className="group block border-2 border-border p-8 mb-6 hover:bg-foreground transition-all duration-200"
|
className="inline-flex h-11 items-center gap-2 rounded-full px-8 text-sm font-semibold text-white hover:opacity-90"
|
||||||
|
style={{ background: INK }}
|
||||||
>
|
>
|
||||||
<h3 className="font-heading text-2xl font-bold mb-3 text-foreground group-hover:text-background transition-all duration-200">
|
{t('免费注册')} <ArrowRight size={14} />
|
||||||
{t('立即注册,开始使用')}
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-muted-foreground group-hover:text-background/60 leading-relaxed mb-6 transition-all duration-200">
|
|
||||||
{t(
|
|
||||||
'兼容 OpenAI / Claude / Gemini 协议。一个 API Key,调用所有主流模型。免去多平台充值与管理的麻烦。'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<span className="inline-flex items-center bg-foreground text-background border-2 border-foreground px-6 py-3 text-sm font-mono font-bold uppercase tracking-widest group-hover:bg-background group-hover:text-foreground transition-colors duration-200">
|
|
||||||
{t('免费注册')} →
|
|
||||||
</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── Providers Marquee Section ──────────────────────────────── */
|
/* ─── Footer ────────────────────────────────────────────────── */
|
||||||
|
|
||||||
const PROVIDER_LOGOS = [
|
function HomeFooter() {
|
||||||
{ name: 'OpenAI', className: 'opacity-60' },
|
|
||||||
{ name: 'Claude', className: 'opacity-60' },
|
|
||||||
{ name: 'Gemini', className: 'opacity-60' },
|
|
||||||
{ name: 'DeepSeek', className: 'opacity-60' },
|
|
||||||
{ name: 'Qwen', className: 'opacity-60' },
|
|
||||||
{ name: 'MiniMax', className: 'opacity-60' },
|
|
||||||
{ name: 'Kimi', className: 'opacity-60' },
|
|
||||||
{ name: '智谱', className: 'opacity-60' },
|
|
||||||
{ name: 'Groq', className: 'opacity-60' },
|
|
||||||
{ name: 'Azure', className: 'opacity-60' },
|
|
||||||
];
|
|
||||||
|
|
||||||
function ProvidersSection() {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="bg-foreground text-background border-t-4 border-background">
|
|
||||||
{/* Provider logos marquee area */}
|
|
||||||
<div className="w-full py-16 px-6">
|
|
||||||
<div className="max-w-6xl mx-auto text-center">
|
|
||||||
<p className="font-mono text-xs text-background/30 tracking-widest uppercase mb-3">
|
|
||||||
{'// supported providers'}
|
|
||||||
</p>
|
|
||||||
<h2 className="font-heading text-2xl font-bold mb-8">
|
|
||||||
{t('40+ AI 供应商,统一接入')}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="overflow-hidden">
|
|
||||||
<div className="home-marquee flex gap-16 items-center">
|
|
||||||
{[...PROVIDER_LOGOS, ...PROVIDER_LOGOS].map((logo, i) => (
|
|
||||||
<span
|
|
||||||
key={i}
|
|
||||||
className="font-mono text-sm text-background/40 whitespace-nowrap tracking-wider"
|
|
||||||
>
|
|
||||||
{logo.name}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-10">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => navigate('/pricing')}
|
|
||||||
className="inline-flex items-center bg-background text-foreground border-2 border-background px-8 py-3 text-sm font-mono font-bold uppercase tracking-widest hover:bg-transparent hover:text-background transition-colors duration-200"
|
|
||||||
>
|
|
||||||
{t('查看全部模型')} →
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-center pt-6 pb-8">
|
|
||||||
<p className="font-mono text-xs text-background/30 tracking-wide">
|
|
||||||
{t('免费注册,分钟级接入。兼容你现有的 SDK 和工作流。')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ─── Dark Footer ────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
function DarkFooter() {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<footer className="bg-foreground text-background border-t border-background/10 py-12 px-6">
|
<footer className="border-t" style={{ borderColor: LINE, background: BG }}>
|
||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-[1400px] mx-auto px-6 lg:px-10 py-12">
|
||||||
<div className="flex flex-col md:flex-row items-center justify-between gap-6 mb-8">
|
<div className="flex flex-col md:flex-row items-center justify-between gap-6 mb-8">
|
||||||
<div className="flex items-center gap-6">
|
<div className="flex items-center gap-6">
|
||||||
<Link
|
<Link to="/pricing" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||||
to="/pricing"
|
|
||||||
className="font-mono text-xs text-background/40 hover:text-background transition-all duration-200"
|
|
||||||
>
|
|
||||||
{t('定价')}
|
{t('定价')}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link to="/contact" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||||
to="/console"
|
{t('联系销售')}
|
||||||
className="font-mono text-xs text-background/40 hover:text-background transition-all duration-200"
|
</Link>
|
||||||
>
|
<Link to="/docs" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||||
{t('控制台')}
|
{t('文档')}
|
||||||
|
</Link>
|
||||||
|
<Link to="/about" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||||
|
About
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<Link to="/user-agreement" className="text-xs hover:opacity-70" style={{ color: DIM }}>
|
||||||
|
{t('用户协议')}
|
||||||
|
</Link>
|
||||||
|
<Link to="/privacy-policy" className="text-xs hover:opacity-70" style={{ color: DIM }}>
|
||||||
|
{t('隐私政策')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-background/10 pt-6 flex flex-col md:flex-row items-center justify-between gap-4">
|
<div className="border-t pt-6 flex flex-col md:flex-row items-center justify-between gap-4" style={{ borderColor: LINE }}>
|
||||||
<span className="font-mono text-xs text-background/30">
|
<div className="flex items-center gap-2.5">
|
||||||
© 2026 {getSystemName()}
|
<img src="/logo.jpg" alt="logo" className="h-6 w-6 rounded-full" />
|
||||||
|
<span className="font-heading text-sm font-semibold tracking-tight" style={{ color: INK }}>TuringToken</span>
|
||||||
|
</div>
|
||||||
|
<span className="text-xs" style={{ color: DIM }}>
|
||||||
|
© 2026 {getSystemName()} · Made for developers.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -766,22 +378,17 @@ function DarkFooter() {
|
||||||
/* ─── Main Home Page ────────────────────────────────────────── */
|
/* ─── Main Home Page ────────────────────────────────────────── */
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background text-foreground">
|
<div className="min-h-screen" style={{ background: BG }}>
|
||||||
<div className="home-page">
|
<div className="home-page">
|
||||||
|
<HomeNavBar />
|
||||||
<HeroSection />
|
<HeroSection />
|
||||||
<FeaturesSection />
|
<FeaturesSection />
|
||||||
<HowItWorksSection />
|
<CTASection />
|
||||||
<QuickStartSection />
|
<HomeFooter />
|
||||||
<PricingSection />
|
|
||||||
<ProvidersSection />
|
|
||||||
<DarkFooter />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue