feat: 添加前端页面和业务说明书

refactor(server): 重构服务层代码结构
feat(server): 添加基础设施、跨境电商、AI决策等核心服务
docs: 完善前端业务说明书和开发进度文档
style: 格式化代码和文档
This commit is contained in:
2026-03-18 19:12:38 +08:00
parent c932a67be2
commit 6d0d2b6157
140 changed files with 23859 additions and 5833 deletions

View File

@@ -0,0 +1,302 @@
import React from 'react';
import { Button, Card, Table, Input, Select, DatePicker, Space, Modal, Form, InputNumber, Tag, Badge, message, Spin, Alert } from 'antd';
// 业务按钮组件
export const BusinessButton: React.FC<{
type: 'primary' | 'default' | 'dashed' | 'danger' | 'link';
onClick: () => void;
children: React.ReactNode;
loading?: boolean;
disabled?: boolean;
}> = ({ type, onClick, children, loading = false, disabled = false }) => {
return (
<Button
type={type}
onClick={onClick}
loading={loading}
disabled={disabled}
style={{
borderRadius: 4,
fontWeight: '500',
}}
>
{children}
</Button>
);
};
// 业务卡片组件
export const BusinessCard: React.FC<{
title: string;
children: React.ReactNode;
extra?: React.ReactNode;
style?: React.CSSProperties;
}> = ({ title, children, extra, style }) => {
return (
<Card
title={title}
extra={extra}
style={{
borderRadius: 8,
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.09)',
marginBottom: 16,
...style,
}}
>
{children}
</Card>
);
};
// 业务表格组件
export const BusinessTable: React.FC<{
columns: any[];
dataSource: any[];
rowKey: string;
pagination?: boolean | any;
rowSelection?: any;
}> = ({ columns, dataSource, rowKey, pagination = true, rowSelection }) => {
return (
<Table
columns={columns}
dataSource={dataSource}
rowKey={rowKey}
pagination={pagination}
rowSelection={rowSelection}
style={{
borderRadius: 8,
overflow: 'hidden',
}}
size="middle"
/>
);
};
// 业务输入框组件
export const BusinessInput: React.FC<{
placeholder: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
style?: React.CSSProperties;
prefix?: React.ReactNode;
suffix?: React.ReactNode;
}> = ({ placeholder, value, onChange, style, prefix, suffix }) => {
return (
<Input
placeholder={placeholder}
value={value}
onChange={onChange}
style={{
borderRadius: 4,
...style,
}}
prefix={prefix}
suffix={suffix}
/>
);
};
// 业务选择器组件
export const BusinessSelect: React.FC<{
placeholder: string;
value: string;
onChange: (value: string) => void;
options: { label: string; value: string }[];
style?: React.CSSProperties;
}> = ({ placeholder, value, onChange, options, style }) => {
return (
<Select
placeholder={placeholder}
value={value}
onChange={onChange}
style={{
borderRadius: 4,
...style,
}}
>
{options.map((option) => (
<Select.Option key={option.value} value={option.value}>
{option.label}
</Select.Option>
))}
</Select>
);
};
// 业务日期选择器组件
export const BusinessDatePicker: React.FC<{
placeholder: string;
value: any;
onChange: (dates: any, dateStrings: any) => void;
style?: React.CSSProperties;
range?: boolean;
}> = ({ placeholder, value, onChange, style, range = false }) => {
const { RangePicker, DatePicker: AntDatePicker } = DatePicker;
return range ? (
<RangePicker
placeholder={[placeholder, placeholder]}
value={value}
onChange={onChange}
style={{
borderRadius: 4,
...style,
}}
/>
) : (
<AntDatePicker
placeholder={placeholder}
value={value}
onChange={onChange}
style={{
borderRadius: 4,
...style,
}}
/>
);
};
// 业务模态框组件
export const BusinessModal: React.FC<{
title: string;
open: boolean;
onCancel: () => void;
onOk: () => void;
children: React.ReactNode;
width?: number;
footer?: React.ReactNode;
}> = ({ title, open, onCancel, onOk, children, width = 600, footer }) => {
return (
<Modal
title={title}
open={open}
onCancel={onCancel}
onOk={onOk}
width={width}
footer={footer}
style={{
borderRadius: 8,
}}
>
{children}
</Modal>
);
};
// 业务表单组件
export const BusinessForm: React.FC<{
form: any;
onFinish: (values: any) => void;
children: React.ReactNode;
layout?: 'horizontal' | 'vertical' | 'inline';
}> = ({ form, onFinish, children, layout = 'vertical' }) => {
return (
<Form
form={form}
onFinish={onFinish}
layout={layout}
style={{
width: '100%',
}}
>
{children}
</Form>
);
};
// 业务加载组件
export const BusinessLoading: React.FC<{
loading: boolean;
children: React.ReactNode;
tip?: string;
}> = ({ loading, children, tip = 'Loading...' }) => {
return (
<Spin spinning={loading} tip={tip}>
{children}
</Spin>
);
};
// 业务提示组件
export const BusinessAlert: React.FC<{
type: 'success' | 'info' | 'warning' | 'error';
message: string;
description?: string;
closable?: boolean;
}> = ({ type, message, description, closable = true }) => {
return (
<Alert
type={type}
message={message}
description={description}
closable={closable}
style={{
marginBottom: 16,
}}
/>
);
};
// 业务标签组件
export const BusinessTag: React.FC<{
color: string;
children: React.ReactNode;
}> = ({ color, children }) => {
return (
<Tag color={color} style={{ borderRadius: 4 }}>
{children}
</Tag>
);
};
// 业务徽章组件
export const BusinessBadge: React.FC<{
status: 'success' | 'processing' | 'default' | 'error' | 'warning';
text: string;
}> = ({ status, text }) => {
return (
<Badge status={status} text={text} />
);
};
// 业务消息组件
export const BusinessMessage: {
success: (content: string) => void;
error: (content: string) => void;
warning: (content: string) => void;
info: (content: string) => void;
} = {
success: (content) => message.success(content),
error: (content) => message.error(content),
warning: (content) => message.warning(content),
info: (content) => message.info(content),
};
// 业务间距组件
export const BusinessSpace: React.FC<{
children: React.ReactNode;
size?: 'small' | 'middle' | 'large';
direction?: 'horizontal' | 'vertical';
}> = ({ children, size = 'middle', direction = 'horizontal' }) => {
return (
<Space size={size} direction={direction}>
{children}
</Space>
);
};
export default {
BusinessButton,
BusinessCard,
BusinessTable,
BusinessInput,
BusinessSelect,
BusinessDatePicker,
BusinessModal,
BusinessForm,
BusinessLoading,
BusinessAlert,
BusinessTag,
BusinessBadge,
BusinessMessage,
BusinessSpace,
};

View File

@@ -0,0 +1,26 @@
import React from 'react';
import { Layout as AntLayout } from 'antd';
import MenuComponent from './MenuComponent';
import { Outlet } from 'react-router-dom';
const { Sider, Content } = AntLayout;
const Layout: React.FC = () => {
return (
<AntLayout style={{ minHeight: '100vh' }}>
<Sider width={200} style={{ background: '#fff' }}>
<div className="logo" style={{ padding: '16px', textAlign: 'center', fontWeight: 'bold', fontSize: '18px' }}>
Crawlful Hub
</div>
<MenuComponent />
</Sider>
<AntLayout>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
<Outlet />
</Content>
</AntLayout>
</AntLayout>
);
};
export default Layout;

View File

@@ -0,0 +1,89 @@
import React from 'react';
import { Menu } from 'antd';
import {
DashboardOutlined,
ShoppingOutlined,
OrderedListOutlined,
TabletOutlined,
InboxOutlined,
TeamOutlined,
DollarOutlined,
SafetyCertificateOutlined,
SettingOutlined,
HomeOutlined
} from '@ant-design/icons';
import { Link, useLocation } from 'react-router-dom';
const MenuComponent: React.FC = () => {
const location = useLocation();
const currentPath = location.pathname;
const menuItems = [
{
key: '/dashboard',
icon: <DashboardOutlined />,
label: <Link to="/dashboard">Dashboard</Link>,
},
{
key: '/product',
icon: <ShoppingOutlined />,
label: <Link to="/product">Product</Link>,
},
{
key: '/orders',
icon: <OrderedListOutlined />,
label: <Link to="/orders">Orders</Link>,
},
{
key: '/ad',
icon: <TabletOutlined />,
label: <Link to="/ad">Ad</Link>,
},
{
key: '/inventory',
icon: <InboxOutlined />,
label: <Link to="/inventory">Inventory</Link>,
},
{
key: '/b2b',
icon: <TeamOutlined />,
label: <Link to="/b2b">B2B</Link>,
},
{
key: '/finance',
icon: <DollarOutlined />,
label: <Link to="/finance">Finance</Link>,
},
{
key: '/compliance',
icon: <SafetyCertificateOutlined />,
label: <Link to="/compliance">Compliance</Link>,
},
{
key: '/settings',
icon: <SettingOutlined />,
label: <Link to="/settings">Settings</Link>,
},
{
key: '/independent-site',
icon: <HomeOutlined />,
label: <Link to="/independent-site">Independent Site</Link>,
},
];
return (
<div className="menu-container">
<Menu
mode="inline"
selectedKeys={[currentPath]}
style={{
height: '100%',
borderRight: 0,
}}
items={menuItems}
/>
</div>
);
};
export default MenuComponent;