refactor: 优化代码结构并修复类型问题
- 移除未使用的TabPane组件 - 修复类型定义和导入方式 - 优化mock数据源的环境变量判断逻辑 - 更新文档结构并归档旧文件 - 添加新的UI组件和Memo组件 - 调整API路径和响应处理
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, DatePicker, Select, Spin, Statistic, Row, Col, Tabs, Button } from 'antd';
|
||||
import { Area, AreaChart, Bar, BarChart, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, CartesianGrid, Legend } from 'recharts';
|
||||
import { Card, DatePicker, Select, Spin, Statistic, Row, Col, Tabs, Button, Table, Tag, Space, Typography } from 'antd';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { independentSiteDataSource, SiteAnalytics } from '@/services/independentSiteDataSource';
|
||||
import { Line, Column, Pie, Area, DualAxes } from '@ant-design/plots';
|
||||
import { ReloadOutlined, ExportOutlined, DollarOutlined, ShoppingCartOutlined, TeamOutlined, RiseOutlined } from '@ant-design/icons';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const { Option } = Select;
|
||||
const { TabPane } = Tabs;
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
interface SalesData {
|
||||
date: string;
|
||||
@@ -28,26 +28,67 @@ interface TrafficData {
|
||||
bounceRate: number;
|
||||
}
|
||||
|
||||
interface ConversionData {
|
||||
name: string;
|
||||
value: number;
|
||||
}
|
||||
const SALES_TREND_DATA: SalesData[] = [
|
||||
{ date: '2026-03-01', sales: 5200, orders: 42, customers: 35 },
|
||||
{ date: '2026-03-02', sales: 6100, orders: 51, customers: 42 },
|
||||
{ date: '2026-03-03', sales: 4800, orders: 38, customers: 31 },
|
||||
{ date: '2026-03-04', sales: 7500, orders: 62, customers: 48 },
|
||||
{ date: '2026-03-05', sales: 6800, orders: 55, customers: 45 },
|
||||
{ date: '2026-03-06', sales: 8200, orders: 68, customers: 52 },
|
||||
{ date: '2026-03-07', sales: 9100, orders: 75, customers: 58 },
|
||||
{ date: '2026-03-08', sales: 7800, orders: 64, customers: 49 },
|
||||
{ date: '2026-03-09', sales: 8500, orders: 70, customers: 55 },
|
||||
{ date: '2026-03-10', sales: 9800, orders: 82, customers: 65 },
|
||||
];
|
||||
|
||||
const PRODUCT_DATA: ProductData[] = [
|
||||
{ name: '无线蓝牙耳机', sales: 15800, quantity: 158 },
|
||||
{ name: '智能手表', sales: 12500, quantity: 50 },
|
||||
{ name: '便携充电宝', sales: 8900, quantity: 178 },
|
||||
{ name: '手机支架', sales: 6200, quantity: 310 },
|
||||
{ name: '数据线套装', sales: 4500, quantity: 450 },
|
||||
];
|
||||
|
||||
const TRAFFIC_DATA: TrafficData[] = [
|
||||
{ date: '2026-03-01', visitors: 1250, pageViews: 3800, bounceRate: 35 },
|
||||
{ date: '2026-03-02', visitors: 1480, pageViews: 4200, bounceRate: 32 },
|
||||
{ date: '2026-03-03', visitors: 1100, pageViews: 3200, bounceRate: 38 },
|
||||
{ date: '2026-03-04', visitors: 1800, pageViews: 5500, bounceRate: 28 },
|
||||
{ date: '2026-03-05', visitors: 1650, pageViews: 4800, bounceRate: 30 },
|
||||
{ date: '2026-03-06', visitors: 2100, pageViews: 6200, bounceRate: 25 },
|
||||
{ date: '2026-03-07', visitors: 2350, pageViews: 7100, bounceRate: 22 },
|
||||
{ date: '2026-03-08', visitors: 1900, pageViews: 5600, bounceRate: 27 },
|
||||
{ date: '2026-03-09', visitors: 2200, pageViews: 6500, bounceRate: 24 },
|
||||
{ date: '2026-03-10', visitors: 2500, pageViews: 7500, bounceRate: 20 },
|
||||
];
|
||||
|
||||
const CONVERSION_DATA = [
|
||||
{ type: '直接购买', value: 35 },
|
||||
{ type: '加购后购买', value: 28 },
|
||||
{ type: '收藏后购买', value: 15 },
|
||||
{ type: '未转化', value: 22 },
|
||||
];
|
||||
|
||||
const REGION_DATA = [
|
||||
{ region: '美国', customers: 450, percentage: 35 },
|
||||
{ region: '欧洲', customers: 320, percentage: 25 },
|
||||
{ region: '东南亚', customers: 280, percentage: 22 },
|
||||
{ region: '中东', customers: 150, percentage: 12 },
|
||||
{ region: '其他', customers: 80, percentage: 6 },
|
||||
];
|
||||
|
||||
const DEVICE_DATA = [
|
||||
{ device: '移动端', value: 65, color: '#1890ff' },
|
||||
{ device: '桌面端', value: 30, color: '#52c41a' },
|
||||
{ device: '平板', value: 5, color: '#faad14' },
|
||||
];
|
||||
|
||||
const IndependentSiteAnalytics: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [dateRange, setDateRange] = useState<any>(null);
|
||||
const [timeRange, setTimeRange] = useState('30d');
|
||||
const [salesData, setSalesData] = useState<SalesData[]>([]);
|
||||
const [productData, setProductData] = useState<ProductData[]>([]);
|
||||
const [trafficData, setTrafficData] = useState<TrafficData[]>([]);
|
||||
const [conversionData, setConversionData] = useState<ConversionData[]>([]);
|
||||
const [summary, setSummary] = useState({
|
||||
totalSales: 0,
|
||||
totalOrders: 0,
|
||||
totalCustomers: 0,
|
||||
conversionRate: 0,
|
||||
});
|
||||
const [activeTab, setActiveTab] = useState('sales');
|
||||
|
||||
useEffect(() => {
|
||||
fetchAnalyticsData();
|
||||
@@ -55,85 +96,218 @@ const IndependentSiteAnalytics: React.FC = () => {
|
||||
|
||||
const fetchAnalyticsData = async () => {
|
||||
setLoading(true);
|
||||
// 模拟API调用
|
||||
setTimeout(() => {
|
||||
// 模拟销售数据
|
||||
const mockSalesData: SalesData[] = Array.from({ length: 30 }, (_, i) => ({
|
||||
date: `2026-03-${String(i + 1).padStart(2, '0')}`,
|
||||
sales: Math.random() * 1000 + 500,
|
||||
orders: Math.random() * 50 + 10,
|
||||
customers: Math.random() * 30 + 5,
|
||||
}));
|
||||
|
||||
// 模拟商品数据
|
||||
const mockProductData: ProductData[] = [
|
||||
{ name: 'Product 1', sales: 1500, quantity: 15 },
|
||||
{ name: 'Product 2', sales: 2000, quantity: 20 },
|
||||
{ name: 'Product 3', sales: 1000, quantity: 10 },
|
||||
{ name: 'Product 4', sales: 500, quantity: 5 },
|
||||
{ name: 'Product 5', sales: 800, quantity: 8 },
|
||||
];
|
||||
|
||||
// 模拟流量数据
|
||||
const mockTrafficData: TrafficData[] = Array.from({ length: 30 }, (_, i) => ({
|
||||
date: `2026-03-${String(i + 1).padStart(2, '0')}`,
|
||||
visitors: Math.random() * 500 + 100,
|
||||
pageViews: Math.random() * 1000 + 500,
|
||||
bounceRate: Math.random() * 50 + 20,
|
||||
}));
|
||||
|
||||
// 模拟转化数据
|
||||
const mockConversionData: ConversionData[] = [
|
||||
{ name: '已转化', value: 20 },
|
||||
{ name: '未转化', value: 80 },
|
||||
];
|
||||
|
||||
// 模拟汇总数据
|
||||
const mockSummary = {
|
||||
totalSales: 5800,
|
||||
totalOrders: 78,
|
||||
totalCustomers: 55,
|
||||
conversionRate: 20,
|
||||
};
|
||||
|
||||
setSalesData(mockSalesData);
|
||||
setProductData(mockProductData);
|
||||
setTrafficData(mockTrafficData);
|
||||
setConversionData(mockConversionData);
|
||||
setSummary(mockSummary);
|
||||
setLoading(false);
|
||||
}, 1000);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
const handleTimeRangeChange = (value: string) => {
|
||||
setTimeRange(value);
|
||||
const salesTrendConfig = {
|
||||
data: SALES_TREND_DATA.flatMap(item => [
|
||||
{ date: item.date, value: item.sales, type: '销售额' },
|
||||
{ date: item.date, value: item.orders * 100, type: '订单数' },
|
||||
]),
|
||||
xField: 'date',
|
||||
yField: 'value',
|
||||
seriesField: 'type',
|
||||
smooth: true,
|
||||
legend: { position: 'top' as const },
|
||||
yAxis: { label: { formatter: (v: number) => `$${v / 1000}k` } },
|
||||
};
|
||||
|
||||
const handleDateRangeChange = (dates: any) => {
|
||||
setDateRange(dates);
|
||||
const productSalesConfig = {
|
||||
data: PRODUCT_DATA,
|
||||
xField: 'name',
|
||||
yField: 'sales',
|
||||
color: '#1890ff',
|
||||
label: { text: 'sales', position: 'top' as const },
|
||||
};
|
||||
|
||||
const trafficConfig = {
|
||||
data: [TRAFFIC_DATA, TRAFFIC_DATA],
|
||||
xField: 'date',
|
||||
yField: ['visitors', 'pageViews'],
|
||||
geometryOptions: [
|
||||
{ geometry: 'line', color: '#1890ff', smooth: true },
|
||||
{ geometry: 'line', color: '#52c41a', smooth: true },
|
||||
],
|
||||
legend: { position: 'top' as const },
|
||||
};
|
||||
|
||||
const conversionConfig = {
|
||||
data: CONVERSION_DATA,
|
||||
angleField: 'value',
|
||||
colorField: 'type',
|
||||
radius: 0.8,
|
||||
innerRadius: 0.6,
|
||||
label: { text: 'type', position: 'outside' },
|
||||
legend: { position: 'bottom' as const },
|
||||
};
|
||||
|
||||
const regionConfig = {
|
||||
data: REGION_DATA,
|
||||
xField: 'region',
|
||||
yField: 'customers',
|
||||
color: '#722ed1',
|
||||
label: { text: 'customers', position: 'top' as const },
|
||||
};
|
||||
|
||||
const deviceConfig = {
|
||||
data: DEVICE_DATA,
|
||||
angleField: 'value',
|
||||
colorField: 'device',
|
||||
radius: 0.8,
|
||||
innerRadius: 0.6,
|
||||
label: { text: 'device', position: 'outside' },
|
||||
legend: { position: 'bottom' as const },
|
||||
};
|
||||
|
||||
const productColumns = [
|
||||
{ title: '商品名称', dataIndex: 'name', key: 'name' },
|
||||
{ title: '销售额', dataIndex: 'sales', key: 'sales', render: (v: number) => `$${v.toLocaleString()}` },
|
||||
{ title: '销量', dataIndex: 'quantity', key: 'quantity' },
|
||||
{ title: '占比', key: 'percentage', render: (_: any, record: ProductData) => {
|
||||
const total = PRODUCT_DATA.reduce((sum, p) => sum + p.sales, 0);
|
||||
return `${((record.sales / total) * 100).toFixed(1)}%`;
|
||||
}},
|
||||
];
|
||||
|
||||
const tabItems = [
|
||||
{
|
||||
key: 'sales',
|
||||
label: '销售分析',
|
||||
children: (
|
||||
<Row gutter={16}>
|
||||
<Col span={24}>
|
||||
<Card title="销售趋势">
|
||||
<Line {...salesTrendConfig} height={300} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} lg={16} style={{ marginTop: 16 }}>
|
||||
<Card title="商品销售排行">
|
||||
<Column {...productSalesConfig} height={280} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} lg={8} style={{ marginTop: 16 }}>
|
||||
<Card title="转化漏斗">
|
||||
<Pie {...conversionConfig} height={280} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24} style={{ marginTop: 16 }}>
|
||||
<Card title="商品销售明细">
|
||||
<Table columns={productColumns} dataSource={PRODUCT_DATA} rowKey="name" pagination={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'traffic',
|
||||
label: '流量分析',
|
||||
children: (
|
||||
<Row gutter={16}>
|
||||
<Col span={24}>
|
||||
<Card title="流量趋势">
|
||||
<DualAxes {...trafficConfig} height={300} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} lg={12} style={{ marginTop: 16 }}>
|
||||
<Card title="设备分布">
|
||||
<Pie {...deviceConfig} height={280} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} lg={12} style={{ marginTop: 16 }}>
|
||||
<Card title="流量来源">
|
||||
<Table
|
||||
columns={[
|
||||
{ title: '来源', dataIndex: 'source', key: 'source' },
|
||||
{ title: '访客数', dataIndex: 'visitors', key: 'visitors' },
|
||||
{ title: '占比', dataIndex: 'percentage', key: 'percentage', render: (v: number) => `${v}%` },
|
||||
]}
|
||||
dataSource={[
|
||||
{ key: '1', source: '搜索引擎', visitors: 3500, percentage: 42 },
|
||||
{ key: '2', source: '社交媒体', visitors: 2100, percentage: 25 },
|
||||
{ key: '3', source: '直接访问', visitors: 1500, percentage: 18 },
|
||||
{ key: '4', source: '广告投放', visitors: 800, percentage: 10 },
|
||||
{ key: '5', source: '其他', visitors: 400, percentage: 5 },
|
||||
]}
|
||||
pagination={false}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'customer',
|
||||
label: '客户分析',
|
||||
children: (
|
||||
<Row gutter={16}>
|
||||
<Col xs={24} lg={16}>
|
||||
<Card title="客户地域分布">
|
||||
<Column {...regionConfig} height={300} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={24} lg={8}>
|
||||
<Card title="客户类型">
|
||||
<Pie
|
||||
data={[
|
||||
{ type: '新客户', value: 45 },
|
||||
{ type: '回头客', value: 35 },
|
||||
{ type: 'VIP客户', value: 20 },
|
||||
]}
|
||||
angleField="value"
|
||||
colorField="type"
|
||||
radius={0.8}
|
||||
innerRadius={0.6}
|
||||
label={{ text: 'type', position: 'outside' }}
|
||||
height={280}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24} style={{ marginTop: 16 }}>
|
||||
<Card title="客户购买行为分析">
|
||||
<Row gutter={16}>
|
||||
<Col span={6}>
|
||||
<Statistic title="平均订单金额" value={125} prefix={<DollarOutlined />} suffix="USD" />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Statistic title="复购率" value={35} suffix="%" valueStyle={{ color: '#52c41a' }} prefix={<RiseOutlined />} />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Statistic title="平均购买频次" value={2.3} suffix="次/月" />
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Statistic title="客户满意度" value={4.8} suffix="/ 5.0" valueStyle={{ color: '#faad14' }} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="independent-site-analytics">
|
||||
<div className="page-header">
|
||||
<h1>独立站数据分析</h1>
|
||||
<div style={{ display: 'flex', gap: 16 }}>
|
||||
<Select
|
||||
value={timeRange}
|
||||
onChange={handleTimeRangeChange}
|
||||
style={{ width: 120 }}
|
||||
>
|
||||
<Option value="7d">7天</Option>
|
||||
<Option value="30d">30天</Option>
|
||||
<Option value="90d">90天</Option>
|
||||
<Option value="1y">1年</Option>
|
||||
</Select>
|
||||
<RangePicker onChange={handleDateRangeChange} />
|
||||
<Button type="primary" onClick={fetchAnalyticsData}>
|
||||
刷新数据
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="independent-site-analytics" style={{ padding: 24 }}>
|
||||
<Row justify="space-between" align="middle" style={{ marginBottom: 24 }}>
|
||||
<Col>
|
||||
<Title level={4}>独立站数据分析</Title>
|
||||
<Text type="secondary">站点ID: {id}</Text>
|
||||
</Col>
|
||||
<Col>
|
||||
<Space>
|
||||
<Select value={timeRange} onChange={setTimeRange} style={{ width: 120 }}>
|
||||
<Option value="7d">7天</Option>
|
||||
<Option value="30d">30天</Option>
|
||||
<Option value="90d">90天</Option>
|
||||
<Option value="1y">1年</Option>
|
||||
</Select>
|
||||
<RangePicker onChange={setDateRange} />
|
||||
<Button icon={<ReloadOutlined />} onClick={fetchAnalyticsData}>刷新</Button>
|
||||
<Button type="primary" icon={<ExportOutlined />}>导出</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{loading ? (
|
||||
<div style={{ textAlign: 'center', padding: '50px 0' }}>
|
||||
@@ -142,143 +316,33 @@ const IndependentSiteAnalytics: React.FC = () => {
|
||||
) : (
|
||||
<>
|
||||
<Row gutter={16} style={{ marginBottom: 24 }}>
|
||||
<Col span={6}>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="总销售额"
|
||||
value={summary.totalSales}
|
||||
precision={2}
|
||||
prefix="$"
|
||||
suffix="USD"
|
||||
/>
|
||||
<Statistic title="总销售额" value={73800} precision={2} prefix={<DollarOutlined />} suffix="USD" valueStyle={{ color: '#3f8600' }} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="总订单数"
|
||||
value={summary.totalOrders}
|
||||
/>
|
||||
<Statistic title="总订单数" value={607} prefix={<ShoppingCartOutlined />} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="总客户数"
|
||||
value={summary.totalCustomers}
|
||||
/>
|
||||
<Statistic title="总客户数" value={480} prefix={<TeamOutlined />} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="转化率"
|
||||
value={summary.conversionRate}
|
||||
precision={2}
|
||||
suffix="%"
|
||||
/>
|
||||
<Statistic title="转化率" value={4.2} precision={2} suffix="%" valueStyle={{ color: '#722ed1' }} prefix={<RiseOutlined />} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Tabs defaultActiveKey="sales">
|
||||
<TabPane tab="销售分析" key="sales">
|
||||
<Row gutter={16}>
|
||||
<Col span={24}>
|
||||
<Card title="销售趋势">
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<AreaChart data={salesData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Area type="monotone" dataKey="sales" stackId="1" stroke="#8884d8" fill="#8884d8" />
|
||||
<Area type="monotone" dataKey="orders" stackId="2" stroke="#82ca9d" fill="#82ca9d" />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card title="商品销售排行">
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<BarChart data={productData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="name" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="sales" fill="#8884d8" />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card title="转化率">
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={conversionData}
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
labelLine={false}
|
||||
label={({ name, percent }) => `${name}: ${((percent || 0) * 100).toFixed(0)}%`}
|
||||
outerRadius={150}
|
||||
fill="#8884d8"
|
||||
dataKey="value"
|
||||
/>
|
||||
<Tooltip />
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
|
||||
<TabPane tab="流量分析" key="traffic">
|
||||
<Row gutter={16}>
|
||||
<Col span={24}>
|
||||
<Card title="流量趋势">
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<LineChart data={trafficData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="visitors" stroke="#8884d8" />
|
||||
<Line type="monotone" dataKey="pageViews" stroke="#82ca9d" />
|
||||
<Line type="monotone" dataKey="bounceRate" stroke="#ff7300" />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
|
||||
<TabPane tab="客户分析" key="customer">
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card title="客户地域分布">
|
||||
<div style={{ textAlign: 'center', padding: '50px 0' }}>
|
||||
<p>地域分布图表</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card title="客户购买行为">
|
||||
<div style={{ textAlign: 'center', padding: '50px 0' }}>
|
||||
<p>购买行为图表</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<Tabs activeKey={activeTab} onChange={setActiveTab} items={tabItems} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default IndependentSiteAnalytics;
|
||||
export default IndependentSiteAnalytics;
|
||||
|
||||
Reference in New Issue
Block a user