add:表格过滤行数据以及下拉、日期、文本输入类型条件.

This commit is contained in:
kvkens 2018-09-20 16:24:06 +08:00
parent c31f73979c
commit 81491aa586
13 changed files with 15810 additions and 14718 deletions

BIN
demo/.DS_Store vendored

Binary file not shown.

Binary file not shown.

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

@ -0,0 +1,99 @@
/**
*
* @title 按条件和值过滤
* @description 可以根据输入项目以及判断条件对表格内的数据进行过滤
*
*/
import React, { Component } from 'react';
import Table from '../../src';
const columns26 = [
{ title: "姓名", width: 150, dataIndex: "name", key: "name", filterType: "text" },
{ title: "年龄", width: 100, dataIndex: "age", key: "age", filterType: "dropdown" },
{ title: "日期", width: 200, dataIndex: "date", key: "date", filterType: "date" },
{ title: "居住地址", width: 150, dataIndex: "address", key: "address", filterType: "text" },
{ 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 Demo6 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} onFilterRowsChange={this.handlerFilterRowsChange} filterable={true} bordered columns={columns26} data={data26} />;
}
}
export default Demo6;

File diff suppressed because one or more lines are too long

2
dist/demo.css vendored
View File

@ -8545,6 +8545,8 @@ ul {
box-shadow: none; } box-shadow: 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 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

29434
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"
}, },

63
src/FilterType.js Normal file
View File

@ -0,0 +1,63 @@
import React, { Component } from 'react';
import FormControl from 'bee-form-control';
import Button from 'bee-button';
import Icon from 'bee-icon';
import Select from 'bee-select';
import DatePicker from 'bee-datepicker';
import Menu from 'bee-menus';
import Dropdown from 'bee-dropdown';
const { Item } = Menu;
const format = "YYYY-MM-DD dddd";
class FilterType extends Component {
renderControl = (rendertype) => {
switch (rendertype) {
case 'text':
const 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 <div><FormControl
className={this.props.className}
onChange={this.props.onChange}
style={{ width: "70%" }}
/>
<Dropdown
trigger={['click']}
overlay={dropmenu}
animation="slide-up"
>
<Button shape="border" style={{ marginLeft: "5px", minWidth: "26px", width: "26px", padding: 0, marginBottom: "4px" }}><Icon style={{ padding: 0 }} type="uf-arrow-c-o-down" /></Button>
</Dropdown>
</div>
case 'dropdown':
return <Select
{...this.props}
/>
case 'date':
return <DatePicker
{...this.props}
/>
default:
break;
}
}
render() {
let { rendertype } = this.props;
return (
this.renderControl(rendertype)
);
}
}
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();
} }
@ -178,26 +178,26 @@ class Table extends Component{
} }
} }
computeTableWidth(){ computeTableWidth() {
//如果用户传了scroll.x按用户传的为主 //如果用户传了scroll.x按用户传的为主
let setWidthParam = this.props.scroll.x let setWidthParam = this.props.scroll.x
if(typeof(setWidthParam) == 'number'){ if (typeof (setWidthParam) == 'number') {
let numSetWidthParam = parseInt(setWidthParam); let numSetWidthParam = parseInt(setWidthParam);
this.contentWidth = numSetWidthParam; this.contentWidth = numSetWidthParam;
}else{ } else {
//计算总表格宽度、根据表格宽度和各列的宽度和比较,重置最后一列 //计算总表格宽度、根据表格宽度和各列的宽度和比较,重置最后一列
this.contentDomWidth = this.contentTable.getBoundingClientRect().width//表格容器宽度 this.contentDomWidth = this.contentTable.getBoundingClientRect().width//表格容器宽度
this.contentWidth = this.contentDomWidth;//默认与容器宽度一样 this.contentWidth = this.contentDomWidth;//默认与容器宽度一样
if(typeof(setWidthParam)=='string' && setWidthParam.indexOf('%')){ if (typeof (setWidthParam) == 'string' && setWidthParam.indexOf('%')) {
this.contentWidth = this.contentWidth * parseInt(setWidthParam) /100 this.contentWidth = this.contentWidth * parseInt(setWidthParam) / 100
} }
} }
const computeObj = this.columnManager.getColumnWidth(this.contentWidth); const computeObj = this.columnManager.getColumnWidth(this.contentWidth);
let lastShowIndex = computeObj.lastShowIndex; let lastShowIndex = computeObj.lastShowIndex;
this.computeWidth = computeObj.computeWidth; this.computeWidth = computeObj.computeWidth;
if(this.computeWidth < this.contentWidth){ if (this.computeWidth < this.contentWidth) {
let contentWidthDiff = this.contentWidth - this.computeWidth; let contentWidthDiff = this.contentWidth - this.computeWidth;
this.setState({contentWidthDiff,lastShowIndex}); this.setState({ contentWidthDiff, lastShowIndex });
} }
} }
@ -208,7 +208,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();
@ -256,8 +256,8 @@ class Table extends Component{
} }
getHeader(columns, fixed) { getHeader(columns, fixed) {
const { showHeader, expandIconAsCell, clsPrefix ,onDragStart,onDragEnter,onDragOver,onDrop,draggable, const { 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({
@ -268,12 +268,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 ? (
@ -281,18 +281,22 @@ 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}
/> />
) : 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] || [];
@ -307,10 +311,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) {
@ -325,7 +329,22 @@ 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
}); });
}
});
if (this.props.filterable) {
rows.push(filterCol);
}
return rows.filter(row => row.length > 0); return rows.filter(row => row.length > 0);
} }
@ -340,12 +359,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 ' '
} }
} }
@ -409,7 +428,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);
@ -420,13 +439,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;
} }
@ -499,7 +518,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
@ -518,9 +537,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 }} />;
@ -528,15 +547,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>);
@ -565,9 +584,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';
} }
} }
@ -606,7 +625,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)} */}
@ -719,16 +738,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)) {
@ -773,7 +792,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) {
@ -821,7 +840,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,9 @@ $table-move-in-color: $bg-color-base;
} }
&-thead{ &-thead{
.filter-text,.filter-dropdown,.filter-date {
font-weight: normal;
}
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,75 +182,143 @@ 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;
//固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动 //固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动
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 } = this.props;
switch (type) {
//文本输入
case 'text':
return <FilterType
rendertype={type}
className={`${clsPrefix} filter-text`}
onChange={debounce(500, this.handlerFilterTextChange.bind(this, dataIndex))}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
/>
//下拉框选择
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)}
/>
//日期
case 'date':
return <FilterType
rendertype={type}
className={`${clsPrefix} filter-date`}
onClick={() => { }}
onChange={this.handlerFilterTextChange.bind(this, dataIndex)}
/>
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);
} }
})} })}