Commit bc271234 authored by 邓晓峰's avatar 邓晓峰

Merge branch 'fix/table' into 'dev'

fix: update table See merge request !27
parents a834a2fe 49522451
Pipeline #25747 failed with stages
in 8 seconds
......@@ -45,7 +45,7 @@ const Demo = () => {
return (
<div style={{ height: '400px' }}>
{!!dataSource.length && (
<BasicTable dataSource={dataSource} columns={columns} scroll={{ y: 294 }} />
<BasicTable dataSource={dataSource} columns={columns} bordered={true} />
)}
{!dataSource.length && <Empty description={'暂无数据'} />}
</div>
......
......@@ -8,7 +8,7 @@ const BasicTable = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('basic-table');
return <Table className={classNames(prefixCls)} {...props} bordered />;
return <Table className={classNames(prefixCls)} scroll={{ y: 'calc(100% - 40px)' }} {...props} />;
};
BasicTable.defaultProps = {
......
......@@ -2,16 +2,21 @@
@basic-table-prefix-cls: ~'@{ant-prefix}-basic-table';
.@{basic-table-prefix-cls} {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
.ant-table-wrapper,
.ant-spin-nested-loading,
.ant-spin-container {
height: 100%;
}
.ant-table.ant-table-bordered {
height: calc(100% - 64px);
.ant-spin-container,
.ant-table,
.ant-table-container,
.ant-table-content {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
}
.ant-table-tbody > tr {
......@@ -22,10 +27,6 @@
background: rgba(255, 255, 255, 0);
}
.ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td {
background: rgba(255, 255, 255, 0);
}
.ant-table-thead > tr > th {
font-weight: 600;
background: white;
......@@ -37,7 +38,10 @@
.ant-table tfoot > tr > th,
.ant-table tfoot > tr > td {
padding: 8px 8px;
border-right: 1px solid #dbe7fb;
}
.ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td {
background: rgba(255, 255, 255, 0);
}
.ant-table-tbody > tr:nth-child(2n-1) {
......@@ -48,6 +52,10 @@
background: #edf2ff;
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid #dbe7fb;
}
.ant-table.ant-table-bordered
> .ant-table-container
> .ant-table-content
......@@ -116,8 +124,4 @@
border-right: 0;
border-bottom: 0;
}
.ant-table-tbody > tr > td {
border-bottom: 1px solid #dbe7fb;
}
}
......@@ -2,17 +2,24 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { ConfigProvider } from 'antd';
import noDataLight from './assets/noDataLight.svg';
import noDataDark from './assets/noDataDark.svg';
import { ReactComponent as noDataLight } from './assets/noDataLight.svg';
import { ReactComponent as noDataDark } from './assets/noDataDark.svg';
import errorLight from './assets/errorLight.png';
import errorDark from './assets/errorDark.png';
import './index.less';
const IconBase = ({ icon: SvgIcon }) => {
const SvgAttributes = {
width: '100%',
height: '100%',
};
return <SvgIcon {...SvgAttributes} />;
};
const Empty = ({ description, image, theme, size, statusCode, imageStyle, children }) => {
const alt = description ? description : 'empty';
const des = description ? description : DESC_DATA[`${statusCode}`];
const imageSrc = image ? image : IMAGE_DATA[theme][statusCode == '0' ? 0 : 1];
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('panda-empty');
......@@ -20,7 +27,12 @@ const Empty = ({ description, image, theme, size, statusCode, imageStyle, childr
let imageNode = null;
if (typeof image === 'string') {
if (statusCode == '0') {
imageNode = <IconBase icon={IMAGE_DATA[theme][0]} />;
} else {
let imageSrc = image ? image : IMAGE_DATA[theme][1];
imageNode = <img alt={alt} src={imageSrc} />;
}
} else {
imageNode = image;
}
......
......@@ -30,14 +30,14 @@ group:
已选指标树 props 参考 https://ant.design/components/tree-cn/#API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| -------------- | ------------------------------ | ------------------ | -------------- |
| buttonProps | 指标选择按钮 | object | { } |
| width | 模态框宽度 | number | 900 |
| title | 模态框标题 | string | 选择显示字段 |
| cancelText | 模态框取消文本 | string | 取消选择 |
| cancelText | 模态框取消按钮文字 | string | 取消选择 |
| okText | 模态框确认按钮文字 | string | 确定 |
| placeholder | 搜索框占位符 | string | 搜索关键词 |
| searchPrefix | 搜索框前置图标 | ReactNode | SearchOutlined |
| targetValue | 指标类型 | string | 重要指标 |
| maximum | 最多可选择指标数量 | number | 0 |
| dataSource | 指标列表数据源 | array | [ ] |
| selectData | 已选指标数据 | array | [ ] |
......@@ -45,6 +45,5 @@ group:
| onModalCancel | 点击模态框取消按钮的回调 | function(value){ } | - |
| onModalOk | 模态框点击确定回调 | function(value){ } | - |
| onModalClose | 模态框点击关闭回调 | function(value){ } | - |
| onSearch | 搜索框输入事件的回调,会返回搜索框输入信息 | function(value){ } | - |
| onRadioChange | 指标类型切换的回调 | function(value){ } | - |
| onTreeDrop | 拖动选中树节点的回调 | function(value){ } | - |
| onCancelSelect | 点击已选指标树的删除按钮的回调 | function(value){ } | - |
......@@ -18,12 +18,7 @@ const Demo = () => {
})
.then(function (response) {
if (response.code == '0') {
let curData = response.data.map((item) => ({
title: item.Name,
key: item.Name,
checked: false,
...item,
}));
let curData = response.data;
setQuotaList(curData);
}
})
......@@ -45,114 +40,23 @@ const Demo = () => {
};
const onModalCancel = () => {
let newQuotaList = [...quotaList];
newQuotaList.forEach((item) => {
item.checked = false;
});
setQuotaList(newQuotaList);
setSelectData([]);
console.log('onModalCancel');
};
const onCheckboxChange = (e) => {
let curData = [...selectData];
let newQuotaList = [...quotaList];
let data = curData.filter((item) => item.title === e.target.value);
if (data.length) {
curData = curData.filter((item) => item.title !== e.target.value);
} else {
curData.push({ key: e.target.value, title: e.target.value });
}
newQuotaList.forEach((item) => {
if (item.title === e.target.value) item.checked = !item.checked;
});
setSelectData(curData);
setQuotaList(newQuotaList);
console.log(e.target.value, 'onCheckboxChange');
};
const onSearch = (e) => {
if (e.type === 'keydown') {
console.log(e.target.value, 'onSearch');
}
};
const onRadioChange = (e) => {
console.log(e, 'onRadioChange');
};
const onCancelSelect = ({ title }) => {
let curData = [...selectData];
let newQuotaList = [...quotaList];
let data = curData.filter((item) => item.title !== title);
newQuotaList.forEach((item) => {
if (item.title === title) item.checked = !item.checked;
});
setSelectData(data);
setQuotaList(newQuotaList);
console.log(title, 'onCancelSelect');
const onCheckboxChange = ({ selectList }) => {
setSelectData(selectList);
console.log(selectList, 'onCheckboxChange');
};
const onDragEnter = (info) => {
console.log(info, 'onDragEnter');
};
const onDrop = (info) => {
console.log(info, 'onDrop');
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
const loop = (data, key, callback) => {
for (let i = 0; i < data.length; i++) {
if (data[i].key === key) {
return callback(data[i], i, data);
}
if (data[i].children) {
loop(data[i].children, key, callback);
}
}
const onCancelSelect = ({ selectList }) => {
setSelectData(selectList);
console.log(selectList, 'onCancelSelect');
};
const data = [...selectData];
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (!info.dropToGap) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else if (
(info.node.props.children || []).length > 0 && // Has children
info.node.props.expanded && // Is expanded
dropPosition === 1 // On the bottom gap
) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
setSelectData(data);
const onTreeDrop = ({ selectList }) => {
setSelectData(selectList);
console.log(selectList, 'onTreeDrop');
};
return (
......@@ -165,19 +69,11 @@ const Demo = () => {
onModalOk={onModalOk}
onModalClose={onModalClose}
maximum={3}
targetValue={'emphasis'}
dataSource={quotaList}
selectData={selectData}
onSearch={onSearch}
searchPrefix={<SearchOutlined />}
onRadioChange={onRadioChange}
onCheckboxChange={onCheckboxChange}
onCancelSelect={onCancelSelect}
treeProps={{
draggable: true,
onDragEnter,
onDrop,
}}
onTreeDrop={onTreeDrop}
/>
);
};
......
import React, { useContext, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Button, Input, Radio, Modal, Checkbox, Row, Col, Tree, ConfigProvider } from 'antd';
......@@ -13,25 +13,67 @@ const QuotaSelect = ({
width,
title,
cancelText,
okText,
onModalOk,
onModalCancel,
onModalClose,
searchPrefix,
placeholder,
targetValue,
maximum,
dataSource,
selectData,
onSearch,
onRadioChange,
onCheckboxChange,
onCancelSelect,
treeProps,
onTreeDrop,
}) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('quota-select');
const [visible, setVisible] = useState(false);
const [targetValue, setTargetValue] = useState('emphasis');
const [allQuotaList, setAllQuotaList] = useState([]);
const [quotaList, setQuotaList] = useState([]);
useEffect(() => {
if (dataSource.length > 0) {
let data = dataSource.map((item) => ({
...item,
checked: false,
title: item.Name,
key: item.Name,
}));
setAllQuotaList(data);
}
}, [dataSource]);
useEffect(() => {
if (targetValue === 'emphasis') {
filterEmphasisQuota();
}
}, [allQuotaList]);
useEffect(() => {
let data = [...allQuotaList];
data.forEach((item) => {
item.checked = false;
if (selectData.length > 0) {
selectData.forEach((child) => {
if (child.key === item.key) {
item.checked = true;
}
});
}
});
setAllQuotaList(data);
}, [selectData]);
// 过滤重点指标
const filterEmphasisQuota = () => {
let newQuotaList = [...allQuotaList];
newQuotaList = newQuotaList.filter((item) => item.IsShow === '1');
setQuotaList(newQuotaList);
};
// 展示模态框
const showModal = () => {
......@@ -48,11 +90,134 @@ const QuotaSelect = ({
}
};
const onOk = (e) => {
const onOk = () => {
onModalOk && onModalOk();
setVisible(false);
};
// 切换重点与全部
const onRadioChange = (e) => {
if (e.target.value === 'all') {
setQuotaList(allQuotaList);
} else {
filterEmphasisQuota();
}
setTargetValue(e.target.value);
};
// 搜索指标
const onSearch = (e) => {
if (e.type === 'keydown' || e.target.value === '') {
if (e.target.value !== '') {
let newQuotaList = [];
quotaList.forEach((item) => {
if (item.Name.indexOf(e.target.value) > -1) newQuotaList.push(item);
});
setQuotaList(newQuotaList);
} else {
if (targetValue === 'all') {
setQuotaList(allQuotaList);
} else {
filterEmphasisQuota();
}
}
}
};
// 处理复选框点击事件
const handleCheckboxChange = (e) => {
let newQuotaList = [...allQuotaList];
let curSelectKey = [];
let curSelectList = [...selectData];
let data = curSelectList.filter((item) => item.title === e.target.value);
if (data.length) {
curSelectList = curSelectList.filter((item) => item.title !== e.target.value);
} else {
curSelectList.push({ key: e.target.value, title: e.target.value });
}
newQuotaList.forEach((item) => {
if (item.title === e.target.value) {
item.checked = !item.checked;
}
});
curSelectKey = curSelectList.map((item) => item.key);
onCheckboxChange({
selectKey: curSelectKey,
selectList: curSelectList,
});
setAllQuotaList(newQuotaList);
};
// 处理取消选择按钮点击事件
const handleCancelSelect = ({ title }) => {
let data = [...selectData];
data = data.filter((item) => item.title !== title);
onCancelSelect({
selectKey: data.map((item) => item.key),
selectList: data,
});
};
// 拖动选中树节点
const handleDrop = (info) => {
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
const loop = (data, key, callback) => {
for (let i = 0; i < data.length; i++) {
if (data[i].key === key) {
return callback(data[i], i, data);
}
if (data[i].children) {
loop(data[i].children, key, callback);
}
}
};
const data = [...selectData];
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (!info.dropToGap) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else if (
(info.node.props.children || []).length > 0 && // Has children
info.node.props.expanded && // Is expanded
dropPosition === 1 // On the bottom gap
) {
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
onTreeDrop({
selectKey: data.map((item) => item.key),
selectList: data,
});
};
return (
<div className={classNames(prefixCls)}>
<Button {...buttonProps} onClick={showModal} />
......@@ -61,6 +226,7 @@ const QuotaSelect = ({
width={width}
title={title}
cancelText={cancelText}
okText={okText}
visible={visible}
onCancel={handleCancel}
onOk={onOk}
......@@ -103,10 +269,10 @@ const QuotaSelect = ({
</div>
</div>
<div className={classNames(`${prefixCls}-modal-option-wrap`)}>
{!dataSource.length && <Empty />}
{!quotaList.length && <Empty />}
<Row gutter={[0, 6]}>
{!!dataSource.length &&
dataSource.map((item) => (
{!!quotaList.length &&
quotaList.map((item) => (
<Col span={8} key={item.key}>
<Checkbox
value={item.title}
......@@ -115,7 +281,7 @@ const QuotaSelect = ({
(selectData.length > maximum || selectData.length === maximum) &&
!item.checked
}
onChange={onCheckboxChange}
onChange={handleCheckboxChange}
>
{item.title}
</Checkbox>
......@@ -129,14 +295,14 @@ const QuotaSelect = ({
已选:{selectData.length}/{maximum}
</div>
<div className={classNames(`${prefixCls}-modal-tree`)}>
<Tree {...treeProps}>
<Tree draggable={true} onDrop={handleDrop} {...treeProps}>
{selectData.map((item) => (
<TreeNode
key={item.key}
title={
<div className={classNames(`${prefixCls}-modal-tree-title`)}>
<div>{item.title}</div>
<CloseOutlined onClick={() => onCancelSelect(item)} />
<CloseOutlined onClick={() => handleCancelSelect(item)} />
</div>
}
/>
......@@ -155,9 +321,9 @@ QuotaSelect.defaultProps = {
width: 900,
title: '选择显示字段',
cancelText: '取消选择',
okText: '确定',
placeholder: '搜索关键词',
searchPrefix: <SearchOutlined />,
targetValue: 'emphasis',
maximum: 0,
dataSource: [],
selectData: [],
......@@ -165,9 +331,8 @@ QuotaSelect.defaultProps = {
onModalCancel: () => {},
onModalOk: () => {},
onModalClose: () => {},
onSearch: () => {},
onRadioChange: () => {},
onCancelSelect: () => {},
onTreeDrop: () => {},
};
QuotaSelect.propTypes = {
......@@ -175,9 +340,9 @@ QuotaSelect.propTypes = {
width: PropTypes.number,
title: PropTypes.string,
cancelText: PropTypes.string,
okText: PropTypes.string,
placeholder: PropTypes.string,
searchPrefix: PropTypes.node,
targetValue: PropTypes.string,
maximum: PropTypes.number,
dataSource: PropTypes.array,
selectData: PropTypes.array,
......@@ -185,9 +350,8 @@ QuotaSelect.propTypes = {
onModalCancel: PropTypes.func,
onModalOk: PropTypes.func,
onModalClose: PropTypes.func,
onSearch: PropTypes.func,
onRadioChange: PropTypes.func,
onCancelSelect: PropTypes.func,
onTreeDrop: PropTypes.func,
};
export default QuotaSelect;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment