257 lines
7.6 KiB
TypeScript
257 lines
7.6 KiB
TypeScript
import React, { useEffect, useState, useMemo, useRef } from "react"
|
|
|
|
import {
|
|
ActionType,
|
|
PageContainer, ProColumns, ProTable,
|
|
} from '@ant-design/pro-components';
|
|
import { statisticscontrollerGetordersorce, statisticscontrollerGetinativeusersbymonth } from "@/servers/api/statistics";
|
|
import ReactECharts from 'echarts-for-react';
|
|
import { App, Button, Space, Tag } from 'antd';
|
|
import { HistoryOrder } from "../Order";
|
|
import dayjs from 'dayjs';
|
|
const ListPage: React.FC = () => {
|
|
|
|
const [data, setData] = useState({});
|
|
|
|
useEffect(() => {
|
|
statisticscontrollerGetordersorce().then(({ data, success }) => {
|
|
if(success) setData(data)
|
|
});
|
|
}, []);
|
|
|
|
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,
|
|
},
|
|
emphasis: {
|
|
focus: 'series'
|
|
},
|
|
xAxisIndex: 0,
|
|
yAxisIndex: 0,
|
|
},
|
|
{
|
|
name: '老客户',
|
|
type: 'bar',
|
|
data: data?.inactiveRes?.map(v=> v.old_user_count)?.sort(_=>-1),
|
|
label: {
|
|
show: true,
|
|
},
|
|
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)
|
|
},
|
|
color: '#fff'
|
|
},
|
|
"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>
|
|
<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>
|
|
)
|
|
}
|
|
|
|
export default ListPage; |