forked from yoone/WEB
1
0
Fork 0
WEB/src/pages/Statistics/OrderSource/index.tsx

358 lines
8.9 KiB
TypeScript

import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
statisticscontrollerGetinativeusersbymonth,
statisticscontrollerGetordersource,
} from '@/servers/api/statistics';
import {
ActionType,
PageContainer,
ProColumns,
ProForm,
ProFormSelect,
ProTable,
} from '@ant-design/pro-components';
import { Space, Tag } from 'antd';
import dayjs from 'dayjs';
import ReactECharts from 'echarts-for-react';
import * as countries from 'i18n-iso-countries';
import zhCN from 'i18n-iso-countries/langs/zh';
import { HistoryOrder } from '../Order';
countries.registerLocale(zhCN);
const ListPage: React.FC = () => {
const [data, setData] = useState({});
const initialValues = {
country: ['CA'],
};
function handleSubmit(values: typeof initialValues) {
statisticscontrollerGetordersource({ params: values }).then(
({ data, success }) => {
if (success) setData(data);
},
);
}
useEffect(() => {
handleSubmit(initialValues);
}, []);
const option = useMemo(() => {
if (!data.inactiveRes) return {};
const xAxisData = data?.inactiveRes
?.map((v) => v.order_month)
?.sort((_) => -1);
const arr = data?.res?.map((v) => v.first_order_month_group);
const uniqueArr = arr
.filter((item, index) => arr.indexOf(item) === index)
.sort((a, b) => a.localeCompare(b));
const series = [
{
name: '新客户',
type: 'bar',
data: data?.inactiveRes?.map((v) => v.new_user_count)?.sort((_) => -1),
label: {
show: true,
formatter: function (params) {
if (!params.value) return '';
return (
Math.abs(params.value) +
'\n' +
Math.abs(
data?.inactiveRes?.find(
(item) => item.order_month === params.name,
)?.new_user_total || 0,
)
);
},
color: '#000000',
},
emphasis: {
focus: 'series',
},
xAxisIndex: 0,
yAxisIndex: 0,
},
{
name: '老客户',
type: 'bar',
data: data?.inactiveRes?.map((v) => v.old_user_count)?.sort((_) => -1),
label: {
show: true,
formatter: function (params) {
if (!params.value) return '';
return (
Math.abs(params.value) +
'\n' +
Math.abs(
data?.inactiveRes?.find(
(item) => item.order_month === params.name,
)?.old_user_total || 0,
)
);
},
color: '#000000',
},
emphasis: {
focus: 'series',
},
xAxisIndex: 0,
yAxisIndex: 0,
},
...uniqueArr?.map((v) => {
data?.res?.filter((item) => item.order_month === v);
return {
name: v,
type: 'bar',
stack: 'total',
label: {
show: true,
formatter: function (params) {
if (!params.value) return '';
return (
Math.abs(params.value) +
'\n' +
+Math.abs(
data?.res?.find(
(item) =>
item.order_month === params.name &&
item.first_order_month_group === v,
)?.total || 0,
)
);
},
color: '#000000',
},
data: xAxisData.map((month) => {
return (
data?.res?.find(
(item) =>
item.order_month === month &&
item.first_order_month_group === v,
)?.order_count || 0
);
}),
xAxisIndex: 0,
yAxisIndex: 0,
};
}),
{
name: '未复购客户',
type: 'bar',
data: data?.inactiveRes
?.map((v) => -v.inactive_user_count)
?.sort((_) => -1),
stack: 'total',
label: {
show: true,
},
emphasis: {
focus: 'series',
},
xAxisIndex: 1,
yAxisIndex: 1,
barWidth: '60%',
itemStyle: {
color: '#f44336',
},
},
];
return {
grid: [
{ top: '10%', height: '70%' },
{ bottom: '10%', height: '10%' },
],
legend: {
selectedMode: false,
},
xAxis: [
{
type: 'category',
data: xAxisData,
gridIndex: 0,
},
{
type: 'category',
data: xAxisData,
gridIndex: 1,
},
],
yAxis: [
{
type: 'value',
gridIndex: 0,
},
{
type: 'value',
gridIndex: 1,
},
],
series,
};
}, [data]);
const [tableData, setTableData] = useState<any[]>([]);
const actionRef = useRef<ActionType>();
const columns: ProColumns[] = [
{
title: '用户名',
dataIndex: 'username',
hideInSearch: true,
render: (_, record) => {
if (record.billing.first_name || record.billing.last_name)
return record.billing.first_name + ' ' + record.billing.last_name;
return record.shipping.first_name + ' ' + record.shipping.last_name;
},
},
{
title: '邮箱',
dataIndex: 'email',
},
{
title: '首单时间',
dataIndex: 'first_purchase_date',
valueType: 'dateMonth',
sorter: true,
render: (_, record) =>
record.first_purchase_date
? dayjs(record.first_purchase_date).format('YYYY-MM-DD HH:mm:ss')
: '-',
},
{
title: '尾单时间',
hideInSearch: true,
dataIndex: 'last_purchase_date',
valueType: 'dateTime',
sorter: true,
},
{
title: '订单数',
dataIndex: 'orders',
hideInSearch: true,
sorter: true,
},
{
title: '金额',
dataIndex: 'total',
hideInSearch: true,
sorter: true,
},
{
title: 'state',
dataIndex: 'state',
render: (_, record) => record?.billing.state || record?.shipping.state,
},
{
title: 'city',
dataIndex: 'city',
hideInSearch: true,
render: (_, record) => record?.billing.city || record?.shipping.city,
},
{
title: '标签',
dataIndex: 'tags',
render: (_, record) => {
return (
<Space>
{(record.tags || []).map((tag) => {
return (
<Tag
key={tag}
closable
onClose={async () => {
const { success, message: msg } =
await customercontrollerDeltag({
email: record.email,
tag,
});
return false;
}}
>
{tag}
</Tag>
);
})}
</Space>
);
},
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => {
return (
<HistoryOrder
email={record.email}
tags={record.tags}
tableRef={actionRef}
/>
);
},
},
];
return (
<PageContainer ghost>
<ProForm
initialValues={initialValues}
layout="inline"
onFinish={handleSubmit}
>
<ProFormSelect
name="country"
label="区域"
mode="multiple"
placeholder="请选择区域"
showSearch
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={getCountryOptions()}
/>
</ProForm>
<ReactECharts
option={option}
style={{ height: 1050 }}
onEvents={{
click: async (params) => {
if (params.componentType === 'series') {
setTableData([]);
const { success, data } =
await statisticscontrollerGetinativeusersbymonth({
month: params.name,
});
if (success) setTableData(data);
}
},
}}
/>
{tableData?.length ? (
<ProTable
search={false}
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
dataSource={tableData}
columns={columns}
/>
) : (
<></>
)}
</PageContainer>
);
};
// 获取所有国家/地区的选项
const getCountryOptions = () => {
// 获取所有国家的 ISO 代码
const countryCodes = countries.getAlpha2Codes();
// 将国家代码转换为选项数组
return Object.keys(countryCodes).map((code) => ({
label: countries.getName(code, 'zh') || code, // 使用中文名称, 如果没有则使用代码
value: code,
}));
};
export default ListPage;