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; } pointer-events: none; }
.u-table-scroll-position-right .u-table-fixed-right { .u-table-scroll-position-right .u-table-fixed-right {
box-shadow: none; } 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 { .u-table-thead th {
background: #f7f7f7; background: #f7f7f7;
overflow: hidden; overflow: hidden;

2
dist/demo.css.map vendored

File diff suppressed because one or more lines are too long

27275
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": { "dependencies": {
"bee-dnd": "^1.0.2", "bee-dnd": "^1.0.2",
"bee-dropdown": "^1.0.1",
"bee-loading": "^1.0.3", "bee-loading": "^1.0.3",
"bee-menus": "^1.0.7",
"bee-popover": "^1.0.2", "bee-popover": "^1.0.2",
"bee-select": "^1.0.8", "bee-select": "^1.0.8",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"object-path": "^0.11.3", "object-path": "^0.11.3",
"shallowequal": "^1.0.2", "shallowequal": "^1.0.2",
"throttle-debounce": "^2.0.1",
"tinper-bee-core": "latest", "tinper-bee-core": "latest",
"warning": "^3.0.0" "warning": "^3.0.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

@ -41,7 +41,7 @@ const propTypes = {
getBodyWrapper: PropTypes.func, getBodyWrapper: PropTypes.func,
children: PropTypes.node, children: PropTypes.node,
draggable: PropTypes.bool, draggable: PropTypes.bool,
minColumnWidth:PropTypes.number minColumnWidth: PropTypes.number
}; };
const defaultProps = { const defaultProps = {
@ -53,10 +53,10 @@ const defaultProps = {
rowKey: 'key', rowKey: 'key',
rowClassName: () => '', rowClassName: () => '',
expandedRowClassName: () => '', expandedRowClassName: () => '',
onExpand() {}, onExpand() { },
onExpandedRowsChange() {}, onExpandedRowsChange() { },
onRowClick() {}, onRowClick() { },
onRowDoubleClick() {}, onRowDoubleClick() { },
clsPrefix: 'u-table', clsPrefix: 'u-table',
bodyStyle: {}, bodyStyle: {},
style: {}, style: {},
@ -68,15 +68,15 @@ const defaultProps = {
rowRef: () => null, rowRef: () => null,
getBodyWrapper: body => body, getBodyWrapper: body => body,
emptyText: () => 'No Data', emptyText: () => 'No Data',
minColumnWidth:80 minColumnWidth: 80
}; };
class Table extends Component{ class Table extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
let expandedRowKeys = []; let expandedRowKeys = [];
let rows = [...props.data]; let rows = [...props.data];
this.columnManager = new ColumnManager(props.columns, props.children,props.originWidth); this.columnManager = new ColumnManager(props.columns, props.children, props.originWidth);
this.store = createStore({ currentHoverKey: null }); this.store = createStore({ currentHoverKey: null });
if (props.defaultExpandAllRows) { if (props.defaultExpandAllRows) {
@ -126,9 +126,9 @@ class Table extends Component{
} }
componentDidMount() { componentDidMount() {
setTimeout(this.resetScrollY,300); setTimeout(this.resetScrollY, 300);
//后续也放在recevice里面 //后续也放在recevice里面
if(!this.props.originWidth){ if (!this.props.originWidth) {
this.computeTableWidth(); this.computeTableWidth();
} }
if (this.columnManager.isAnyColumnsFixed()) { if (this.columnManager.isAnyColumnsFixed()) {
@ -159,7 +159,7 @@ class Table extends Component{
} else if (nextProps.children !== this.props.children) { } else if (nextProps.children !== this.props.children) {
this.columnManager.reset(null, nextProps.children); this.columnManager.reset(null, nextProps.children);
} }
if(!nextProps.originWidth){ if (!nextProps.originWidth) {
this.computeTableWidth(); this.computeTableWidth();
} }
@ -202,8 +202,8 @@ class Table extends Component{
this.contentWidth = this.computeWidth; this.contentWidth = this.computeWidth;
this.setState({contentWidth:this.contentWidth});//重新渲染,为了显示滚动条 this.setState({contentWidth:this.contentWidth});//重新渲染,为了显示滚动条
} }
} }
onExpandedRowsChange(expandedRowKeys) { onExpandedRowsChange(expandedRowKeys) {
if (!this.props.expandedRowKeys) { if (!this.props.expandedRowKeys) {
this.setState({ expandedRowKeys }); this.setState({ expandedRowKeys });
@ -211,7 +211,7 @@ class Table extends Component{
this.props.onExpandedRowsChange(expandedRowKeys); this.props.onExpandedRowsChange(expandedRowKeys);
} }
onExpanded(expanded, record, index,e ) { onExpanded(expanded, record, index, e) {
if (e) { if (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -259,8 +259,8 @@ class Table extends Component{
} }
getHeader(columns, fixed) { getHeader(columns, fixed) {
const { showHeader, expandIconAsCell, clsPrefix ,onDragStart,onDragEnter,onDragOver,onDrop,draggable, const { filterDelay, onFilterRowsDropChange, onFilterRowsChange, filterable, showHeader, expandIconAsCell, clsPrefix, onDragStart, onDragEnter, onDragOver, onDrop, draggable,
onMouseDown,onMouseMove,onMouseUp,dragborder,onThMouseMove,dragborderKey,minColumnWidth,headerHeight} = this.props; onMouseDown, onMouseMove, onMouseUp, dragborder, onThMouseMove, dragborderKey, minColumnWidth, headerHeight } = this.props;
const rows = this.getHeaderRows(columns); const rows = this.getHeaderRows(columns);
if (expandIconAsCell && fixed !== 'right') { if (expandIconAsCell && fixed !== 'right') {
rows[0].unshift({ rows[0].unshift({
@ -271,12 +271,12 @@ class Table extends Component{
}); });
} }
const trStyle =headerHeight?{height:headerHeight}:(fixed ? this.getHeaderRowStyle(columns, rows) : null); const trStyle = headerHeight ? { height: headerHeight } : (fixed ? this.getHeaderRowStyle(columns, rows) : null);
let drop = draggable?{onDragStart,onDragOver,onDrop,onDragEnter,draggable}:{}; let drop = draggable ? { onDragStart, onDragOver, onDrop, onDragEnter, draggable } : {};
let dragBorder = dragborder?{onMouseDown,onMouseMove,onMouseUp,dragborder,onThMouseMove,dragborderKey}:{}; let dragBorder = dragborder ? { onMouseDown, onMouseMove, onMouseUp, dragborder, onThMouseMove, dragborderKey } : {};
let contentWidthDiff = 0; let contentWidthDiff = 0;
//非固定表格,宽度不够时自动扩充 //非固定表格,宽度不够时自动扩充
if(!fixed){ if (!fixed) {
contentWidthDiff = this.state.contentWidthDiff contentWidthDiff = this.state.contentWidthDiff
} }
return showHeader ? ( return showHeader ? (
@ -284,18 +284,23 @@ class Table extends Component{
{...drop} {...drop}
{...dragBorder} {...dragBorder}
minColumnWidth={minColumnWidth} minColumnWidth={minColumnWidth}
contentWidthDiff = {contentWidthDiff} contentWidthDiff={contentWidthDiff}
lastShowIndex = {this.state.lastShowIndex} lastShowIndex={this.state.lastShowIndex}
clsPrefix={clsPrefix} clsPrefix={clsPrefix}
rows={rows} rows={rows}
contentTable = {this.contentTable} contentTable={this.contentTable}
rowStyle={trStyle} rowStyle={trStyle}
fixed={fixed} fixed={fixed}
filterable={filterable}
onFilterRowsChange={onFilterRowsChange}
onFilterRowsDropChange={onFilterRowsDropChange}
filterDelay={filterDelay}
/> />
) : null; ) : null;
} }
getHeaderRows(columns, currentRow = 0, rows) { getHeaderRows(columns, currentRow = 0, rows) {
let filterCol = [];
rows = rows || []; rows = rows || [];
rows[currentRow] = rows[currentRow] || []; rows[currentRow] = rows[currentRow] || [];
@ -310,10 +315,10 @@ class Table extends Component{
className: column.className || '', className: column.className || '',
children: column.title, children: column.title,
drgHover: column.drgHover, drgHover: column.drgHover,
fixed:column.fixed, fixed: column.fixed,
width:column.width width: column.width
}; };
if(column.onHeadCellClick){ if (column.onHeadCellClick) {
cell.onClick = column.onHeadCellClick; cell.onClick = column.onHeadCellClick;
} }
if (column.children) { if (column.children) {
@ -328,7 +333,23 @@ class Table extends Component{
if (cell.colSpan !== 0) { if (cell.colSpan !== 0) {
rows[currentRow].push(cell); 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); return rows.filter(row => row.length > 0);
} }
@ -343,12 +364,12 @@ class Table extends Component{
colCount = this.columnManager.leafColumns().length; colCount = this.columnManager.leafColumns().length;
} }
function contentContainer () { function contentContainer() {
if(content && content.props && content.props.style){ if (content && content.props && content.props.style) {
return ( return (
<div style={{height: content.props.style.height}}></div> <div style={{ height: content.props.style.height }}></div>
) )
}else{ } else {
return ' ' return ' '
} }
} }
@ -412,7 +433,7 @@ class Table extends Component{
expandedRowContent = expandedRowRender(record, i, indent); expandedRowContent = expandedRowRender(record, i, indent);
} }
//只有当使用expandedRowRender参数的时候才去识别isHiddenExpandIcon隐藏行展开的icon //只有当使用expandedRowRender参数的时候才去识别isHiddenExpandIcon隐藏行展开的icon
if(expandedRowRender && typeof props.haveExpandIcon == 'function'){ if (expandedRowRender && typeof props.haveExpandIcon == 'function') {
isHiddenExpandIcon = props.haveExpandIcon(record, i); isHiddenExpandIcon = props.haveExpandIcon(record, i);
} }
const className = rowClassName(record, i, indent); const className = rowClassName(record, i, indent);
@ -423,13 +444,13 @@ class Table extends Component{
} }
let fixedIndex = i; let fixedIndex = i;
//判断是否是tree结构 //判断是否是tree结构
if(this.treeType){ if (this.treeType) {
fixedIndex = this.treeRowIndex; fixedIndex = this.treeRowIndex;
} }
if(props.fixedHeight){ if (props.fixedHeight) {
height = props.fixedHeight height = props.fixedHeight
}else{ } else {
height = (fixed && fixedColumnsBodyRowsHeight[fixedIndex]) ? fixedColumnsBodyRowsHeight[fixedIndex] : null; height = (fixed && fixedColumnsBodyRowsHeight[fixedIndex]) ? fixedColumnsBodyRowsHeight[fixedIndex] : null;
} }
@ -502,7 +523,7 @@ class Table extends Component{
getColGroup(columns, fixed) { getColGroup(columns, fixed) {
let cols = []; let cols = [];
let {contentWidthDiff=0,lastShowIndex=0} = this.state; let { contentWidthDiff = 0, lastShowIndex = 0 } = this.state;
if (this.props.expandIconAsCell && fixed !== 'right') { if (this.props.expandIconAsCell && fixed !== 'right') {
cols.push( cols.push(
<col <col
@ -521,9 +542,9 @@ class Table extends Component{
} else { } else {
leafColumns = this.columnManager.leafColumns(); leafColumns = this.columnManager.leafColumns();
} }
cols = cols.concat(leafColumns.map((c,i,arr) => { cols = cols.concat(leafColumns.map((c, i, arr) => {
let width = c.width; let width = c.width;
if(lastShowIndex == i ){ if (lastShowIndex == i) {
width = parseInt(width) + contentWidthDiff; width = parseInt(width) + contentWidthDiff;
} }
return <col key={c.key} style={{ width: width, minWidth: c.width }} />; return <col key={c.key} style={{ width: width, minWidth: c.width }} />;
@ -531,15 +552,15 @@ class Table extends Component{
return <colgroup>{cols}</colgroup>; return <colgroup>{cols}</colgroup>;
} }
renderDragHideTable=()=>{ renderDragHideTable = () => {
const {columns,dragborder,dragborderKey} = this.props; const { columns, dragborder, dragborderKey } = this.props;
if(!dragborder)return null; if (!dragborder) return null;
let sum = 0; 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)=>{ columns.map((da, i) => {
sum += da.width?da.width:0; sum += da.width ? da.width : 0;
return(<div className={`${this.props.clsPrefix}-hiden-drag-li`} key={da+"_hiden_"+i} style={{left:sum+"px"}}></div>); return (<div className={`${this.props.clsPrefix}-hiden-drag-li`} key={da + "_hiden_" + i} style={{ left: sum + "px" }}></div>);
}) })
} }
</div>); </div>);
@ -568,9 +589,9 @@ class Table extends Component{
let tableClassName = ''; let tableClassName = '';
//表格元素的宽度大于容器的宽度也显示滚动条 //表格元素的宽度大于容器的宽度也显示滚动条
if (scroll.x || fixed || this.contentDomWidth<this.contentWidth) { if (scroll.x || fixed || this.contentDomWidth < this.contentWidth) {
tableClassName = `${clsPrefix}-fixed`; tableClassName = `${clsPrefix}-fixed`;
if(!footerScroll){ if (!footerScroll) {
bodyStyle.overflowX = bodyStyle.overflowX || 'auto'; bodyStyle.overflowX = bodyStyle.overflowX || 'auto';
} }
} }
@ -609,7 +630,7 @@ class Table extends Component{
{this.getRows(columns, fixed)} {this.getRows(columns, fixed)}
</tbody> </tbody>
) : null; ) : null;
let _drag_class = this.props.dragborder?"table-drag-bordered":"" let _drag_class = this.props.dragborder ? "table-drag-bordered" : ""
return ( return (
<table className={` ${tableClassName} table-bordered ${_drag_class} `} style={tableStyle} > <table className={` ${tableClassName} table-bordered ${_drag_class} `} style={tableStyle} >
{/* {this.props.dragborder?null:this.getColGroup(columns, fixed)} */} {/* {this.props.dragborder?null:this.getColGroup(columns, fixed)} */}
@ -722,16 +743,16 @@ class Table extends Component{
syncFixedTableRowHeight() { syncFixedTableRowHeight() {
//this.props.height、headerHeight分别为用户传入的行高和表头高度如果有值所有行的高度都是固定的主要为了避免在千行数据中有固定列时获取行高度有问题 //this.props.height、headerHeight分别为用户传入的行高和表头高度如果有值所有行的高度都是固定的主要为了避免在千行数据中有固定列时获取行高度有问题
const { clsPrefix ,height,headerHeight} = this.props; const { clsPrefix, height, headerHeight } = this.props;
const headRows = this.refs.headTable ? const headRows = this.refs.headTable ?
this.refs.headTable.querySelectorAll('thead') : this.refs.headTable.querySelectorAll('thead') :
this.refs.bodyTable.querySelectorAll('thead'); this.refs.bodyTable.querySelectorAll('thead');
const bodyRows = this.refs.bodyTable.querySelectorAll(`.${clsPrefix}-row`) || []; const bodyRows = this.refs.bodyTable.querySelectorAll(`.${clsPrefix}-row`) || [];
const fixedColumnsHeadRowsHeight = [].map.call( const fixedColumnsHeadRowsHeight = [].map.call(
headRows, row => headerHeight?headerHeight:(row.getBoundingClientRect().height || 'auto') headRows, row => headerHeight ? headerHeight : (row.getBoundingClientRect().height || 'auto')
); );
const fixedColumnsBodyRowsHeight = [].map.call( 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) && if (shallowequal(this.state.fixedColumnsHeadRowsHeight, fixedColumnsHeadRowsHeight) &&
shallowequal(this.state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) { shallowequal(this.state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) {
@ -776,7 +797,7 @@ class Table extends Component{
if (e.target !== this.scrollTarget && this.scrollTarget !== headTable) { if (e.target !== this.scrollTarget && this.scrollTarget !== headTable) {
return; return;
} }
if ( e.target.scrollLeft !== this.lastScrollLeft) { if (e.target.scrollLeft !== this.lastScrollLeft) {
if (e.target === bodyTable && headTable) { if (e.target === bodyTable && headTable) {
headTable.scrollLeft = e.target.scrollLeft; headTable.scrollLeft = e.target.scrollLeft;
} else if (e.target === headTable && bodyTable) { } else if (e.target === headTable && bodyTable) {
@ -824,7 +845,7 @@ class Table extends Component{
if (props.useFixedHeader || (props.scroll && props.scroll.y)) { if (props.useFixedHeader || (props.scroll && props.scroll.y)) {
className += ` ${clsPrefix}-fixed-header`; className += ` ${clsPrefix}-fixed-header`;
} }
if(props.bordered){ if (props.bordered) {
className += ` ${clsPrefix}-bordered`; className += ` ${clsPrefix}-bordered`;
} }
className += ` ${clsPrefix}-scroll-position-${this.state.scrollPosition}`; className += ` ${clsPrefix}-scroll-position-${this.state.scrollPosition}`;

View File

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

View File

@ -1,7 +1,9 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import shallowequal from 'shallowequal'; 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 = { const propTypes = {
clsPrefix: PropTypes.string, clsPrefix: PropTypes.string,
@ -11,23 +13,23 @@ const propTypes = {
const grap = 16;//偏移数值 const grap = 16;//偏移数值
class TableHeader extends Component{ class TableHeader extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
this.currentObj = null; this.currentObj = null;
this.state = { this.state = {
border:false border: false
} }
//拖拽宽度处理 //拖拽宽度处理
if(!props.dragborder)return; if (!props.dragborder) return;
this.border = false; this.border = false;
this.theadKey = new Date().getTime(); this.theadKey = new Date().getTime();
this.drag = { this.drag = {
initPageLeftX:0, initPageLeftX: 0,
initLeft:0, initLeft: 0,
x:0, x: 0,
width:0, width: 0,
} }
// let _da = {}; // let _da = {};
// Object.assign(_da,this.props.rows[0]); // Object.assign(_da,this.props.rows[0]);
@ -36,96 +38,96 @@ class TableHeader extends Component{
let _row = []; let _row = [];
this.props.rows[0].forEach(item => { 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); _row.push(newItem);
}); });
this.drag.data = _row;//JSON.parse(JSON.stringify(this.props.rows[0])); this.drag.data = _row;//JSON.parse(JSON.stringify(this.props.rows[0]));
} }
static defaultProps = { static defaultProps = {
contentWidthDiff:0 contentWidthDiff: 0
} }
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
return !shallowequal(nextProps, this.props); return !shallowequal(nextProps, this.props);
} }
onDragStart=(event,data)=>{ onDragStart = (event, data) => {
event.dataTransfer.effectAllowed = "move"; event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("Text",data.key); event.dataTransfer.setData("Text", data.key);
this.currentObj = data; this.currentObj = data;
event.dataTransfer.setDragImage(event.target, 0, 0); event.dataTransfer.setDragImage(event.target, 0, 0);
this.props.onDragStart(event,data); this.props.onDragStart(event, data);
} }
onDragOver=(event,data)=>{ onDragOver = (event, data) => {
if(!this.currentObj || this.currentObj.key == data.key)return; if (!this.currentObj || this.currentObj.key == data.key) return;
event.preventDefault(); event.preventDefault();
this.props.onDragOver(event,data); this.props.onDragOver(event, data);
} }
onDragEnter=(event,data)=>{ onDragEnter = (event, data) => {
if(!this.currentObj || this.currentObj.key == data.key)return; if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDragEnter(event,data); this.props.onDragEnter(event, data);
} }
onDrop=(event,data)=>{ onDrop = (event, data) => {
if(!this.currentObj ||this.currentObj.key == data.key)return; if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDrop(event,data); this.props.onDrop(event, data);
} }
onMouseOver=(event,data)=>{ onMouseOver = (event, data) => {
//如果是固定列没有拖拽功能 //如果是固定列没有拖拽功能
if(this.border || data.fixed)return; if (this.border || data.fixed) return;
const {clsPrefix} = this.props; const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`; 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; // const {clsPrefix} = this.props;
// event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`; // event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`;
} }
onMouseOut=(event,data)=>{ onMouseOut = (event, data) => {
if(this.border)return; if (this.border) return;
const {clsPrefix} = this.props; const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`; event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
} }
onMouseDown=(event,data)=>{ onMouseDown = (event, data) => {
this.border = true; this.border = true;
const {clsPrefix,contentTable} = this.props; const { clsPrefix, contentTable } = this.props;
this.drag.initPageLeftX = event.pageX; this.drag.initPageLeftX = event.pageX;
this.drag.initLeft = tryParseInt(event.target.style.left); this.drag.initLeft = tryParseInt(event.target.style.left);
this.drag.x = this.drag.initLeft; 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; 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; 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); this.contentTableWidth = parseInt(styleWidth);
}else{ } else {
this.contentTableWidth = parseInt(contentTableDom.scrollWidth) this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
} }
} }
onMouseUp=(event,data)=>{ onMouseUp = (event, data) => {
this.border = false; this.border = false;
const {clsPrefix} = this.props; const { clsPrefix } = this.props;
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`; event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
} }
onThMouseUp=(event,data)=>{ onThMouseUp = (event, data) => {
this.border = false; this.border = false;
const {clsPrefix} = this.props; const { clsPrefix } = this.props;
let eventDom = event.target; let eventDom = event.target;
let optDom ; let optDom;
if(eventDom.classList.contains('.th-drag-gap-hover')){ if (eventDom.classList.contains('.th-drag-gap-hover')) {
optDom = eventDom; optDom = eventDom;
}else{ } else {
optDom = eventDom.querySelector(`.${clsPrefix}-thead-th-drag-gap`); optDom = eventDom.querySelector(`.${clsPrefix}-thead-th-drag-gap`);
} }
if(optDom){ if (optDom) {
optDom.classList.remove('th-drag-gap-hover'); optDom.classList.remove('th-drag-gap-hover');
optDom.classList.add('th-drag-gap'); optDom.classList.add('th-drag-gap');
} }
@ -133,25 +135,25 @@ class TableHeader extends Component{
} }
onThMouseMove=(event,data)=>{ onThMouseMove = (event, data) => {
if(!this.border)return; if (!this.border) return;
//固定表头拖拽 //固定表头拖拽
const {dragborderKey,contentTable} = this.props; const { dragborderKey, contentTable } = this.props;
let x = (event.pageX - this.drag.initPageLeftX) + this.drag.initLeft-0; let x = (event.pageX - this.drag.initPageLeftX) + this.drag.initLeft - 0;
let contentTableDom = document.getElementById("u-table-drag-thead-"+this.theadKey).parentNode; let contentTableDom = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
if(!this.contentTableWidth){ if (!this.contentTableWidth) {
const styleWidth = contentTableDom.style.width; 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); this.contentTableWidth = parseInt(styleWidth);
}else{ } else {
this.contentTableWidth = parseInt(contentTableDom.scrollWidth) this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
} }
} }
const newTableWidth = this.contentTableWidth + x; const newTableWidth = this.contentTableWidth + x;
const newWidth = this.drag.width + 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'); let moveDom = event.target.querySelector('.th-drag-gap-hover');
moveDom && moveDom.classList.remove('th-drag-gap-hover'); moveDom && moveDom.classList.remove('th-drag-gap-hover');
@ -160,8 +162,8 @@ class TableHeader extends Component{
} }
//设置hiden的left //设置hiden的left
//"u-table-drag-hide-table" //"u-table-drag-hide-table"
let currentHideDom = document.getElementById("u-table-drag-hide-table-"+dragborderKey).getElementsByTagName("div")[this.drag.currIndex]; let currentHideDom = document.getElementById("u-table-drag-hide-table-" + dragborderKey).getElementsByTagName("div")[this.drag.currIndex];
currentHideDom.style.left = (this.drag.initPageLeftX+x-grap)+"px"; currentHideDom.style.left = (this.drag.initPageLeftX + x - grap) + "px";
//获取最小宽度,不让拖动 //获取最小宽度,不让拖动
// let minWidth = 0; // let minWidth = 0;
@ -180,8 +182,8 @@ class TableHeader extends Component{
//设置当前的宽度 //设置当前的宽度
let currentData = this.drag.data[this.drag.currIndex]; let currentData = this.drag.data[this.drag.currIndex];
currentData.width = newWidth; currentData.width = newWidth;
let currentDom = document.getElementById("u-table-drag-thead-"+this.theadKey).getElementsByTagName("th")[this.drag.currIndex]; let currentDom = document.getElementById("u-table-drag-thead-" + this.theadKey).getElementsByTagName("th")[this.drag.currIndex];
currentDom.style.width = newWidth+"px"; currentDom.style.width = newWidth + "px";
// this.contentTableWidth = newTableWidth; // this.contentTableWidth = newTableWidth;
contentTableDom.style.width = newTableWidth+'px'; contentTableDom.style.width = newTableWidth+'px';
this.drag.x = x; this.drag.x = x;
@ -189,68 +191,142 @@ class TableHeader extends Component{
contentColDomArr[this.drag.currIndex].style.width = newWidth+"px" ; contentColDomArr[this.drag.currIndex].style.width = newWidth+"px" ;
//固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动 //固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动
const siblingDom = contentTableDom.parentNode.nextElementSibling; const siblingDom = contentTableDom.parentNode.nextElementSibling;
if(siblingDom){ if (siblingDom) {
const bodyTableDom = siblingDom.querySelector('table') const bodyTableDom = siblingDom.querySelector('table')
//2、是的话将表头对应的表格的宽度给表体对应的表格的宽度 //2、是的话将表头对应的表格的宽度给表体对应的表格的宽度
bodyTableDom.style.width = newTableWidth+'px'; bodyTableDom.style.width = newTableWidth + 'px';
//3、对应的col也要跟这变 //3、对应的col也要跟这变
let colDomArr = bodyTableDom.querySelectorAll('colgroup 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属性 //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() { render() {
const { clsPrefix, rowStyle ,onDragStart,onDragOver,onDrop,draggable,rows, const { clsPrefix, rowStyle, onDragStart, onDragOver, onDrop, draggable, rows, filterable, onFilterRowsChange,
onMouseDown,onMouseMove,onMouseUp,dragborder,onMouseOut,contentWidthDiff,fixed,lastShowIndex onMouseDown, onMouseMove, onMouseUp, dragborder, onMouseOut, contentWidthDiff, fixed, lastShowIndex
} = this.props; } = this.props;
let attr = dragborder?{id:`u-table-drag-thead-${this.theadKey}`}:{} let attr = dragborder ? { id: `u-table-drag-thead-${this.theadKey}` } : {}
return ( return (
<thead className={`${clsPrefix}-thead`} {...attr}> <thead className={`${clsPrefix}-thead`} {...attr}>
{ {
rows.map((row, index) => ( rows.map((row, index) => (
<tr key={index} style={rowStyle}> <tr key={index} style={rowStyle}>
{row.map((da, i,arr) => { {row.map((da, i, arr) => {
let thHover = da.drgHover?` ${clsPrefix}-thead th-drag-hover`:""; let thHover = da.drgHover ? ` ${clsPrefix}-thead th-drag-hover` : "";
delete da.drgHover; delete da.drgHover;
let fixedStyle=''; let fixedStyle = '';
if(!fixed && da.fixed){ if (!fixed && da.fixed) {
fixedStyle=`${clsPrefix}-row-fixed-columns-in-body`; fixedStyle = `${clsPrefix}-row-fixed-columns-in-body`;
} }
if(lastShowIndex == i){ if (lastShowIndex == i) {
da.width = parseInt(da.width) + contentWidthDiff; da.width = parseInt(da.width) + contentWidthDiff;
} }
if(draggable){ if (draggable) {
return ( <th {...da} return (<th {...da}
onDragStart={(event)=>{this.onDragStart(event,da)}} onDragStart={(event) => { this.onDragStart(event, da) }}
onDragOver={(event)=>{this.onDragOver(event,da)}} onDragOver={(event) => { this.onDragOver(event, da) }}
onDrop={(event)=>{this.onDrop(event,da)}} onDrop={(event) => { this.onDrop(event, da) }}
onDragEnter={(event)=>{this.onDragEnter(event,da)}} onDragEnter={(event) => { this.onDragEnter(event, da) }}
draggable={draggable} draggable={draggable}
className={`${da.className} ${clsPrefix}-thead th-drag ${thHover} ${fixedStyle}`} className={`${da.className} ${clsPrefix}-thead th-drag ${thHover} ${fixedStyle}`}
key={da.key} />) key={da.key} />)
}else if(dragborder){ } else if (dragborder) {
return(<th return (<th
style={{width:da.width}} style={{ width: da.width }}
onMouseMove={(event)=>{this.onThMouseMove(event,da)}} onMouseMove={(event) => { this.onThMouseMove(event, da) }}
onMouseUp={(event)=>{this.onThMouseUp(event,da)}} onMouseUp={(event) => { this.onThMouseUp(event, da) }}
className={`${da.className} ${clsPrefix}-thead-th ${fixedStyle}`} className={`${da.className} ${clsPrefix}-thead-th ${fixedStyle}`}
key={i} > key={i} >
{da.children} {da.children}
<div ref={el=>this.gap = el } <div ref={el => this.gap = el}
onMouseMove={(event)=>{this.onMouseMove(event,da)}} onMouseMove={(event) => { this.onMouseMove(event, da) }}
onMouseOut={(event)=>{this.onMouseOut(event,da)}} onMouseOut={(event) => { this.onMouseOut(event, da) }}
onMouseDown={(event)=>{this.onMouseDown(event,da)}} onMouseDown={(event) => { this.onMouseDown(event, da) }}
onMouseUp={(event)=>{this.onMouseUp(event,da)}} onMouseUp={(event) => { this.onMouseUp(event, da) }}
onMouseOver={(event)=>{this.onMouseOver(event,da)}} onMouseOver={(event) => { this.onMouseOver(event, da) }}
className={`${clsPrefix}-thead-th-drag-gap `}></div> className={`${clsPrefix}-thead-th-drag-gap `}></div>
</th>) </th>)
}else{ } else {
let th = da.onClick?(<th {...da} className={` ${fixedStyle}`} key={i} onClick={(event)=>{da.onClick(da,event)}}/>):(<th {...da} key={i} className={` ${fixedStyle}`} />); 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); return (th);
} }
})} })}