活动页
parent
26f4721989
commit
2295f9ffbf
@ -0,0 +1,292 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import { PageContainer } from '@ant-design/pro-layout';
|
||||||
|
import type { ActionType, ProColumns, ProFormInstance } from '@ant-design/pro-components';
|
||||||
|
import { ProTable } from '@ant-design/pro-components';
|
||||||
|
import { Button, Card, message } from 'antd';
|
||||||
|
import Constants from '@/constants';
|
||||||
|
import {
|
||||||
|
exportPageByAgentUsingPost,
|
||||||
|
getActivityPageByAgentUsingPost,
|
||||||
|
getSignActivityPageUsingPost,
|
||||||
|
} from '@/services/pop-b2b2c/pbcActivityController';
|
||||||
|
|
||||||
|
type QueryParams = API.PbcActivityActionRecordDTO;
|
||||||
|
|
||||||
|
const actionTypeText: Record<number, string> = {
|
||||||
|
4: '打卡签到',
|
||||||
|
5: '下单活动',
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildParams = (params: Record<string, any>): QueryParams => {
|
||||||
|
const { current, pageSize, orderTimeRange, orderFinishTimeRange, ...rest } = params;
|
||||||
|
const payload: QueryParams = {
|
||||||
|
...rest,
|
||||||
|
current,
|
||||||
|
pageSize,
|
||||||
|
pbcActionType: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Array.isArray(orderTimeRange) && orderTimeRange.length === 2) {
|
||||||
|
payload.pbcActionStartTime = `${orderTimeRange[0]} 00:00:00`;
|
||||||
|
payload.pbcActionEndTime = `${orderTimeRange[1]} 23:59:59`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(orderFinishTimeRange) && orderFinishTimeRange.length === 2) {
|
||||||
|
payload.pbcOrderFinishStartTime = `${orderFinishTimeRange[0]} 00:00:00`;
|
||||||
|
payload.pbcOrderFinishEndTime = `${orderFinishTimeRange[1]} 23:59:59`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LotteryDetail: React.FC = () => {
|
||||||
|
const summaryActionRef = useRef<ActionType>();
|
||||||
|
const detailActionRef = useRef<ActionType>();
|
||||||
|
const summaryFormRef = useRef<ProFormInstance<QueryParams>>();
|
||||||
|
const [selectedAgent, setSelectedAgent] = useState<API.PurchaseAgentStatsVO>();
|
||||||
|
const filtersRef = useRef<QueryParams>({});
|
||||||
|
|
||||||
|
const summaryColumns: ProColumns<API.PurchaseAgentStatsVO>[] = [
|
||||||
|
{
|
||||||
|
title: '#',
|
||||||
|
dataIndex: 'index',
|
||||||
|
valueType: 'indexBorder',
|
||||||
|
width: 60,
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '采购员',
|
||||||
|
dataIndex: 'pbcPurchaseAgentName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '抽奖总次数',
|
||||||
|
dataIndex: 'totalCount',
|
||||||
|
search: false,
|
||||||
|
renderText: (value) => `${value ?? 0}次`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '剩余次数',
|
||||||
|
dataIndex: 'notPrizeCount',
|
||||||
|
search: false,
|
||||||
|
renderText: (value) => `${value ?? 0}次`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
search: false,
|
||||||
|
render: (_, record) => [
|
||||||
|
<a
|
||||||
|
key="view"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedAgent(record);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商家名称',
|
||||||
|
dataIndex: 'pbcBusinessName',
|
||||||
|
hideInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
dataIndex: 'pbcOrderState',
|
||||||
|
valueType: 'select',
|
||||||
|
hideInTable: true,
|
||||||
|
valueEnum: {
|
||||||
|
1: { text: Constants.orderStateEnum['1']?.text || '预订单' },
|
||||||
|
2: { text: Constants.orderStateEnum['2']?.text || '已配货' },
|
||||||
|
3: { text: Constants.orderStateEnum['3']?.text || '已取消' },
|
||||||
|
4: { text: Constants.orderStateEnum['4']?.text || '已完成' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下单时间',
|
||||||
|
dataIndex: 'orderTimeRange',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
hideInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '下单完成时间',
|
||||||
|
dataIndex: 'orderFinishTimeRange',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
hideInTable: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const detailColumns: ProColumns<API.PbcActivityActionRecord_>[] = [
|
||||||
|
{
|
||||||
|
title: '#',
|
||||||
|
dataIndex: 'index',
|
||||||
|
valueType: 'indexBorder',
|
||||||
|
width: 60,
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '采购员',
|
||||||
|
dataIndex: 'pbcPurchaseAgentName',
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '抽奖类型',
|
||||||
|
dataIndex: 'pbcActionType',
|
||||||
|
search: false,
|
||||||
|
renderText: (value) => actionTypeText[value as number] || '其它',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '抽奖次数',
|
||||||
|
dataIndex: 'pbcId',
|
||||||
|
search: false,
|
||||||
|
render: () => '1次',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作时间',
|
||||||
|
dataIndex: 'pbcActionTime',
|
||||||
|
valueType: 'dateTime',
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
search: false,
|
||||||
|
render: () => [
|
||||||
|
<a
|
||||||
|
key="detail"
|
||||||
|
onClick={() => {
|
||||||
|
message.info('查看功能即将上线');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleExport = async () => {
|
||||||
|
const values = summaryFormRef.current?.getFieldsValue() || {};
|
||||||
|
const payload = buildParams({ ...values, current: 1, pageSize: 9999 });
|
||||||
|
const hide = message.loading('正在处理', 0);
|
||||||
|
try {
|
||||||
|
const res = await exportPageByAgentUsingPost(payload);
|
||||||
|
hide();
|
||||||
|
if (res.retcode && typeof res.data === 'string' && res.data) {
|
||||||
|
window.open(res.data);
|
||||||
|
} else {
|
||||||
|
message.error(res.retmsg || '导出失败,请重试');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
hide();
|
||||||
|
message.error('导出失败,请重试');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const summaryRequest = async (params: Record<string, any>) => {
|
||||||
|
const payload = buildParams(params);
|
||||||
|
filtersRef.current = { ...payload, current: undefined, pageSize: undefined };
|
||||||
|
const res = await getActivityPageByAgentUsingPost(payload);
|
||||||
|
const records = res.data?.records || [];
|
||||||
|
if (records.length) {
|
||||||
|
setSelectedAgent((prev) => {
|
||||||
|
if (!prev) {
|
||||||
|
return records[0];
|
||||||
|
}
|
||||||
|
const exists = records.find(
|
||||||
|
(item) => item.pbcPurchaseAgentId === prev.pbcPurchaseAgentId,
|
||||||
|
);
|
||||||
|
return exists ? prev : records[0];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setSelectedAgent(undefined);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
data: records,
|
||||||
|
total: res.data?.total || 0,
|
||||||
|
success: Boolean(res.retcode),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const detailRequest = async (params: Record<string, any>) => {
|
||||||
|
if (!selectedAgent) {
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
total: 0,
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const payload: QueryParams = {
|
||||||
|
...filtersRef.current,
|
||||||
|
...params,
|
||||||
|
pbcPurchaseAgentId: selectedAgent.pbcPurchaseAgentId,
|
||||||
|
pbcPurchaseAgentName: selectedAgent.pbcPurchaseAgentName,
|
||||||
|
};
|
||||||
|
const res = await getSignActivityPageUsingPost(payload);
|
||||||
|
return {
|
||||||
|
data: res.data?.records || [],
|
||||||
|
total: res.data?.total || 0,
|
||||||
|
success: Boolean(res.retcode),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
detailActionRef.current?.reload();
|
||||||
|
}, [selectedAgent]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer header={{ title: '' }}>
|
||||||
|
<Card bordered={false}>
|
||||||
|
<ProTable<API.PurchaseAgentStatsVO>
|
||||||
|
actionRef={summaryActionRef}
|
||||||
|
formRef={summaryFormRef}
|
||||||
|
columns={summaryColumns}
|
||||||
|
rowKey="pbcPurchaseAgentId"
|
||||||
|
request={summaryRequest}
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
search={{
|
||||||
|
labelWidth: 'auto',
|
||||||
|
span: 6,
|
||||||
|
}}
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize: 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
}}
|
||||||
|
dateFormatter="string"
|
||||||
|
scroll={{
|
||||||
|
y: 'calc(50vh - 200px)',
|
||||||
|
}}
|
||||||
|
options={false}
|
||||||
|
toolBarRender={() => [
|
||||||
|
<Button key="export" type="primary" onClick={handleExport}>
|
||||||
|
导出
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card bordered={false} style={{ marginTop: 24 }} title="抽奖明细">
|
||||||
|
<ProTable<API.PbcActivityActionRecord_>
|
||||||
|
actionRef={detailActionRef}
|
||||||
|
columns={detailColumns}
|
||||||
|
rowKey="pbcId"
|
||||||
|
request={detailRequest}
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
search={false}
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize: 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
}}
|
||||||
|
dateFormatter="string"
|
||||||
|
options={false}
|
||||||
|
scroll={{
|
||||||
|
y: 'calc(50vh - 200px)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LotteryDetail;
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { PageContainer } from '@ant-design/pro-layout';
|
||||||
|
import type { ActionType, ProColumns, ProFormInstance } from '@ant-design/pro-components';
|
||||||
|
import { ProTable } from '@ant-design/pro-components';
|
||||||
|
import { Button, message } from 'antd';
|
||||||
|
import {
|
||||||
|
exportPageByAgentUsingPost,
|
||||||
|
getSignActivityPageUsingPost,
|
||||||
|
} from '@/services/pop-b2b2c/pbcActivityController';
|
||||||
|
|
||||||
|
type QueryParams = API.PbcActivityActionRecordDTO;
|
||||||
|
|
||||||
|
const formatParams = (params: Record<string, any>): QueryParams => {
|
||||||
|
const { current, pageSize, pbcActionTimeRange, ...rest } = params;
|
||||||
|
let start: string | undefined;
|
||||||
|
let end: string | undefined;
|
||||||
|
|
||||||
|
if (Array.isArray(pbcActionTimeRange) && pbcActionTimeRange.length === 2) {
|
||||||
|
start = `${pbcActionTimeRange[0]} 00:00:00`;
|
||||||
|
end = `${pbcActionTimeRange[1]} 23:59:59`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
current,
|
||||||
|
pageSize,
|
||||||
|
pbcActionStartTime: start,
|
||||||
|
pbcActionEndTime: end,
|
||||||
|
pbcActionType: 4,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const SignInActivity: React.FC = () => {
|
||||||
|
const actionRef = useRef<ActionType>();
|
||||||
|
const formRef = useRef<ProFormInstance<QueryParams>>();
|
||||||
|
|
||||||
|
const columns: ProColumns<API.PbcActivityActionRecord_>[] = [
|
||||||
|
{
|
||||||
|
title: '#',
|
||||||
|
dataIndex: 'index',
|
||||||
|
valueType: 'indexBorder',
|
||||||
|
width: 60,
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '抽奖编码',
|
||||||
|
dataIndex: 'pbcOrderNo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '采购员',
|
||||||
|
dataIndex: 'pbcPurchaseAgentName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商家名称',
|
||||||
|
dataIndex: 'pbcBusinessName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打卡时间',
|
||||||
|
dataIndex: 'pbcActionTime',
|
||||||
|
valueType: 'dateTime',
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '打卡时间',
|
||||||
|
dataIndex: 'pbcActionTimeRange',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
hideInTable: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const request = async (params: Record<string, any>) => {
|
||||||
|
const payload = formatParams(params);
|
||||||
|
const res = await getSignActivityPageUsingPost(payload);
|
||||||
|
return {
|
||||||
|
data: res.data?.records || [],
|
||||||
|
total: res.data?.total || 0,
|
||||||
|
success: Boolean(res.retcode),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExport = async () => {
|
||||||
|
const values = formRef.current?.getFieldsValue() || {};
|
||||||
|
const payload = formatParams({ ...values, current: 1, pageSize: 9999 });
|
||||||
|
const hide = message.loading('正在处理', 0);
|
||||||
|
try {
|
||||||
|
const res = await exportPageByAgentUsingPost(payload);
|
||||||
|
hide();
|
||||||
|
if (res.retcode && typeof res.data === 'string' && res.data) {
|
||||||
|
window.open(res.data);
|
||||||
|
} else {
|
||||||
|
message.error(res.retmsg || '导出失败,请重试');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
hide();
|
||||||
|
message.error('导出失败,请重试');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer header={{ title: '' }}>
|
||||||
|
<ProTable<API.PbcActivityActionRecord_>
|
||||||
|
actionRef={actionRef}
|
||||||
|
formRef={formRef}
|
||||||
|
columns={columns}
|
||||||
|
rowKey="pbcId"
|
||||||
|
request={request}
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
search={{
|
||||||
|
labelWidth: 'auto',
|
||||||
|
span: 6,
|
||||||
|
}}
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize: 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
}}
|
||||||
|
scroll={{
|
||||||
|
y: 'calc(100vh - 320px)',
|
||||||
|
}}
|
||||||
|
options={false}
|
||||||
|
dateFormatter="string"
|
||||||
|
toolBarRender={() => [
|
||||||
|
<Button key="export" type="primary" onClick={handleExport}>
|
||||||
|
导出
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignInActivity;
|
||||||
@ -0,0 +1,331 @@
|
|||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
|
import { PageContainer } from '@ant-design/pro-layout';
|
||||||
|
import { Card, Col, Row, Segmented, Typography } from 'antd';
|
||||||
|
import type { PieConfig } from '@ant-design/plots';
|
||||||
|
import { Pie } from '@ant-design/plots';
|
||||||
|
|
||||||
|
const { Title, Paragraph, Text } = Typography;
|
||||||
|
|
||||||
|
type RangeKey = 'day' | 'month' | 'all';
|
||||||
|
|
||||||
|
type ChartDatum = {
|
||||||
|
label: string;
|
||||||
|
value: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DataMap = Record<RangeKey, ChartDatum[]>;
|
||||||
|
|
||||||
|
const signMerchantData: DataMap = {
|
||||||
|
day: [
|
||||||
|
{ label: 'A商家', value: 35 },
|
||||||
|
{ label: 'B商家', value: 25 },
|
||||||
|
{ label: 'C商家', value: 18 },
|
||||||
|
{ label: 'D商家', value: 12 },
|
||||||
|
{ label: 'E商家', value: 10 },
|
||||||
|
{ label: 'F商家', value: 8 },
|
||||||
|
{ label: 'G商家', value: 6 },
|
||||||
|
{ label: 'H商家', value: 5 },
|
||||||
|
{ label: 'I商家', value: 4 },
|
||||||
|
{ label: 'J商家', value: 3 },
|
||||||
|
],
|
||||||
|
month: [
|
||||||
|
{ label: 'A商家', value: 260 },
|
||||||
|
{ label: 'B商家', value: 200 },
|
||||||
|
{ label: 'C商家', value: 180 },
|
||||||
|
{ label: 'D商家', value: 140 },
|
||||||
|
{ label: 'E商家', value: 120 },
|
||||||
|
{ label: 'F商家', value: 100 },
|
||||||
|
{ label: 'G商家', value: 80 },
|
||||||
|
{ label: 'H商家', value: 60 },
|
||||||
|
{ label: 'I商家', value: 45 },
|
||||||
|
{ label: 'J商家', value: 30 },
|
||||||
|
],
|
||||||
|
all: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const signAgentData: DataMap = {
|
||||||
|
day: [
|
||||||
|
{ label: 'A采购员', value: 40 },
|
||||||
|
{ label: 'B采购员', value: 30 },
|
||||||
|
{ label: 'C采购员', value: 20 },
|
||||||
|
{ label: 'D采购员', value: 15 },
|
||||||
|
{ label: 'E采购员', value: 12 },
|
||||||
|
{ label: 'F采购员', value: 10 },
|
||||||
|
{ label: 'G采购员', value: 8 },
|
||||||
|
{ label: 'H采购员', value: 6 },
|
||||||
|
{ label: 'I采购员', value: 5 },
|
||||||
|
{ label: 'J采购员', value: 4 },
|
||||||
|
],
|
||||||
|
month: [
|
||||||
|
{ label: 'A采购员', value: 320 },
|
||||||
|
{ label: 'B采购员', value: 230 },
|
||||||
|
{ label: 'C采购员', value: 180 },
|
||||||
|
{ label: 'D采购员', value: 150 },
|
||||||
|
{ label: 'E采购员', value: 130 },
|
||||||
|
{ label: 'F采购员', value: 110 },
|
||||||
|
{ label: 'G采购员', value: 95 },
|
||||||
|
{ label: 'H采购员', value: 80 },
|
||||||
|
{ label: 'I采购员', value: 70 },
|
||||||
|
{ label: 'J采购员', value: 55 },
|
||||||
|
],
|
||||||
|
all: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const orderMerchantData: DataMap = {
|
||||||
|
day: [
|
||||||
|
{ label: 'A商家', value: 30 },
|
||||||
|
{ label: 'B商家', value: 27 },
|
||||||
|
{ label: 'C商家', value: 19 },
|
||||||
|
{ label: 'D商家', value: 14 },
|
||||||
|
{ label: 'E商家', value: 12 },
|
||||||
|
{ label: 'F商家', value: 9 },
|
||||||
|
{ label: 'G商家', value: 7 },
|
||||||
|
{ label: 'H商家', value: 6 },
|
||||||
|
{ label: 'I商家', value: 5 },
|
||||||
|
{ label: 'J商家', value: 3 },
|
||||||
|
],
|
||||||
|
month: [
|
||||||
|
{ label: 'A商家', value: 280 },
|
||||||
|
{ label: 'B商家', value: 230 },
|
||||||
|
{ label: 'C商家', value: 200 },
|
||||||
|
{ label: 'D商家', value: 180 },
|
||||||
|
{ label: 'E商家', value: 150 },
|
||||||
|
{ label: 'F商家', value: 120 },
|
||||||
|
{ label: 'G商家', value: 100 },
|
||||||
|
{ label: 'H商家', value: 85 },
|
||||||
|
{ label: 'I商家', value: 70 },
|
||||||
|
{ label: 'J商家', value: 55 },
|
||||||
|
],
|
||||||
|
all: [
|
||||||
|
{ label: 'A商家', value: 680 },
|
||||||
|
{ label: 'B商家', value: 620 },
|
||||||
|
{ label: 'C商家', value: 550 },
|
||||||
|
{ label: 'D商家', value: 480 },
|
||||||
|
{ label: 'E商家', value: 440 },
|
||||||
|
{ label: 'F商家', value: 360 },
|
||||||
|
{ label: 'G商家', value: 310 },
|
||||||
|
{ label: 'H商家', value: 290 },
|
||||||
|
{ label: 'I商家', value: 240 },
|
||||||
|
{ label: 'J商家', value: 200 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const orderAgentData: DataMap = {
|
||||||
|
day: [
|
||||||
|
{ label: 'A采购员', value: 28 },
|
||||||
|
{ label: 'B采购员', value: 24 },
|
||||||
|
{ label: 'C采购员', value: 20 },
|
||||||
|
{ label: 'D采购员', value: 16 },
|
||||||
|
{ label: 'E采购员', value: 12 },
|
||||||
|
{ label: 'F采购员', value: 10 },
|
||||||
|
{ label: 'G采购员', value: 8 },
|
||||||
|
{ label: 'H采购员', value: 6 },
|
||||||
|
{ label: 'I采购员', value: 5 },
|
||||||
|
{ label: 'J采购员', value: 4 },
|
||||||
|
],
|
||||||
|
month: [
|
||||||
|
{ label: 'A采购员', value: 260 },
|
||||||
|
{ label: 'B采购员', value: 240 },
|
||||||
|
{ label: 'C采购员', value: 220 },
|
||||||
|
{ label: 'D采购员', value: 180 },
|
||||||
|
{ label: 'E采购员', value: 160 },
|
||||||
|
{ label: 'F采购员', value: 140 },
|
||||||
|
{ label: 'G采购员', value: 120 },
|
||||||
|
{ label: 'H采购员', value: 95 },
|
||||||
|
{ label: 'I采购员', value: 80 },
|
||||||
|
{ label: 'J采购员', value: 70 },
|
||||||
|
],
|
||||||
|
all: [
|
||||||
|
{ label: 'A采购员', value: 620 },
|
||||||
|
{ label: 'B采购员', value: 580 },
|
||||||
|
{ label: 'C采购员', value: 520 },
|
||||||
|
{ label: 'D采购员', value: 480 },
|
||||||
|
{ label: 'E采购员', value: 430 },
|
||||||
|
{ label: 'F采购员', value: 360 },
|
||||||
|
{ label: 'G采购员', value: 320 },
|
||||||
|
{ label: 'H采购员', value: 280 },
|
||||||
|
{ label: 'I采购员', value: 240 },
|
||||||
|
{ label: 'J采购员', value: 220 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildPieConfig = (data: ChartDatum[]): PieConfig => ({
|
||||||
|
data,
|
||||||
|
angleField: 'value',
|
||||||
|
colorField: 'label',
|
||||||
|
radius: 0.8,
|
||||||
|
legend: false,
|
||||||
|
label: {
|
||||||
|
type: 'inner',
|
||||||
|
offset: '-30%',
|
||||||
|
content: ({ percent }) => `${Math.round(Number(percent) * 100)}%`,
|
||||||
|
style: {
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
statistic: {
|
||||||
|
title: false,
|
||||||
|
content: {
|
||||||
|
formatter: () => 'Top 10',
|
||||||
|
style: {
|
||||||
|
fontSize: '16px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderRanking = (data: ChartDatum[]) => {
|
||||||
|
const total = data.reduce((sum, item) => sum + item.value, 0);
|
||||||
|
return (
|
||||||
|
<div style={{ paddingLeft: 16 }}>
|
||||||
|
{data.map((item, index) => {
|
||||||
|
const percent = total ? Math.round((item.value / total) * 100) : 0;
|
||||||
|
return (
|
||||||
|
<Paragraph key={item.label} style={{ marginBottom: 8 }}>
|
||||||
|
<Text strong style={{ marginRight: 8 }}>
|
||||||
|
{index + 1}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ marginRight: 8 }}>{item.label}</Text>
|
||||||
|
<Text type="secondary">
|
||||||
|
{item.value}次 | {percent}%
|
||||||
|
</Text>
|
||||||
|
</Paragraph>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ActivityStatistics: React.FC = () => {
|
||||||
|
const [signRange, setSignRange] = useState<RangeKey>('day');
|
||||||
|
const [signAgentRange, setSignAgentRange] = useState<RangeKey>('day');
|
||||||
|
const [orderRange, setOrderRange] = useState<RangeKey>('day');
|
||||||
|
const [orderAgentRange, setOrderAgentRange] = useState<RangeKey>('day');
|
||||||
|
|
||||||
|
const signMerchant = useMemo(() => signMerchantData[signRange], [signRange]);
|
||||||
|
const signAgent = useMemo(() => signAgentData[signAgentRange], [signAgentRange]);
|
||||||
|
const orderMerchant = useMemo(() => orderMerchantData[orderRange], [orderRange]);
|
||||||
|
const orderAgent = useMemo(() => orderAgentData[orderAgentRange], [orderAgentRange]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer header={{ title: '' }}>
|
||||||
|
<Card bordered={false} style={{ marginBottom: 24 }}>
|
||||||
|
<Row justify="space-between" align="middle" style={{ marginBottom: 16 }}>
|
||||||
|
<Col>
|
||||||
|
<Title level={4} style={{ margin: 0 }}>
|
||||||
|
打卡签到活动
|
||||||
|
</Title>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={24} style={{ marginBottom: 24 }}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card
|
||||||
|
title="商家打卡前10统计"
|
||||||
|
extra={
|
||||||
|
<Segmented
|
||||||
|
options={[{ label: '当日', value: 'day' }, { label: '当月', value: 'month' }]}
|
||||||
|
value={signRange}
|
||||||
|
onChange={(value) => setSignRange(value as RangeKey)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
bordered={false}
|
||||||
|
>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...buildPieConfig(signMerchant)} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>{renderRanking(signMerchant)}</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card
|
||||||
|
title="采购员打卡前10统计"
|
||||||
|
extra={
|
||||||
|
<Segmented
|
||||||
|
options={[{ label: '当日', value: 'day' }, { label: '当月', value: 'month' }]}
|
||||||
|
value={signAgentRange}
|
||||||
|
onChange={(value) => setSignAgentRange(value as RangeKey)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
bordered={false}
|
||||||
|
>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...buildPieConfig(signAgent)} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>{renderRanking(signAgent)}</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card bordered={false}>
|
||||||
|
<Row justify="space-between" align="middle" style={{ marginBottom: 16 }}>
|
||||||
|
<Col>
|
||||||
|
<Title level={4} style={{ margin: 0 }}>
|
||||||
|
下单活动
|
||||||
|
</Title>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={24} style={{ marginBottom: 24 }}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card
|
||||||
|
title="商家下单前10统计"
|
||||||
|
extra={
|
||||||
|
<Segmented
|
||||||
|
options={[
|
||||||
|
{ label: '当日', value: 'day' },
|
||||||
|
{ label: '当月', value: 'month' },
|
||||||
|
{ label: '全部', value: 'all' },
|
||||||
|
]}
|
||||||
|
value={orderRange}
|
||||||
|
onChange={(value) => setOrderRange(value as RangeKey)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
bordered={false}
|
||||||
|
>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...buildPieConfig(orderMerchant)} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>{renderRanking(orderMerchant)}</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Card
|
||||||
|
title="采购员下单前10统计"
|
||||||
|
extra={
|
||||||
|
<Segmented
|
||||||
|
options={[
|
||||||
|
{ label: '当日', value: 'day' },
|
||||||
|
{ label: '当月', value: 'month' },
|
||||||
|
{ label: '全部', value: 'all' },
|
||||||
|
]}
|
||||||
|
value={orderAgentRange}
|
||||||
|
onChange={(value) => setOrderAgentRange(value as RangeKey)}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
bordered={false}
|
||||||
|
>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Pie {...buildPieConfig(orderAgent)} />
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>{renderRanking(orderAgent)}</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActivityStatistics;
|
||||||
Loading…
Reference in New Issue