This commit is contained in:
wanghaoo 2018-09-25 14:37:25 +08:00
commit ec825b944c
14 changed files with 14753 additions and 13822 deletions

BIN
demo/.DS_Store vendored

Binary file not shown.

Binary file not shown.

106
demo/demolist/Demo26.js Normal file
View File

@ -0,0 +1,106 @@
/**
*
* @title 按条件和值过滤
* @description 可以根据输入项目以及判断条件对表格内的数据进行过滤
*
*/
import React, { Component } from 'react';
import Table from '../../src';
const columns26 = [
{ title: "姓名", width: 180, dataIndex: "name", key: "name", filterType: "text", filterDropdown: "show" },
{ title: "年龄", width: 120, dataIndex: "age", key: "age", filterType: "dropdown" },
{ title: "日期", width: 200, dataIndex: "date", key: "date", filterType: "date" },
{ title: "居住地址", width: 120, dataIndex: "address", key: "address", filterType: "dropdown" },
{ title: "备注", dataIndex: "mark", key: "mark" }
];
const data26 = [
{
key: "1",
name: "John Brown",
age: 32,
date: "2018-09-18 09:46:44",
address: "朝阳区",
mark: "无"
},
{
key: "2",
name: "Jim Green",
age: 40,
date: "2018-09-18 09:46:44",
address: "朝阳区",
mark: "无"
},
{
key: "3",
name: "Jim Green",
age: 40,
date: "2018-09-18 09:46:44",
address: "东城区",
mark: "无"
},
{
key: "4",
name: "Jim Green",
age: 40,
date: "2018-09-18 09:46:44",
address: "东城区",
mark: "无"
}, {
key: "5",
name: "John Brown",
age: 32,
date: "2018-09-18 09:46:44",
address: "海淀区",
mark: "无"
},
{
key: "6",
name: "Jim Green",
age: 48,
date: "2018-09-18 09:46:44",
address: "海淀区",
mark: "无"
},
{
key: "7",
name: "Jim Green",
age: 40,
date: "2018-09-18 09:46:44",
address: "海淀区",
mark: "无"
},
{
key: "8",
name: "Jim Green",
age: 38,
date: "2018-09-18 09:46:44",
address: "海淀区",
mark: "无"
}
];
class Demo26 extends Component {
handlerFilterRowsChange = (key, val) => {
console.log('准备构建AJAX请求接收参数key=', key, ' value=', val);
}
handlerFilterRowsDropChange = (key, val) => {
console.log('过滤条件类型:', key, val);
}
render() {
return <Table
onFilterRowsDropChange={this.handlerFilterRowsDropChange}//下拉条件的回调(key,val)=>()
onFilterRowsChange={this.handlerFilterRowsChange}//触发输入操作以及其他的回调(key,val)=>()
filterDelay={500}//输入文本多少ms触发回调函数默认300ms
filterable={true}//是否开启过滤数据功能
bordered
columns={columns26}
data={data26} />;
}
}
export default Demo26;

File diff suppressed because one or more lines are too long

5
dist/demo.css vendored
View File

@ -8543,6 +8543,11 @@ ul {
pointer-events: none; }
.u-table-scroll-position-right .u-table-fixed-right {
box-shadow: none; }
.u-table-thead .filter-text, .u-table-thead .filter-dropdown, .u-table-thead .filter-date {
font-weight: normal; }
.u-table-thead .filter-wrap {
display: -ms-flexbox;
display: flex; }
.u-table-thead th {
background: #f7f7f7;
overflow: hidden;

2
dist/demo.css.map vendored

File diff suppressed because one or more lines are too long

27727
dist/demo.js vendored

File diff suppressed because one or more lines are too long

2
dist/demo.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -47,13 +47,16 @@
},
"dependencies": {
"bee-dnd": "^1.0.2",
"bee-dropdown": "^1.0.1",
"bee-loading": "^1.0.3",
"bee-menus": "^1.0.7",
"bee-popover": "^1.0.2",
"bee-select": "^1.0.8",
"classnames": "^2.2.5",
"lodash.clonedeep": "^4.5.0",
"object-path": "^0.11.3",
"shallowequal": "^1.0.2",
"throttle-debounce": "^2.0.1",
"tinper-bee-core": "latest",
"warning": "^3.0.0"
},
@ -88,4 +91,4 @@
"react-addons-test-utils": "^15.5.0",
"react-dom": "^15.5.0"
}
}
}

35
src/FilterDropDown.js Normal file
View File

@ -0,0 +1,35 @@
import React, { Component } from 'react';
import Dropdown from 'bee-dropdown';
import Menu from 'bee-menus';
import Button from 'bee-button';
import Icon from 'bee-icon';
const { Item } = Menu;
class FilterDropDown extends Component {
render() {
let dropmenu = (
<Menu
onSelect={this.props.onSelectDropdown}
>
<Item key="1">等于</Item>
<Item key="2">包含</Item>
<Item key="3">以结尾</Item>
<Item key="4"></Item>
<Item key="5">不等于</Item>
<Item key="6">不包含</Item>
<Item key="7">以开始</Item>
</Menu>
);
return (
<Dropdown
trigger={['click']}
overlay={dropmenu}
animation="slide-up"
>
<Button shape="border" style={{ marginLeft: "5px", minWidth: "0px", width: "38px", padding: 0 }}><Icon style={{ padding: 0 }} type="uf-navmenu" /></Button>
</Dropdown>
);
}
}
export default FilterDropDown;

57
src/FilterType.js Normal file
View File

@ -0,0 +1,57 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import FormControl from 'bee-form-control';
import Select from 'bee-select';
import DatePicker from 'bee-datepicker';
import FilterDropDown from './FilterDropDown';
const propTypes = {
filterDropdown: PropTypes.string
};
class FilterType extends Component {
renderControl = (rendertype) => {
let { filterDropdown, className, onChange, onSelectDropdown, clsPrefix } = this.props;
switch (rendertype) {
case 'text':
return <div className={`${clsPrefix} filter-wrap`}><FormControl
className={className}
onChange={onChange}
/>
{filterDropdown == 'show' && <FilterDropDown
onSelectDropdown={onSelectDropdown}
>
</FilterDropDown>}
</div>
case 'dropdown':
return <div className={`${clsPrefix} filter-wrap`}><Select
{...this.props}
/>{filterDropdown == 'show' && <FilterDropDown
onSelectDropdown={onSelectDropdown}
>
</FilterDropDown>}</div>
case 'date':
return <div className={`${clsPrefix} filter-wrap`}><DatePicker
{...this.props}
/>{filterDropdown == 'show' && <FilterDropDown
onSelectDropdown={onSelectDropdown}
>
</FilterDropDown>}
</div>
default:
break;
}
}
render() {
let { rendertype } = this.props;
return (
this.renderControl(rendertype)
);
}
}
FilterType.propTypes = propTypes;
FilterType.defaultProps = {
filterDropdown: 'show'
}
export default FilterType;

View File

@ -10,92 +10,92 @@ import createStore from './createStore';
import Loading from 'bee-loading';
const propTypes = {
data: PropTypes.array,
expandIconAsCell: PropTypes.bool,
defaultExpandAllRows: PropTypes.bool,
expandedRowKeys: PropTypes.array,
defaultExpandedRowKeys: PropTypes.array,
useFixedHeader: PropTypes.bool,
columns: PropTypes.array,
clsPrefix: PropTypes.string,
bodyStyle: PropTypes.object,
style: PropTypes.object,
//特殊的渲染规则的key值
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
rowClassName: PropTypes.func,
expandedRowClassName: PropTypes.func,
childrenColumnName: PropTypes.string,
onExpand: PropTypes.func,
onExpandedRowsChange: PropTypes.func,
indentSize: PropTypes.number,
onRowClick: PropTypes.func,
onRowDoubleClick: PropTypes.func,
expandIconColumnIndex: PropTypes.number,
//是否显示表头
showHeader: PropTypes.bool,
title: PropTypes.func,
footer: PropTypes.func,
emptyText: PropTypes.func,
scroll: PropTypes.object,
rowRef: PropTypes.func,
getBodyWrapper: PropTypes.func,
children: PropTypes.node,
draggable: PropTypes.bool,
minColumnWidth:PropTypes.number
data: PropTypes.array,
expandIconAsCell: PropTypes.bool,
defaultExpandAllRows: PropTypes.bool,
expandedRowKeys: PropTypes.array,
defaultExpandedRowKeys: PropTypes.array,
useFixedHeader: PropTypes.bool,
columns: PropTypes.array,
clsPrefix: PropTypes.string,
bodyStyle: PropTypes.object,
style: PropTypes.object,
//特殊的渲染规则的key值
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
rowClassName: PropTypes.func,
expandedRowClassName: PropTypes.func,
childrenColumnName: PropTypes.string,
onExpand: PropTypes.func,
onExpandedRowsChange: PropTypes.func,
indentSize: PropTypes.number,
onRowClick: PropTypes.func,
onRowDoubleClick: PropTypes.func,
expandIconColumnIndex: PropTypes.number,
//是否显示表头
showHeader: PropTypes.bool,
title: PropTypes.func,
footer: PropTypes.func,
emptyText: PropTypes.func,
scroll: PropTypes.object,
rowRef: PropTypes.func,
getBodyWrapper: PropTypes.func,
children: PropTypes.node,
draggable: PropTypes.bool,
minColumnWidth: PropTypes.number
};
const defaultProps = {
data: [],
useFixedHeader: false,
expandIconAsCell: false,
defaultExpandAllRows: false,
defaultExpandedRowKeys: [],
rowKey: 'key',
rowClassName: () => '',
expandedRowClassName: () => '',
onExpand() {},
onExpandedRowsChange() {},
onRowClick() {},
onRowDoubleClick() {},
clsPrefix: 'u-table',
bodyStyle: {},
style: {},
childrenColumnName: 'children',
indentSize: 15,
expandIconColumnIndex: 0,
showHeader: true,
scroll: {},
rowRef: () => null,
getBodyWrapper: body => body,
emptyText: () => 'No Data',
minColumnWidth:80
data: [],
useFixedHeader: false,
expandIconAsCell: false,
defaultExpandAllRows: false,
defaultExpandedRowKeys: [],
rowKey: 'key',
rowClassName: () => '',
expandedRowClassName: () => '',
onExpand() { },
onExpandedRowsChange() { },
onRowClick() { },
onRowDoubleClick() { },
clsPrefix: 'u-table',
bodyStyle: {},
style: {},
childrenColumnName: 'children',
indentSize: 15,
expandIconColumnIndex: 0,
showHeader: true,
scroll: {},
rowRef: () => null,
getBodyWrapper: body => body,
emptyText: () => 'No Data',
minColumnWidth: 80
};
class Table extends Component{
constructor(props){
super(props);
let expandedRowKeys = [];
let rows = [...props.data];
this.columnManager = new ColumnManager(props.columns, props.children,props.originWidth);
this.store = createStore({ currentHoverKey: null });
class Table extends Component {
constructor(props) {
super(props);
let expandedRowKeys = [];
let rows = [...props.data];
this.columnManager = new ColumnManager(props.columns, props.children, props.originWidth);
this.store = createStore({ currentHoverKey: null });
if (props.defaultExpandAllRows) {
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
expandedRowKeys.push(this.getRowKey(row, i));
rows = rows.concat(row[props.childrenColumnName] || []);
}
} else {
expandedRowKeys = props.expandedRowKeys || props.defaultExpandedRowKeys;
}
this.state = {
expandedRowKeys,
data: props.data,
currentHoverKey: null,
scrollPosition: 'left',
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: [],
if (props.defaultExpandAllRows) {
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
expandedRowKeys.push(this.getRowKey(row, i));
rows = rows.concat(row[props.childrenColumnName] || []);
}
} else {
expandedRowKeys = props.expandedRowKeys || props.defaultExpandedRowKeys;
}
this.state = {
expandedRowKeys,
data: props.data,
currentHoverKey: null,
scrollPosition: 'left',
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: [],
}
this.onExpandedRowsChange = this.onExpandedRowsChange.bind(this);
this.onExpanded = this.onExpanded.bind(this);
@ -126,9 +126,9 @@ class Table extends Component{
}
componentDidMount() {
setTimeout(this.resetScrollY,300);
setTimeout(this.resetScrollY, 300);
//后续也放在recevice里面
if(!this.props.originWidth){
if (!this.props.originWidth) {
this.computeTableWidth();
}
if (this.columnManager.isAnyColumnsFixed()) {
@ -159,14 +159,14 @@ class Table extends Component{
} else if (nextProps.children !== this.props.children) {
this.columnManager.reset(null, nextProps.children);
}
if(!nextProps.originWidth){
if (!nextProps.originWidth) {
this.computeTableWidth();
}
}
componentDidUpdate() {
if (this.columnManager.isAnyColumnsFixed()) {
this.syncFixedTableRowHeight();
}
@ -202,8 +202,8 @@ class Table extends Component{
this.contentWidth = this.computeWidth;
this.setState({contentWidth:this.contentWidth});//重新渲染,为了显示滚动条
}
}
onExpandedRowsChange(expandedRowKeys) {
if (!this.props.expandedRowKeys) {
this.setState({ expandedRowKeys });
@ -211,7 +211,7 @@ class Table extends Component{
this.props.onExpandedRowsChange(expandedRowKeys);
}
onExpanded(expanded, record, index,e ) {
onExpanded(expanded, record, index, e) {
if (e) {
e.preventDefault();
e.stopPropagation();
@ -259,8 +259,8 @@ class Table extends Component{
}
getHeader(columns, fixed) {
const { showHeader, expandIconAsCell, clsPrefix ,onDragStart,onDragEnter,onDragOver,onDrop,draggable,
onMouseDown,onMouseMove,onMouseUp,dragborder,onThMouseMove,dragborderKey,minColumnWidth,headerHeight} = this.props;
const { filterDelay, onFilterRowsDropChange, onFilterRowsChange, filterable, showHeader, expandIconAsCell, clsPrefix, onDragStart, onDragEnter, onDragOver, onDrop, draggable,
onMouseDown, onMouseMove, onMouseUp, dragborder, onThMouseMove, dragborderKey, minColumnWidth, headerHeight } = this.props;
const rows = this.getHeaderRows(columns);
if (expandIconAsCell && fixed !== 'right') {
rows[0].unshift({
@ -271,31 +271,36 @@ class Table extends Component{
});
}
const trStyle =headerHeight?{height:headerHeight}:(fixed ? this.getHeaderRowStyle(columns, rows) : null);
let drop = draggable?{onDragStart,onDragOver,onDrop,onDragEnter,draggable}:{};
let dragBorder = dragborder?{onMouseDown,onMouseMove,onMouseUp,dragborder,onThMouseMove,dragborderKey}:{};
const trStyle = headerHeight ? { height: headerHeight } : (fixed ? this.getHeaderRowStyle(columns, rows) : null);
let drop = draggable ? { onDragStart, onDragOver, onDrop, onDragEnter, draggable } : {};
let dragBorder = dragborder ? { onMouseDown, onMouseMove, onMouseUp, dragborder, onThMouseMove, dragborderKey } : {};
let contentWidthDiff = 0;
//非固定表格,宽度不够时自动扩充
if(!fixed){
contentWidthDiff = this.state.contentWidthDiff
if (!fixed) {
contentWidthDiff = this.state.contentWidthDiff
}
return showHeader ? (
<TableHeader
{...drop}
{...dragBorder}
minColumnWidth={minColumnWidth}
contentWidthDiff = {contentWidthDiff}
lastShowIndex = {this.state.lastShowIndex}
contentWidthDiff={contentWidthDiff}
lastShowIndex={this.state.lastShowIndex}
clsPrefix={clsPrefix}
rows={rows}
contentTable = {this.contentTable}
contentTable={this.contentTable}
rowStyle={trStyle}
fixed={fixed}
filterable={filterable}
onFilterRowsChange={onFilterRowsChange}
onFilterRowsDropChange={onFilterRowsDropChange}
filterDelay={filterDelay}
/>
) : null;
}
getHeaderRows(columns, currentRow = 0, rows) {
let filterCol = [];
rows = rows || [];
rows[currentRow] = rows[currentRow] || [];
@ -310,10 +315,10 @@ class Table extends Component{
className: column.className || '',
children: column.title,
drgHover: column.drgHover,
fixed:column.fixed,
width:column.width
fixed: column.fixed,
width: column.width
};
if(column.onHeadCellClick){
if (column.onHeadCellClick) {
cell.onClick = column.onHeadCellClick;
}
if (column.children) {
@ -328,7 +333,23 @@ class Table extends Component{
if (cell.colSpan !== 0) {
rows[currentRow].push(cell);
}
//判断是否启用过滤
if (this.props.filterable) {
//组装Filter需要的Col
filterCol.push({
key: column.key,
children: "过滤渲染",
width: column.width,
filtertype: column.filterType,
dataindex: column.dataIndex,
datasource: this.props.data,
filterdropdown: column.filterDropdown
});
}
});
if (this.props.filterable) {
rows.push(filterCol);
}
return rows.filter(row => row.length > 0);
}
@ -343,12 +364,12 @@ class Table extends Component{
colCount = this.columnManager.leafColumns().length;
}
function contentContainer () {
if(content && content.props && content.props.style){
return (
<div style={{height: content.props.style.height}}></div>
)
}else{
function contentContainer() {
if (content && content.props && content.props.style) {
return (
<div style={{ height: content.props.style.height }}></div>
)
} else {
return ' '
}
}
@ -412,8 +433,8 @@ class Table extends Component{
expandedRowContent = expandedRowRender(record, i, indent);
}
//只有当使用expandedRowRender参数的时候才去识别isHiddenExpandIcon隐藏行展开的icon
if(expandedRowRender && typeof props.haveExpandIcon == 'function'){
isHiddenExpandIcon = props.haveExpandIcon(record, i);
if (expandedRowRender && typeof props.haveExpandIcon == 'function') {
isHiddenExpandIcon = props.haveExpandIcon(record, i);
}
const className = rowClassName(record, i, indent);
@ -423,16 +444,16 @@ class Table extends Component{
}
let fixedIndex = i;
//判断是否是tree结构
if(this.treeType){
if (this.treeType) {
fixedIndex = this.treeRowIndex;
}
if(props.fixedHeight){
if (props.fixedHeight) {
height = props.fixedHeight
}else{
height = (fixed && fixedColumnsBodyRowsHeight[fixedIndex]) ? fixedColumnsBodyRowsHeight[fixedIndex] : null;
} else {
height = (fixed && fixedColumnsBodyRowsHeight[fixedIndex]) ? fixedColumnsBodyRowsHeight[fixedIndex] : null;
}
let leafColumns;
@ -443,8 +464,8 @@ class Table extends Component{
} else {
leafColumns = this.columnManager.leafColumns();
}
rst.push(
<TableRow
indent={indent}
@ -495,14 +516,14 @@ class Table extends Component{
}
getRows(columns, fixed) {
//统计index只有含有鼠表结构才有用因为数表结构时固定列的索引取值有问题
this.treeRowIndex = 0;
//统计index只有含有鼠表结构才有用因为数表结构时固定列的索引取值有问题
this.treeRowIndex = 0;
return this.getRowsByData(this.state.data, true, 0, columns, fixed);
}
getColGroup(columns, fixed) {
let cols = [];
let {contentWidthDiff=0,lastShowIndex=0} = this.state;
let { contentWidthDiff = 0, lastShowIndex = 0 } = this.state;
if (this.props.expandIconAsCell && fixed !== 'right') {
cols.push(
<col
@ -521,9 +542,9 @@ class Table extends Component{
} else {
leafColumns = this.columnManager.leafColumns();
}
cols = cols.concat(leafColumns.map((c,i,arr) => {
cols = cols.concat(leafColumns.map((c, i, arr) => {
let width = c.width;
if(lastShowIndex == i ){
if (lastShowIndex == i) {
width = parseInt(width) + contentWidthDiff;
}
return <col key={c.key} style={{ width: width, minWidth: c.width }} />;
@ -531,21 +552,21 @@ class Table extends Component{
return <colgroup>{cols}</colgroup>;
}
renderDragHideTable=()=>{
const {columns,dragborder,dragborderKey} = this.props;
if(!dragborder)return null;
renderDragHideTable = () => {
const { columns, dragborder, dragborderKey } = this.props;
if (!dragborder) return null;
let sum = 0;
return(<div id={`u-table-drag-hide-table-${dragborderKey}`} className={`${this.props.clsPrefix}-hiden-drag`} >
return (<div id={`u-table-drag-hide-table-${dragborderKey}`} className={`${this.props.clsPrefix}-hiden-drag`} >
{
columns.map((da,i)=>{
sum += da.width?da.width:0;
return(<div className={`${this.props.clsPrefix}-hiden-drag-li`} key={da+"_hiden_"+i} style={{left:sum+"px"}}></div>);
columns.map((da, i) => {
sum += da.width ? da.width : 0;
return (<div className={`${this.props.clsPrefix}-hiden-drag-li`} key={da + "_hiden_" + i} style={{ left: sum + "px" }}></div>);
})
}
</div>);
}
getLeftFixedTable() {
getLeftFixedTable() {
return this.getTable({
columns: this.columnManager.leftColumns(),
fixed: 'left',
@ -568,9 +589,9 @@ class Table extends Component{
let tableClassName = '';
//表格元素的宽度大于容器的宽度也显示滚动条
if (scroll.x || fixed || this.contentDomWidth<this.contentWidth) {
if (scroll.x || fixed || this.contentDomWidth < this.contentWidth) {
tableClassName = `${clsPrefix}-fixed`;
if(!footerScroll){
if (!footerScroll) {
bodyStyle.overflowX = bodyStyle.overflowX || 'auto';
}
}
@ -609,7 +630,7 @@ class Table extends Component{
{this.getRows(columns, fixed)}
</tbody>
) : null;
let _drag_class = this.props.dragborder?"table-drag-bordered":""
let _drag_class = this.props.dragborder ? "table-drag-bordered" : ""
return (
<table className={` ${tableClassName} table-bordered ${_drag_class} `} style={tableStyle} >
{/* {this.props.dragborder?null:this.getColGroup(columns, fixed)} */}
@ -722,19 +743,19 @@ class Table extends Component{
syncFixedTableRowHeight() {
//this.props.height、headerHeight分别为用户传入的行高和表头高度如果有值所有行的高度都是固定的主要为了避免在千行数据中有固定列时获取行高度有问题
const { clsPrefix ,height,headerHeight} = this.props;
const { clsPrefix, height, headerHeight } = this.props;
const headRows = this.refs.headTable ?
this.refs.headTable.querySelectorAll('thead') :
this.refs.bodyTable.querySelectorAll('thead');
this.refs.headTable.querySelectorAll('thead') :
this.refs.bodyTable.querySelectorAll('thead');
const bodyRows = this.refs.bodyTable.querySelectorAll(`.${clsPrefix}-row`) || [];
const fixedColumnsHeadRowsHeight = [].map.call(
headRows, row => headerHeight?headerHeight:(row.getBoundingClientRect().height || 'auto')
headRows, row => headerHeight ? headerHeight : (row.getBoundingClientRect().height || 'auto')
);
const fixedColumnsBodyRowsHeight = [].map.call(
bodyRows, row => height?height:(row.getBoundingClientRect().height || 'auto')
bodyRows, row => height ? height : (row.getBoundingClientRect().height || 'auto')
);
if (shallowequal(this.state.fixedColumnsHeadRowsHeight, fixedColumnsHeadRowsHeight) &&
shallowequal(this.state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) {
shallowequal(this.state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) {
return;
}
this.setState({
@ -771,12 +792,12 @@ class Table extends Component{
const { scroll = {} } = this.props;
const { headTable, bodyTable, fixedColumnsBodyLeft, fixedColumnsBodyRight } = this.refs;
// Prevent scrollTop setter trigger onScroll event
// http://stackoverflow.com/q/1386696
if (e.target !== this.scrollTarget && this.scrollTarget !== headTable) {
return;
}
if ( e.target.scrollLeft !== this.lastScrollLeft) {
// Prevent scrollTop setter trigger onScroll event
// http://stackoverflow.com/q/1386696
if (e.target !== this.scrollTarget && this.scrollTarget !== headTable) {
return;
}
if (e.target.scrollLeft !== this.lastScrollLeft) {
if (e.target === bodyTable && headTable) {
headTable.scrollLeft = e.target.scrollLeft;
} else if (e.target === headTable && bodyTable) {
@ -824,14 +845,14 @@ class Table extends Component{
if (props.useFixedHeader || (props.scroll && props.scroll.y)) {
className += ` ${clsPrefix}-fixed-header`;
}
if(props.bordered){
if (props.bordered) {
className += ` ${clsPrefix}-bordered`;
}
className += ` ${clsPrefix}-scroll-position-${this.state.scrollPosition}`;
const isTableScroll = this.columnManager.isAnyColumnsFixed() ||
props.scroll.x ||
props.scroll.y;
props.scroll.x ||
props.scroll.y;
let loading = props.loading;
if (typeof loading === 'boolean') {
loading = {
@ -843,18 +864,18 @@ class Table extends Component{
{this.getTitle()}
<div className={`${clsPrefix}-content`}>
{this.columnManager.isAnyColumnsLeftFixed() &&
<div className={`${clsPrefix}-fixed-left`}>
{this.getLeftFixedTable()}
</div>}
<div className={`${clsPrefix}-fixed-left`}>
{this.getLeftFixedTable()}
</div>}
<div className={isTableScroll ? `${clsPrefix}-scroll` : ''}>
{this.getTable({ columns: this.columnManager.groupedColumns() })}
{this.getEmptyText()}
{this.getFooter()}
</div>
{this.columnManager.isAnyColumnsRightFixed() &&
<div className={`${clsPrefix}-fixed-right`}>
{this.getRightFixedTable()}
</div>}
<div className={`${clsPrefix}-fixed-right`}>
{this.getRightFixedTable()}
</div>}
</div>
<Loading
container={this}

View File

@ -272,7 +272,12 @@ $table-move-in-color: $bg-color-base;
}
&-thead{
.filter-text,.filter-dropdown,.filter-date {
font-weight: normal;
}
.filter-wrap{
display: flex;
}
th{
background: $table-head-background-color;
overflow: hidden;

View File

@ -1,157 +1,159 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import shallowequal from 'shallowequal';
import {tryParseInt,ObjectAssign} from './utils';
import { throttle, debounce } from 'throttle-debounce';
import { tryParseInt, ObjectAssign } from './utils';
import FilterType from './FilterType';
const propTypes = {
clsPrefix: PropTypes.string,
rowStyle: PropTypes.object,
rows: PropTypes.array,
clsPrefix: PropTypes.string,
rowStyle: PropTypes.object,
rows: PropTypes.array,
}
const grap = 16;//偏移数值
class TableHeader extends Component{
class TableHeader extends Component {
constructor(props){
constructor(props) {
super(props);
this.currentObj = null;
this.state = {
border:false
border: false
}
//拖拽宽度处理
if(!props.dragborder)return;
if (!props.dragborder) return;
this.border = false;
this.theadKey = new Date().getTime();
this.drag = {
initPageLeftX:0,
initLeft:0,
x:0,
width:0,
initPageLeftX: 0,
initLeft: 0,
x: 0,
width: 0,
}
// let _da = {};
// Object.assign(_da,this.props.rows[0]);
// this.drag.data = JSON.parse(JSON.stringify(this.props.rows[0]));
// let a = this.props.rows[0];
let _row = [];
this.props.rows[0].forEach(item => {
let newItem = item.key != "checkbox"?ObjectAssign(item):item;
let newItem = item.key != "checkbox" ? ObjectAssign(item) : item;
_row.push(newItem);
});
this.drag.data = _row;//JSON.parse(JSON.stringify(this.props.rows[0]));
}
static defaultProps = {
contentWidthDiff:0
contentWidthDiff: 0
}
shouldComponentUpdate(nextProps) {
return !shallowequal(nextProps, this.props);
}
onDragStart=(event,data)=>{
onDragStart = (event, data) => {
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("Text",data.key);
event.dataTransfer.setData("Text", data.key);
this.currentObj = data;
event.dataTransfer.setDragImage(event.target, 0, 0);
this.props.onDragStart(event,data);
this.props.onDragStart(event, data);
}
onDragOver=(event,data)=>{
if(!this.currentObj || this.currentObj.key == data.key)return;
onDragOver = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
event.preventDefault();
this.props.onDragOver(event,data);
this.props.onDragOver(event, data);
}
onDragEnter=(event,data)=>{
if(!this.currentObj || this.currentObj.key == data.key)return;
this.props.onDragEnter(event,data);
onDragEnter = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDragEnter(event, data);
}
onDrop=(event,data)=>{
if(!this.currentObj ||this.currentObj.key == data.key)return;
this.props.onDrop(event,data);
onDrop = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDrop(event, data);
}
onMouseOver=(event,data)=>{
onMouseOver = (event, data) => {
//如果是固定列没有拖拽功能
if(this.border || data.fixed)return;
const {clsPrefix} = this.props;
if (this.border || data.fixed) return;
const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`;
}
onMouseMove=(event,data)=>{
onMouseMove = (event, data) => {
//如果是固定列没有拖拽功能
if(this.border || data.fixed)return;
if (this.border || data.fixed) return;
// const {clsPrefix} = this.props;
// event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`;
}
onMouseOut=(event,data)=>{
if(this.border)return;
const {clsPrefix} = this.props;
onMouseOut = (event, data) => {
if (this.border) return;
const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
}
onMouseDown=(event,data)=>{
onMouseDown = (event, data) => {
this.border = true;
const {clsPrefix,contentTable} = this.props;
const { clsPrefix, contentTable } = this.props;
this.drag.initPageLeftX = event.pageX;
this.drag.initLeft = tryParseInt(event.target.style.left);
this.drag.x = this.drag.initLeft;
this.drag.currIndex = this.props.rows[0].findIndex(da=>da.key==data.key);
this.drag.currIndex = this.props.rows[0].findIndex(da => da.key == data.key);
this.drag.width = this.drag.data[this.drag.currIndex].width;
let contentTableDom = document.getElementById("u-table-drag-thead-"+this.theadKey).parentNode;
let contentTableDom = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
const styleWidth = contentTableDom.style.width;
if(styleWidth && (typeof (styleWidth)=='number'|| styleWidth.includes('px') )){
this.contentTableWidth = parseInt(styleWidth);
}else{
this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
if (styleWidth && (typeof (styleWidth) == 'number' || styleWidth.includes('px'))) {
this.contentTableWidth = parseInt(styleWidth);
} else {
this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
}
}
onMouseUp=(event,data)=>{
onMouseUp = (event, data) => {
this.border = false;
const {clsPrefix} = this.props;
const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
}
onThMouseUp=(event,data)=>{
onThMouseUp = (event, data) => {
this.border = false;
const {clsPrefix} = this.props;
const { clsPrefix } = this.props;
let eventDom = event.target;
let optDom ;
if(eventDom.classList.contains('.th-drag-gap-hover')){
let optDom;
if (eventDom.classList.contains('.th-drag-gap-hover')) {
optDom = eventDom;
}else{
} else {
optDom = eventDom.querySelector(`.${clsPrefix}-thead-th-drag-gap`);
}
if(optDom){
if (optDom) {
optDom.classList.remove('th-drag-gap-hover');
optDom.classList.add('th-drag-gap');
}
}
onThMouseMove=(event,data)=>{
if(!this.border)return;
onThMouseMove = (event, data) => {
if (!this.border) return;
//固定表头拖拽
const {dragborderKey,contentTable} = this.props;
let x = (event.pageX - this.drag.initPageLeftX) + this.drag.initLeft-0;
let contentTableDom = document.getElementById("u-table-drag-thead-"+this.theadKey).parentNode;
if(!this.contentTableWidth){
const { dragborderKey, contentTable } = this.props;
let x = (event.pageX - this.drag.initPageLeftX) + this.drag.initLeft - 0;
let contentTableDom = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
if (!this.contentTableWidth) {
const styleWidth = contentTableDom.style.width;
if(styleWidth && (typeof (styleWidth)=='number'|| styleWidth.includes('px') )){
if (styleWidth && (typeof (styleWidth) == 'number' || styleWidth.includes('px'))) {
this.contentTableWidth = parseInt(styleWidth);
}else{
} else {
this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
}
}
const newTableWidth = this.contentTableWidth + x;
const newWidth = this.drag.width + x;
if(newWidth<this.props.minColumnWidth){
if (newWidth < this.props.minColumnWidth) {
//清楚样式
let moveDom = event.target.querySelector('.th-drag-gap-hover');
moveDom && moveDom.classList.remove('th-drag-gap-hover');
@ -160,15 +162,15 @@ class TableHeader extends Component{
}
//设置hiden的left
//"u-table-drag-hide-table"
let currentHideDom = document.getElementById("u-table-drag-hide-table-"+dragborderKey).getElementsByTagName("div")[this.drag.currIndex];
currentHideDom.style.left = (this.drag.initPageLeftX+x-grap)+"px";
let currentHideDom = document.getElementById("u-table-drag-hide-table-" + dragborderKey).getElementsByTagName("div")[this.drag.currIndex];
currentHideDom.style.left = (this.drag.initPageLeftX + x - grap) + "px";
//获取最小宽度,不让拖动
// let minWidth = 0;
// for(let i=0;i<=this.drag.currIndex;i++){
// minWidth += this.drag.data[i].width;
// }
// //判断最小值后在赋值 todo
// let currLeft = this.drag.initPageLeftX+x-grap;
// console.log("currLeft minWidth ",currLeft + " "+minWidth);
@ -178,10 +180,10 @@ class TableHeader extends Component{
// currentHideDom.style.left = currLeft+"px";
//设置当前的宽度
let currentData = this.drag.data[this.drag.currIndex];
currentData.width = newWidth;
let currentDom = document.getElementById("u-table-drag-thead-"+this.theadKey).getElementsByTagName("th")[this.drag.currIndex];
currentDom.style.width = newWidth+"px";
let currentData = this.drag.data[this.drag.currIndex];
currentData.width = newWidth;
let currentDom = document.getElementById("u-table-drag-thead-" + this.theadKey).getElementsByTagName("th")[this.drag.currIndex];
currentDom.style.width = newWidth + "px";
// this.contentTableWidth = newTableWidth;
contentTableDom.style.width = newTableWidth+'px';
this.drag.x = x;
@ -189,71 +191,145 @@ class TableHeader extends Component{
contentColDomArr[this.drag.currIndex].style.width = newWidth+"px" ;
//固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动
const siblingDom = contentTableDom.parentNode.nextElementSibling;
if(siblingDom){
if (siblingDom) {
const bodyTableDom = siblingDom.querySelector('table')
//2、是的话将表头对应的表格的宽度给表体对应的表格的宽度
bodyTableDom.style.width = newTableWidth+'px';
bodyTableDom.style.width = newTableWidth + 'px';
//3、对应的col也要跟这变
let colDomArr = bodyTableDom.querySelectorAll('colgroup col')
colDomArr[this.drag.currIndex].style.width = newWidth+"px" ;
colDomArr[this.drag.currIndex].style.width = newWidth + "px";
//4、设置overflow属性
}
}
/**
* @description 过滤输入后的回调函数
*/
handlerFilterTextChange = (key, val) => {
let { onFilterRowsChange } = this.props;
if (onFilterRowsChange) {
onFilterRowsChange(key, val);
}
}
/**
* @description 过滤输入后的回调函数
*/
handlerFilterDropChange = (key, val) => {
let { onFilterRowsDropChange } = this.props;
if (onFilterRowsDropChange) {
onFilterRowsDropChange(key, val.key);
}
}
/**
* @description 过滤渲染的组件类型
*/
filterRenderType = (type, dataIndex, index) => {
const { clsPrefix, rows, filterDelay } = this.props;
switch (type) {
//文本输入
case 'text':
return <FilterType
rendertype={type}
clsPrefix={clsPrefix}
className={`${clsPrefix} filter-text`}
onChange={debounce(filterDelay || 300, this.handlerFilterTextChange.bind(this, dataIndex))}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
filterDropdown={rows[1][index]['filterdropdown']}
/>
//下拉框选择
case 'dropdown':
let selectDataSource = [];
if (rows.length > 0) {
let hash = {};
//处理下拉重复对象组装dropdown
selectDataSource = Array.from(rows[1][0].datasource, x => ({ key: x[dataIndex], value: x[dataIndex] }));
selectDataSource = selectDataSource.reduceRight((item, next) => {
hash[next.key] ? '' : hash[next.key] = true && item.push(next);
return item
}, []);
}
return <FilterType
rendertype={type}
className={`${clsPrefix} filter-dropdown`}
data={selectDataSource}
onChange={this.handlerFilterTextChange.bind(this, dataIndex)}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
filterDropdown={rows[1][index]['filterdropdown']}
/>
//日期
case 'date':
return <FilterType
rendertype={type}
className={`${clsPrefix} filter-date`}
onClick={() => { }}
onChange={this.handlerFilterTextChange.bind(this, dataIndex)}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
filterDropdown={rows[1][index]['filterdropdown']}
/>
default:
//不匹配类型默认文本输入
return <div></div>
}
}
render() {
const { clsPrefix, rowStyle ,onDragStart,onDragOver,onDrop,draggable,rows,
onMouseDown,onMouseMove,onMouseUp,dragborder,onMouseOut,contentWidthDiff,fixed,lastShowIndex
} = this.props;
let attr = dragborder?{id:`u-table-drag-thead-${this.theadKey}`}:{}
const { clsPrefix, rowStyle, onDragStart, onDragOver, onDrop, draggable, rows, filterable, onFilterRowsChange,
onMouseDown, onMouseMove, onMouseUp, dragborder, onMouseOut, contentWidthDiff, fixed, lastShowIndex
} = this.props;
let attr = dragborder ? { id: `u-table-drag-thead-${this.theadKey}` } : {}
return (
<thead className={`${clsPrefix}-thead`} {...attr}>
{
rows.map((row, index) => (
<tr key={index} style={rowStyle}>
{row.map((da, i,arr) => {
let thHover = da.drgHover?` ${clsPrefix}-thead th-drag-hover`:"";
{row.map((da, i, arr) => {
let thHover = da.drgHover ? ` ${clsPrefix}-thead th-drag-hover` : "";
delete da.drgHover;
let fixedStyle='';
if(!fixed && da.fixed){
fixedStyle=`${clsPrefix}-row-fixed-columns-in-body`;
let fixedStyle = '';
if (!fixed && da.fixed) {
fixedStyle = `${clsPrefix}-row-fixed-columns-in-body`;
}
if(lastShowIndex == i){
if (lastShowIndex == i) {
da.width = parseInt(da.width) + contentWidthDiff;
}
if(draggable){
return ( <th {...da}
onDragStart={(event)=>{this.onDragStart(event,da)}}
onDragOver={(event)=>{this.onDragOver(event,da)}}
onDrop={(event)=>{this.onDrop(event,da)}}
onDragEnter={(event)=>{this.onDragEnter(event,da)}}
if (draggable) {
return (<th {...da}
onDragStart={(event) => { this.onDragStart(event, da) }}
onDragOver={(event) => { this.onDragOver(event, da) }}
onDrop={(event) => { this.onDrop(event, da) }}
onDragEnter={(event) => { this.onDragEnter(event, da) }}
draggable={draggable}
className={`${da.className} ${clsPrefix}-thead th-drag ${thHover} ${fixedStyle}`}
key={da.key} />)
}else if(dragborder){
return(<th
style={{width:da.width}}
onMouseMove={(event)=>{this.onThMouseMove(event,da)}}
onMouseUp={(event)=>{this.onThMouseUp(event,da)}}
} else if (dragborder) {
return (<th
style={{ width: da.width }}
onMouseMove={(event) => { this.onThMouseMove(event, da) }}
onMouseUp={(event) => { this.onThMouseUp(event, da) }}
className={`${da.className} ${clsPrefix}-thead-th ${fixedStyle}`}
key={i} >
{da.children}
<div ref={el=>this.gap = el }
onMouseMove={(event)=>{this.onMouseMove(event,da)}}
onMouseOut={(event)=>{this.onMouseOut(event,da)}}
onMouseDown={(event)=>{this.onMouseDown(event,da)}}
onMouseUp={(event)=>{this.onMouseUp(event,da)}}
onMouseOver={(event)=>{this.onMouseOver(event,da)}}
{da.children}
<div ref={el => this.gap = el}
onMouseMove={(event) => { this.onMouseMove(event, da) }}
onMouseOut={(event) => { this.onMouseOut(event, da) }}
onMouseDown={(event) => { this.onMouseDown(event, da) }}
onMouseUp={(event) => { this.onMouseUp(event, da) }}
onMouseOver={(event) => { this.onMouseOver(event, da) }}
className={`${clsPrefix}-thead-th-drag-gap `}></div>
</th>)
}else{
let th = da.onClick?(<th {...da} className={` ${fixedStyle}`} key={i} onClick={(event)=>{da.onClick(da,event)}}/>):(<th {...da} key={i} className={` ${fixedStyle}`} />);
</th>)
} else {
let th;
if (filterable && index == rows.length - 1) {
da.children = this.filterRenderType(da['filtertype'], da.dataindex, i);
th = <th {...da} key={i} className={` ${fixedStyle}`} />;
} else {
th = da.onClick ? (<th {...da} className={` ${fixedStyle}`} key={i} onClick={(event) => { da.onClick(da, event) }} />) : (<th {...da} key={i} className={` ${fixedStyle}`} />);
}
return (th);
}
})}
})}
</tr>
))
}