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; }
.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 th {
background: #f7f7f7;
overflow: hidden;

2
dist/demo.css.map vendored

File diff suppressed because one or more lines are too long

29688
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"
}
}
}

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

@ -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();
}
@ -178,27 +178,27 @@ class Table extends Component{
}
}
computeTableWidth(){
//如果用户传了scroll.x按用户传的为主
let setWidthParam = this.props.scroll.x
if(typeof(setWidthParam) == 'number'){
let numSetWidthParam = parseInt(setWidthParam);
this.contentWidth = numSetWidthParam;
}else{
//计算总表格宽度、根据表格宽度和各列的宽度和比较,重置最后一列
this.contentDomWidth = this.contentTable.getBoundingClientRect().width//表格容器宽度
this.contentWidth = this.contentDomWidth;//默认与容器宽度一样
if(typeof(setWidthParam)=='string' && setWidthParam.indexOf('%')){
this.contentWidth = this.contentWidth * parseInt(setWidthParam) /100
}
}
const computeObj = this.columnManager.getColumnWidth(this.contentWidth);
let lastShowIndex = computeObj.lastShowIndex;
this.computeWidth = computeObj.computeWidth;
if(this.computeWidth < this.contentWidth){
let contentWidthDiff = this.contentWidth - this.computeWidth;
this.setState({contentWidthDiff,lastShowIndex});
computeTableWidth() {
//如果用户传了scroll.x按用户传的为主
let setWidthParam = this.props.scroll.x
if (typeof (setWidthParam) == 'number') {
let numSetWidthParam = parseInt(setWidthParam);
this.contentWidth = numSetWidthParam;
} else {
//计算总表格宽度、根据表格宽度和各列的宽度和比较,重置最后一列
this.contentDomWidth = this.contentTable.getBoundingClientRect().width//表格容器宽度
this.contentWidth = this.contentDomWidth;//默认与容器宽度一样
if (typeof (setWidthParam) == 'string' && setWidthParam.indexOf('%')) {
this.contentWidth = this.contentWidth * parseInt(setWidthParam) / 100
}
}
const computeObj = this.columnManager.getColumnWidth(this.contentWidth);
let lastShowIndex = computeObj.lastShowIndex;
this.computeWidth = computeObj.computeWidth;
if (this.computeWidth < this.contentWidth) {
let contentWidthDiff = this.contentWidth - this.computeWidth;
this.setState({ contentWidthDiff, lastShowIndex });
}
}
onExpandedRowsChange(expandedRowKeys) {
@ -208,7 +208,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();
@ -256,8 +256,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 { 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({
@ -268,31 +268,35 @@ 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}
/>
) : null;
}
getHeaderRows(columns, currentRow = 0, rows) {
let filterCol = [];
rows = rows || [];
rows[currentRow] = rows[currentRow] || [];
@ -307,10 +311,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) {
@ -325,7 +329,22 @@ 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
});
}
});
if (this.props.filterable) {
rows.push(filterCol);
}
return rows.filter(row => row.length > 0);
}
@ -340,12 +359,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 ' '
}
}
@ -409,8 +428,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);
@ -420,16 +439,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;
@ -440,8 +459,8 @@ class Table extends Component{
} else {
leafColumns = this.columnManager.leafColumns();
}
rst.push(
<TableRow
indent={indent}
@ -492,14 +511,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
@ -518,9 +537,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 }} />;
@ -528,21 +547,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',
@ -565,9 +584,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';
}
}
@ -606,7 +625,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)} */}
@ -719,19 +738,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({
@ -768,12 +787,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) {
@ -821,14 +840,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 = {
@ -840,18 +859,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,9 @@ $table-move-in-color: $bg-color-base;
}
&-thead{
.filter-text,.filter-dropdown,.filter-date {
font-weight: normal;
}
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,80 +180,148 @@ 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;
contentTableDom.style.width = newTableWidth + 'px';
this.drag.x = x;
//固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动
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 } = 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() {
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>
))
}