|
|
|
@ -1,16 +1,25 @@
|
|
|
|
import React, { useState, useEffect, useRef } from 'react';
|
|
|
|
import React, { useState, useEffect, useRef, useMemo, useLayoutEffect } from 'react';
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
import styles from './CustomerInfoManagement.less';
|
|
|
|
import styles from './CustomerInfoManagement.less';
|
|
|
|
|
|
|
|
import { Select, Space, Button, Input } from 'antd';
|
|
|
|
|
|
|
|
import { PlusOutlined, SearchOutlined, ReloadOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
|
import StandardTable from '@/components/StandardTable';
|
|
|
|
|
|
|
|
import topIcon from '@/assets/business_basic/top_icon1.svg';
|
|
|
|
|
|
|
|
import topIcon2 from '@/assets/business_basic/top_icon2.svg';
|
|
|
|
|
|
|
|
import topIcon3 from '@/assets/business_basic/top_icon3.svg';
|
|
|
|
|
|
|
|
import topIcon4 from '@/assets/business_basic/top_icon4.svg';
|
|
|
|
import CustomerInfoManagementDetail from './CustomerInfoManagementDetail';
|
|
|
|
import CustomerInfoManagementDetail from './CustomerInfoManagementDetail';
|
|
|
|
|
|
|
|
|
|
|
|
const CustomerInfoManagement = () => {
|
|
|
|
const CustomerInfoManagement = () => {
|
|
|
|
const [searchKeyword, setSearchKeyword] = useState('');
|
|
|
|
const [searchKeyword, setSearchKeyword] = useState('');
|
|
|
|
const [customerType, setCustomerType] = useState('全部');
|
|
|
|
|
|
|
|
const [customerLevel, setCustomerLevel] = useState('全部');
|
|
|
|
|
|
|
|
const [cooperationStatus, setCooperationStatus] = useState('全部');
|
|
|
|
|
|
|
|
const [selectedRows, setSelectedRows] = useState([]);
|
|
|
|
const [selectedRows, setSelectedRows] = useState([]);
|
|
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
const [pageSize, setPageSize] = useState(10);
|
|
|
|
const [pageSize, setPageSize] = useState(10);
|
|
|
|
|
|
|
|
// 列表筛选与数据(演示数据,可替换为接口)
|
|
|
|
|
|
|
|
const [filters, setFilters] = useState({
|
|
|
|
|
|
|
|
customerType: '',
|
|
|
|
|
|
|
|
customerGrade: '',
|
|
|
|
|
|
|
|
cooperationStatus: '',
|
|
|
|
|
|
|
|
});
|
|
|
|
// 新增:详情页面切换状态
|
|
|
|
// 新增:详情页面切换状态
|
|
|
|
const [showDetail, setShowDetail] = useState(false);
|
|
|
|
const [showDetail, setShowDetail] = useState(false);
|
|
|
|
const [detailData, setDetailData] = useState(null);
|
|
|
|
const [detailData, setDetailData] = useState(null);
|
|
|
|
@ -32,21 +41,27 @@ const CustomerInfoManagement = () => {
|
|
|
|
|
|
|
|
|
|
|
|
// 客户类型分布图表配置
|
|
|
|
// 客户类型分布图表配置
|
|
|
|
const customerTypeChartOption = {
|
|
|
|
const customerTypeChartOption = {
|
|
|
|
title: {
|
|
|
|
// title: {
|
|
|
|
text: '客户类型分布',
|
|
|
|
// text: '客户类型分布',
|
|
|
|
left: 'left',
|
|
|
|
// left: 'left',
|
|
|
|
textStyle: {
|
|
|
|
// textStyle: {
|
|
|
|
fontSize: 16,
|
|
|
|
// fontSize: 16,
|
|
|
|
fontWeight: 600,
|
|
|
|
// fontWeight: 600,
|
|
|
|
},
|
|
|
|
// color: '#333',
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
|
|
|
|
// },
|
|
|
|
tooltip: {
|
|
|
|
tooltip: {
|
|
|
|
trigger: 'axis',
|
|
|
|
trigger: 'axis',
|
|
|
|
axisPointer: {
|
|
|
|
axisPointer: {
|
|
|
|
type: 'shadow',
|
|
|
|
type: 'shadow',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
backgroundColor: 'rgba(255,255,255,0.95)',
|
|
|
|
|
|
|
|
borderColor: '#e0e0e0',
|
|
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
|
|
textStyle: { color: '#333' },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
grid: {
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
top: 16,
|
|
|
|
left: '3%',
|
|
|
|
left: '3%',
|
|
|
|
right: '4%',
|
|
|
|
right: '4%',
|
|
|
|
bottom: '3%',
|
|
|
|
bottom: '3%',
|
|
|
|
@ -57,23 +72,44 @@ const CustomerInfoManagement = () => {
|
|
|
|
data: ['客户', '供应商', '第3周', '第4周'],
|
|
|
|
data: ['客户', '供应商', '第3周', '第4周'],
|
|
|
|
axisLabel: {
|
|
|
|
axisLabel: {
|
|
|
|
rotate: 0,
|
|
|
|
rotate: 0,
|
|
|
|
|
|
|
|
color: '#4E5856',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
|
|
lineStyle: { color: '#C9E3DE' },
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
axisTick: { show: false },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
yAxis: {
|
|
|
|
yAxis: {
|
|
|
|
type: 'value',
|
|
|
|
type: 'value',
|
|
|
|
max: 100,
|
|
|
|
max: 100,
|
|
|
|
|
|
|
|
axisLine: { show: false },
|
|
|
|
|
|
|
|
axisTick: { show: false },
|
|
|
|
|
|
|
|
axisLabel: { color: '#4E5856' },
|
|
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
|
|
lineStyle: { color: '#E9F3F1', type: 'dashed' },
|
|
|
|
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
series: [
|
|
|
|
series: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
name: '数量',
|
|
|
|
name: '数量',
|
|
|
|
type: 'bar',
|
|
|
|
type: 'bar',
|
|
|
|
data: [56, 32, 85, 15],
|
|
|
|
data: [56, 32, 85, 15],
|
|
|
|
|
|
|
|
barWidth: 26,
|
|
|
|
itemStyle: {
|
|
|
|
itemStyle: {
|
|
|
|
color: '#1890ff',
|
|
|
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
|
|
|
|
|
{ offset: 0, color: '#7FC8B6' },
|
|
|
|
|
|
|
|
{ offset: 1, color: '#008F8E' },
|
|
|
|
|
|
|
|
]),
|
|
|
|
|
|
|
|
// barBorderRadius: [6, 6, 0, 0],
|
|
|
|
|
|
|
|
shadowColor: 'rgba(0,0,0,0.08)',
|
|
|
|
|
|
|
|
shadowBlur: 6,
|
|
|
|
|
|
|
|
shadowOffsetY: 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
label: {
|
|
|
|
label: {
|
|
|
|
show: true,
|
|
|
|
show: true,
|
|
|
|
position: 'top',
|
|
|
|
position: 'top',
|
|
|
|
|
|
|
|
color: '#4E5856',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
],
|
|
|
|
@ -81,81 +117,113 @@ const CustomerInfoManagement = () => {
|
|
|
|
|
|
|
|
|
|
|
|
// 客户价值分布环形图配置
|
|
|
|
// 客户价值分布环形图配置
|
|
|
|
const customerValueChartOption = {
|
|
|
|
const customerValueChartOption = {
|
|
|
|
title: {
|
|
|
|
// title: {
|
|
|
|
text: '客户价值分布',
|
|
|
|
// text: '客户价值分布',
|
|
|
|
left: 'left',
|
|
|
|
// left: 'left',
|
|
|
|
textStyle: {
|
|
|
|
// textStyle: {
|
|
|
|
fontSize: 16,
|
|
|
|
// fontSize: 16,
|
|
|
|
fontWeight: 600,
|
|
|
|
// fontWeight: 600,
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
tooltip: {
|
|
|
|
tooltip: {
|
|
|
|
trigger: 'item',
|
|
|
|
trigger: 'item',
|
|
|
|
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
|
|
|
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
legend: {
|
|
|
|
legend: {
|
|
|
|
orient: 'vertical',
|
|
|
|
orient: 'vertical',
|
|
|
|
left: 'right',
|
|
|
|
right: '6%',
|
|
|
|
top: 'middle',
|
|
|
|
top: '32%',
|
|
|
|
|
|
|
|
itemWidth: 16,
|
|
|
|
|
|
|
|
itemHeight: 4,
|
|
|
|
|
|
|
|
itemGap: 16,
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
|
|
color: '#666',
|
|
|
|
|
|
|
|
fontWeight: 'normal'
|
|
|
|
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
series: [
|
|
|
|
series: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
name: '客户价值',
|
|
|
|
name: '客户价值',
|
|
|
|
type: 'pie',
|
|
|
|
type: 'pie',
|
|
|
|
radius: ['40%', '70%'],
|
|
|
|
radius: ['40%', '65%'],
|
|
|
|
avoidLabelOverlap: false,
|
|
|
|
center: ['30%', '50%'],
|
|
|
|
|
|
|
|
// avoidLabelOverlap: false,
|
|
|
|
itemStyle: {
|
|
|
|
itemStyle: {
|
|
|
|
borderRadius: 10,
|
|
|
|
// borderRadius: 10,
|
|
|
|
borderColor: '#fff',
|
|
|
|
// borderColor: '#fff',
|
|
|
|
borderWidth: 2,
|
|
|
|
// borderWidth: 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
label: {
|
|
|
|
label: {
|
|
|
|
show: false,
|
|
|
|
show: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
emphasis: {
|
|
|
|
// emphasis: {
|
|
|
|
label: {
|
|
|
|
// label: {
|
|
|
|
show: true,
|
|
|
|
// show: true,
|
|
|
|
fontSize: 16,
|
|
|
|
// fontSize: 16,
|
|
|
|
fontWeight: 'bold',
|
|
|
|
// fontWeight: 'bold',
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
data: [
|
|
|
|
data: [
|
|
|
|
{ value: 180, name: '高价值客户', itemStyle: { color: '#5B9BD5' } },
|
|
|
|
{ value: 180, name: '高价值客户', itemStyle: { color: '#5CB3FF' } },
|
|
|
|
{ value: 120, name: '中等客户', itemStyle: { color: '#FFC000' } },
|
|
|
|
{ value: 120, name: '中等客户', itemStyle: { color: '#FFDE73' } },
|
|
|
|
{ value: 89, name: '小客户', itemStyle: { color: '#9E7CC1' } },
|
|
|
|
{ value: 89, name: '小客户', itemStyle: { color: '#A990EA' } },
|
|
|
|
],
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化图表
|
|
|
|
// 图表初始化与销毁:根据详情模式切换,返回列表后重新初始化
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
// 初始化客户类型分布图表
|
|
|
|
if (!showDetail) {
|
|
|
|
if (customerTypeChartRef.current) {
|
|
|
|
if (customerTypeChartRef.current) {
|
|
|
|
customerTypeChartInstance.current = echarts.init(customerTypeChartRef.current);
|
|
|
|
customerTypeChartInstance.current = echarts.init(customerTypeChartRef.current);
|
|
|
|
customerTypeChartInstance.current.setOption(customerTypeChartOption);
|
|
|
|
customerTypeChartInstance.current.setOption(customerTypeChartOption);
|
|
|
|
}
|
|
|
|
// 额外一次 resize,确保初始化后尺寸正确
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
// 初始化客户价值分布图表
|
|
|
|
customerTypeChartInstance.current?.resize();
|
|
|
|
if (customerValueChartRef.current) {
|
|
|
|
});
|
|
|
|
customerValueChartInstance.current = echarts.init(customerValueChartRef.current);
|
|
|
|
}
|
|
|
|
customerValueChartInstance.current.setOption(customerValueChartOption);
|
|
|
|
if (customerValueChartRef.current) {
|
|
|
|
}
|
|
|
|
customerValueChartInstance.current = echarts.init(customerValueChartRef.current);
|
|
|
|
|
|
|
|
customerValueChartInstance.current.setOption(customerValueChartOption);
|
|
|
|
|
|
|
|
// 额外一次 resize,确保初始化后尺寸正确
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
|
|
|
customerValueChartInstance.current?.resize();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 响应式调整
|
|
|
|
const handleResize = () => {
|
|
|
|
const handleResize = () => {
|
|
|
|
customerTypeChartInstance.current?.resize();
|
|
|
|
customerTypeChartInstance.current?.resize();
|
|
|
|
customerValueChartInstance.current?.resize();
|
|
|
|
customerValueChartInstance.current?.resize();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清理函数
|
|
|
|
return () => {
|
|
|
|
return () => {
|
|
|
|
window.removeEventListener('resize', handleResize);
|
|
|
|
window.removeEventListener('resize', handleResize);
|
|
|
|
customerTypeChartInstance.current?.dispose();
|
|
|
|
|
|
|
|
customerTypeChartInstance.current = null;
|
|
|
|
|
|
|
|
customerValueChartInstance.current?.dispose();
|
|
|
|
|
|
|
|
customerValueChartInstance.current = null;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 进入详情时,释放实例以避免无容器绑定
|
|
|
|
customerTypeChartInstance.current?.dispose();
|
|
|
|
customerTypeChartInstance.current?.dispose();
|
|
|
|
|
|
|
|
customerTypeChartInstance.current = null;
|
|
|
|
customerValueChartInstance.current?.dispose();
|
|
|
|
customerValueChartInstance.current?.dispose();
|
|
|
|
};
|
|
|
|
customerValueChartInstance.current = null;
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
}, [showDetail]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 返回列表时恢复滚动位置,确保布局稳定后再滚动
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
|
|
|
if (!showDetail) {
|
|
|
|
|
|
|
|
// 等待本帧布局完成
|
|
|
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
|
|
|
window.scrollTo(0, prevScrollY || 0);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}, [showDetail]);
|
|
|
|
|
|
|
|
|
|
|
|
// 最近活动数据
|
|
|
|
// 最近活动数据
|
|
|
|
const recentActivities = [
|
|
|
|
const recentActivities = [
|
|
|
|
@ -239,6 +307,48 @@ const CustomerInfoManagement = () => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 列配置(用于 StandardTable)
|
|
|
|
|
|
|
|
const columns = useMemo(() => {
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
|
|
{ title: '客户名称', dataIndex: 'customerName', key: 'customerName', width: 220 },
|
|
|
|
|
|
|
|
{ title: '联系人', dataIndex: 'contact', key: 'contact', width: 120 },
|
|
|
|
|
|
|
|
{ title: '联系电话', dataIndex: 'phone', key: 'phone', width: 140 },
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
title: '分类', dataIndex: 'classification', key: 'classification', width: 110,
|
|
|
|
|
|
|
|
render: (val) => (
|
|
|
|
|
|
|
|
<span className={`${styles.tag} ${val === '高价值' ? styles.tagGold : styles.tagBlue}`}>{val}</span>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
title: '交易额度(月)', dataIndex: 'monthlyAmount', key: 'monthlyAmount', width: 150,
|
|
|
|
|
|
|
|
render: (v) => `¥${Number(v).toLocaleString()}`
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
title: '合作状态', dataIndex: 'cooperationStatus', key: 'cooperationStatus', width: 110,
|
|
|
|
|
|
|
|
render: (val) => (
|
|
|
|
|
|
|
|
<span className={`${styles.tag} ${val === '合作中' ? styles.tagGreen : styles.tagOrange}`}>{val}</span>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
title: '满意度', dataIndex: 'satisfaction', key: 'satisfaction', width: 120,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
title: '操作', key: 'action', fixed: 'right', width: 200,
|
|
|
|
|
|
|
|
render: (_, row) => (
|
|
|
|
|
|
|
|
<Space size={12}>
|
|
|
|
|
|
|
|
<Button type="link" size="small" className="viewDetailBtn" onClick={() => {
|
|
|
|
|
|
|
|
setPrevScrollY(window.pageYOffset || document.documentElement.scrollTop || 0);
|
|
|
|
|
|
|
|
setDetailData(row);
|
|
|
|
|
|
|
|
setShowDetail(true);
|
|
|
|
|
|
|
|
}}>查看详情</Button>
|
|
|
|
|
|
|
|
<Button type="link" size="small" className="editBtn">修改</Button>
|
|
|
|
|
|
|
|
<Button type="link" size="small" danger className="deleteBtn">删除</Button>
|
|
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
// 处理选择
|
|
|
|
// 处理选择
|
|
|
|
const handleSelectRow = (id) => {
|
|
|
|
const handleSelectRow = (id) => {
|
|
|
|
if (selectedRows.includes(id)) {
|
|
|
|
if (selectedRows.includes(id)) {
|
|
|
|
@ -262,7 +372,7 @@ const CustomerInfoManagement = () => {
|
|
|
|
const stars = [];
|
|
|
|
const stars = [];
|
|
|
|
const fullStars = Math.floor(rating);
|
|
|
|
const fullStars = Math.floor(rating);
|
|
|
|
const hasHalfStar = rating % 1 !== 0;
|
|
|
|
const hasHalfStar = rating % 1 !== 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < fullStars; i++) {
|
|
|
|
for (let i = 0; i < fullStars; i++) {
|
|
|
|
stars.push(<span key={i} className={styles.starFull}>★</span>);
|
|
|
|
stars.push(<span key={i} className={styles.starFull}>★</span>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -282,7 +392,7 @@ const CustomerInfoManagement = () => {
|
|
|
|
if (showDetail) {
|
|
|
|
if (showDetail) {
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className={styles.container}>
|
|
|
|
<div className={styles.container}>
|
|
|
|
<div style={{marginBottom:10}}>
|
|
|
|
<div style={{ marginBottom: 10 }}>
|
|
|
|
<button
|
|
|
|
<button
|
|
|
|
className={styles.backBtn}
|
|
|
|
className={styles.backBtn}
|
|
|
|
onClick={() => {
|
|
|
|
onClick={() => {
|
|
|
|
@ -292,7 +402,7 @@ const CustomerInfoManagement = () => {
|
|
|
|
window.scrollTo(0, prevScrollY);
|
|
|
|
window.scrollTo(0, prevScrollY);
|
|
|
|
}, 0);
|
|
|
|
}, 0);
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
style={{padding:'6px 12px',border:'1px solid #d9d9d9',borderRadius:6,background:'#fff',fontSize:12,cursor:'pointer'}}
|
|
|
|
style={{ padding: '6px 12px', border: '1px solid #d9d9d9', borderRadius: 6, background: '#fff', fontSize: 12, cursor: 'pointer' }}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
← 返回列表
|
|
|
|
← 返回列表
|
|
|
|
</button>
|
|
|
|
</button>
|
|
|
|
@ -304,286 +414,198 @@ const CustomerInfoManagement = () => {
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className={styles.container}>
|
|
|
|
<div className={styles.container}>
|
|
|
|
{/* KPI卡片区域 */}
|
|
|
|
<div className={styles.mainCard}>
|
|
|
|
<div className={styles.kpiRow}>
|
|
|
|
{/* KPI卡片区域 */}
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
<div className={styles.kpiGrid}>
|
|
|
|
<div className={styles.kpiIcon}>👥</div>
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
<div className={styles.kpiValue}>{kpiData.totalCustomers}</div>
|
|
|
|
<div className={styles.kpiText}>
|
|
|
|
<div className={styles.kpiTitle}>总客户数</div>
|
|
|
|
<div className={styles.kpiValue}>{kpiData.totalCustomers}</div>
|
|
|
|
</div>
|
|
|
|
<div className={styles.kpiTitle}>总客户数</div>
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
</div>
|
|
|
|
<div className={styles.kpiIcon}>👑</div>
|
|
|
|
<img src={topIcon} alt="icon" className={styles.kpiIconImg} />
|
|
|
|
<div className={styles.kpiValue}>{kpiData.highValueCustomers}</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiTitle}>高价值客户</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
|
|
|
|
<div className={styles.kpiIcon}>🤝</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiValue}>{kpiData.inCooperation}</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiTitle}>合作中</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
|
|
|
|
<div className={styles.kpiIcon}>➕</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiValue}>{kpiData.newThisMonth}</div>
|
|
|
|
|
|
|
|
<div className={styles.kpiTitle}>本月新增</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 图表和活动区域 */}
|
|
|
|
|
|
|
|
<div className={styles.chartRow}>
|
|
|
|
|
|
|
|
{/* 客户类型分布图表 */}
|
|
|
|
|
|
|
|
<div className={styles.chartCard}>
|
|
|
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
|
|
|
<div className={styles.chartTitle}>客户类型分布</div>
|
|
|
|
|
|
|
|
<select className={styles.timeSelect} defaultValue="全部时间">
|
|
|
|
|
|
|
|
<option value="全部时间">全部时间</option>
|
|
|
|
|
|
|
|
<option value="本月">本月</option>
|
|
|
|
|
|
|
|
<option value="本季度">本季度</option>
|
|
|
|
|
|
|
|
<option value="本年">本年</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
ref={customerTypeChartRef}
|
|
|
|
<div className={styles.kpiText}>
|
|
|
|
className={styles.chartContainer}
|
|
|
|
<div className={styles.kpiValue}>{kpiData.highValueCustomers}</div>
|
|
|
|
/>
|
|
|
|
<div className={styles.kpiTitle}>高价值客户</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<img src={topIcon2} alt="icon" className={styles.kpiIconImg} />
|
|
|
|
{/* 客户价值分布图表 */}
|
|
|
|
|
|
|
|
<div className={styles.chartCard}>
|
|
|
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
|
|
|
<div className={styles.chartTitle}>客户价值分布</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
ref={customerValueChartRef}
|
|
|
|
<div className={styles.kpiText}>
|
|
|
|
className={styles.chartContainer}
|
|
|
|
<div className={styles.kpiValue}>{kpiData.inCooperation}</div>
|
|
|
|
/>
|
|
|
|
<div className={styles.kpiTitle}>合作中</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<img src={topIcon3} alt="icon" className={styles.kpiIconImg} />
|
|
|
|
{/* 最近活动列表 */}
|
|
|
|
|
|
|
|
<div className={styles.activityCard}>
|
|
|
|
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
|
|
|
<div className={styles.chartTitle}>最近活动</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className={styles.activityList}>
|
|
|
|
<div className={styles.kpiCard}>
|
|
|
|
{recentActivities.map((activity) => (
|
|
|
|
<div className={styles.kpiText}>
|
|
|
|
<div key={activity.id} className={styles.activityItem}>
|
|
|
|
<div className={styles.kpiValue}>{kpiData.newThisMonth}</div>
|
|
|
|
<div className={styles.activityIcon}>
|
|
|
|
<div className={styles.kpiTitle}>本月新增</div>
|
|
|
|
{activity.id === 1 && '📄'}
|
|
|
|
</div>
|
|
|
|
{activity.id === 2 && '✅'}
|
|
|
|
<img src={topIcon4} alt="icon" className={styles.kpiIconImg} />
|
|
|
|
{activity.id === 3 && '💬'}
|
|
|
|
|
|
|
|
{activity.id === 4 && '👤'}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.activityContent}>
|
|
|
|
|
|
|
|
<div className={styles.activityTitle}>{activity.title}</div>
|
|
|
|
|
|
|
|
<div className={styles.activityDesc}>{activity.description}</div>
|
|
|
|
|
|
|
|
<div className={styles.activityTime}>🕐 {activity.time}</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 客户列表区域 */}
|
|
|
|
{/* 图表和活动区域 */}
|
|
|
|
<div className={styles.tableCard}>
|
|
|
|
<div className={styles.chartRow}>
|
|
|
|
<div className={styles.tableHeader}>
|
|
|
|
{/* 客户类型分布图表 */}
|
|
|
|
<div className={styles.tableTitle}>客户列表</div>
|
|
|
|
<div className={styles.chartCard} style={{ flex: 9 }}>
|
|
|
|
</div>
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
|
|
|
|
<div className={styles.chartTitle}>客户类型分布</div>
|
|
|
|
|
|
|
|
<Select
|
|
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
|
|
className={styles.timeSelect}
|
|
|
|
|
|
|
|
defaultValue="全部时间"
|
|
|
|
|
|
|
|
options={[
|
|
|
|
|
|
|
|
{ value: '全部时间', label: '全部时间' },
|
|
|
|
|
|
|
|
{ value: '本月', label: '本月' },
|
|
|
|
|
|
|
|
{ value: '本季度', label: '本季度' },
|
|
|
|
|
|
|
|
{ value: '本年', label: '本年' },
|
|
|
|
|
|
|
|
]}
|
|
|
|
|
|
|
|
onChange={(v) => {/* 可根据需要触发筛选 */ }}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
ref={customerTypeChartRef}
|
|
|
|
|
|
|
|
className={styles.chartContainer}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 筛选栏 */}
|
|
|
|
{/* 客户价值分布图表 */}
|
|
|
|
<div className={styles.filterBar}>
|
|
|
|
<div className={styles.chartCard} style={{ flex: 6 }}>
|
|
|
|
<div className={styles.filterGroup}>
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
<input
|
|
|
|
<div className={styles.chartTitle}>客户价值分布</div>
|
|
|
|
type="text"
|
|
|
|
</div>
|
|
|
|
className={styles.searchInput}
|
|
|
|
<div
|
|
|
|
placeholder="搜索关键词"
|
|
|
|
ref={customerValueChartRef}
|
|
|
|
value={searchKeyword}
|
|
|
|
className={styles.chartContainer}
|
|
|
|
onChange={(e) => setSearchKeyword(e.target.value)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
<select
|
|
|
|
|
|
|
|
className={styles.filterSelect}
|
|
|
|
|
|
|
|
value={customerType}
|
|
|
|
|
|
|
|
onChange={(e) => setCustomerType(e.target.value)}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<option value="全部">客户类型: 全部</option>
|
|
|
|
|
|
|
|
<option value="客户">客户</option>
|
|
|
|
|
|
|
|
<option value="供应商">供应商</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
<select
|
|
|
|
|
|
|
|
className={styles.filterSelect}
|
|
|
|
|
|
|
|
value={customerLevel}
|
|
|
|
|
|
|
|
onChange={(e) => setCustomerLevel(e.target.value)}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<option value="全部">客户等级: 全部</option>
|
|
|
|
|
|
|
|
<option value="高价值">高价值</option>
|
|
|
|
|
|
|
|
<option value="常规客户">常规客户</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
<select
|
|
|
|
|
|
|
|
className={styles.filterSelect}
|
|
|
|
|
|
|
|
value={cooperationStatus}
|
|
|
|
|
|
|
|
onChange={(e) => setCooperationStatus(e.target.value)}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<option value="全部">合作状态: 全部</option>
|
|
|
|
|
|
|
|
<option value="合作中">合作中</option>
|
|
|
|
|
|
|
|
<option value="暂停合作">暂停合作</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
<button className={styles.queryBtn} onClick={() => console.log('查询')}>
|
|
|
|
|
|
|
|
🔍 查询
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<button className={styles.resetBtn} onClick={() => {
|
|
|
|
|
|
|
|
setCustomerType('全部');
|
|
|
|
|
|
|
|
setCustomerLevel('全部');
|
|
|
|
|
|
|
|
setCooperationStatus('全部');
|
|
|
|
|
|
|
|
}}>
|
|
|
|
|
|
|
|
🔄 重置
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<button className={styles.addBtn}>
|
|
|
|
|
|
|
|
➕ 新增客户
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<button className={styles.exportBtn}>
|
|
|
|
|
|
|
|
📥 批量导出
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 表格 */}
|
|
|
|
{/* 最近活动列表 */}
|
|
|
|
<div className={styles.tableWrapper}>
|
|
|
|
<div className={styles.activityCard} style={{ flex: 9 }}>
|
|
|
|
<table className={styles.dataTable}>
|
|
|
|
<div className={styles.chartHeader}>
|
|
|
|
<thead>
|
|
|
|
<div className={styles.chartTitle}>最近活动</div>
|
|
|
|
<tr>
|
|
|
|
</div>
|
|
|
|
<th>
|
|
|
|
<div className={styles.activityGrid}>
|
|
|
|
<input
|
|
|
|
{recentActivities.map((activity) => (
|
|
|
|
type="checkbox"
|
|
|
|
<div key={activity.id} className={styles.activityCardItem}>
|
|
|
|
checked={selectedRows.length === tableData.length}
|
|
|
|
<div className={styles.activityCardHeader}>
|
|
|
|
onChange={handleSelectAll}
|
|
|
|
<div className={styles.activityCardTitle}>{activity.title}</div>
|
|
|
|
/>
|
|
|
|
<div className={styles.activityCardTime}>{activity.time}</div>
|
|
|
|
</th>
|
|
|
|
</div>
|
|
|
|
<th>客户名称</th>
|
|
|
|
<div className={styles.activityCardDesc}>{activity.description}</div>
|
|
|
|
<th>联系人</th>
|
|
|
|
</div>
|
|
|
|
<th>联系电话</th>
|
|
|
|
|
|
|
|
<th>分类</th>
|
|
|
|
|
|
|
|
<th>交易额度(月)</th>
|
|
|
|
|
|
|
|
<th>合作状态</th>
|
|
|
|
|
|
|
|
<th>满意度</th>
|
|
|
|
|
|
|
|
<th>操作</th>
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
|
|
{tableData.map((row) => (
|
|
|
|
|
|
|
|
<tr key={row.id}>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
|
|
checked={selectedRows.includes(row.id)}
|
|
|
|
|
|
|
|
onChange={() => handleSelectRow(row.id)}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>{row.customerName}</td>
|
|
|
|
|
|
|
|
<td>{row.contact}</td>
|
|
|
|
|
|
|
|
<td>{row.phone}</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<span className={`${styles.tag} ${row.classification === '高价值' ? styles.tagGold : styles.tagBlue}`}>
|
|
|
|
|
|
|
|
{row.classification}
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>¥{row.monthlyAmount.toLocaleString()}</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<span className={`${styles.tag} ${row.cooperationStatus === '合作中' ? styles.tagGreen : styles.tagOrange}`}>
|
|
|
|
|
|
|
|
{row.cooperationStatus}
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<div className={styles.stars}>
|
|
|
|
|
|
|
|
{renderStars(row.satisfaction)}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<div className={styles.actionBtns}>
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
|
|
|
className={styles.actionBtn}
|
|
|
|
|
|
|
|
onClick={() => {
|
|
|
|
|
|
|
|
// 记录当前滚动位置
|
|
|
|
|
|
|
|
setPrevScrollY(window.pageYOffset || document.documentElement.scrollTop || 0);
|
|
|
|
|
|
|
|
setDetailData(row);
|
|
|
|
|
|
|
|
setShowDetail(true);
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
查看详情
|
|
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<button className={styles.actionBtn}>修改</button>
|
|
|
|
|
|
|
|
<button className={`${styles.actionBtn} ${styles.deleteBtn}`}>删除</button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
))}
|
|
|
|
))}
|
|
|
|
</tbody>
|
|
|
|
</div>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 分页 */}
|
|
|
|
{/* 客户列表区域 */}
|
|
|
|
<div className={styles.pagination}>
|
|
|
|
<div className={styles.bottomSection}>
|
|
|
|
<div className={styles.paginationInfo}>
|
|
|
|
<div className={styles.sectionHeader}>
|
|
|
|
共85条
|
|
|
|
<span className={styles.sectionBar} />
|
|
|
|
<select
|
|
|
|
<span className={styles.sectionTitle}>客户列表</span>
|
|
|
|
className={styles.pageSizeSelect}
|
|
|
|
|
|
|
|
value={pageSize}
|
|
|
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
|
|
|
setPageSize(Number(e.target.value));
|
|
|
|
|
|
|
|
setCurrentPage(1);
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<option value="10">10 / page</option>
|
|
|
|
|
|
|
|
<option value="20">20 / page</option>
|
|
|
|
|
|
|
|
<option value="50">50 / page</option>
|
|
|
|
|
|
|
|
<option value="100">100 / page</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className={styles.paginationControls}>
|
|
|
|
<div className={styles.filterContent}>
|
|
|
|
<button
|
|
|
|
<div className={styles.filterItem}>
|
|
|
|
className={styles.pageBtn}
|
|
|
|
<Input.Search
|
|
|
|
disabled={currentPage === 1}
|
|
|
|
placeholder="搜索关键词"
|
|
|
|
onClick={() => setCurrentPage(currentPage - 1)}
|
|
|
|
allowClear
|
|
|
|
>
|
|
|
|
value={searchKeyword}
|
|
|
|
‹
|
|
|
|
onChange={(e) => setSearchKeyword(e.target.value)}
|
|
|
|
</button>
|
|
|
|
onSearch={(val) => setSearchKeyword(val)}
|
|
|
|
{currentPage > 3 && (
|
|
|
|
style={{ minWidth: 150 }}
|
|
|
|
<>
|
|
|
|
/>
|
|
|
|
<button className={styles.pageBtn} onClick={() => setCurrentPage(1)}>1</button>
|
|
|
|
</div>
|
|
|
|
<span className={styles.pageEllipsis}>...</span>
|
|
|
|
<div className={styles.filterItem}>
|
|
|
|
</>
|
|
|
|
<span className={styles.filterLabel}>客户类型:</span>
|
|
|
|
)}
|
|
|
|
<Select
|
|
|
|
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
|
|
|
|
value={filters.customerType}
|
|
|
|
let pageNum;
|
|
|
|
onChange={(v) => setFilters({ ...filters, customerType: v })}
|
|
|
|
if (currentPage <= 3) {
|
|
|
|
placeholder="全部"
|
|
|
|
pageNum = i + 1;
|
|
|
|
options={[
|
|
|
|
} else if (currentPage >= totalPages - 2) {
|
|
|
|
{ label: '全部', value: '' },
|
|
|
|
pageNum = totalPages - 4 + i;
|
|
|
|
]}
|
|
|
|
} else {
|
|
|
|
allowClear
|
|
|
|
pageNum = currentPage - 2 + i;
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
if (pageNum > totalPages) return null;
|
|
|
|
<div className={styles.filterItem}>
|
|
|
|
return (
|
|
|
|
<span className={styles.filterLabel}>客户等级:</span>
|
|
|
|
<button
|
|
|
|
<Select
|
|
|
|
key={pageNum}
|
|
|
|
value={filters.customerGrade}
|
|
|
|
className={`${styles.pageBtn} ${currentPage === pageNum ? styles.pageBtnActive : ''}`}
|
|
|
|
onChange={(v) => setFilters({ ...filters, customerGrade: v })}
|
|
|
|
onClick={() => setCurrentPage(pageNum)}
|
|
|
|
placeholder="全部"
|
|
|
|
>
|
|
|
|
options={[
|
|
|
|
{pageNum}
|
|
|
|
{ label: '全部', value: '' },
|
|
|
|
</button>
|
|
|
|
]}
|
|
|
|
);
|
|
|
|
allowClear
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
{currentPage < totalPages - 2 && (
|
|
|
|
</div>
|
|
|
|
<>
|
|
|
|
<div className={styles.filterItem}>
|
|
|
|
<span className={styles.pageEllipsis}>...</span>
|
|
|
|
<span className={styles.filterLabel}>合作状态:</span>
|
|
|
|
<button className={styles.pageBtn} onClick={() => setCurrentPage(totalPages)}>{totalPages}</button>
|
|
|
|
<Select
|
|
|
|
</>
|
|
|
|
value={filters.cooperationStatus}
|
|
|
|
)}
|
|
|
|
onChange={(v) => setFilters({ ...filters, cooperationStatus: v })}
|
|
|
|
<button
|
|
|
|
placeholder="全部"
|
|
|
|
className={styles.pageBtn}
|
|
|
|
options={[
|
|
|
|
disabled={currentPage === totalPages}
|
|
|
|
{ label: '全部', value: '' },
|
|
|
|
onClick={() => setCurrentPage(currentPage + 1)}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
allowClear
|
|
|
|
›
|
|
|
|
/>
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<Space className={styles.filterButtons}>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
|
|
icon={<SearchOutlined />}
|
|
|
|
|
|
|
|
className={styles.queryBtn}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
查询
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
icon={<ReloadOutlined />}
|
|
|
|
|
|
|
|
className={styles.resetBtn}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
重置
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
|
|
<Space className={styles.filterButtonsRight}>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
|
|
icon={<PlusOutlined />}
|
|
|
|
|
|
|
|
className={styles.addBtn}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
新增客户
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
|
|
|
// icon={<ExportOutlined />}
|
|
|
|
|
|
|
|
className={styles.exportBtn}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
批量导出
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.tableWrapper}>
|
|
|
|
|
|
|
|
<StandardTable
|
|
|
|
|
|
|
|
rowKey="id"
|
|
|
|
|
|
|
|
columns={columns}
|
|
|
|
|
|
|
|
data={{
|
|
|
|
|
|
|
|
list: tableData,
|
|
|
|
|
|
|
|
pagination: {
|
|
|
|
|
|
|
|
total: tableData.length,
|
|
|
|
|
|
|
|
pageSize,
|
|
|
|
|
|
|
|
current: currentPage,
|
|
|
|
|
|
|
|
showTotal: (total) => `共 ${total} 条`,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
selectionType="checkbox"
|
|
|
|
|
|
|
|
selectedRowKeys={selectedRows}
|
|
|
|
|
|
|
|
onSelectRow={(row) => handleSelectRow(row.id)}
|
|
|
|
|
|
|
|
onSelectAll={(checked) => checked ? setSelectedRows(tableData.map(i => i.id)) : setSelectedRows([])}
|
|
|
|
|
|
|
|
onChangePage={(page) => setCurrentPage(page)}
|
|
|
|
|
|
|
|
onChangePageSize={(size) => { setPageSize(size); setCurrentPage(1); }}
|
|
|
|
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|