diff --git a/demo/demolist/Demo1201.js b/demo/demolist/Demo1201.js new file mode 100644 index 0000000..38f38f3 --- /dev/null +++ b/demo/demolist/Demo1201.js @@ -0,0 +1,68 @@ +/** +* +* @title 拖拽改变行顺序 +* @parent 拖拽改变行顺序 +* @description 拖拽改变行顺序 +* Demo1201 +*/ + +import React, { Component } from "react"; +import {Button,Tooltip} from "tinper-bee"; +import Table from "../../src"; + +const columns = [ + { + title: "员工编号", dataIndex: "a", key: "a", width: 120, className: "rowClassName", + fixed:'left', + render: (text, record, index) => { + return ( + + {text} + + ); + } + }, + { title: "员工姓名", dataIndex: "b", key: "b", width:200 }, + { title: "性别", dataIndex: "c", key: "c", width: 500 }, + { title: "部门", dataIndex: "d", key: "d", width: 100 }, + { title: "职级", dataIndex: "e", key: "e", width: 100,fixed:'right'} +]; + +const data = [ + { a: "ASVAL_201903280005", b: "小张", c: "男", d: "财务二科", e: "M1", key: "1001" }, + { a: "ASVAL_201903200004", b: "小明", c: "男", d: "财务一科", e: "T1", key: "1002" }, + { a: "ASVAL_201903120002", b: "小红", c: "女", d: "财务一科", e: "T2", key: "1003" } +]; + +class Demo1201 extends Component { + + constructor(props) { + super(props); + this.state = { + data: data + } + } + handleClick = () => { + console.log('这是第' , this.currentIndex , '行'); + console.log('内容:' , this.currentRecord); + } + + render() { + return ( + + ); + } +} + +export default Demo1201; diff --git a/demo/demolist/Demo1304.js b/demo/demolist/Demo1304.js new file mode 100644 index 0000000..cb6160f --- /dev/null +++ b/demo/demolist/Demo1304.js @@ -0,0 +1,72 @@ +/** +* +* @title 表格单选,且选中行填充颜色 +* @parent 表格-单选-radio-行选中 +* @description 表格增加单选、radio 和背景色的示例。 +* Demo1304 +*/ + +import React, { Component } from "react"; +import {Button,Tooltip,Radio} from "tinper-bee"; + +import Table from "../../src"; + + + +const data = [ + { check: "ASVAL_201903280005",a: "ASVAL_201903280005", b: "小张", c: "男", d: "财务二科", key: "1" }, + { check: "ASVAL_201903200004",a: "ASVAL_201903200004", b: "小明", c: "男", d: "财务一科", key: "2" }, + { check: "ASVAL_201903120002",a: "ASVAL_201903120002", b: "小红", c: "女", d: "财务一科", key: "3" } +]; + +class Demo1304 extends Component { + + constructor(props){ + super(props); + this.state = { + data: data, + selectedRowIndex: 0, + selectedValue:"ASVAL_201903200004" + } + } + + render() { + let {selectedValue} = this.state; + let columns = [ + { title: "单选", dataIndex: "check", key: "check", width: 80,render(text, record, index){ + return( + + + ) + }}, + { title: "员工编号", dataIndex: "a", key: "a", width: 300}, + { title: "员工姓名", dataIndex: "b", key: "b", width: 500 }, + { title: "性别", dataIndex: "c", key: "c", width: 500 }, + { title: "部门", dataIndex: "d", key: "d", width: 200 } + ]; + + return ( +
{ + if (this.state.selectedRowIndex == index) { + return 'selected'; + } else { + return ''; + } + }} + onRowClick={(record,index,indent)=>{ + this.setState({ + selectedRowIndex: index, + selectedValue:record.check + }); + }} + title={currentData =>
员工信息统计表
} + footer={currentData =>
合计: 共{data.length}条数据
} + /> + ); + } +} + +export default Demo1304; diff --git a/docs/api.md b/docs/api.md index 2e24cb1..7f16e7e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -70,6 +70,8 @@ import 'bee-table/build/Table.css'; | height | 自定义表格行高 | number | - | | headerHeight | 自定义表头行高 | number | - | | size | 表格大小 | `sm | md | lg` | 'md' | +| rowDraggAble | 是否增加行交换顺序功能 | boolean| false + > 快捷键部分参考示例 (快捷键在table中的简单使用应用) diff --git a/src/Table.js b/src/Table.js index 06a9cbd..6482af9 100644 --- a/src/Table.js +++ b/src/Table.js @@ -54,6 +54,7 @@ const propTypes = { tabIndex:PropTypes.string, hoverContent:PropTypes.func, size: PropTypes.oneOf(['sm', 'md', 'lg']), + rowDraggAble: PropTypes.bool, }; const defaultProps = { @@ -88,7 +89,8 @@ const defaultProps = { setRowParentIndex:()=>{}, tabIndex:'0', heightConsistent:false, - size: 'md' + size: 'md', + rowDraggAble:false }; class Table extends Component { @@ -522,10 +524,25 @@ class Table extends Component { indent={1} expandable={false} store={this.store} - dragborderKey={this.props.dragborderKey} + dragborderKey={this.props.dragborderKey} + rowDraggAble={props.rowDraggAble} + onDragRow={this.onDragRow} /> ); } + + onDragRow = (currentIndex,targetIndex)=>{ + let {data} = this.state, + currentObj = data[currentIndex], + targetObj = data[targetIndex]; + console.log(currentIndex+" ----------onRowDragEnd-------- "+targetIndex); + data.splice(targetIndex, 0, data.splice(currentIndex, 1).shift()); + console.log(" _data---- ",data); + this.setState({ + data: data, + }); + } + /** * * @@ -660,6 +677,9 @@ class Table extends Component { rootIndex = {rootIndex} syncHover = {props.syncHover} bodyDisplayInRow = {props.bodyDisplayInRow} + rowDraggAble={props.rowDraggAble} + onDragRow={this.onDragRow} + contentTable={this.contentTable} /> ); this.treeRowIndex++; diff --git a/src/Table.scss b/src/Table.scss index fc4b2b4..a93cf00 100644 --- a/src/Table.scss +++ b/src/Table.scss @@ -546,8 +546,8 @@ $icon-color:#505F79; &-filter-icon{ position: absolute; width: 30px; - height: 38px ; - line-height: 38px; + height: 39px ; + line-height: 39px; right: 0px ; top:1px ; z-index: 2; diff --git a/src/TableHeader.js b/src/TableHeader.js index 042dd4d..0e1c24e 100644 --- a/src/TableHeader.js +++ b/src/TableHeader.js @@ -30,6 +30,7 @@ class TableHeader extends Component { this.minWidth = 80;//确定最小宽度就是80 this.table = null; this._thead = null;//当前对象 + this.event = false;//避免多次绑定问题 } static defaultProps = { @@ -103,12 +104,20 @@ class TableHeader extends Component { * 事件初始化 */ initEvent(){ - this.dragBorderEventInit();//列宽 - this.dragAbleEventInit();//交换列 - if(this.table && this.table.tr){ - this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',this.table.tr[0]);//body mouseup + let {dragborder,draggable} = this.props; + if(!this.event){ //避免多次绑定问题。 + this.event = true; + if(dragborder){ + this.dragBorderEventInit();//列宽 + } + if(dragborder){ + this.dragAbleEventInit();//交换列 + } + if(this.table && this.table.tr){ + this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',this.table.tr[0]);//body mouseup + } + this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'',document.body);//body mouseup } - this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'',document.body);//body mouseup } /** @@ -398,6 +407,7 @@ class TableHeader extends Component { }; onDragOver = (e) => { + let event = Event.getEvent(e); event.preventDefault(); }; diff --git a/src/TableRow.js b/src/TableRow.js index dfdd98c..da6c2fc 100644 --- a/src/TableRow.js +++ b/src/TableRow.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { Event,EventUtil} from "./utils"; import TableCell from './TableCell'; import ExpandIcon from './ExpandIcon'; @@ -29,6 +30,8 @@ const propTypes = { expandIconAsCell: PropTypes.bool, expandRowByClick: PropTypes.bool, store: PropTypes.object.isRequired, + rowDraggAble: PropTypes.bool, + onDragRow: PropTypes.func, }; const defaultProps = { @@ -39,7 +42,9 @@ const defaultProps = { expandRowByClick: false, onHover() {}, className:'', - setRowParentIndex:()=>{} + setRowParentIndex:()=>{}, + rowDraggAble:false, + // onDragRow:()=>{} }; class TableRow extends Component{ @@ -54,11 +59,12 @@ class TableRow extends Component{ this.onMouseEnter = this.onMouseEnter.bind(this); this.onMouseLeave = this.onMouseLeave.bind(this); this.expandHeight = 0; + this.event = false; } componentDidMount() { - const { store, hoverKey,treeType } = this.props; + const { store, hoverKey,treeType,rowDraggAble } = this.props; this.unsubscribe = store.subscribe(() => { if (store.getState().currentHoverKey === hoverKey) { this.setState({ hovered: true }); @@ -71,23 +77,174 @@ class TableRow extends Component{ if(treeType){ this.setRowParentIndex(); } - - + } + + /** + * 事件初始化 + */ + initEvent=()=>{ + let events = [ + {key:'dragstart',fun:this.onDragStart},//用户开始拖动元素时触发 + {key:'dragover', fun:this.onDragOver},//当某被拖动的对象在另一对象容器范围内拖动时触发此事件 + {key:'drop', fun:this.onDrop}, //在一个拖动过程中,释放鼠标键时触发此事件 + + {key:'dragenter', fun:this.onDragEnter}, + {key:'dragleave', fun:this.onDragLeave}, + ]; + this.eventListen(events,'',this.element); + } + + /** + * 事件移除,提供性能以及内存泄漏等问题。 + */ + removeDragAbleEvent=()=>{ + let events = [ + {key:'dragstart',fun:this.onDragStart}, + {key:'dragover', fun:this.onDragOver}, + {key:'drop', fun:this.onDrop}, + + {key:'dragenter', fun:this.onDragEnter}, + {key:'dragleave', fun:this.onDragLeave}, + ]; + this.eventListen(events,'remove',this.element); } + /** + * 事件绑定和移除函数 + */ + eventListen(events,type,eventSource){ + for (let i = 0; i < events.length; i++) { + const _event = events[i]; + if(type === "remove"){ + EventUtil.removeHandler(eventSource,_event.key,_event.fun); + }else{ + EventUtil.addHandler(eventSource,_event.key,_event.fun); + } + } + } + + /** + * 开始调整交换列的事件 + */ + onDragStart = (e) => { + if (!this.props.rowDraggAble) return; + let event = Event.getEvent(e) , + target = Event.getTarget(event); + this.currentIndex = target.getAttribute("data-row-key"); + this._dragCurrent = target; + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.setData("Text", this.currentIndex); + } + + onDragOver = (e) => { + let event = Event.getEvent(e); + event.preventDefault(); + }; + + /** + * 在一个拖动过程中,释放鼠标键时触发此事件。【目标事件】 + * @memberof TableHeader + */ + onDrop = (e) => { + let {rowDraggAble,onDragRow} = this.props; + let event = Event.getEvent(e) , + _target = Event.getTarget(event),target = _target.parentNode; + let currentIndex = target.getAttribute("data-row-key"); + if(!currentIndex || currentIndex === this.currentIndex)return; + if(target.nodeName.toUpperCase() === "TR"){ + this.synchronizeTableTr(this.currentIndex,null); + // target.setAttribute("style",""); + // this.synchronizeTrStyle(this.currentIndex,false); + } + let _currentIndex = event.dataTransfer.getData("text"); + onDragRow && onDragRow(parseInt(this.currentIndex--),parseInt(currentIndex--)); + }; + + /** + * 同步自己,也需要同步当前行的行显示 + */ + synchronizeTableTr = (currentIndex,type)=>{ + let {contentTable} = this.props; + let _table_trs = contentTable.querySelector('.u-table-scroll table tbody'), + _table_fixed_left_trs = contentTable.querySelector('.u-table-fixed-left table tbody'), + _table_fixed_right_trs = contentTable.querySelector('.u-table-fixed-right table tbody'); + + this.synchronizeTrStyle(_table_trs,currentIndex,type); + if(_table_fixed_left_trs){ + this.synchronizeTrStyle(_table_fixed_left_trs,currentIndex,type); + } + if(_table_fixed_right_trs){ + this.synchronizeTrStyle(_table_fixed_right_trs,currentIndex,type); + } + } + + /** + * 设置同步的style + */ + synchronizeTrStyle = (_elementBody,id,type)=>{ + let {contentTable} = this.props, + trs = _elementBody.getElementsByTagName("tr"), + currentObj; + for (let index = 0; index < trs.length; index++) { + const element = trs[index]; + if(element.getAttribute("data-row-key") == id){ + currentObj = element; + } + } + if(type){ + currentObj && currentObj.setAttribute("style","border-bottom:2px dashed rgba(5,0,0,0.25)"); + }else{ + currentObj && currentObj.setAttribute("style",""); + } + } + + onDragEnter = (e) => { + let event = Event.getEvent(e) , + _target = Event.getTarget(event),target = _target.parentNode; + let currentIndex = target.getAttribute("data-row-key"); + if(!currentIndex || currentIndex === this.currentIndex)return; + if(target.nodeName.toUpperCase() === "TR"){ + this.synchronizeTableTr(currentIndex,true); + // target.setAttribute("style","border-bottom:2px dashed rgba(5,0,0,0.25)"); + // // target.style.backgroundColor = 'rgb(235, 236, 240)'; + } + } + + onDragLeave = (e) => { + let event = Event.getEvent(e) , + _target = Event.getTarget(event),target = _target.parentNode; + let currentIndex = target.getAttribute("data-row-key"); + if(!currentIndex || currentIndex === this.currentIndex)return; + if(target.nodeName.toUpperCase() === "TR"){ + this.synchronizeTableTr(currentIndex,null); + } + } + componentDidUpdate(prevProps) { + const { rowDraggAble } = this.props; + if(!this.event){ + this.event = true; + if(rowDraggAble){ + this.initEvent(); + } + } + if(this.props.treeType){ this.setRowParentIndex(); } this.setRowHeight() } + componentWillUnmount() { - const { record, onDestroy, index } = this.props; + const { record, onDestroy, index,rowDraggAble } = this.props; onDestroy(record, index); if (this.unsubscribe) { this.unsubscribe(); } + if(rowDraggAble){ + this.removeDragAbleEvent(); + } } @@ -98,7 +255,6 @@ class TableRow extends Component{ } setRowParentIndex(){ const {index,setRowParentIndex,fixedIndex,rootIndex} = this.props; - // console.log('rootIndex',rootIndex<0?index:rootIndex,'index',fixedIndex); setRowParentIndex(rootIndex<0?index:rootIndex,fixedIndex); } @@ -163,7 +319,7 @@ class TableRow extends Component{ render() { const { clsPrefix, columns, record, height, visible, index, - expandIconColumnIndex, expandIconAsCell, expanded, expandRowByClick, + expandIconColumnIndex, expandIconAsCell, expanded, expandRowByClick,rowDraggAble, expandable, onExpand, needIndentSpaced, indent, indentSize,isHiddenExpandIcon,fixed,bodyDisplayInRow } = this.props; let showSum = false; @@ -171,7 +327,6 @@ class TableRow extends Component{ if (this.state.hovered) { className += ` ${clsPrefix}-hover`; } - // console.log('className--'+className,index); //判断是否为合计行 if(className.indexOf('sumrow')>-1){ showSum = true; @@ -223,14 +378,17 @@ class TableRow extends Component{ if (!visible) { style.display = 'none'; } + return ( diff --git a/src/lib/filterColumn.js b/src/lib/filterColumn.js index 2808879..82bf5ea 100644 --- a/src/lib/filterColumn.js +++ b/src/lib/filterColumn.js @@ -102,11 +102,11 @@ export default function filterColumn(Table, Popover) { this.checkedColumItemClick(da); } } - return (