ttk-server-parent
Version:
712 lines (647 loc) • 24.2 kB
JavaScript
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { Table } from 'antd'
import { Map, List, is, fromJS, Record } from 'immutable'
import { Resizable } from 'react-resizable';
import Checkbox from '../checkbox/index'
import uuid from './uuid'
//import $ from 'jquery'
import changeColSize from './resize'
import DecorateTable from './DecorateTable'
import NoData from '../nodata'
import classNames from 'classnames'
const ResizeableTitle = (props) => {
const { onResize, width, ...restProps } = props;
// if (!width) {
// return <th {...restProps} />;
// }
return (
<Resizable width={width ? width : 100} height={0} onResize={onResize}>
<th {...restProps} ></th>
</Resizable>
)
}
class AntTable extends Component {
static defaultProps = {
resizeColumn: true
}
constructor(props) {
super(props)
const memoryWidthLocalSotrage = this.memoryWidth(props)
this.state = {
resizeColumn: this.props.allowColResize,
selectValue: props.checkboxValue ? this.initSelectValue(props.checkboxValue, props.dataSource) : new Map(),
checkboxAllStatus: null,
checkboxId: new Map(),
columns: [],
memoryWidth: memoryWidthLocalSotrage,
sumWidth: 1090
}
if (this.props.allowColResize ){
const { newCol, sumWidth } = this.initStateWidth(props.columns, [], memoryWidthLocalSotrage)
this.state.columns = newCol
this.state.sumWidth = sumWidth
}
}
componentWillMount = () =>{
}
memoryWidth = (props) => {
const{ remberName } = props
if( !remberName ){
return {}
}
const memoryWidth = this.getAppData(remberName)
return memoryWidth
}
removeDom = () => {
let me = $(ReactDOM.findDOMNode(this))
let table = me.find('table')
let point = table.find('.table-needDel')
const { noDelCheckbox } = this.props
point.each(function (index, obj) {
let num = $(obj).attr('data-rol')
let sign = $(obj).parents('tr').find('.table-needDel2').attr('data-sign')
if (!sign) {
sign = $(obj).parents('tr').find('.table-needDel').attr('data-sign')
}
let backgroundColor = index % 2 == 0 ? '#fff' : '#F9F8FA '
$(obj).parents('tr').css('background', backgroundColor).attr('data-background', backgroundColor).attr('data-hover', sign).find('td')
let next = $(obj).parents('tr')
for (var i = 0; i < num - 1; i++) {
if (!noDelCheckbox) {
next.eq(0).next().css('background', backgroundColor).attr('data-hover', sign).find('td')
} else {
next.eq(0).next().css('background', backgroundColor).attr('data-hover', sign).find('td').eq(0)
}
next = next.eq(0).next()
}
$(obj).parents('tbody').find(`tr[data-hover=${sign}]`).hover(() => {
$(obj).parents('tbody').find(`tr[data-hover=${sign}]`).addClass('mk-active')
$(`.ant-table-fixed tbody`).find(`tr[data-hover=${sign}]`).addClass('mk-active')
}, () => {
$(obj).parents('tbody').find(`tr[data-hover=${sign}]`).removeClass('mk-active')
$(`.ant-table-fixed tbody`).find(`tr[data-hover=${sign}]`).removeClass('mk-active')
})
})
try {
let fixedTable = me.find('.ant-table-fixed')
let point = table.find('.table-needDel2')
let num = point.attr('data-rol')
point.each(function (index, obj) {
let num = $(obj).attr('data-rol')
let sign = $(obj).attr('data-sign')
let backgroundColor = table.find(`tr[data-hover=${sign}]`).eq(0).attr('data-background')
$(obj).parents('tr').attr('data-hover', sign).css('background', backgroundColor)
let next = $(obj).parents('tr').attr('data-hover', sign).find(`.table-needDel2[data-sign=${sign}]`)
for (var i = 0; i < num - 1; i++) {
next.eq(0).next().attr('data-hover', sign).css('background', backgroundColor)
next = next.eq(0).next()
}
$(obj).parents('tr').hover(() => {
table.find(`tr[data-hover=${sign}]`).addClass('mk-active')
fixedTable.find(`tr[data-hover=${sign}]`).addClass('mk-active')
}, () => {
table.find(`tr[data-hover=${sign}]`).removeClass('mk-active')
fixedTable.find(`tr[data-hover=${sign}]`).removeClass('mk-active')
})
})
} catch (err) {
}
}
componentWillReceiveProps(nextProps){
const { memoryWidth } = this.state
if( nextProps.checkboxKey ){
this.initCheckboxId(nextProps.dataSource)
}
if( nextProps.checkboxValue ){
const selectValue = this.initSelectValue(nextProps.checkboxValue, nextProps.dataSource)
this.setState({
selectValue
})
}
if( nextProps.allowColResize ){
const { newCol, sumWidth } = this.initStateWidth(nextProps.columns, this.state.columns, memoryWidth)
this.setState({
columns: newCol,
sumWidth
})
}
}
components = {
header: {
cell: ResizeableTitle,
},
}
handleResize = index => (e, { size }) => {
const { columns, appContainerWidth } = this.state
delete columns[columns.length-1]
const Index = columns.findIndex(item => item.dataIndex == index)
if( Index == -1 ){
return
}
let preWidth = columns[Index].width
columns[Index].width = size.width
let sumWidth = 0,
columnDetails = [],
param = {}
columns.forEach(item => {
columnDetails.push({
fieldName: item.dataIndex,
width: item.width,
isVisible: true
})
sumWidth = sumWidth + item.width
})
param.columnDetails = columnDetails
if( sumWidth <= appContainerWidth){
columns[Index].width = preWidth
}
this.setState({
columns: columns,
sumWidth
})
let that = this,res
this.onResizend(function(){
res = that.props.onResizeEnd(param)
})
}
showTheadTitle = (title) => {
if( Object.prototype.toString.call(title) == "[object String]" ){
return <span title={title}>{title}</span>
}else{
return title
}
}
onResizend = (onResizend) => {
/**
* <<<算法说明>>>
* ---------------------------------------------------------------------------------
* 1. 默认窗口状态 normal.
* 2. 调整窗口大小时状态 resizing.
* 3. 调整窗口大小时设置动作状态为 resizing, 并设置延时任务. 若已存在延时任务,则重新设置.
* 4. 若500毫秒后没有断续调整大小,则认为调整结束,执行resizend事件.
*/
let that = this,
timeOutTask = function(){
that.state.taskPtr && clearTimeout(that.state.taskPtr)
let taskPtr = setTimeout(function(){
onResizend && onResizend();
}, 500)
that.setState({taskPtr: taskPtr})
}
timeOutTask()
}
initStateWidth = (data, columns, memoryWidth) => {
if( !data ){
return []
}
let sumWidth = 0
let norSetWidth = 0
let flag = false
data.forEach(item => {
if( item.width ){
norSetWidth++
}else{
flag = true
}
})
if( flag ){
norSetWidth=0
}
let appContainerWidth = null
try{
const dom = document.getElementsByClassName('edfx-app-portal-content-main')[0]
if( dom ){
appContainerWidth = dom.offsetWidth - 160 + 80
}else{
appContainerWidth = window.innerWidth - 100 - 160 + 80
}
}catch(err){
console.log(err)
appContainerWidth = 1090
}
let avrWidth = Math.ceil((appContainerWidth)/ (data.length -1 ))
let sumWidth1 = 0
data.map((item) => {
if(item.width){
sumWidth1 = sumWidth1 + item.width
}
})
const newCol = data.map((item)=>{
item.title = this.showTheadTitle(item.title)
if(sumWidth1+80+60 < appContainerWidth && !item.fixed){
item.width = avrWidth
}
sumWidth= sumWidth + item.width
return item
})
this.state.appContainerWidth = appContainerWidth
return {newCol, sumWidth}
}
setTableHeight = () => {
try{
const { dataSource, className, scroll, noCalculate } = this.props
if( noCalculate ){
return
}
if( !scroll ){
return
}
let container = ReactDOM.findDOMNode(this)
if( !container ){
setTimeout(()=>{
this.setTableHeight()
}, 100)
}
const tableBody = container.getElementsByClassName('ant-table-body')[0]
if( this.state.resizeColumn && dataSource && dataSource.length == 0 ){
tableBody.style.overflowY = null
}
if( !scroll.x && !scroll.y ){
tableBody.style.height = 'auto'
return
}
if( !scroll.y ){
container.style.overflowY = 'auto'
}
if( tableBody.offsetHeight <= container.offsetHeight ){
container.style.overflowY = 'hidden'
}
if( !tableBody || this.props.dataSource && dataSource.length == 0 ){
tableBody.style.height = 'auto'
return
}
tableBody.style.height = container.offsetHeight + 'px'
const table = tableBody.getElementsByTagName('table')[0]
tableBody.style.overflowY = 'auto'
}catch(err){
console.log(err)
}
}
componentDidUpdate() {
// this.removeDom()
this.setTableHeight()
if (this.state.resizeColumn) {
let me = $(ReactDOM.findDOMNode(this))
let table = me.find('table')
let id = uuid()
table.attr('id', id)
// changeColSize(id, this.onResize)
// 去掉所有col上面的width
// this.setColumnsWidth(id)
}
}
componentDidMount() {
// 设置列表可拖动
// this.removeDom()
this.setTableHeight()
if (this.state.resizeColumn) {
let me = $(ReactDOM.findDOMNode(this))
let table = me.find('table')
let id = uuid()
table.attr('id', id)
// changeColSize(id)
// 去掉所有col上面的width
// this.setColumnsWidth(id)
}
let height = ReactDOM.findDOMNode(this).offsetHeight,
titleHeight = document.getElementsByClassName('ant-table-thead')[0].clientHeight
if(height !== this.state.height){
this.setState({
height: height - titleHeight - 32
})
}
/**
* 合并首列包含CHECKBOX的情况
*/
}
// setColumnsWidth = (id) => {
// let me = $(ReactDOM.findDOMNode(this))
// let table = me.find(`#${id}`)
// let colgroup = table.find('colgroup')
// let cols = colgroup.find('col')
// $(cols).each(function (index, el) {
// this.style.width = 'auto'
// })
// }
getColumns = () => {
let columns
if( this.state.allowColResize ){
columns = this.state.columns
}else{
columns = this.props.columns
}
let children = fromJS(columns),
renderColumns = []
if (!children || children.size == 0) {
return []
}
for (let i = 0; i < children.size; i++) {
let child = children.get(i)
let column = this.getColumnByMeta(child)
if(column)
renderColumns.push(column)
}
return renderColumns
}
getColumnByMeta = (meta) => {
let children = meta.get('children'),
ret = { ...meta.toJS() }
if(ret._visible === false)
return undefined
if (children && children.size > 0) {
ret.children = []
for (let sub of children) {
let o = this.getColumnByMeta(sub)
if(!o) continue
if(!ret.children)
ret.children = []
ret.children.push(o)
}
}
return ret
}
initSelectValue = (selcted, all) =>{
let selectValue = new Map()
const { checkboxKey } = this.props
selcted.forEach(item => {
const i = all.find(key => key[checkboxKey] == item )
selectValue = selectValue.set(item, i)
})
return selectValue
}
showCheckboxType = () => {
let { selectValue, checkboxId} = this.state
let obj = {}
if( !checkboxId.size ){
obj.checked = false
}else if( this.checkAllItem() ){
obj.checked = true
}else if( this.noCheckItem() ){
obj.checked = false
}else{
obj.checked = false
obj.indeterminate = true
}
return obj
}
noCheckItem = () => {
let { selectValue, checkboxId} = this.state
let flag = true
for( const key of checkboxId.keys() ){
if( selectValue.has(key) ){
flag = false
}
}
return flag
}
checkAllItem = () => {
let { selectValue, checkboxId} = this.state
let flag = true
for( const key of checkboxId.keys() ){
if( !selectValue.has(key) && typeof key != "undefined"){
flag = false
}
}
return flag
}
checkboxAllClick = (e) => {
let { selectValue, checkboxId} = this.state
if( selectValue.size == 0 ){
for( const [key, value] of checkboxId.entries() ) {
selectValue = selectValue.set(key, value)
}
}else if(this.checkAllItem()) {
selectValue = new Map()
}else{
for( const [key, value] of checkboxId.entries() ) {
selectValue = selectValue.set(key, value)
}
}
this.setState({
selectValue
})
this.update(selectValue)
}
checkboxItemClick = (e, key, record) => {
let map = this.state.selectValue
if( !map.has(key) ){
map = map.set(key, record)
}else(
map = map.delete(key)
)
this.setState({
selectValue: map
})
this.update(map)
}
initCheckboxId = (data) => {
if( !data ) {
return
}
let map = new Map()
const { checkboxKey } = this.props
data.forEach(item => {
if( !map.has(item[checkboxKey]) ){
map = map.set(item[checkboxKey], item)
}
})
this.setState({
checkboxId: map
})
}
rowSpan = (text, record, index) => {
const { checkboxKey } = this.props
const { dataSource } = this.props
if(!record[checkboxKey]) return 1;
const key = dataSource.findIndex(item => item[checkboxKey]==record[checkboxKey])
let num = 1
if( key == index ){
let i = 0
while( dataSource[index+i] && dataSource[index+i][checkboxKey] && dataSource[key] && dataSource[key][checkboxKey] && (dataSource[index+i][checkboxKey] == dataSource[key][checkboxKey]) ){
i++
}
num = i
}else{
num = 0
}
return num
}
renderChekbox = (type) => {
const { checkboxKey } = this.props
const { selectValue, columns } = this.state
if( type == 1 ) {
return {
title: <Checkbox {...this.showCheckboxType()} onClick={this.checkboxAllClick}/>,
dataIndex: 'checkboxKey',
key: 'checkboxKey',
className: "mk-table-checkbox",
width: 60,
render: (text, record, index) => {
const obj = {
children: record[checkboxKey]? <Checkbox
checked={selectValue.has(record[checkboxKey])}
onClick={(e)=>this.checkboxItemClick(e, record[checkboxKey], record)}
/>:null,
props: {
rowSpan: this.rowSpan(text, record, index),
},
}
return obj
}
}
}else{
return [
{
title: <Checkbox {...this.showCheckboxType()} onClick={this.checkboxAllClick}/>,
dataIndex: 'checkboxKey',
key: 'checkboxKey',
width: 60,
className: "mk-table-checkbox",
render: (text, record, index) => {
const obj = {
children: <Checkbox
checked={selectValue.has(record[checkboxKey])}
onClick={(e)=>this.checkboxItemClick(e, record[checkboxKey], record)}
/>,
props: {
rowSpan: this.rowSpan(text, record, index),
},
}
return obj
}
},
...columns
]
}
}
update = (data) => {
if( this.props.checkboxChange ) {
const arr = []
const arrValue = []
const { selectValue } = this.state
for( const [key, value] of data.entries() ){
arr.push(key)
arrValue.push(value)
}
this.props.checkboxChange(arr, arrValue)
}
}
rnederTitle = (text) => {
return <span title={text}>{text}</span>
}
decorateColumns = (columns) => {
return columns.map((col, index)=>{
if( !(col.tip == false) && !col.render && col.dataIndex ){
col.render = this.rnederTitle
}
if( this.state.resizeColumn ){
return {
...col,
onHeaderCell: (column) => ({
width: column.width,
onResize: this.handleResize(column.dataIndex),
}),
}
}else{
return col
}
})
}
getChildrenTitle = (item) => {
const obj = {
...item,
title: this.showTheadTitle(item.title)
}
if( item.children ){
const arr = []
for( const value of item.children.values() ){
arr.push(this.getChildrenTitle(value))
}
obj.children = arr
}
return obj
}
decorateHeaderTitle = (column) => {
if( !column ){
return undefined
}
return column.map(item => {
return this.getChildrenTitle(item)
})
}
render() {
let { ...otherProps } = this.props
let { columns, sumWidth } = this.state,
children = fromJS(this.props.columns),
renderColumn = [],
height = this.state.height, top, small = false, loading
if(height >= 238){
top = (height - 238)/2
}else{
small = true
top = (height - 168)/2
}
if(otherProps.loading != undefined){
loading = {
size: 'large',
spinning: otherProps.loading,
tip:"数据加载中..."
}
}
let emptyText = <NoData style={{position: 'relative', marginTop: top, paddingBottom: top}} small={small}>暂无数据</NoData>,
locale = {
'emptyText': emptyText
}
if (children && children.size > 0) {
// for (let i = 0; i < children.size; i++) {
// let child = children.get(i)
// if(child && child.get('children')){
// let nextColumns = []
// let nextChildren = child.get('children')
// for (let j = 0; j < nextChildren.size; j++) {
// let nextChild = nextChildren.get(j)
//
// let _visible = nextChild.get('_visible') === false ? false : true
// if (!_visible) continue
//
// nextColumns.push(nextChild.toJS())
// }
// renderColumn.push(nextColumns)
// } else {
// let _visible = child.get('_visible') === false ? false : true
// if (!_visible) continue
//
// renderColumn.push(child.toJS())
// }
// }
let renderColumn = this.getColumns()
if( this.props.checkboxKey ) {
renderColumn = [ this.renderChekbox(1) , ...renderColumn ]
}
const columns3 = this.decorateColumns(renderColumn)
let newColumn = this.decorateHeaderTitle(columns3)
let scrollX = this.props.dataSource&&this.props.dataSource.length > 0 ? sumWidth : null
if( this.state.resizeColumn ){
return <Table {...this.props }
scroll={{...this.props.scroll, x: scrollX}}
components={this.components}
columns={this.decorateHeaderTitle(columns3)}
locale={{'emptyText': emptyText}}
loading={loading}
/>
}else{
return <Table {...this.props } columns={this.decorateHeaderTitle(columns3)} locale={{'emptyText': emptyText}} loading={loading}/>
}
}
else {
return <Table {...this.props } columns={this.decorateHeaderTitle(this.props.columns)} locale={{'emptyText': emptyText}} loading={loading}/>
}
}
}
AntTable.Column = Table.Column
AntTable.ColumnGroup = Table.ColumnGroup
AntTable.rowSelection = Table.rowSelection
AntTable.selection = Table.selection
export default AntTable