- 按 app / shared / entities / features 分层,路由懒加载并抽出布局组件 - 请求层改为可插拔拦截器,统一错误类型、超时取消与端点拆分 - 抽取播放器、骨架屏、网格等复用组件,点赞收藏接入统一交互反馈 - 关于页重做为无边框极光风格,补充 iOS / Google Play 下载入口 - 修复播放页滚轮切集吞事件、页面误滚动、后台持续播放与声音记忆问题 - 语言按本地偏好与 IP 识别,国旗改为内联 SVG - 清理未使用的旧站点文件,补充 ESLint 配置
101 lines
3.9 KiB
React
101 lines
3.9 KiB
React
// Author: fruit.com.cn
|
|
import { ArrowRight, Clapperboard, Cpu, Play, Smartphone, Sparkles, Users } from 'lucide-react';
|
|
import { Link } from 'react-router-dom';
|
|
import { useLocale } from '../../app/providers/AppProviders';
|
|
import { aboutContent } from './content';
|
|
|
|
const APP_DOWNLOAD_URL = 'https://cdnetworksdist.okrivo.xyz/wPwBG';
|
|
|
|
const PILLARS = [
|
|
{ key: 'join', icon: Users },
|
|
{ key: 'produce', icon: Clapperboard },
|
|
{ key: 'compute', icon: Cpu },
|
|
];
|
|
|
|
export function AboutPage() {
|
|
const { locale } = useLocale();
|
|
const copy = aboutContent[locale.code] || aboutContent.en;
|
|
|
|
return (
|
|
<div className="about-page">
|
|
<section className="about-hero">
|
|
<div className="about-hero-copy">
|
|
<span className="about-kicker">{copy.kicker}</span>
|
|
<h1>{copy.heroTitle}</h1>
|
|
<p>{copy.heroText}</p>
|
|
<div className="about-hero-actions">
|
|
<Link to="/" className="about-primary"><Sparkles size={16} />{copy.explore}</Link>
|
|
<Link to="/shorts" className="about-secondary"><Play size={16} fill="currentColor" />{copy.watchShorts}</Link>
|
|
</div>
|
|
<div className="about-stores">
|
|
<span className="about-stores-label">{copy.downloadLabel}</span>
|
|
<div className="about-stores-row">
|
|
<a className="about-store" href={APP_DOWNLOAD_URL} target="_blank" rel="noopener noreferrer">
|
|
<Smartphone size={20} />
|
|
<span><small>{copy.iosSmall}</small><b>App Store</b></span>
|
|
</a>
|
|
<a className="about-store" href={APP_DOWNLOAD_URL} target="_blank" rel="noopener noreferrer">
|
|
<Play size={20} fill="currentColor" />
|
|
<span><small>{copy.androidSmall}</small><b>Google Play</b></span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div className="about-values">{copy.values.map((value) => <span key={value}>{value}</span>)}</div>
|
|
</div>
|
|
<div className="about-hero-visual" aria-hidden="true">
|
|
<span className="about-float about-float-a">{copy.joinTitle}</span>
|
|
<span className="about-float about-float-b">{copy.produceTitle}</span>
|
|
<span className="about-float about-float-c">{copy.computeTitle}</span>
|
|
<div className="about-phone">
|
|
<span className="about-phone-glow" />
|
|
<span className="about-phone-logo">ymb</span>
|
|
<span className="about-phone-play"><Play size={26} fill="currentColor" /></span>
|
|
<small>SHORTS</small>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="about-section">
|
|
<h2>{copy.whoTitle}</h2>
|
|
<p className="about-lead">{copy.whoText}</p>
|
|
</section>
|
|
|
|
<section className="about-section">
|
|
<h2>{copy.pillarsTitle}</h2>
|
|
<div className="about-pillars">
|
|
{PILLARS.map(({ key, icon: Icon }) => (
|
|
<article className="about-pillar" key={key}>
|
|
<span className="about-pillar-icon"><Icon size={22} /></span>
|
|
<h3>{copy[`${key}Title`]}</h3>
|
|
<p>{copy[`${key}Text`]}</p>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="about-section">
|
|
<h2>{copy.roadmapTitle}</h2>
|
|
<ol className="about-roadmap">
|
|
{copy.roadmap.map((step, index) => (
|
|
<li key={step.title}>
|
|
<span className="about-step-index">{String(index + 1).padStart(2, '0')}</span>
|
|
<div>
|
|
<b>{step.year} · {step.title}</b>
|
|
<p>{step.text}</p>
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</section>
|
|
|
|
<section className="about-cta">
|
|
<div>
|
|
<h2>{copy.ctaTitle}</h2>
|
|
<p>{copy.ctaText}</p>
|
|
</div>
|
|
<Link to="/shorts" className="about-primary">{copy.ctaButton}<ArrowRight size={16} /></Link>
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|