首页重构为 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 ProfitDashboard from './pages/ProfitDashboard';
|
||||
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 Dashboard = lazy(() => import('./pages/Dashboard'));
|
||||
|
|
@ -102,10 +107,6 @@ const DistributorApply = lazy(() => import('./pages/DistributorApply'));
|
|||
const DistributorCenter = lazy(() => import('./pages/DistributorCenter'));
|
||||
const DistributorAdmin = lazy(() => import('./pages/DistributorAdmin'));
|
||||
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() {
|
||||
const { provider } = useParams();
|
||||
|
|
@ -545,6 +546,14 @@ function App() {
|
|||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/contact'
|
||||
element={
|
||||
<Suspense fallback={<Loading></Loading>} key={location.pathname}>
|
||||
<Contact />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/docs'
|
||||
element={
|
||||
|
|
|
|||
|
|
@ -15,16 +15,16 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Modal, Form, Typography, Space, Button } from '@douyinfe/semi-ui';
|
||||
import { IconLock } from '@douyinfe/semi-icons';
|
||||
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 {
|
||||
API,
|
||||
showError,
|
||||
showSuccess,
|
||||
mergeSelfResponseIntoLocalUser,
|
||||
} from '../../helpers';
|
||||
import { UserContext } from '../../context/User';
|
||||
import { buildAdminUserPhoneFieldRules } from '../table/users/modals/userPhoneFormRules';
|
||||
|
||||
const { Text, Title } = Typography;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ For commercial licensing, please contact support@quantumnous.com
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from '@douyinfe/semi-ui';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from '@douyinfe/semi-ui';
|
||||
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 { 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 { API, mergeSelfResponseIntoLocalUser } from '../../helpers';
|
||||
import AdminInitialSetupModal from '../../components/auth/AdminInitialSetupModal';
|
||||
|
||||
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 { toastConstants } from '../constants';
|
||||
import React from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import {
|
||||
THINK_TAG_REGEX,
|
||||
MESSAGE_ROLES,
|
||||
} from '../constants/playground.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';
|
||||
|
||||
const HTMLToastContent = ({ htmlContent }) => {
|
||||
|
|
@ -144,6 +141,15 @@ export function parseCommissionPercentStringToBps(s) {
|
|||
export function getSystemName() {
|
||||
let system_name = localStorage.getItem('system_name');
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,17 +39,17 @@ i18n
|
|||
load: 'currentOnly',
|
||||
supportedLngs: supportedLanguages,
|
||||
resources: {
|
||||
en: enTranslation,
|
||||
'zh-CN': zhCNTranslation,
|
||||
'zh-TW': zhTWTranslation,
|
||||
fr: frTranslation,
|
||||
ru: ruTranslation,
|
||||
ja: jaTranslation,
|
||||
vi: viTranslation,
|
||||
id: idTranslation,
|
||||
ms: msTranslation,
|
||||
th: thTranslation,
|
||||
sw: swTranslation,
|
||||
en: { translation: enTranslation },
|
||||
'zh-CN': { translation: zhCNTranslation },
|
||||
'zh-TW': { translation: zhTWTranslation },
|
||||
fr: { translation: frTranslation },
|
||||
ru: { translation: ruTranslation },
|
||||
ja: { translation: jaTranslation },
|
||||
vi: { translation: viTranslation },
|
||||
id: { translation: idTranslation },
|
||||
ms: { translation: msTranslation },
|
||||
th: { translation: thTranslation },
|
||||
sw: { translation: swTranslation },
|
||||
},
|
||||
fallbackLng: 'zh-CN',
|
||||
lng: 'zh-CN',
|
||||
|
|
|
|||
|
|
@ -5695,6 +5695,21 @@
|
|||
"主题切换": "Theme Toggle",
|
||||
"顶栏显示主题切换按钮,允许用户切换亮色/暗色模式": "Show theme toggle in header bar, allowing users to switch between light/dark mode",
|
||||
"语言选择器": "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
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useCallback, useRef, useContext } from 'react';
|
||||
import React, { useState, useContext, useCallback } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
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 { StatusContext } from '../../context/Status';
|
||||
import { stringToColor, getSystemName } from '../../helpers';
|
||||
|
||||
|
||||
/* ==================================================================
|
||||
TokenDance-style Home Page
|
||||
Design: black/white minimal with serif headings
|
||||
Light-themed Home Page
|
||||
Design: clean white with purple accents
|
||||
================================================================== */
|
||||
|
||||
/* ─── Hero Marquee Carousel Texts ────────────────────────── */
|
||||
const CAROUSEL_TEXTS = [
|
||||
'OpenAI 协议',
|
||||
'Claude 协议',
|
||||
'Gemini 协议',
|
||||
'智能路由',
|
||||
'统一计费',
|
||||
'模型丰富',
|
||||
'安全可靠',
|
||||
'开箱即用',
|
||||
];
|
||||
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';
|
||||
|
||||
/* ─── Hero Section ──────────────────────────────────────────── */
|
||||
/* ─── NavBar ────────────────────────────────────────────────── */
|
||||
|
||||
/* --- Helper: Theme Toggle --- */
|
||||
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() {
|
||||
function HomeNavBar() {
|
||||
const { t } = useTranslation();
|
||||
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 (
|
||||
<section className="relative bg-black text-white overflow-hidden">
|
||||
<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="fixed top-0 z-50 w-full border-b border-white/10 bg-black">
|
||||
<div className="flex h-14 items-center px-4 lg:px-6 max-w-[1400px] mx-auto">
|
||||
<Link to="/" className="flex items-center gap-2 flex-shrink-0">
|
||||
<img src="/logo.jpg" alt="logo" className="w-7 h-7 rounded-full object-cover" />
|
||||
<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>
|
||||
<header className="sticky top-0 z-50 border-b bg-white/85 backdrop-blur-md" style={{ borderColor: LINE }}>
|
||||
<div className="flex h-16 items-center px-6 lg:px-10 max-w-[1400px] 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>
|
||||
<span className="text-[10px] font-mono px-1.5 py-0.5 rounded border" style={{ borderColor: LINE, color: DIM }}>BETA</span>
|
||||
</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">
|
||||
{[
|
||||
{ key: "model", label: "模型", icon: <Box size={16} />, to: "/pricing" },
|
||||
{ key: "benchmark", label: "评测", icon: <Trophy size={16} />, to: "/benchmarks" },
|
||||
{ key: "docs", label: "文档", icon: <BookOpen size={16} />, to: "/docs" },
|
||||
{ key: "console", label: "控制台", icon: <Grid3X3 size={16} />, to: "/console" },
|
||||
{ key: 'model', label: t('定价'), icon: <Box size={16} />, to: '/pricing' },
|
||||
{ key: 'benchmark', label: t('评测'), icon: <Trophy size={16} />, to: '/benchmarks' },
|
||||
{ key: 'docs', label: t('文档'), icon: <BookOpen size={16} />, to: '/docs' },
|
||||
{ key: 'console', label: t('控制台'), icon: <Grid3X3 size={16} />, to: '/console' },
|
||||
].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>
|
||||
<div className="flex items-center gap-1">
|
||||
{showThemeToggle && <HomeThemeToggle />}
|
||||
{showLanguageSelector && <HomeLanguageSelector />}
|
||||
<div className="flex items-center ml-4">
|
||||
{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) }}>
|
||||
{userState.user.username?.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</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">
|
||||
{t("登录")}
|
||||
<Link
|
||||
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>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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" }}>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
/* ─── 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">
|
||||
<p className="font-mono text-sm text-white/30 mb-6 tracking-wide font-body">
|
||||
{"// unified model API gateway"}
|
||||
</p>
|
||||
<div className="w-[60px] h-[4px] bg-white mb-6" />
|
||||
<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服务平台")}
|
||||
<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 }}>
|
||||
<span className="h-1.5 w-1.5 rounded-full" style={{ background: ACC }} />
|
||||
<span>{t('All systems normal')}</span>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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">
|
||||
{t("开始使用")}
|
||||
|
||||
<div className="flex flex-wrap items-center gap-3 mb-8">
|
||||
{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 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>
|
||||
</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 className="home-fade-in-delay-1 font-body">
|
||||
<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">
|
||||
</div>
|
||||
|
||||
{/* 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">
|
||||
<span className="w-3 h-3 rounded-full bg-red-500/60" />
|
||||
<span className="w-3 h-3 rounded-full bg-yellow-500/60" />
|
||||
<span className="w-3 h-3 rounded-full bg-green-500/60" />
|
||||
<span className="w-3 h-3 rounded-full bg-red-400/60" />
|
||||
<span className="w-3 h-3 rounded-full bg-yellow-400/60" />
|
||||
<span className="w-3 h-3 rounded-full bg-green-400/60" />
|
||||
</div>
|
||||
<span className="font-mono text-[10px] text-white/20 tracking-wide">terminal</span>
|
||||
<button type="button" onClick={copyCmd} className="text-white/30 hover:text-white/70 transition-colors" aria-label="Copy">
|
||||
<span className="font-mono text-[10px] tracking-wide" style={{ color: DIM }}>terminal</span>
|
||||
<button type="button" onClick={copyCmd} className="hover:opacity-70 transition-opacity" style={{ color: DIM }} aria-label="Copy">
|
||||
{copied ? <Check size={14} /> : <Copy size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
<pre className="p-5 text-sm font-mono leading-relaxed text-white/80 overflow-x-auto">
|
||||
<code>{`curl https://api.turingtoken.ai/v1/chat/completions \\
|
||||
-H "Authorization: Bearer \$YOUR_API_KEY" \\
|
||||
<pre className="p-5 text-sm font-mono leading-relaxed overflow-x-auto" style={{ color: INK, background: '#1e1e2e' }}>
|
||||
<code className="text-[#cdd6f4]">{`curl https://api.turingtoken.ai/v1/chat/completions \\
|
||||
-H "Authorization: Bearer $YOUR_API_KEY" \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-d '{
|
||||
"model": "gpt-4o",
|
||||
|
|
@ -238,70 +204,61 @@ function HeroSection() {
|
|||
}'`}</code>
|
||||
</pre>
|
||||
</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>
|
||||
|
||||
{/* Hero brand wordmark — TURINGTOKEN */}
|
||||
<div className="w-full overflow-hidden px-6 pb-2">
|
||||
{/* Dark brand wordmark strip */}
|
||||
<div className="w-full overflow-hidden border-t" style={{ borderColor: LINE, background: INK }}>
|
||||
<div
|
||||
className="inline-flex whitespace-nowrap origin-left font-mono font-bold uppercase leading-[0.85] select-none tracking-tight"
|
||||
style={{ fontSize: 'clamp(4rem, 20vw, 12rem)', transform: 'scaleX(1.04)' }}
|
||||
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(3rem, 16vw, 10rem)', transform: 'scaleX(1.04)' }}
|
||||
>
|
||||
<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>
|
||||
</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>
|
||||
);
|
||||
}const FEATURES = [
|
||||
}
|
||||
|
||||
/* ─── Features Section ──────────────────────────────────────── */
|
||||
|
||||
const FEATURES = [
|
||||
{
|
||||
titleKey: '多协议兼容',
|
||||
descKey:
|
||||
'原生支持 OpenAI、Claude、Gemini 文本协议,覆盖图像 / 视频 / 文本转语音生成。无需修改代码,切换 Base URL 即可接入。',
|
||||
descKey: '原生支持 OpenAI、Claude、Gemini 文本协议,覆盖图像 / 视频 / 文本转语音生成。无需修改代码,切换 Base URL 即可接入。',
|
||||
code: 'baseURL: "api.turingtoken.ai"',
|
||||
},
|
||||
{
|
||||
titleKey: '智能路由',
|
||||
descKey:
|
||||
'根据模型名称自动路由至对应供应商。一个入口,无需关心底层调度。',
|
||||
descKey: '根据模型名称自动路由至对应供应商。一个入口,无需关心底层调度。',
|
||||
code: 'route(model) → provider',
|
||||
},
|
||||
{
|
||||
titleKey: '统一计费',
|
||||
descKey:
|
||||
'跨供应商统一 Token 消耗统计与账单。告别多平台分别充值的混乱。',
|
||||
descKey: '跨供应商统一 Token 消耗统计与账单。告别多平台分别充值的混乱。',
|
||||
code: 'billing.unified()',
|
||||
},
|
||||
{
|
||||
titleKey: '容错降级',
|
||||
descKey:
|
||||
'同一模型支持多供应商端点自动切换;单次请求可指定多个候选模型,逐级降级,保障服务持续可用。',
|
||||
descKey: '同一模型支持多供应商端点自动切换;单次请求可指定多个候选模型,逐级降级,保障服务持续可用。',
|
||||
code: 'fallback: model[] → provider[]',
|
||||
},
|
||||
{
|
||||
titleKey: '模型丰富',
|
||||
descKey:
|
||||
'接入 MiniMax、通义千问、Kimi、智谱、DeepSeek 等国内头部模型。持续扩展中。',
|
||||
descKey: '接入 MiniMax、通义千问、Kimi、智谱、DeepSeek 等国内头部模型。持续扩展中。',
|
||||
code: 'models.list() → 80+',
|
||||
},
|
||||
{
|
||||
titleKey: '开箱即用',
|
||||
descKey:
|
||||
'一键登录,分钟级接入。兼容现有 SDK,零迁移成本。',
|
||||
descKey: '一键登录,分钟级接入。兼容现有 SDK,零迁移成本。',
|
||||
code: 'import OpenAI from "openai"',
|
||||
},
|
||||
];
|
||||
|
|
@ -309,27 +266,28 @@ function HeroSection() {
|
|||
function FeaturesSection() {
|
||||
const { t } = useTranslation();
|
||||
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">
|
||||
<p className="font-mono text-xs text-muted-foreground tracking-widest uppercase mb-3">
|
||||
{/* features */}
|
||||
</p>
|
||||
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight mb-16 text-foreground">
|
||||
<div className="font-mono text-[11px] tracking-[0.25em] uppercase mb-3" style={{ color: DIM }}>
|
||||
{'// features'}
|
||||
</div>
|
||||
<h2 className="font-heading text-3xl font-bold md:text-4xl tracking-tight mb-16" style={{ color: INK }}>
|
||||
{t('为接入 AI 模型的开发者而造。')}
|
||||
</h2>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3">
|
||||
{FEATURES.map((f, i) => (
|
||||
<div
|
||||
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}
|
||||
</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)}
|
||||
</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)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -340,422 +298,76 @@ function FeaturesSection() {
|
|||
);
|
||||
}
|
||||
|
||||
/* ─── How It Works Section ──────────────────────────────────── */
|
||||
/* ─── CTA Section ───────────────────────────────────────────── */
|
||||
|
||||
const STEPS = [
|
||||
{
|
||||
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() {
|
||||
function CTASection() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<section
|
||||
id="how-it-works"
|
||||
className="border-y-4 border-border"
|
||||
<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%, ${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">
|
||||
<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('三步接入,分钟级上线')}
|
||||
{t('立即接入。')}
|
||||
</h2>
|
||||
</div>
|
||||
{STEPS.map((s, i) => (
|
||||
<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 className="text-base leading-[1.7] mb-9" style={{ color: SUB }}>
|
||||
{t('注册送 ¥10 试用金,分键跑完一组 benchmark,一拍压测。')}
|
||||
</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
|
||||
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('立即注册,开始使用')}
|
||||
</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>
|
||||
{t('免费注册')} <ArrowRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
/* ─── Providers Marquee Section ──────────────────────────────── */
|
||||
/* ─── Footer ────────────────────────────────────────────────── */
|
||||
|
||||
const PROVIDER_LOGOS = [
|
||||
{ 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() {
|
||||
function HomeFooter() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<footer className="bg-foreground text-background border-t border-background/10 py-12 px-6">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<footer className="border-t" style={{ borderColor: LINE, background: BG }}>
|
||||
<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 items-center gap-6">
|
||||
<Link
|
||||
to="/pricing"
|
||||
className="font-mono text-xs text-background/40 hover:text-background transition-all duration-200"
|
||||
>
|
||||
<Link to="/pricing" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||
{t('定价')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/console"
|
||||
className="font-mono text-xs text-background/40 hover:text-background transition-all duration-200"
|
||||
>
|
||||
{t('控制台')}
|
||||
<Link to="/contact" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||
{t('联系销售')}
|
||||
</Link>
|
||||
<Link to="/docs" className="font-mono text-xs hover:opacity-70 transition-all duration-200" style={{ color: DIM }}>
|
||||
{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>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-background/10 pt-6 flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<span className="font-mono text-xs text-background/30">
|
||||
© 2026 {getSystemName()}
|
||||
<div className="border-t pt-6 flex flex-col md:flex-row items-center justify-between gap-4" style={{ borderColor: LINE }}>
|
||||
<div className="flex items-center gap-2.5">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -766,22 +378,17 @@ function DarkFooter() {
|
|||
/* ─── Main Home Page ────────────────────────────────────────── */
|
||||
|
||||
const Home = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<div className="min-h-screen" style={{ background: BG }}>
|
||||
<div className="home-page">
|
||||
<HomeNavBar />
|
||||
<HeroSection />
|
||||
<FeaturesSection />
|
||||
<HowItWorksSection />
|
||||
<QuickStartSection />
|
||||
<PricingSection />
|
||||
<ProvidersSection />
|
||||
<DarkFooter />
|
||||
<CTASection />
|
||||
<HomeFooter />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue