feat: 添加货币和汇率管理功能

refactor: 重构前端路由和登录逻辑

docs: 更新业务闭环、任务和架构文档

style: 调整代码格式和文件结构

chore: 更新依赖项和配置文件
This commit is contained in:
2026-03-19 19:08:15 +08:00
parent 8de9ea0aaa
commit eafa1bbe94
203 changed files with 20240 additions and 39580 deletions

View File

@@ -1,4 +1,5 @@
import React, { useState } from 'react';
import { useNavigate } from 'umi';
import {
Card,
Form,
@@ -39,6 +40,7 @@ export const LoginPage: React.FC = () => {
const [loading, setLoading] = useState(false);
const [loginError, setLoginError] = useState<string | null>(null);
const [captchaCode, setCaptchaCode] = useState('');
const navigate = useNavigate();
const generateCaptcha = () => {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
@@ -68,6 +70,9 @@ export const LoginPage: React.FC = () => {
}
message.success('Login successful! Redirecting...');
setTimeout(() => {
navigate('/dashboard');
}, 1000);
} catch (error) {
setLoginError('Login failed. Please check your credentials.');
} finally {

View File

@@ -0,0 +1,486 @@
import React, { useState } from 'react';
import { Link, useNavigate } from 'umi';
import { Card, Button, Typography, Row, Col, Tag, Carousel, Pagination } from 'antd';
import { ArrowRightOutlined, CheckCircleOutlined, DollarOutlined, BarChartOutlined, ZapOutlined, GlobeOutlined, StarOutlined, UserOutlined, CompanyOutlined, TrendingUpOutlined } from '@ant-design/icons';
import Navbar from '@/components/Navbar';
const { Title, Paragraph, Text } = Typography;
const CaseStudy: React.FC = () => {
const navigate = useNavigate();
const [activeCategory, setActiveCategory] = useState('all');
const [currentPage, setCurrentPage] = useState(1);
const caseStudies = [
{
id: 1,
title: '中小商户案例月销售额提升45%',
category: 'small',
company: '广州某跨境电商公司',
industry: '电子产品',
challenge: '手动选品效率低,定价策略单一,运营成本高',
solution: '使用智能选品系统和AI动态定价实现自动化运营',
results: [
'月销售额提升45%',
'运营成本降低30%',
'选品效率提升60%',
],
testimonial: '"Crawlful Hub帮助我们实现了店铺的自动化运营节省了大量人力成本销售额提升了40%。"',
author: '张总',
position: 'CEO',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
{
id: 2,
title: '大型企业案例多店铺管理效率提升60%',
category: 'enterprise',
company: '深圳某品牌电商',
industry: '服装行业',
challenge: '多店铺管理复杂,数据分散,难以统一运营',
solution: '使用多店铺管理系统,实现数据集中管理和统一运营',
results: [
'管理效率提升60%',
'数据处理时间减少70%',
'运营成本降低25%',
],
testimonial: '"多店铺管理功能让我们能够集中管理所有店铺,数据一目了然,大大提高了管理效率。"',
author: '李经理',
position: '运营总监',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
{
id: 3,
title: '跨境电商案例利润率提升30%',
category: 'crossborder',
company: '杭州某跨境电商平台',
industry: '家居用品',
challenge: '跨平台价格差异难以把握,利润空间小',
solution: '使用跨平台套利系统,发现价格差异,优化定价策略',
results: [
'利润率提升30%',
'价格优化效率提升80%',
'市场竞争力增强',
],
testimonial: '"跨平台套利系统帮助我们发现了很多价格差异利润率提高了30%,市场竞争力大大增强。"',
author: '王女士',
position: '业务经理',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
{
id: 4,
title: '新手卖家案例:快速启动电商业务',
category: 'small',
company: '上海某个人卖家',
industry: '美妆产品',
challenge: '缺乏电商运营经验,选品困难,运营成本高',
solution: '使用智能选品系统和自动上架功能,快速启动业务',
results: [
'业务启动时间缩短50%',
'选品准确率提升70%',
'首月销售额达到预期目标',
],
testimonial: '"作为新手卖家Crawlful Hub帮助我快速启动了电商业务选品和上架都变得非常简单。"',
author: '陈先生',
position: '个人卖家',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
{
id: 5,
title: '传统企业转型案例线上销售额占比提升至60%',
category: 'enterprise',
company: '北京某传统制造企业',
industry: '机械设备',
challenge: '线上业务占比低,数字化转型困难',
solution: '使用全功能电商管理系统,实现线上线下一体化运营',
results: [
'线上销售额占比提升至60%',
'客户获取成本降低40%',
'品牌知名度提升',
],
testimonial: '"Crawlful Hub帮助我们成功实现了数字化转型线上销售额占比从10%提升到了60%。"',
author: '赵总',
position: '总经理',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
{
id: 6,
title: '多平台运营案例管理效率提升70%',
category: 'crossborder',
company: '厦门某跨境电商公司',
industry: '玩具产品',
challenge: '多平台运营管理复杂,数据不同步,运营效率低',
solution: '使用多平台集成管理系统,实现数据同步和统一运营',
results: [
'管理效率提升70%',
'数据同步时间减少90%',
'运营成本降低35%',
],
testimonial: '"多平台集成管理系统让我们能够统一管理所有平台的店铺,效率大大提升。"',
author: '刘经理',
position: '运营主管',
image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',
},
];
const filteredCases = activeCategory === 'all'
? caseStudies
: caseStudies.filter(caseStudy => caseStudy.category === activeCategory);
const itemsPerPage = 3;
const totalPages = Math.ceil(filteredCases.length / itemsPerPage);
const currentCases = filteredCases.slice(
(currentPage - 1) * itemsPerPage,
currentPage * itemsPerPage
);
const categories = [
{ value: 'all', label: '全部案例' },
{ value: 'small', label: '中小商户' },
{ value: 'enterprise', label: '大型企业' },
{ value: 'crossborder', label: '跨境电商' },
];
return (
<div className="case-study-page">
<Navbar />
{/* 页面头部 */}
<section className="case-header">
<div className="container">
<Title level={1}></Title>
<Paragraph className="subtitle">
</Paragraph>
</div>
</section>
{/* 分类筛选 */}
<section className="category-filter">
<div className="container">
<div className="categories">
{categories.map(category => (
<Button
key={category.value}
type={activeCategory === category.value ? 'primary' : 'default'}
onClick={() => {
setActiveCategory(category.value);
setCurrentPage(1);
}}
>
{category.label}
</Button>
))}
</div>
</div>
</section>
{/* 案例列表 */}
<section className="case-list">
<div className="container">
<Row gutter={[32, 32]}>
{currentCases.map(caseStudy => (
<Col key={caseStudy.id} xs={24} md={8}>
<Card hoverable className="case-card">
<div className="case-image">
<img src={caseStudy.image} alt={caseStudy.title} />
</div>
<div className="case-content">
<div className="case-meta">
<Tag color="blue">{caseStudy.industry}</Tag>
<Tag color="green">{caseStudy.company}</Tag>
</div>
<Title level={4}>{caseStudy.title}</Title>
<Paragraph className="case-challenge">
<Text strong></Text>{caseStudy.challenge}
</Paragraph>
<Paragraph className="case-solution">
<Text strong></Text>{caseStudy.solution}
</Paragraph>
<div className="case-results">
<Title level={5}></Title>
<ul>
{caseStudy.results.map((result, index) => (
<li key={index}>
<CheckCircleOutlined className="result-icon" />
{result}
</li>
))}
</ul>
</div>
<div className="case-testimonial">
<div className="testimonial-content">
<StarOutlined className="star" />
<StarOutlined className="star" />
<StarOutlined className="star" />
<StarOutlined className="star" />
<StarOutlined className="star" />
<Paragraph>{caseStudy.testimonial}</Paragraph>
</div>
<div className="testimonial-author">
<UserOutlined className="author-icon" />
<div>
<Text strong>{caseStudy.author}</Text>
<Text type="secondary">{caseStudy.position}</Text>
</div>
</div>
</div>
<Button type="primary" className="case-button" onClick={() => navigate(`/case-study/${caseStudy.id}`)}>
<ArrowRightOutlined />
</Button>
</div>
</Card>
</Col>
))}
</Row>
{/* 分页 */}
{totalPages > 1 && (
<div className="pagination">
<Pagination
current={currentPage}
total={filteredCases.length}
pageSize={itemsPerPage}
onChange={setCurrentPage}
showSizeChanger={false}
/>
</div>
)}
</div>
</section>
{/* 客户评价轮播 */}
<section className="testimonial-carousel">
<div className="container">
<Title level={2}></Title>
<Carousel autoplay className="carousel">
{caseStudies.map(caseStudy => (
<div key={caseStudy.id} className="carousel-item">
<Card className="testimonial-card">
<div className="testimonial-rating">
{[1, 2, 3, 4, 5].map(star => (
<StarOutlined key={star} className="star" />
))}
</div>
<Paragraph>{caseStudy.testimonial}</Paragraph>
<div className="testimonial-author">
<UserOutlined className="author-icon" />
<div>
<Text strong>{caseStudy.author}</Text>
<Text type="secondary">{caseStudy.position}{caseStudy.company}</Text>
</div>
</div>
</Card>
</div>
))}
</Carousel>
</div>
</section>
{/* 行动召唤 */}
<section className="cta">
<div className="container">
<Title level={2}></Title>
<Paragraph></Paragraph>
<Button type="primary" size="large" onClick={() => navigate('/auth/register')}>
</Button>
</div>
</section>
<style jsx>{`
.case-study-page {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.case-header {
padding: 140px 0 40px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
text-align: center;
}
@media (max-width: 768px) {
.case-header {
padding: 120px 0 30px;
}
}
.subtitle {
font-size: 18px;
color: #666;
margin: 16px 0;
}
.category-filter {
padding: 40px 0;
background: #fff;
}
.categories {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.case-list {
padding: 40px 0 80px;
background: #f5f7fa;
}
.case-card {
border-radius: 8px;
overflow: hidden;
transition: all 0.3s ease;
}
.case-card:hover {
transform: translateY(-8px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}
.case-image {
height: 200px;
overflow: hidden;
}
.case-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.case-card:hover .case-image img {
transform: scale(1.05);
}
.case-content {
padding: 24px;
}
.case-meta {
margin-bottom: 16px;
}
.case-challenge,
.case-solution {
margin: 12px 0;
}
.case-results {
margin: 24px 0;
}
.case-results ul {
list-style: none;
padding: 0;
margin: 0;
}
.case-results li {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.result-icon {
color: #52c41a;
}
.case-testimonial {
margin: 24px 0;
padding: 16px;
background: #f0f2f5;
border-radius: 8px;
}
.testimonial-rating {
color: #faad14;
margin-bottom: 16px;
}
.testimonial-author {
display: flex;
align-items: center;
gap: 8px;
margin-top: 16px;
}
.author-icon {
font-size: 24px;
color: #1890ff;
}
.case-button {
margin-top: 16px;
}
.pagination {
margin-top: 40px;
display: flex;
justify-content: center;
}
.testimonial-carousel {
padding: 80px 0;
background: #fff;
}
.carousel {
margin-top: 40px;
}
.carousel-item {
padding: 0 16px;
}
.testimonial-card {
padding: 32px;
border-radius: 8px;
text-align: center;
}
.star {
color: #faad14;
margin-right: 4px;
}
.cta {
padding: 80px 0;
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
color: #fff;
text-align: center;
}
.cta .ant-btn {
margin-top: 24px;
}
@media (max-width: 768px) {
.case-header {
padding: 60px 0 30px;
}
.category-filter {
padding: 30px 0;
}
.case-list {
padding: 30px 0 60px;
}
.testimonial-carousel {
padding: 60px 0;
}
.cta {
padding: 60px 0;
}
}
`}</style>
</div>
);
};
export default CaseStudy;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,493 @@
import React, { useState } from 'react';
import { Link, useNavigate } from 'umi';
import { Card, Button, Typography, Divider, Radio, Row, Col, Tag, Alert } from 'antd';
import { CheckCircleOutlined, CloseCircleOutlined, ArrowRightOutlined, DollarOutlined, UsersOutlined, ShieldOutlined, BarChartOutlined, ZapOutlined, GlobeOutlined, StarOutlined } from '@ant-design/icons';
import Navbar from '@/components/Navbar';
const { Title, Paragraph, Text } = Typography;
const Pricing: React.FC = () => {
const navigate = useNavigate();
const [billingCycle, setBillingCycle] = useState<'monthly' | 'yearly'>('monthly');
const plans = [
{
name: '免费版',
price: 0,
billing: '永久免费',
features: [
'基础功能',
'最多1个店铺',
'500条商品数据',
'邮件支持',
'基础报表',
'手动操作',
],
cta: '开始免费使用',
popular: false,
buttonType: 'primary',
onClick: () => navigate('/auth/register'),
},
{
name: '专业版',
price: billingCycle === 'monthly' ? 999 : 9990,
billing: billingCycle === 'monthly' ? '每月' : '每年',
features: [
'所有核心功能',
'最多10个店铺',
'5000条商品数据',
'优先邮件支持',
'高级报表',
'AI智能选品',
'自动上架',
'动态定价',
'跨平台套利',
],
cta: '选择专业版',
popular: true,
buttonType: 'primary',
onClick: () => navigate('/checkout?plan=professional'),
},
{
name: '企业版',
price: 0,
billing: '定制',
features: [
'完整功能',
'无限店铺',
'无限商品数据',
'24/7专属支持',
'定制化报表',
'AI店铺托管',
'定制化开发',
'API接入',
'专属客户经理',
],
cta: '联系销售',
popular: false,
buttonType: 'default',
onClick: () => navigate('/contact'),
},
];
const compareFeatures = [
{ feature: '核心功能', free: true, professional: true, enterprise: true },
{ feature: '店铺数量', free: '1个', professional: '10个', enterprise: '无限' },
{ feature: '商品数据', free: '500条', professional: '5000条', enterprise: '无限' },
{ feature: 'AI智能选品', free: false, professional: true, enterprise: true },
{ feature: '自动上架', free: false, professional: true, enterprise: true },
{ feature: '动态定价', free: false, professional: true, enterprise: true },
{ feature: '跨平台套利', free: false, professional: true, enterprise: true },
{ feature: 'AI店铺托管', free: false, professional: false, enterprise: true },
{ feature: '技术支持', free: '邮件', professional: '优先邮件', enterprise: '24/7专属' },
{ feature: '定制化开发', free: false, professional: false, enterprise: true },
{ feature: 'API接入', free: false, professional: false, enterprise: true },
];
return (
<div className="pricing-page">
<Navbar />
{/* 页面头部 */}
<section className="pricing-header">
<div className="container">
<Title level={1}></Title>
<Paragraph className="subtitle">
</Paragraph>
<div className="billing-cycle">
<Text></Text>
<Radio.Group value={billingCycle} onChange={(e) => setBillingCycle(e.target.value)}>
<Radio.Button value="monthly"></Radio.Button>
<Radio.Button value="yearly"> <Tag color="green">16%</Tag></Radio.Button>
</Radio.Group>
<Text></Text>
</div>
</div>
</section>
{/* 定价方案 */}
<section className="pricing-plans">
<div className="container">
<Row gutter={[32, 32]}>
{plans.map((plan, index) => (
<Col key={index} xs={24} md={8}>
<Card className={`plan-card ${plan.popular ? 'popular' : ''}`}>
{plan.popular && (
<div className="popular-badge">
<StarOutlined />
</div>
)}
<div className="plan-header">
<Title level={3}>{plan.name}</Title>
<div className="price">
<DollarOutlined />
<span className="price-value">{plan.price}</span>
<span className="price-unit">/{plan.billing === '永久免费' ? '' : plan.billing === '每月' ? '月' : '年'}</span>
</div>
{plan.billing === '永久免费' && (
<Text type="secondary">{plan.billing}</Text>
)}
</div>
<Divider />
<div className="plan-features">
{plan.features.map((feature, idx) => (
<div key={idx} className="feature-item">
<CheckCircleOutlined className="feature-icon" />
<Text>{feature}</Text>
</div>
))}
</div>
<Button
type={plan.buttonType as any}
size="large"
className="plan-button"
onClick={plan.onClick}
>
{plan.cta}
</Button>
</Card>
</Col>
))}
</Row>
</div>
</section>
{/* 功能对比 */}
<section className="feature-comparison">
<div className="container">
<Title level={2}></Title>
<div className="comparison-table">
<div className="table-header">
<div className="feature-cell"></div>
<div className="plan-cell"></div>
<div className="plan-cell"></div>
<div className="plan-cell"></div>
</div>
{compareFeatures.map((item, index) => (
<div key={index} className="table-row">
<div className="feature-cell">{item.feature}</div>
<div className="plan-cell">
{typeof item.free === 'boolean' ? (
item.free ?
<CheckCircleOutlined className="check-icon" /> :
<CloseCircleOutlined className="close-icon" />
) : (
<Text>{item.free}</Text>
)}
</div>
<div className="plan-cell">
{typeof item.professional === 'boolean' ? (
item.professional ?
<CheckCircleOutlined className="check-icon" /> :
<CloseCircleOutlined className="close-icon" />
) : (
<Text>{item.professional}</Text>
)}
</div>
<div className="plan-cell">
{typeof item.enterprise === 'boolean' ? (
item.enterprise ?
<CheckCircleOutlined className="check-icon" /> :
<CloseCircleOutlined className="close-icon" />
) : (
<Text>{item.enterprise}</Text>
)}
</div>
</div>
))}
</div>
</div>
</section>
{/* 常见问题 */}
<section className="faq">
<div className="container">
<Title level={2}></Title>
<Row gutter={[32, 32]}>
<Col xs={24} md={12}>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
</Paragraph>
</Card>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
billing cycle
</Paragraph>
</Card>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
billing cycle
</Paragraph>
</Card>
</Col>
<Col xs={24} md={12}>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
16%使2
</Paragraph>
</Card>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
</Paragraph>
</Card>
<Card className="faq-card">
<Title level={4}></Title>
<Paragraph>
14
</Paragraph>
</Card>
</Col>
</Row>
</div>
</section>
{/* 行动召唤 */}
<section className="cta">
<div className="container">
<Title level={2}></Title>
<Paragraph></Paragraph>
<Button type="primary" size="large" onClick={() => navigate('/auth/register')}>
</Button>
</div>
</section>
<style jsx>{`
.pricing-page {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.pricing-header {
padding: 140px 0 40px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
text-align: center;
}
@media (max-width: 768px) {
.pricing-header {
padding: 120px 0 30px;
}
}
.subtitle {
font-size: 18px;
color: #666;
margin: 16px 0 32px;
}
.billing-cycle {
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
margin-top: 32px;
}
.pricing-plans {
padding: 60px 0;
background: #fff;
}
.plan-card {
border-radius: 8px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.plan-card:hover {
transform: translateY(-8px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}
.plan-card.popular {
border: 2px solid #1890ff;
transform: scale(1.05);
}
.plan-card.popular:hover {
transform: scale(1.05) translateY(-8px);
}
.popular-badge {
position: absolute;
top: 0;
right: 0;
background: #1890ff;
color: #fff;
padding: 4px 16px;
border-radius: 0 8px 0 8px;
font-size: 12px;
font-weight: bold;
display: flex;
align-items: center;
gap: 4px;
}
.plan-header {
text-align: center;
margin-bottom: 24px;
}
.price {
display: flex;
align-items: baseline;
justify-content: center;
margin: 16px 0;
}
.price-value {
font-size: 36px;
font-weight: bold;
color: #1890ff;
margin: 0 4px;
}
.price-unit {
font-size: 16px;
color: #666;
}
.plan-features {
margin: 24px 0;
}
.feature-item {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
}
.feature-icon {
color: #52c41a;
}
.plan-button {
width: 100%;
margin-top: 24px;
}
.feature-comparison {
padding: 80px 0;
background: #f5f7fa;
}
.comparison-table {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.table-header {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
background: #f0f2f5;
padding: 16px;
font-weight: bold;
border-bottom: 1px solid #e8e8e8;
}
.table-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
padding: 16px;
border-bottom: 1px solid #e8e8e8;
}
.table-row:last-child {
border-bottom: none;
}
.feature-cell {
font-weight: 500;
}
.plan-cell {
text-align: center;
}
.check-icon {
color: #52c41a;
font-size: 18px;
}
.close-icon {
color: #ff4d4f;
font-size: 18px;
}
.faq {
padding: 80px 0;
background: #fff;
}
.faq-card {
padding: 24px;
border-radius: 8px;
transition: all 0.3s ease;
}
.faq-card:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08);
}
.cta {
padding: 80px 0;
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
color: #fff;
text-align: center;
}
.cta .ant-btn {
margin-top: 24px;
}
@media (max-width: 768px) {
.pricing-header {
padding: 60px 0 30px;
}
.pricing-plans {
padding: 40px 0;
}
.feature-comparison {
padding: 60px 0;
}
.table-header,
.table-row {
grid-template-columns: 1fr;
gap: 8px;
}
.plan-cell {
text-align: left;
display: flex;
align-items: center;
gap: 8px;
}
.faq {
padding: 60px 0;
}
.cta {
padding: 60px 0;
}
}
`}</style>
</div>
);
};
export default Pricing;

View File

@@ -1,119 +1,8 @@
import React from 'react';
import { Card, Typography, Row, Col, Statistic, Divider } from 'antd';
import {
ShoppingOutlined,
FileTextOutlined,
ShopOutlined,
DollarOutlined,
RiseOutlined,
FallOutlined,
} from '@ant-design/icons';
import Homepage from './Homepage';
const { Title, Text } = Typography;
const Dashboard: React.FC = () => {
return (
<div>
<Title level={4}></Title>
<Text type="secondary"></Text>
<Divider />
{/* 核心指标卡片 */}
<Row gutter={[16, 16]}>
<Col xs={24} sm={12} md={6}>
<Card hoverable>
<Statistic
title="商品数量"
value={1280}
prefix={<ShoppingOutlined style={{ color: '#1890ff' }} />}
valueStyle={{ color: '#1890ff' }}
/>
<div style={{ marginTop: 8 }}>
<Text type="success">
<RiseOutlined /> +12
</Text>
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card hoverable>
<Statistic
title="订单数量"
value={960}
prefix={<FileTextOutlined style={{ color: '#52c41a' }} />}
valueStyle={{ color: '#52c41a' }}
/>
<div style={{ marginTop: 8 }}>
<Text type="success">
<RiseOutlined /> +8%
</Text>
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card hoverable>
<Statistic
title="商户数量"
value={120}
prefix={<ShopOutlined style={{ color: '#722ed1' }} />}
valueStyle={{ color: '#722ed1' }}
/>
<div style={{ marginTop: 8 }}>
<Text type="secondary">
98
</Text>
</div>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card hoverable>
<Statistic
title="总销售额"
value={1280000}
prefix={<DollarOutlined style={{ color: '#fa8c16' }} />}
valueStyle={{ color: '#fa8c16' }}
precision={2}
/>
<div style={{ marginTop: 8 }}>
<Text type="danger">
<FallOutlined /> -2%
</Text>
</div>
</Card>
</Col>
</Row>
{/* 系统功能介绍 */}
<Row gutter={[16, 16]} style={{ marginTop: 24 }}>
<Col span={24}>
<Card title="系统功能">
<Text>
使 Crawlful Hub
</Text>
<Divider />
<Row gutter={[16, 16]}>
<Col xs={24} md={8}>
<Card type="inner" title="商品管理">
<Text></Text>
</Card>
</Col>
<Col xs={24} md={8}>
<Card type="inner" title="订单管理">
<Text></Text>
</Card>
</Col>
<Col xs={24} md={8}>
<Card type="inner" title="数据分析">
<Text></Text>
</Card>
</Col>
</Row>
</Card>
</Col>
</Row>
</div>
);
const IndexPage: React.FC = () => {
return <Homepage />;
};
export default Dashboard;
export default IndexPage;