UNPKG

35.4 kBJavaScriptView Raw
1import React, { Component } from "react";
2import ReactDOM from 'react-dom';
3import PropTypes from "prop-types";
4import { debounce } from "throttle-debounce";
5import { Event,EventUtil} from "./lib/utils";
6import FilterType from "./FilterType";
7
8const propTypes = {
9 clsPrefix: PropTypes.string,
10 rowStyle: PropTypes.object,
11 rows: PropTypes.array
12};
13
14
15function getDiv(id){
16 let div = document.createElement("div");
17 div.className = "u-table-drag-hidden-cont";
18 div.id = id;
19 return div;
20}
21
22class TableHeader extends Component {
23 constructor(props) {
24 super(props);
25 this.currentObj = null;
26 this.theadKey = new Date().getTime();
27 this.drag = {
28 option:''
29 };
30 this.minWidth = parseInt(props.minColumnWidth);
31 this.table = null;
32 this._thead = null;//当前对象
33 this.event = false;//避免多次绑定问题
34 this.lastColumWidth = null;//非固定列最后一列的初始化宽度
35 this.fixedTable = {};
36 }
37
38 static defaultProps = {
39 contentWidthDiff: 0
40 };
41
42 componentWillReceiveProps(nextProps) {
43 // 表格column改变时,要重新绑定拖拽事件,否则拖拽不生效
44 const { columnsChildrenList:oldCols } = this.props;
45 const { columnsChildrenList:newCols } = nextProps;
46 if (this._thead) {
47 if(newCols.length !== oldCols.length){
48 this.event = false;
49 return;
50 }
51 oldCols.some((item, index) => {
52 if (newCols[index] && newCols[index].dataIndex !== item.dataIndex) {
53 this.event = false;
54 return true;
55 }
56 });
57 }
58 }
59
60 componentDidUpdate(){
61 this.initTable();
62 this.initEvent();
63 }
64
65 componentDidMount(){
66 let uid = "_table_uid_"+new Date().getTime();
67 this._table_none_cont_id = uid;
68 let div = getDiv(uid);
69 document.querySelector("body").appendChild(div);
70 }
71
72 componentWillUnmount(){
73 this.fixedTable = null;
74 if(!this.table)return;
75 if (this.props.draggable){
76 this.removeDragAbleEvent();
77 }
78 if(this.props.dragborder){
79 this.removeDragBorderEvent();
80 }
81 this.doEventList(this.table.tr,(tr)=>{
82 this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'remove',tr);
83 })
84 // this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'remove',this.table.tr[0]);
85 this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'remove',document.body);
86 }
87
88 /**
89 * 获取table的属性存放在this.table 中。(公用方法)
90 * @returns
91 * @memberof TableHeader
92 */
93 initTable(){
94 const {contentTable} = this.props;
95 if(!this.props.dragborder && !this.props.draggable)return;
96 let tableDome = this._thead.parentNode;
97 let table = {};
98 if(tableDome && tableDome.nodeName && tableDome.nodeName.toUpperCase() == "TABLE"){
99 table.table = tableDome;
100 table.cols = tableDome.getElementsByTagName("col");
101 table.ths = tableDome.getElementsByTagName("th");
102 table.tr = tableDome.getElementsByTagName("tr");
103 table.tableBody = contentTable.querySelector('.u-table-scroll .u-table-body') && contentTable.querySelector('.u-table-scroll .u-table-body');
104 table.tableBodyCols = contentTable.querySelector('.u-table-scroll .u-table-body') && contentTable.querySelector('.u-table-scroll .u-table-body').getElementsByTagName("col");
105 table.bodyRows = table.tableBody && table.tableBody.querySelectorAll('tr') || [];
106
107 table.fixedLeftHeaderTable = contentTable.querySelector('.u-table-fixed-left .u-table-header') ;
108 table.fixedRighHeadertTable = contentTable.querySelector('.u-table-fixed-right .u-table-header');
109 table.contentTableHeader = contentTable.querySelector('.u-table-scroll .u-table-header');
110 table.fixedLeftBodyTable = contentTable.querySelectorAll('.u-table-fixed-left .u-table-body-outer') ;
111 if (table.fixedLeftBodyTable) {
112 const leftBodyTableIndex = table.fixedLeftBodyTable.length-1 < 0 ? 0 : table.fixedLeftBodyTable.length-1
113 table.fixedLeftBodyTable = table.fixedLeftBodyTable[leftBodyTableIndex]
114 }
115
116 table.fixedRightBodyTable = contentTable.querySelectorAll('.u-table-fixed-right .u-table-body-outer') ;
117 if (table.fixedRightBodyTable) {
118 const rightBodyTableIndex = table.fixedRightBodyTable.length-1 < 0 ? 0 : table.fixedRightBodyTable.length-1
119 table.fixedRightBodyTable = table.fixedRightBodyTable[rightBodyTableIndex]
120 }
121
122 table.innerTableBody= contentTable.querySelector('.u-table-scroll .u-table-body table');
123 table.fixedLeftBodyRows = table.fixedLeftBodyTable && table.fixedLeftBodyTable.querySelectorAll('tr') || [];
124 table.fixedRightBodyRows = table.fixedRightBodyTable && table.fixedRightBodyTable.querySelectorAll('tr') || [];
125 }
126
127
128 this.table = table;
129
130 if(!this.props.dragborder)return;
131 if(document.getElementById("u-table-drag-thead-" + this.theadKey)){
132 this.fixedTable = {};
133 let _fixedParentContext = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
134 let siblingDom = _fixedParentContext.parentNode.nextElementSibling;
135 if (siblingDom) {
136 let fixedTable = siblingDom.querySelector("table");
137 this.fixedTable.table = fixedTable
138 this.fixedTable.cols = fixedTable.getElementsByTagName("col");
139 // this.fixedTable.ths = fixedTable.tableDome.getElementsByTagName("th");
140 }
141 }
142 }
143
144 /**
145 * 事件初始化
146 */
147 initEvent(){
148 let {dragborder,draggable,rows} = this.props;
149 // 当传入的 columns 为空时,不绑定拖拽事件
150 if(Object.prototype.toString.call(rows) === '[object Array]' && rows.length === 0){
151 return;
152 }
153 if(!this.event){ //避免多次绑定问题。
154 this.event = true;
155 if(dragborder){
156 this.dragBorderEventInit();//列宽
157 }
158 if(draggable){
159 this.dragAbleEventInit();//交换列
160 }
161 if(this.table && this.table.tr){
162 // this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',this.table.tr[0]);//body mouseup
163 this.doEventList(this.table.tr,(tr)=>{
164 this.eventListen([{key:'mousedown',fun:this.onTrMouseDown}],'',tr);//body mouseup
165 })
166 }
167 this.eventListen([{key:'mouseup',fun:this.bodyonLineMouseUp}],'',document.body);//body mouseup
168 }
169 }
170
171
172 doEventList(trs,action){
173 for (let index = 0; index < trs.length; index++) {
174 action(trs[index]);
175 }
176 }
177
178 /**
179 * 拖拽列宽事件的监听
180 */
181 dragBorderEventInit (){
182 if(!this.props.dragborder )return;
183 let events = [
184 {key:'mouseup', fun:this.onTrMouseUp},
185 {key:'mousemove', fun:this.onTrMouseMove},
186 // {key:'mousemove', fun:debounce(50,this.onTrMouseMove)},//函数节流后体验很差
187 ];
188 this.doEventList(this.table.tr,(tr)=>{
189 this.eventListen(events,'',tr);//表示把事件添加到th元素上
190 })
191 // this.eventListen(events,'',this.table.tr[0]);//表示把事件添加到th元素上
192 }
193
194 /**
195 * 删除拖动改变列宽的事件监听
196 */
197 removeDragBorderEvent(){
198 let events = [
199 {key:'mouseup', fun:this.onTrMouseUp},
200 {key:'mousemove', fun:this.onTrMouseMove},
201 ];
202 // this.eventListen(events,'remove',this.table.tr[0]);
203 this.doEventList(this.table.tr,(tr)=>{
204 this.eventListen(events,'remove',this.table.tr);
205 })
206 }
207
208 eventListen(events,type,eventSource){
209 if(!this.table)return;
210 if(!eventSource){
211 console.log("Please set the attributes of column !");
212 return;
213 }
214 let {tr} = this.table;
215 for (let i = 0; i < events.length; i++) {
216 const _event = events[i];
217 if(type === "remove"){
218 EventUtil.removeHandler(eventSource,_event.key,_event.fun);
219 }else{
220 EventUtil.addHandler(eventSource,_event.key,_event.fun);
221 }
222 }
223 }
224
225 /**
226 *
227 *根据 data-type 来获取当前拖拽的对象的Object,如果为null表示拖动的对象并非是online
228 * @memberof TableHeader
229 */
230 getOnLineObject = (_element) =>{
231 let type = _element.getAttribute('data-type'),elementObj = null;
232 if(!type){
233 let element = _element.parentElement||parentNode;//兼容写法。
234 if(element.getAttribute('data-type')){
235 elementObj = element;
236 }
237 }else{
238 elementObj = _element;
239 }
240 return elementObj;
241 }
242
243 /**
244 * 调整列宽的down事件
245 * @memberof TableHeader
246 */
247 onTrMouseDown = (e) => {
248 const { eventNoStop } = this.props;
249 !eventNoStop && Event.stopPropagation(e);
250 let event = Event.getEvent(e) ,
251 targetEvent = Event.getTarget(event);
252 const { clsPrefix, contentTable,lastShowIndex,columnsChildrenList } = this.props;
253 // let currentElement = this.getOnLineObject(targetEvent);
254 let currentElement = this.getTargetToType(targetEvent);
255 if(!currentElement)return;
256 let type = currentElement.getAttribute('data-type');
257 if(!this.props.dragborder && !this.props.draggable)return;
258 if(type == 'online' && this.props.dragborder){
259 // if(!this.props.dragborder)return;
260 targetEvent.setAttribute('draggable',false);//添加交换列效果
261 let currentIndex = -1;
262 let defaultWidth = currentElement.getAttribute("data-th-width");
263 this.drag.option = "border";//拖拽操作
264 if(columnsChildrenList){
265 let columnKey = currentElement.getAttribute("data-line-key");
266 if(columnKey){
267 currentIndex = columnsChildrenList.findIndex(da=> (da.key && da.key.toLowerCase()) === columnKey.toLowerCase());
268 }
269 }
270 if(currentIndex < 0){
271 console.log('Key must be set for column!')
272 return;
273 }
274 let currentObj = this.table.cols[currentIndex];
275 this.drag.currIndex = currentIndex;
276 this.drag.oldLeft = event.x;
277 this.drag.oldWidth = parseInt((currentObj).style.width);
278 this.drag.minWidth = currentObj.style.minWidth != ""?parseInt(currentObj.style.minWidth):defaultWidth;
279 this.drag.tableWidth = parseInt(this.table.table.style.width ?this.table.table.style.width:this.table.table.scrollWidth);
280 if(!this.tableOldWidth){
281 this.tableOldWidth = this.drag.tableWidth;//this.getTableWidth();
282 }
283 if(!this.lastColumWidth){
284 this.lastColumWidth = parseInt(this.table.cols[lastShowIndex].style.width);
285 }
286 }else if(type != 'online' && this.props.draggable){
287 // if (!this.props.draggable || targetEvent.nodeName.toUpperCase() != "TH") return;
288 if (!this.props.draggable) return;
289 let th = this.getTargetToType(targetEvent);
290 th.setAttribute('draggable',true);//添加交换列效果
291 this.drag.option = 'dragAble';
292 this.currentDome = th;
293 let currentIndex = parseInt(th.getAttribute("data-line-index"));
294 this.drag.currIndex = currentIndex;
295 }else{
296 // console.log("onTrMouseDown dragborder or draggable is all false !");
297 return ;
298 }
299 };
300
301 getTableWidth = ()=>{
302 let tableWidth = 0,offWidth = 0;//this.table.cols.length;
303 for (let index = 0; index < this.table.cols.length; index++) {
304 let da = this.table.cols[index];
305 tableWidth += parseInt((da).style.width);
306 }
307 return (tableWidth-offWidth);
308 }
309
310 /**
311 * 根据当前节点查找到有data-type类型的容器返回。
312 * @memberof TableHeader
313 */
314 getTargetToType = (targetEvent) => {
315 let tag = targetEvent;
316 if(targetEvent && !targetEvent.getAttribute("data-type")){
317 tag = this.getTargetToType(targetEvent.parentElement);
318 }
319 return tag;
320 }
321
322
323 /**
324 * 判断当前的target 是否是 th,如果不是,直接递归查找。
325 * @memberof TableHeader
326 */
327 getTargetToTh = (targetEvent) => {
328 let th = targetEvent;
329 if(targetEvent.nodeName.toUpperCase() != "TH"){
330 th = this.getThDome(targetEvent);
331 }
332 // console.log(" getTargetToTh: ", th);
333 return th;
334 }
335 /**
336 * 调整列宽的move事件
337 * @memberof TableHeader
338 */
339 onTrMouseMove = (e) => {
340 if(!this.props.dragborder && !this.props.draggable)return;
341 const { clsPrefix ,dragborder,contentDomWidth,scrollbarWidth,contentTable,headerScroll,lastShowIndex,onDraggingBorder, leftFixedWidth, rightFixedWidth, bodyDisplayInRow, eventNoStop} = this.props;
342 !eventNoStop && Event.stopPropagation(e);
343 let event = Event.getEvent(e);
344 if(this.props.dragborder && this.drag.option == "border"){
345 //移动改变宽度
346 let currentCols = this.table.cols[this.drag.currIndex];
347 let diff = (event.x - this.drag.oldLeft);
348 let newWidth = this.drag.oldWidth + diff;
349 this.drag.newWidth = newWidth > 0 ? newWidth : this.minWidth;
350 if(newWidth > this.minWidth){
351 currentCols.style.width = newWidth +'px';
352
353 // displayinrow 判断、 固定行高判断
354 if(!bodyDisplayInRow) {
355 this.table.bodyRows.forEach((row,index)=>{
356 const leftRow = this.table.fixedLeftBodyRows[index];
357 const rightRow = this.table.fixedRightBodyRows[index];
358 if(leftRow || rightRow) {
359 const height = row.getBoundingClientRect().height;
360 leftRow && (leftRow.style.height = height + "px")
361 rightRow && (rightRow.style.height = height + "px")
362 }
363 })
364 }
365
366 //hao 支持固定表头拖拽 修改表体的width
367 if(this.fixedTable.cols){
368 this.fixedTable.cols[this.drag.currIndex].style.width = newWidth + "px";
369 }
370
371 let newDiff = (parseInt(currentCols.style.minWidth) - parseInt(currentCols.style.width));
372 if(newDiff > 0){//缩小
373 let lastWidth = this.lastColumWidth + newDiff;
374 this.table.cols[lastShowIndex].style.width = lastWidth +"px";//同步表头
375 this.table.tableBodyCols[lastShowIndex].style.width = lastWidth + "px";//同步表体
376
377 }
378 let showScroll = contentDomWidth - (leftFixedWidth + rightFixedWidth) - (this.drag.tableWidth + diff) - scrollbarWidth ;
379 //表头滚动条处理
380 if(headerScroll){
381 if(showScroll < 0){ //小于 0 出现滚动条
382 //找到固定列表格,设置表头的marginBottom值为scrollbarWidth;
383 this.table.contentTableHeader.style.overflowX = 'scroll';
384 this.optTableMargin( this.table.fixedLeftHeaderTable,scrollbarWidth);
385 this.optTableMargin( this.table.fixedRighHeadertTable,scrollbarWidth);
386 }else{ //大于 0 不显示滚动条
387 this.table.contentTableHeader.style.overflowX = 'hidden';
388 this.optTableMargin( this.table.fixedLeftHeaderTable,0);
389 this.optTableMargin( this.table.fixedRighHeadertTable,0);
390 }
391 }else{
392 if(showScroll < 0){
393 this.table.tableBody.style.overflowX = 'auto';
394 this.optTableMargin( this.table.fixedLeftBodyTable,'-'+scrollbarWidth);
395 this.optTableMargin( this.table.fixedRightBodyTable,'-'+scrollbarWidth);
396 this.optTableScroll( this.table.fixedLeftBodyTable,{x:'scroll'});
397 this.optTableScroll( this.table.fixedRightBodyTable,{x:'scroll'});
398 }else{
399 this.table.tableBody.style.overflowX = 'hidden';
400 this.optTableMargin( this.table.fixedLeftBodyTable,0);
401 this.optTableMargin( this.table.fixedRightBodyTable,0);
402 this.optTableScroll( this.table.fixedLeftBodyTable,{x:'auto'});
403 this.optTableScroll( this.table.fixedRightBodyTable,{x:'auto'});
404 }
405 }
406 }else {
407 this.drag.newWidth = this.minWidth;
408 }
409 }
410 // 增加拖拽列宽动作的回调函数
411 this.drag.newWidth && onDraggingBorder && onDraggingBorder(event, this.drag.newWidth);
412 }
413
414 /**
415 * 调整列宽的up事件
416 * @memberof TableHeader
417 */
418 onTrMouseUp = (e) => {
419 let event = Event.getEvent(e);
420 let width = this.drag.newWidth;
421 let opt = this.drag.option;
422 this.mouseClear();
423 if(opt !== "border") return; // fix:点击表头会触发onDropBorder事件的问题
424 this.props.onDropBorder && this.props.onDropBorder(event,width);
425 };
426
427
428 mouseClear(){
429 if(!this.drag || !this.drag.option)return;
430 let {rows} = this.props;
431 let data = {rows:rows[0],cols:this.table.cols,currIndex:this.drag.currIndex};
432 this.props.afterDragColWidth && this.props.afterDragColWidth(data);
433 this.drag = {
434 option:""
435 };
436 this.clearThsDr();
437 }
438
439 clearThsDr =()=>{
440 let ths = this.table.ths;
441 for (let index = 0; index < ths.length; index++) {
442 ths[index].setAttribute('draggable',false);//去掉交换列效果
443 }
444 }
445
446 /**
447 * 当前对象上绑定全局事件,用于拖拽区域以外时的事件处理
448 * @param {*} events
449 * @param {*} type
450 * @memberof TableHeader
451 */
452 bodyonLineMouseUp = (events,type) =>{
453 if(!this.drag || !this.drag.option)return;
454 this.mouseClear();
455 }
456
457
458 /**
459 *相关滚动条联动操作
460 *
461 * @memberof TableHeader
462 */
463 optTableMargin =(table,scrollbarWidth)=>{
464 if(table){
465 table.style.marginBottom = scrollbarWidth + "px"
466 }
467 }
468
469 optTableScroll = (table,overflow ={})=>{
470 if(table){
471 const innerTable = table.querySelector('.u-table-body-inner');
472 if(innerTable){
473 //fixbug: 拖拽列宽后,滚动条滚到表格底部,会导致固定列和非固定列错行
474 overflow.x && (innerTable.style.overflowX = overflow.x);
475 overflow.y && (innerTable.style.overflowY = overflow.y);
476 }
477
478 }
479 }
480
481 //---拖拽交换列代码----start-----
482 /**
483 * 添加换列的事件监听
484 */
485 dragAbleEventInit (){
486 if (!this.props.draggable) return;
487 let events = [
488 {key:'dragstart',fun:this.onDragStart},//用户开始拖动元素时触发
489 {key:'dragover', fun:this.onDragOver},//当某被拖动的对象在另一对象容器范围内拖动时触发此事件
490 {key:'drop', fun:this.onDrop}, //在一个拖动过程中,释放鼠标键时触发此事件
491
492 {key:'dragenter', fun:this.onDragEnter},
493 {key:'dragend', fun:this.onDragEnd},
494 {key:'dragleave', fun:this.onDragLeave},
495 ];
496 this.eventListen(events,'',this.table.tr[0]);//表示把事件添加到th元素上
497 }
498
499 /**
500 * 删除换列的事件监听
501 */
502 removeDragAbleEvent(){
503 let events = [
504 {key:'dragstart',fun:this.onDragStart},
505 {key:'dragover', fun:this.onDragOver},
506 {key:'drop', fun:this.onDrop},
507 {key:'dragenter', fun:this.onDragEnter},
508 {key:'dragend', fun:this.onDragEnd},
509 {key:'dragleave', fun:this.onDragLeave},
510 ];
511 this.eventListen(events,'remove',this.table.tr[0]);
512 }
513
514 /**
515 * 开始调整交换列的事件
516 */
517 onDragStart = (e) => {
518 if (!this.props.draggable) return;
519 if(this.drag && this.drag.option != 'dragAble'){return;}
520 let event = Event.getEvent(e) ,
521 // target = Event.getTarget(event);
522 target = this.getTargetToTh(Event.getTarget(event));
523 let currentIndex = parseInt(target.getAttribute("data-line-index"));
524 let currentKey = target.getAttribute('data-line-key');
525
526 if(event.dataTransfer.setDragImage){
527 var crt = target.cloneNode(true);
528 crt.style.backgroundColor = "#ebecf0";
529 crt.style.width = this.table.cols[currentIndex].style.width;//拖动后再交换列的时候,阴影效果可同步
530 crt.style.height = "40px";
531 // crt.style['line-height'] = "40px";
532 // document.body.appendChild(crt);
533 document.getElementById(this._table_none_cont_id).appendChild(crt);
534 event.dataTransfer.setDragImage(crt, 0, 0);
535 }
536
537 event.dataTransfer.effectAllowed = "move";
538 event.dataTransfer.setData("Text", currentKey);
539 this.currentObj = this.props.rows[0][currentIndex];
540 };
541
542 onDragOver = (e) => {
543 let event = Event.getEvent(e);
544 event.preventDefault();
545 };
546
547 /**
548 * 在一个拖动过程中,释放鼠标键时触发此事件。【目标事件】
549 * @memberof TableHeader
550 */
551 onDrop = (e) => {
552 if (!this.props.draggable) return;
553 let props = this.getCurrentEventData(this._dragCurrent)
554 e.column = {props};
555 if(this.drag && this.drag.option != 'dragAble'){
556 this.props.onDrop(e);
557 return;
558 }
559 let event = Event.getEvent(e) ,
560 target = Event.getTarget(event);
561 event.preventDefault()
562 event.stopPropagation();
563 this.currentDome.setAttribute('draggable',false);//添加交换列效果
564 // let data = this.getCurrentEventData(this._dragCurrent);
565 // if(!data){
566 // this.props.onDrop(e);
567 // return;
568 // }
569 if(!this.props.onDrop)return;
570 // this.props.onDrop(event,target);
571 this.props.onDrop(event,{dragSource:this.currentObj,dragTarg:e.column});
572 };
573
574
575 onDragEnter = (e) => {
576 let event = Event.getEvent(e) ,
577 target = Event.getTarget(event);
578 this._dragCurrent = target;
579 let currentIndex = target.getAttribute("data-line-index");
580 if(!currentIndex || parseInt(currentIndex) === this.drag.currIndex)return;
581 if(target.nodeName.toUpperCase() === "TH"){
582 // target.style.border = "2px dashed rgba(5,0,0,0.25)";
583 target.setAttribute("style","border-right:2px dashed rgb(30, 136, 229)");
584 // target.style.backgroundColor = 'rgb(235, 236, 240)';
585 }
586 }
587
588 onDragEnd = (e) => {
589 let event = Event.getEvent(e) ,
590 target = Event.getTarget(event);
591 this._dragCurrent.setAttribute("style","");
592 event.preventDefault()
593 event.stopPropagation();
594 // this._dragCurrent.style = "";
595 document.getElementById(this._table_none_cont_id).innerHTML = "";
596
597 let data = this.getCurrentEventData(this._dragCurrent);
598 if(!data)return;
599 if (!this.currentObj || this.currentObj.key == data.key) return;
600 if(!this.props.onDragEnd)return;
601 this.props.onDragEnd(event,{dragSource:this.currentObj,dragTarg:data});
602 }
603
604
605 onDragLeave = (e) => {
606 let event = Event.getEvent(e) ,
607 target = Event.getTarget(event);
608 let currentIndex = target.getAttribute("data-line-index");
609 if(!currentIndex || parseInt(currentIndex) === this.drag.currIndex)return;
610 if(target.nodeName.toUpperCase() === "TH"){
611 target.setAttribute("style","");
612 // this._dragCurrent.style = "";
613 }
614 }
615
616
617
618 /**
619 * 获取当前th上的对象数据
620 * @param {*} e
621 * @returns
622 * @memberof TableHeader
623 */
624 getCurrentEventData(th){
625 if(!th){
626 console.log(" event target is not th ! ");
627 return null;
628 }
629 let key = th.getAttribute('data-line-key');
630 let data = this.props.rows[0].find(da=>da.key == key);
631 if(data){
632 return data;
633 }else{
634 console.log(" getCurrentEventData data is null ");
635 return null;
636 }
637 }
638
639 /**
640 * 根据当前鼠标点击的节点,进行递归遍历,最终找到th
641 * @param {*} element
642 * @returns <th />对象
643 * @memberof TableHeader
644 */
645 getThDome(element){
646 let _tagName = element.tagName.toLowerCase();
647 if(element.getAttribute('data-filter-type') === 'filterContext')return null;
648 if(_tagName === 'i')return null;
649 if(_tagName != 'th'){
650 return this.getThDome(element.parentElement);
651 }else{
652 return element;
653 }
654 }
655
656
657//---拖拽列交换----end-----
658
659 /**
660 * 过滤输入后或下拉条件的回调函数
661 */
662 handlerFilterChange = (key, value, condition) => {
663 let { onFilterChange } = this.props;
664 if (onFilterChange) {
665 onFilterChange(key, value, condition);
666 }
667 };
668
669 /**
670 * 过滤行清除回调
671 */
672 handlerFilterClear = (field) => {
673 let { onFilterClear } = this.props;
674 if (onFilterClear) {
675 onFilterClear(field);
676 }
677 }
678
679 /**
680 * 过滤渲染的组件类型
681 */
682 filterRenderType = (type, dataIndex, index) => {
683 const { clsPrefix, rows, filterDelay, locale } = this.props;
684 switch (type) {
685 //文本输入
686 case "text":
687 return (
688 <FilterType
689 locale={locale}//多语
690 rendertype={type}//渲染类型
691 clsPrefix={clsPrefix}//css前缀
692 className={`${clsPrefix} filter-text`}
693 dataIndex={dataIndex}//字段
694 onFilterChange={debounce(filterDelay || 300, this.handlerFilterChange)}//输入框回调
695 onFilterClear={this.handlerFilterClear}//清除回调
696 filterDropdown={rows[1][index]["filterdropdown"]}//是否显示下拉条件
697 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
698 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
699 />
700 );
701 //数值输入
702 case "number":
703 return (
704 <FilterType
705 locale={locale}
706 rendertype={type}
707 clsPrefix={clsPrefix}
708 className={`${clsPrefix} filter-text`}
709 dataIndex={dataIndex}//字段
710 onFilterChange={debounce(filterDelay || 300, this.handlerFilterChange)}//输入框回调并且函数防抖动
711 onFilterClear={this.handlerFilterClear}//清除回调
712 filterDropdown={rows[1][index]["filterdropdown"]}
713 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
714 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
715 filterInputNumberOptions={rows[1][index]["filterinputnumberoptions"]}//设置数值框内的详细属性
716 />
717 );
718 //下拉框选择
719 case "dropdown":
720 let selectDataSource = [];
721 //处理没有输入数据源的时候,系统自动查找自带的数据筛选后注入
722 if (rows.length > 0 && (rows[1][index]["filterdropdownauto"] || "auto") == "auto") {
723 let hash = {};
724 //处理下拉重复对象组装dropdown
725 selectDataSource = Array.from(rows[1][0].datasource, x => ({
726 key: x[dataIndex],
727 value: x[dataIndex]
728 }));
729 selectDataSource = selectDataSource.reduceRight((item, next) => {
730 hash[next.key] ? "" : (hash[next.key] = true && item.push(next));
731 return item;
732 }, []);
733 } else {
734 //从外部数据源加载系统数据
735 selectDataSource = rows[1][index]["filterdropdowndata"];
736 }
737 return (
738 <FilterType
739 locale={locale}
740 rendertype={type}
741 className={`${clsPrefix} filter-dropdown`}
742 data={selectDataSource}
743 notFoundContent={"Loading"}//没有数据显示的默认字
744 dataIndex={dataIndex}//字段
745 onFilterChange={this.handlerFilterChange}//输入框回调
746 onFilterClear={this.handlerFilterClear}//清除回调
747 filterDropdown={rows[1][index]["filterdropdown"]}
748 onFocus={rows[1][index]["filterdropdownfocus"]}
749 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
750 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
751 />
752 );
753 //日期
754 case "date":
755 return (
756 <FilterType
757 locale={locale}
758 rendertype={type}
759 className={`filter-date`}
760 onClick={() => { }}
761 format={rows[1][index]["format"] || "YYYY-MM-DD"}
762 dataIndex={dataIndex}//字段
763 onFilterChange={this.handlerFilterChange}//输入框回调
764 onFilterClear={this.handlerFilterClear}//清除回调
765 filterDropdown={rows[1][index]["filterdropdown"]}
766 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
767 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
768 />
769 );
770 //日期 年
771 case "dateyear":
772 return (
773 <FilterType
774 locale={locale}
775 rendertype={type}
776 className={`filter-date`}
777 onClick={() => { }}
778 format={rows[1][index]["format"] || "YYYY"}
779 dataIndex={dataIndex}//字段
780 onFilterChange={this.handlerFilterChange}//输入框回调
781 onFilterClear={this.handlerFilterClear}//清除回调
782 filterDropdown={rows[1][index]["filterdropdown"]}
783 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
784 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
785 />
786 );
787 //日期 月
788 case "datemonth":
789 return (
790 <FilterType
791 locale={locale}
792 rendertype={type}
793 className={`filter-date`}
794 onClick={() => { }}
795 format={rows[1][index]["format"] || "YYYY-MM"}
796 dataIndex={dataIndex}//字段
797 onFilterChange={this.handlerFilterChange}//输入框回调
798 onFilterClear={this.handlerFilterClear}//清除回调
799 filterDropdown={rows[1][index]["filterdropdown"]}
800 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
801 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
802 />
803 );
804 //日期 周
805 case "dateweek":
806 return (
807 <FilterType
808 locale={locale}
809 rendertype={type}
810 className={`filter-date`}
811 onClick={() => { }}
812 format={rows[1][index]["format"] || "YYYY-Wo"}
813 dataIndex={dataIndex}//字段
814 onFilterChange={this.handlerFilterChange}//输入框回调
815 onFilterClear={this.handlerFilterClear}//清除回调
816 filterDropdown={rows[1][index]["filterdropdown"]}
817 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
818 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
819 />
820 );
821 //日期范围
822 case "daterange":
823 return (
824 <FilterType
825 locale={locale}
826 rendertype={type}
827 className={`filter-date`}
828 onClick={() => { }}
829 format={rows[1][index]["format"] || "YYYY-MM-DD"}
830 dataIndex={dataIndex}//字段
831 onFilterChange={this.handlerFilterChange}//输入框回调
832 onFilterClear={this.handlerFilterClear}//清除回调
833 filterDropdown={rows[1][index]["filterdropdown"]}
834 filterDropdownType={rows[1][index]["filterdropdowntype"]}//下拉的条件类型为string,number
835 filterDropdownIncludeKeys={rows[1][index]["filterdropdownincludekeys"]}//下拉条件按照指定的keys去显示
836 />
837 );
838 default:
839 //不匹配类型默认文本输入
840 return <div />;
841 }
842 };
843
844 onCopy = (data,index, event) => {
845 if(this.props.onCopy) {
846 this.props.onCopy(Object.assign(data,{col: index}),event)
847 }
848 }
849
850
851 render() {
852 const { clsPrefix, rowStyle,draggable,
853 dragborder, rows,filterable,fixed,lastShowIndex,columnsChildrenList
854 } = this.props;
855 let attr = dragborder ? { id: `u-table-drag-thead-${this.theadKey}` } : {};
856 let lastObj = columnsChildrenList[columnsChildrenList.length-1];
857 return (
858 <thead className={`${clsPrefix}-thead`} {...attr} data-theader-fixed='scroll' ref={_thead=>this._thead = _thead} >
859 {rows.map((row, index) => {
860 let _rowLeng = (row.length-1);
861 return(<tr key={index} style={rowStyle} className={(filterable && index == rows.length - 1)?'filterable':''}>
862 {row.map((da, columIndex, arr) => {
863 da.children = da.required ? <span><span className='required'>*</span>{da.children}</span> : da.children;
864 let thHover = da.drgHover
865 ? ` ${clsPrefix}-thead th-drag-hover`
866 : "";
867 delete da.drgHover;
868 let fixedStyle = "";
869 let canDotDrag = "";
870 //主表格下、固定列或者是过滤行中含有固定列时添加该属性
871 if (!fixed && (da.fixed || (filterable && index == rows.length - 1 && rows[0][columIndex].fixed)) ) {
872 fixedStyle = ` ${clsPrefix}-row-fixed-columns-in-body`;
873 }
874
875 if (lastShowIndex == columIndex) {
876 canDotDrag = "th-can-not-drag";
877 }
878 let thClassName = `${da.className}`?`${da.className}`:'';
879 if(da.titleAlign){
880 thClassName += ` text-${da.titleAlign} `;
881 }
882 else if(da.textAlign){
883 thClassName += ` text-${da.textAlign} `;
884 }
885
886 delete da.textAlign;
887 delete da.titleAlign;
888 const keyTemp = {};
889 //避免key为undefined
890 // if(da.dataindex && da.key ===undefined ){
891 keyTemp.key = da.key || da.dataindex || index+'-'+columIndex
892
893 // }
894 if (filterable && index == rows.length - 1) {
895 da.children = this.filterRenderType(
896 da["filtertype"],
897 da.dataindex,
898 columIndex
899 );
900 if(da.key ===undefined ){
901 keyTemp.key = keyTemp.key + '-filterable'
902 }
903 delete da.filterdropdownfocus;
904 }
905
906 let thDefaultObj = {};
907
908 if(draggable){
909 thClassName += ` ${clsPrefix}-thead th-drag ${thHover} `;
910 }
911 if(dragborder){
912 thClassName += ` ${clsPrefix}-thead-th ${canDotDrag}`;
913 }
914 thClassName += ` ${fixedStyle}`;
915 if(!da.fixed ){
916 return (<th {...da} {...keyTemp} className={thClassName} data-th-fixed={da.fixed} data-line-key={da.key}
917 data-line-index={columIndex} data-th-width={da.width} data-type="draggable" onCopy={(event) => {this.onCopy(da,columIndex,event)}}>
918 {da.children}
919 {
920 // && columIndex != _rowLeng
921 dragborder && lastObj && da.key != lastObj.key ? <div ref={el => (this.gap = el)} data-line-key={da.key}
922 data-line-index={columIndex} data-th-width={da.width}
923 data-type="online" className = {`${clsPrefix}-thead-th-drag-gap`}>
924 <div className='online' /></div>:""
925 }
926 </th>)
927 }else{
928 thDefaultObj = {
929 ...da,
930 className:`${thClassName} ${fixedStyle}`,
931 };
932 da.onClick ?thDefaultObj.onClick = (e)=>{da.onClick(da, e)}:"";
933 return (<th {...thDefaultObj} {...keyTemp} data-th-fixed={da.fixed} style={{maxWidth: da.width}} onCopy={this.onCopy}/>)
934 }
935 })}
936 </tr>
937 )})}
938 </thead>
939 );
940 }
941}
942
943TableHeader.propTypes = propTypes;
944export default TableHeader;