| | |
| | | } |
| | | |
| | | render() { |
| | | let { col, config, record, style, className } = this.props |
| | | let { col, config, record, style, className, ...resProps } = this.props |
| | | const { editing, value, err } = this.state |
| | | |
| | | if (!col) return (<td {...resProps} className={className} style={style}/>) |
| | | |
| | | let children = null |
| | | if (col.type === 'text') { |
| | |
| | | } else if (col.editType === 'switch') { |
| | | let _value = record[col.field] !== undefined ? record[col.field] : '' |
| | | return (<td className="editing_table_cell"> |
| | | <CusSwitch config={col} defaultValue={_value} onChange={this.onSwitchChange} onBlur={this.switchBlur}/> |
| | | <CusSwitch config={col} defaultValue={_value} autoFocus={true} onChange={this.onSwitchChange} onBlur={this.switchBlur}/> |
| | | </td>) |
| | | } else { |
| | | let _value = record[col.field] !== undefined ? record[col.field] : '' |
| | |
| | | </td>) |
| | | } |
| | | } else { |
| | | return (<td className={className + ' pointer'} style={style}><div className="mk-mask" onClick={this.focus}></div>{content}</td>) |
| | | return (<td className={className + ' pointer'} style={style}> |
| | | {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null} |
| | | <div className="mk-mask" onClick={this.focus}></div>{content} |
| | | {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null} |
| | | </td>) |
| | | } |
| | | } else { |
| | | children = content |
| | |
| | | {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null} |
| | | </td>) |
| | | } else { |
| | | return (<td className={className + ' pointer'} style={style}><div className="mk-mask" onClick={this.focus}></div>{content}</td>) |
| | | return (<td className={className + ' pointer'} style={style}> |
| | | {col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null} |
| | | <div className="mk-mask" onClick={this.focus}></div>{content} |
| | | {col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null} |
| | | </td>) |
| | | } |
| | | } else { |
| | | children = content |
| | |
| | | } |
| | | } |
| | | |
| | | class BodyAllCell extends React.Component { |
| | | state = { |
| | | err: null |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props.record), fromJS(nextProps.record)) || |
| | | nextState.err !== this.state.err |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('tdFocus', this.tdFocus) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('tdFocus', this.tdFocus) |
| | | } |
| | | |
| | | tdFocus = (id) => { |
| | | const { col, record } = this.props |
| | | |
| | | if (id !== col.uuid + record.$$uuid) return |
| | | this.focus() |
| | | } |
| | | |
| | | enterPress = () => { |
| | | const { col, record } = this.props |
| | | |
| | | setTimeout(() => { |
| | | if (col.enter === '$next') { |
| | | MKEmitter.emit('nextLine', col, record.$$uuid) |
| | | } else { |
| | | MKEmitter.emit('tdFocus', col.enter + record.$$uuid) |
| | | } |
| | | }, 50) |
| | | } |
| | | |
| | | focus = () => { |
| | | const { col, record } = this.props |
| | | |
| | | if (col.editType === 'switch' || col.editType === 'select') { |
| | | let node = document.getElementById(col.uuid + record.$$uuid) |
| | | node && node.click() |
| | | } else { |
| | | let err = null |
| | | let val = record[col.field] !== undefined ? record[col.field] : '' |
| | | |
| | | if (col.type === 'number') { |
| | | val = +val |
| | | if (isNaN(val)) { |
| | | val = 0 |
| | | } |
| | | if (typeof(col.max) === 'number' && val > col.max) { |
| | | err = col.label + '最大为' + col.max |
| | | } else if (typeof(col.min) === 'number' && val < col.min) { |
| | | err = col.label + '最小为' + col.min |
| | | } |
| | | } else if (col.required === 'true' && !val) { |
| | | err = '请填写' + col.label |
| | | } |
| | | |
| | | this.setState({err}, () => { |
| | | let node = document.getElementById(col.uuid + record.$$uuid) |
| | | node && node.select() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | onChange = (val) => { |
| | | const { col, record } = this.props |
| | | |
| | | let err = null |
| | | |
| | | if (col.type === 'number') { |
| | | val = +val |
| | | if (isNaN(val)) { |
| | | val = 0 |
| | | } |
| | | if (typeof(col.max) === 'number' && val > col.max) { |
| | | err = col.label + '最大为' + col.max |
| | | } else if (typeof(col.min) === 'number' && val < col.min) { |
| | | err = col.label + '最小为' + col.min |
| | | } |
| | | } else if (col.required === 'true' && !val) { |
| | | err = '请填写' + col.label |
| | | } |
| | | this.setState({err}) |
| | | MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val}) |
| | | } |
| | | |
| | | onSwitchChange = (val) => { |
| | | const { col, record } = this.props |
| | | |
| | | setTimeout(() => { |
| | | if (col.enter === '$next') { |
| | | MKEmitter.emit('nextLine', col, record.$$uuid) |
| | | } else { |
| | | MKEmitter.emit('tdFocus', col.enter + record.$$uuid) |
| | | } |
| | | }, 50) |
| | | |
| | | MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: val}) |
| | | } |
| | | |
| | | onSelectChange = (val, option) => { |
| | | const { col, record } = this.props |
| | | |
| | | let values = {} |
| | | let _option = col.options.filter(m => m.key === option.key)[0] |
| | | |
| | | if (_option) { |
| | | if (col.linkSubField) { |
| | | col.linkSubField.forEach(m => { |
| | | values[m] = _option[m] !== undefined ? _option[m] : '' |
| | | }) |
| | | } |
| | | |
| | | if (col.editField) { |
| | | values[col.field] = _option.label |
| | | values[col.editField] = val |
| | | } else { |
| | | values[col.field] = val |
| | | } |
| | | } |
| | | |
| | | setTimeout(() => { |
| | | if (col.enter === '$next') { |
| | | MKEmitter.emit('nextLine', col, record.$$uuid) |
| | | } else { |
| | | MKEmitter.emit('tdFocus', col.enter + record.$$uuid) |
| | | } |
| | | }, 50) |
| | | |
| | | MKEmitter.emit('changeRecord', col.tableId, {...record, ...values}) |
| | | } |
| | | |
| | | render() { |
| | | let { col, config, record, style, className } = this.props |
| | | const { err } = this.state |
| | | |
| | | let children = null |
| | | if (col.type === 'text') { |
| | | if (col.editable === 'true') { |
| | | let _value = record[col.field] !== undefined ? record[col.field] : '' |
| | | if (!col.editType || col.editType === 'text') { |
| | | children = (<> |
| | | <Input id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(e) => this.onChange(e.target.value)} onPressEnter={this.enterPress} onBlur={this.onBlur}/> |
| | | {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null} |
| | | </>) |
| | | } else if (col.editType === 'switch') { |
| | | children = ( |
| | | <CusSwitch config={col} autoFocus={false} defaultValue={_value} onChange={this.onSwitchChange} onBlur={() => {}}/> |
| | | ) |
| | | } else { |
| | | children = (<> |
| | | <Select |
| | | showSearch |
| | | defaultValue={_value} |
| | | id={col.uuid + record.$$uuid} |
| | | onBlur={() => this.setState({editing: false})} |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onSelect={this.onSelectChange} |
| | | > |
| | | {col.options.map((item, i) => (<Select.Option key={item.key} disabled={item.$disabled} value={item.value}>{item.label}</Select.Option>))} |
| | | </Select> |
| | | </>) |
| | | } |
| | | } else { |
| | | let content = '' |
| | | if (record[col.field] !== undefined) { |
| | | content = `${record[col.field]}` |
| | | } |
| | | |
| | | if (content !== '') { |
| | | if (col.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(content)) { |
| | | content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)}` |
| | | } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(content)) { |
| | | content = `${content.substr(0, 4)}-${content.substr(5, 2)}-${content.substr(8, 2)} ${content.substr(11, 2)}:${content.substr(14, 2)}:${content.substr(17, 2)}` |
| | | } |
| | | |
| | | content = (col.prefix || '') + content + (col.postfix || '') |
| | | } |
| | | |
| | | if (col.marks) { |
| | | let mark = getMark(col.marks, record, style) |
| | | |
| | | style = mark.style |
| | | |
| | | if (mark.icon) { |
| | | if (mark.position === 'front') { |
| | | content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span> |
| | | } else { |
| | | content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span> |
| | | } |
| | | } |
| | | } |
| | | children = content |
| | | } |
| | | } else if (col.type === 'number') { |
| | | if (col.editable === 'true') { |
| | | let _value = record[col.field] !== undefined ? record[col.field] : '' |
| | | children = (<> |
| | | <InputNumber id={col.uuid + record.$$uuid} defaultValue={_value} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress}/> |
| | | {err ? <Tooltip title={err}><ExclamationCircleOutlined /></Tooltip> : null} |
| | | </>) |
| | | } else { |
| | | let content = '' |
| | | try { |
| | | content = parseFloat(record[col.field]) |
| | | if (isNaN(content)) { |
| | | content = '' |
| | | } |
| | | } catch (e) { |
| | | content = '' |
| | | } |
| | | |
| | | if (content !== '') { |
| | | let decimal = col.decimal || 0 |
| | | if (col.format === 'percent') { |
| | | content = content * 100 |
| | | decimal = decimal > 2 ? decimal - 2 : 0 |
| | | } else if (col.format === 'abs') { |
| | | content = Math.abs(content) |
| | | } |
| | | |
| | | content = content.toFixed(decimal) |
| | | |
| | | if (col.format === 'thdSeparator') { |
| | | content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') |
| | | } |
| | | |
| | | content = col.prefix + content + col.postfix |
| | | } |
| | | |
| | | if (col.marks) { |
| | | let mark = getMark(col.marks, record, style) |
| | | |
| | | style = mark.style |
| | | |
| | | if (mark.icon) { |
| | | if (mark.position === 'front') { |
| | | content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span> |
| | | } else { |
| | | content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span> |
| | | } |
| | | } |
| | | } |
| | | children = content |
| | | } |
| | | } else if (col.type === 'textarea') { |
| | | let content = '' |
| | | if (record[col.field] !== undefined) { |
| | | content = `${record[col.field]}` |
| | | } |
| | | |
| | | if (content) { |
| | | content = col.prefix + content + col.postfix |
| | | } |
| | | |
| | | children = ( |
| | | <div> |
| | | {content ? <Paragraph copyable ellipsis={{ rows: 3, expandable: true }}>{content}</Paragraph> : null } |
| | | </div> |
| | | ) |
| | | } else if (col.type === 'formula') { |
| | | let content = col.formula |
| | | Object.keys(record).forEach(key => { |
| | | let reg = new RegExp('@' + key + '@', 'ig') |
| | | content = content.replace(reg, record[key]) |
| | | }) |
| | | |
| | | if (col.eval !== 'false') { |
| | | try { |
| | | // eslint-disable-next-line |
| | | content = eval(content) |
| | | } catch (e) { |
| | | content = '' |
| | | } |
| | | } |
| | | |
| | | content = content === undefined ? '' : content |
| | | |
| | | if (content !== '') { |
| | | content = `${col.prefix || ''}${content}${col.postfix || ''}` |
| | | |
| | | if (col.eval === 'false') { |
| | | content = content.replace(/\n/ig, '<br/>').replace(/\s/ig, ' ') |
| | | content = <span dangerouslySetInnerHTML={{__html: content}}></span> |
| | | } |
| | | } |
| | | |
| | | if (col.marks) { |
| | | let mark = getMark(col.marks, record, style) |
| | | |
| | | style = mark.style |
| | | |
| | | if (mark.icon) { |
| | | if (mark.position === 'front') { |
| | | content = <span><MkIcon style={{color: mark.color}} type={mark.icon} /> {content}</span> |
| | | } else { |
| | | content = <span>{content} <MkIcon style={{color: mark.color}} type={mark.icon} /></span> |
| | | } |
| | | } |
| | | } |
| | | |
| | | children = content |
| | | } else if (col.type === 'custom') { |
| | | style.padding = '0px' |
| | | if (col.style) { |
| | | style = {...style, ...col.style} |
| | | } |
| | | |
| | | children = ( |
| | | <CardCellComponent data={record} cards={config} elements={col.elements}/> |
| | | ) |
| | | } else if (col.type === 'operation') { |
| | | style.padding = '0px 5px' |
| | | children = ( |
| | | <Button type="link" style={{color: 'rgb(255, 77, 79)', backgroundColor: 'transparent'}} onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})}>删除</Button> |
| | | ) |
| | | } |
| | | |
| | | return (<td className={'editing_all_table_cell ' + className} style={style}>{col.addable ? <PlusCircleOutlined onClick={() => MKEmitter.emit('addRecord', col.tableId, {...record})} className="mk-editable mk-plus"/> : null}{children}{col.delable ? <DeleteOutlined onClick={() => MKEmitter.emit('delRecord', col.tableId, {...record})} className="mk-editable mk-del"/> : null}</td>) |
| | | } |
| | | } |
| | | |
| | | class NormalTable extends Component { |
| | | static propTpyes = { |
| | | statFValue: PropTypes.any, // 合计字段数据 |
| | |
| | | data: [], |
| | | edData: [], |
| | | edColumns: [], |
| | | selectedRowKeys: [], // 表格中选中行 |
| | | tableId: '', // 表格ID |
| | | pageIndex: 1, // 初始页面索引 |
| | | pageSize: 10, // 每页数据条数 |
| | |
| | | _copy.sorter = false |
| | | |
| | | if (item.editable === 'true') { |
| | | _copy.title = <span>{item.label}<EditOutlined className="system-color" style={{position: 'absolute', bottom: '2px', right: '5px'}}/></span> |
| | | _copy.title = <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span> |
| | | } |
| | | edColumns.push(_copy) |
| | | } |
| | |
| | | }) |
| | | |
| | | if (editable === 'true' && data && data.length > 0) { |
| | | this.setState({editable: 'false'}) |
| | | setTimeout(() => { |
| | | this.pickupChange() |
| | | }, 200) |
| | |
| | | if (!is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | this.setState({data: nextProps.data || []}) |
| | | if (this.state.editable === 'true' && !this.state.pickup) { |
| | | this.setState({editable: 'false'}) |
| | | setTimeout(() => { |
| | | this.pickupChange() |
| | | }, 200) |
| | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({edColumns: []}, () => { |
| | | if (this.state.pickup) { |
| | | this.setState({ |
| | | pickup: false |
| | | }, () => { |
| | | this.setState({pickup: true, edColumns: _edColumns}) |
| | | }) |
| | | } else { |
| | | this.setState({edColumns: _edColumns}) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | nextLine = (col, index) => { |
| | | nextLine = (col, uuid) => { |
| | | const { setting } = this.props |
| | | const { edData, initEditLine, tableId } = this.state |
| | | |
| | | if (col.tableId !== tableId) return |
| | | |
| | | index = +index |
| | | let index = edData.findIndex(item => item.$$uuid === uuid) |
| | | let next = edData[index + 1] || null |
| | | |
| | | if (index < edData.length && initEditLine) { |
| | | MKEmitter.emit('tdFocus', initEditLine.uuid + (index + 1)) |
| | | if (next && initEditLine) { |
| | | MKEmitter.emit('tdFocus', initEditLine.uuid + next.$$uuid) |
| | | } else if (col.footEnter === 'add' && setting.addable === 'true') { |
| | | setTimeout(() => { |
| | | this.plusLine() |
| | |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | onSelectChange = selectedRowKeys => { |
| | | this.setState({ selectedRowKeys }) |
| | | |
| | | let activeId = '' |
| | | if (selectedRowKeys.length > 0) { |
| | | activeId = selectedRowKeys.slice(-1)[0] |
| | | } |
| | | this.changedata(activeId) |
| | | this.selectdata(selectedRowKeys) |
| | | } |
| | | |
| | | /** |
| | | * @description 点击整行,触发切换, 判断是否可选,单选或多选,进行对应操作 |
| | | */ |
| | | changeRow = (index) => { |
| | | const { setting } = this.props |
| | | |
| | | if (!setting.tableType || this.state.pickup) return |
| | | |
| | | let newkeys = fromJS(this.state.selectedRowKeys).toJS() |
| | | |
| | | let activeId = '' |
| | | if (setting.tableType === 'radio') { |
| | | activeId = index |
| | | newkeys = [index] |
| | | this.setState({ selectedRowKeys: newkeys }) |
| | | } else { |
| | | if (newkeys.includes(index)) { |
| | | newkeys = newkeys.filter(item => item !== index) |
| | | |
| | | if (newkeys.length > 0) { |
| | | activeId = newkeys.slice(-1)[0] |
| | | } |
| | | } else { |
| | | activeId = index |
| | | newkeys.push(index) |
| | | } |
| | | |
| | | this.setState({ selectedRowKeys: newkeys }) |
| | | } |
| | | |
| | | this.changedata(activeId) |
| | | this.selectdata(newkeys) |
| | | } |
| | | |
| | | changedata = (id) => { |
| | | const { MenuID } = this.props |
| | | const { data } = this.state |
| | | |
| | | let _data = '' |
| | | |
| | | if (id) { |
| | | _data = data.filter(item => item.$$uuid === id)[0] || '' |
| | | } |
| | | |
| | | MKEmitter.emit('resetSelectLine', MenuID, id, _data) |
| | | } |
| | | |
| | | selectdata = (keys) => { |
| | | const { data } = this.state |
| | | |
| | | let _data = data.filter(item => keys.includes(item.$$uuid)) |
| | | |
| | | this.props.chgSelectData(_data) |
| | | } |
| | | |
| | | changeTable = (pagination, filters, sorter) => { |
| | | const { orderfields } = this.state |
| | | |
| | | this.setState({ |
| | | pageIndex: pagination.current, |
| | | pageSize: pagination.pageSize |
| | | pageSize: pagination.pageSize, |
| | | selectedRowKeys: [], |
| | | }) |
| | | |
| | | sorter.field = orderfields[sorter.field] || '' |
| | |
| | | |
| | | if (id !== MenuID) return |
| | | |
| | | if (repage !== 'false') { |
| | | if (repage === 'false') { |
| | | this.setState({ |
| | | pageIndex: 1 |
| | | selectedRowKeys: [], |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | pageIndex: 1, |
| | | selectedRowKeys: [], |
| | | }) |
| | | } |
| | | } |
| | | |
| | | pickupChange = () => { |
| | | const { submit } = this.props |
| | | const { submit, MenuID } = this.props |
| | | const { data } = this.state |
| | | |
| | | let pickup = !this.state.pickup |
| | |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | pickup && MKEmitter.emit('resetSelectLine', MenuID, '', '') |
| | | this.setState({ |
| | | data: [], |
| | | edData: [], |
| | |
| | | |
| | | render() { |
| | | const { setting, statFValue, lineMarks, submit } = this.props |
| | | const { pickup, tableId, data, edData, columns, edColumns, loading, pageOptions } = this.state |
| | | const { pickup, tableId, data, edData, columns, edColumns, loading, pageOptions, selectedRowKeys } = this.state |
| | | |
| | | const components = { |
| | | body: { |
| | | row: BodyRow, |
| | | cell: BodyCell |
| | | cell: setting.editType !== 'multi' || !pickup ? BodyCell : BodyAllCell |
| | | } |
| | | } |
| | | |
| | |
| | | _data = edData |
| | | _data = _data.filter(item => !item.$deleted) |
| | | _columns = edColumns |
| | | } |
| | | |
| | | // 设置表格选择属性:单选、多选、不可选 |
| | | let rowSelection = null |
| | | if (setting.tableType && !pickup) { |
| | | rowSelection = { |
| | | selectedRowKeys, |
| | | type: (setting.tableType === 'radio') ? 'radio' : 'checkbox', |
| | | onChange: this.onSelectChange |
| | | } |
| | | } |
| | | |
| | | let _pagination = false |
| | |
| | | style={setting.style} |
| | | size={setting.size || 'middle'} |
| | | bordered={setting.bordered !== 'false'} |
| | | rowSelection={rowSelection} |
| | | columns={_columns} |
| | | dataSource={_data} |
| | | loading={this.props.loading} |
| | |
| | | onRow={(record, index) => { |
| | | return { |
| | | lineMarks, |
| | | data: record |
| | | data: record, |
| | | onClick: () => {this.changeRow(record.$$uuid)}, |
| | | } |
| | | }} |
| | | onChange={this.changeTable} |