Files
makemd/dashboard/src/pages/Marketing/Ads.tsx

226 lines
5.6 KiB
TypeScript
Raw Normal View History

import React, { useState, useEffect } from 'react';
import { Table, Button, Input, Select, DatePicker, message, Card, Tabs } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined, PlayCircleOutlined, PauseCircleOutlined } from '@ant-design/icons';
import { marketingDataSource, Ad } from '@/services/marketingDataSource';
const { Option } = Select;
const { RangePicker } = DatePicker;
const { Search } = Input;
const { TabPane } = Tabs;
const Ads: React.FC = () => {
const [ads, setAds] = useState<Ad[]>([]);
const [loading, setLoading] = useState(false);
const [filters, setFilters] = useState({
platform: '',
status: '',
search: '',
dateRange: null as [Date, Date] | null,
});
useEffect(() => {
fetchAds();
}, [filters]);
const fetchAds = async () => {
setLoading(true);
try {
const data = await marketingDataSource.fetchAds(filters);
setAds(data);
} catch (error) {
message.error('Failed to load ads');
} finally {
setLoading(false);
}
};
const handleAddAd = () => {
message.info('创建广告功能开发中');
};
const handleStartAd = (id: string) => {
message.success('广告已启动');
fetchAds();
};
const handlePauseAd = (id: string) => {
message.success('广告已暂停');
fetchAds();
};
const handleEditAd = (id: string) => {
message.info('编辑广告功能开发中');
};
const handleDeleteAd = (id: string) => {
message.success('广告已删除');
fetchAds();
};
const columns = [
{
title: '广告名称',
dataIndex: 'name',
key: 'name',
},
{
title: '平台',
dataIndex: 'platform',
key: 'platform',
},
{
title: '活动',
dataIndex: 'campaign',
key: 'campaign',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const statusMap = {
active: '活跃',
paused: '暂停',
completed: '已完成',
};
return statusMap[status] || status;
},
},
{
title: '预算',
dataIndex: 'budget',
key: 'budget',
render: (budget: number) => `$${budget.toFixed(2)}`,
},
{
title: '支出',
dataIndex: 'spend',
key: 'spend',
render: (spend: number) => `$${spend.toFixed(2)}`,
},
{
title: '点击量',
dataIndex: 'clicks',
key: 'clicks',
},
{
title: '转化数',
dataIndex: 'conversions',
key: 'conversions',
},
{
title: 'ROI',
dataIndex: 'roi',
key: 'roi',
render: (roi: number) => `${roi.toFixed(2)}x`,
},
{
title: '操作',
key: 'action',
render: (_: unknown, record: Ad) => (
<div>
{record.status === 'active' ? (
<Button
type="link"
icon={<PauseCircleOutlined />}
onClick={() => handlePauseAd(record.id)}
>
</Button>
) : (
<Button
type="link"
icon={<PlayCircleOutlined />}
onClick={() => handleStartAd(record.id)}
>
</Button>
)}
<Button
type="link"
icon={<EditOutlined />}
onClick={() => handleEditAd(record.id)}
>
</Button>
<Button
type="link"
danger
icon={<DeleteOutlined />}
onClick={() => handleDeleteAd(record.id)}
>
</Button>
</div>
),
},
];
return (
<div className="ads">
<div className="page-header">
<h1>广</h1>
<Button
type="primary"
icon={<PlusOutlined />}
>
广
</Button>
</div>
<div className="filter-section" style={{ marginBottom: 24, display: 'flex', gap: 16, flexWrap: 'wrap' }}>
<Search
placeholder="搜索广告名称或活动"
style={{ width: 300 }}
onChange={(e) => setFilters({ ...filters, search: e.target.value })}
/>
<Select
placeholder="平台"
style={{ width: 120 }}
onChange={(value) => setFilters({ ...filters, platform: value })}
>
<Option value=""></Option>
<Option value="Facebook">Facebook</Option>
<Option value="Google">Google</Option>
<Option value="Instagram">Instagram</Option>
<Option value="TikTok">TikTok</Option>
</Select>
<Select
placeholder="状态"
style={{ width: 120 }}
onChange={(value) => setFilters({ ...filters, status: value })}
>
<Option value=""></Option>
<Option value="active"></Option>
<Option value="paused"></Option>
<Option value="completed"></Option>
</Select>
<RangePicker
style={{ width: 300 }}
onChange={(dates) => setFilters({ ...filters, dateRange: dates })}
/>
<Button
icon={<SearchOutlined />}
onClick={fetchAds}
>
</Button>
</div>
<Card title="广告列表">
<Table
columns={columns}
dataSource={ads}
loading={loading}
rowKey="id"
pagination={{
pageSize: 10,
showSizeChanger: true,
}}
/>
</Card>
</div>
);
};
export default Ads;