| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Table, Typography, Icon, Switch, Input, InputNumber, Tooltip } from 'antd' |
| | | import { Table, Typography, Icon, Switch, Modal, Input, InputNumber, Tooltip, Button, notification, message } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import Utils, { getEditTableSql } from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/main.js' |
| | | import enUS from '@/locales/en-US/main.js' |
| | |
| | | import './index.scss' |
| | | |
| | | const { Paragraph } = Typography |
| | | const { confirm } = Modal |
| | | const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList')) |
| | | |
| | | class BodyRow extends React.Component { |
| | |
| | | MKEmitter.emit('tdFocus', col.enter + record.$Index) |
| | | } |
| | | |
| | | let _record = {...record, [col.field]: value} |
| | | MKEmitter.emit('changeRecord', _record) |
| | | if (value !== record[col.field]) { |
| | | MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: value}) |
| | | } |
| | | } |
| | | |
| | | focus = () => { |
| | |
| | | |
| | | this.setState({editing: false}) |
| | | |
| | | let _record = {...record, [col.field]: value} |
| | | MKEmitter.emit('changeRecord', _record) |
| | | if (value !== record[col.field]) { |
| | | MKEmitter.emit('changeRecord', col.tableId, {...record, [col.field]: value}) |
| | | } |
| | | } |
| | | |
| | | onChange = (val) => { |
| | |
| | | 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={className} style={style}>{children}</td>) |
| | |
| | | columns: PropTypes.array, // 表格列 |
| | | lineMarks: PropTypes.any, // 行标记 |
| | | fields: PropTypes.array, // 组件字段集 |
| | | BData: PropTypes.any, // 主表数据 |
| | | BID: PropTypes.any, // 主表ID |
| | | data: PropTypes.any, // 表格数据 |
| | | total: PropTypes.any, // 总数 |
| | | loading: PropTypes.bool, // 表格加载中 |
| | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | data: [], |
| | | edData: [], |
| | | edColumns: [], |
| | | tableId: '', // 表格ID |
| | | pageIndex: 1, // 初始页面索引 |
| | | pageSize: 10, // 每页数据条数 |
| | | columns: null, // 显示列 |
| | | fields: [], |
| | | pickup: false, // 收起未选择项 |
| | | orderfields: {} // 排序id与field转换 |
| | | orderfields: {}, // 排序id与field转换 |
| | | loading: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { setting, fields, columns, data } = this.props |
| | | let orderfields = {} |
| | | let initEditLine = null |
| | | let edColumns = [] |
| | | let tableId = (() => { |
| | | let uuid = [] |
| | | let _options = 'abcdefghigklmnopqrstuv' |
| | | for (let i = 0; i < 19; i++) { |
| | | uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1)) |
| | | } |
| | | return uuid.join('') |
| | | }) () |
| | | |
| | | let _columns = columns.map(item => { |
| | | let _columns = [] |
| | | columns.forEach(item => { |
| | | if (item.Hide === 'true') return |
| | | if (item.type === 'index') { |
| | | item.field = '$Index' |
| | | item.type = 'text' |
| | | } |
| | | |
| | | item.tableId = tableId |
| | | |
| | | if (!initEditLine && item.editable === 'true') { |
| | | initEditLine = item |
| | | } |
| | |
| | | orderfields[item.uuid] = item.field |
| | | } |
| | | |
| | | return { |
| | | let _item = { |
| | | align: item.Align, |
| | | dataIndex: item.uuid, |
| | | title: item.label, |
| | |
| | | config: item.type === 'custom' || item.type === 'action' ? {setting, columns: fields} : null, |
| | | }) |
| | | } |
| | | |
| | | if (item.type !== 'action') { |
| | | let _copy = fromJS(_item).toJS() |
| | | _copy.sorter = false |
| | | edColumns.push(_copy) |
| | | } |
| | | _columns.push(_item) |
| | | }) |
| | | |
| | | let tableId = (() => { |
| | | let uuid = [] |
| | | let _options = 'abcdefghigklmnopqrstuv' |
| | | for (let i = 0; i < 19; i++) { |
| | | uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1)) |
| | | } |
| | | return uuid.join('') |
| | | }) () |
| | | edColumns.push({ |
| | | align: 'center', |
| | | dataIndex: 'mkoperation', |
| | | title: '操作', |
| | | sorter: false, |
| | | width: 100, |
| | | onCell: record => ({ |
| | | record, |
| | | col: {type: 'operation', tableId: tableId}, |
| | | }) |
| | | }) |
| | | |
| | | if (setting.borderColor) { // 边框颜色 |
| | | let style = `#${tableId} table, #${tableId} tr, #${tableId} th, #${tableId} td {border-color: ${setting.borderColor}}` |
| | |
| | | this.setState({ |
| | | data, |
| | | columns: _columns, |
| | | edColumns, |
| | | tableId, |
| | | orderfields, |
| | | initEditLine |
| | |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('resetTable', this.resetTable) |
| | | const { fields, columns } = this.props |
| | | |
| | | let _fields = [] |
| | | |
| | | let fieldType = {} |
| | | fields.forEach(item => { |
| | | fieldType[item.field] = item.datatype |
| | | }) |
| | | |
| | | columns.forEach(col => { |
| | | if (!col.field || col.type === 'index') return |
| | | |
| | | _fields.push({...col, datatype: fieldType[col.field] || 'Nvarchar(50)'}) |
| | | }) |
| | | |
| | | this.setState({ |
| | | fields: _fields, |
| | | }) |
| | | |
| | | MKEmitter.addListener('nextLine', this.nextLine) |
| | | MKEmitter.addListener('delRecord', this.delRecord) |
| | | MKEmitter.addListener('resetTable', this.resetTable) |
| | | MKEmitter.addListener('changeRecord', this.changeRecord) |
| | | } |
| | | |
| | |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('resetTable', this.resetTable) |
| | | MKEmitter.removeListener('nextLine', this.nextLine) |
| | | MKEmitter.removeListener('delRecord', this.delRecord) |
| | | MKEmitter.removeListener('resetTable', this.resetTable) |
| | | MKEmitter.removeListener('changeRecord', this.changeRecord) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | nextLine = (col, index) => { |
| | | const { data, initEditLine } = this.state |
| | | const { setting } = this.props |
| | | const { edData, initEditLine, tableId } = this.state |
| | | |
| | | if (col.tableId !== tableId) return |
| | | |
| | | index = +index |
| | | |
| | | if (index < data.length && initEditLine) { |
| | | if (index < edData.length && initEditLine) { |
| | | MKEmitter.emit('tdFocus', initEditLine.uuid + (index + 1)) |
| | | } else if (col.footEnter === 'add' && setting.addable === 'true') { |
| | | setTimeout(() => { |
| | | this.plusLine(initEditLine) |
| | | }, 10) |
| | | } else if (col.footEnter === 'sub') { |
| | | setTimeout(() => { |
| | | this.checkData() |
| | | }, 10) |
| | | } |
| | | } |
| | | |
| | | changeRecord = (record) => { |
| | | let _data = this.state.data.map(item => { |
| | | plusLine = (initEditLine) => { |
| | | const { edData, fields } = this.state |
| | | |
| | | let item = {...edData[edData.length - 1]} |
| | | |
| | | item.key = item.key + 1 |
| | | item.$$uuid = '$new' |
| | | item.$Index = item.key + 1 + '' |
| | | |
| | | fields.forEach(col => { |
| | | item[col.field] = item[col.field] !== undefined ? item[col.field] : '' |
| | | |
| | | if (col.initval !== '$copy') { |
| | | item[col.field] = col.initval |
| | | } |
| | | if (col.type === 'number') { |
| | | item[col.field] = +item[col.field] |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } |
| | | }) |
| | | |
| | | this.setState({edData: [...edData, item]}, () => { |
| | | MKEmitter.emit('tdFocus', initEditLine.uuid + item.$Index) |
| | | }) |
| | | } |
| | | |
| | | delRecord = (id, record) => { |
| | | const { tableId, edData } = this.state |
| | | |
| | | if (id !== tableId) return |
| | | |
| | | let _data = [] |
| | | |
| | | if (record.$$uuid === '$new') { |
| | | _data = edData.filter(item => item.$Index !== record.$Index) |
| | | _data = _data.map((item, index) => { |
| | | item.key = index |
| | | item.$Index = 1 + index + '' |
| | | return item |
| | | }) |
| | | } else { |
| | | _data = edData.map(item => { |
| | | if (item.$Index === record.$Index) { |
| | | record.$deleted = true |
| | | return record |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({edData: _data}) |
| | | } |
| | | |
| | | changeRecord = (id, record) => { |
| | | const { tableId } = this.state |
| | | |
| | | if (id !== tableId) return |
| | | |
| | | let _data = this.state.edData.map(item => { |
| | | if (item.$Index === record.$Index) { |
| | | return record |
| | | } else { |
| | |
| | | } |
| | | }) |
| | | |
| | | this.setState({data: _data}) |
| | | this.setState({edData: _data}) |
| | | } |
| | | |
| | | addLine = () => { |
| | | const { BID } = this.props |
| | | const { edData, fields } = this.state |
| | | |
| | | let item = {} |
| | | if (edData.length > 0) { |
| | | item = {...edData[edData.length - 1]} |
| | | item.key = item.key + 1 |
| | | item.$$uuid = '$new' |
| | | item.$Index = item.key + 1 + '' |
| | | } else { |
| | | item.key = 0 |
| | | item.$$uuid = '$new' |
| | | item.$Index = item.key + 1 + '' |
| | | item.$$BID = BID || '' |
| | | } |
| | | |
| | | fields.forEach(col => { |
| | | item[col.field] = item[col.field] !== undefined ? item[col.field] : '' |
| | | |
| | | if (col.initval !== '$copy') { |
| | | item[col.field] = col.initval |
| | | } |
| | | if (col.type === 'number') { |
| | | item[col.field] = +item[col.field] |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } |
| | | }) |
| | | |
| | | this.setState({edData: [...edData, item]}) |
| | | } |
| | | |
| | | checkData = () => { |
| | | const { edData, fields } = this.state |
| | | |
| | | if (edData.length === 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '提交数据不可为空!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | let err = '' |
| | | let data = fromJS(edData).toJS().map(item => { |
| | | let line = [] |
| | | fields.forEach(col => { |
| | | if (col.editable !== 'true' || item.$deleted) { |
| | | if (col.type === 'number') { |
| | | item[col.field] = +item[col.field] |
| | | if (isNaN(item[col.field])) { |
| | | item[col.field] = 0 |
| | | } |
| | | } else { |
| | | item[col.field] = item[col.field] !== undefined ? (item[col.field] + '') : '' |
| | | } |
| | | return |
| | | } |
| | | if (col.type === 'text') { |
| | | let val = item[col.field] !== undefined ? (item[col.field] + '') : '' |
| | | if (col.required === 'true' && !val) { |
| | | line.push(`${col.label}不可为空`) |
| | | } |
| | | item[col.field] = val |
| | | } else if (col.type === 'number') { |
| | | let val = item[col.field] |
| | | if (!val && val !== 0) { |
| | | line.push(`${col.label}不可为空`) |
| | | return |
| | | } |
| | | val = +val |
| | | if (isNaN(val)) { |
| | | line.push(`${col.label}数据格式错误`) |
| | | return |
| | | } |
| | | |
| | | val = +val.toFixed(col.decimal || 0) |
| | | |
| | | if (typeof(col.max) === 'number' && val > col.max) { |
| | | line.push(`${col.label}不可大于${col.max}`) |
| | | } else if (typeof(col.min) === 'number' && val < col.min) { |
| | | line.push(`${col.label}不可小于${col.min}`) |
| | | } |
| | | |
| | | item[col.field] = val |
| | | } |
| | | }) |
| | | |
| | | if (line.length > 0) { |
| | | err += `第${item.$Index}行:` + line.join(',') + ';' |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | |
| | | if (err) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: err, |
| | | duration: 5 |
| | | }) |
| | | } else { |
| | | this.submit(data) |
| | | } |
| | | } |
| | | |
| | | submit = (data) => { |
| | | const { submit, BID } = this.props |
| | | const { fields } = this.state |
| | | |
| | | let result = getEditTableSql(submit, data, fields) |
| | | |
| | | let param = { |
| | | excel_in: result.lines, |
| | | BID: BID || '' |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | |
| | | if (submit.intertype === 'system') { // 系统存储过程 |
| | | param.func = 'sPC_TableData_InUpDe' |
| | | |
| | | if (sessionStorage.getItem('dataM') === 'true') { // 数据权限 |
| | | result.sql = result.sql.replace(/\$@/ig, '/*') |
| | | result.sql = result.sql.replace(/@\$/ig, '*/') |
| | | result.bottom = result.bottom.replace(/\$@/ig, '/*') |
| | | result.bottom = result.bottom.replace(/@\$/ig, '*/') |
| | | } else { |
| | | result.sql = result.sql.replace(/@\$|\$@/ig, '') |
| | | result.bottom = result.bottom.replace(/@\$|\$@/ig, '') |
| | | } |
| | | |
| | | param.excel_in_type = 'true' |
| | | param.LText1 = Utils.formatOptions(result.insert) |
| | | param.LText2 = Utils.formatOptions(result.bottom) |
| | | param.LText = Utils.formatOptions(result.sql) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | param.menuname = submit.logLabel |
| | | |
| | | if (window.GLOB.probation) { |
| | | param.s_debug_type = 'Y' |
| | | } |
| | | |
| | | Api.genericInterface(param).then((res) => { |
| | | if (res.status) { |
| | | this.execSuccess(res) |
| | | } else { |
| | | this.execError(res) |
| | | } |
| | | }, () => { |
| | | this.execError({}) |
| | | }) |
| | | } else if (submit.intertype === 'inner' && submit.innerFunc) { // 自定义存储过程 |
| | | param.func = submit.innerFunc |
| | | |
| | | Api.genericInterface(param).then((res) => { |
| | | if (res.status) { |
| | | this.execSuccess(res) |
| | | } else { |
| | | this.execError(res) |
| | | } |
| | | }, () => { |
| | | this.execError({}) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | execSuccess = (res) => { |
| | | const { submit } = this.props |
| | | |
| | | if (res && res.ErrCode === 'S') { // 执行成功 |
| | | notification.success({ |
| | | top: 92, |
| | | message: res.ErrMesg || this.state.dict['main.action.confirm.success'], |
| | | duration: submit.stime ? submit.stime : 2 |
| | | }) |
| | | } else if (res && res.ErrCode === 'Y') { // 执行成功 |
| | | Modal.success({ |
| | | title: res.ErrMesg || this.state.dict['main.action.confirm.success'] |
| | | }) |
| | | } else if (res && res.ErrCode === '-1') { // 完成后不提示 |
| | | |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | |
| | | if (submit.execSuccess !== 'never') { |
| | | this.repick() |
| | | MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execSuccess, submit) |
| | | } |
| | | } |
| | | |
| | | execError = (res) => { |
| | | const { submit } = this.props |
| | | |
| | | if (res.ErrCode === 'E') { |
| | | Modal.error({ |
| | | title: res.message || res.ErrMesg, |
| | | }) |
| | | } else if (res.ErrCode === 'N') { |
| | | notification.error({ |
| | | top: 92, |
| | | message: res.message || res.ErrMesg, |
| | | duration: submit.ntime ? submit.ntime : 10 |
| | | }) |
| | | } else if (res.ErrCode === 'F') { |
| | | notification.error({ |
| | | className: 'notification-custom-error', |
| | | top: 92, |
| | | message: res.message || res.ErrMesg, |
| | | duration: submit.ftime ? submit.ftime : 10 |
| | | }) |
| | | } else if (res.ErrCode === 'NM') { |
| | | message.error(res.message || res.ErrMesg) |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | |
| | | if (submit.execError !== 'never') { |
| | | this.repick() |
| | | MKEmitter.emit('refreshByButtonResult', submit.$menuId, submit.execError, submit) |
| | | } |
| | | } |
| | | |
| | | repick = () => { |
| | | const { data } = this.state |
| | | |
| | | this.setState({ |
| | | data: [], |
| | | edData: [], |
| | | pickup: false, |
| | | }, () => { |
| | | this.setState({ |
| | | data: data, |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | changeTable = (pagination, filters, sorter) => { |
| | |
| | | |
| | | this.setState({ |
| | | pageIndex: pagination.current, |
| | | pageSize: pagination.pageSize, |
| | | pickup: false |
| | | pageSize: pagination.pageSize |
| | | }) |
| | | |
| | | sorter.field = orderfields[sorter.field] || '' |
| | |
| | | |
| | | if (id !== MenuID) return |
| | | |
| | | if (repage === 'false') { |
| | | if (repage !== 'false') { |
| | | this.setState({ |
| | | pickup: false |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | pageIndex: 1, |
| | | pickup: false |
| | | pageIndex: 1 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | pickupChange = () => { |
| | | this.setState({ |
| | | pickup: !this.state.pickup |
| | | }) |
| | | const { data } = this.state |
| | | |
| | | let pickup = !this.state.pickup |
| | | |
| | | if (!pickup && !is(fromJS(data), fromJS(this.state.edData))) { |
| | | const _this = this |
| | | confirm({ |
| | | title: '数据已修改,确定放弃保存吗?', |
| | | onOk() { |
| | | _this.setState({ |
| | | data: [], |
| | | edData: [], |
| | | pickup |
| | | }, () => { |
| | | _this.setState({ |
| | | data: data, |
| | | edData: pickup ? fromJS(data).toJS() : [] |
| | | }) |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | data: [], |
| | | edData: [], |
| | | pickup, |
| | | loading: false |
| | | }, () => { |
| | | this.setState({ |
| | | data: data, |
| | | edData: pickup ? fromJS(data).toJS() : [] |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { setting, statFValue, lineMarks } = this.props |
| | | const { pickup, tableId, data } = this.state |
| | | const { pickup, tableId, data, edData, columns, edColumns, loading } = this.state |
| | | |
| | | const components = { |
| | | body: { |
| | |
| | | } |
| | | |
| | | // 数据收起时,过滤已选数据 |
| | | let _data = data || [] |
| | | let _data = data |
| | | let _columns = columns |
| | | |
| | | if (pickup) { |
| | | _data = edData |
| | | _data = _data.filter(item => !item.$deleted) |
| | | _columns = edColumns |
| | | } |
| | | |
| | | |
| | | let _pagination = false |
| | | if (setting.laypage !== 'false' && setting.laypage !== false) { |
| | | if (!pickup && setting.laypage !== 'false' && setting.laypage !== false) { |
| | | _pagination = { |
| | | current: this.state.pageIndex, |
| | | pageSize: this.state.pageSize, |
| | |
| | | |
| | | let _footer = '' |
| | | |
| | | if (statFValue && statFValue.length > 0) { |
| | | if (!pickup && statFValue && statFValue.length > 0) { |
| | | _footer = statFValue.map(f => `${f.label}(合计):${f.value}`).join(';') |
| | | } |
| | | |
| | |
| | | return ( |
| | | <div className={`edit-custom-table ${pickup ? 'editable' : ''} ${setting.tableHeader || ''} ${height ? 'fixed-height' : ''} ${setting.mode || ''}`} id={tableId}> |
| | | <Switch title="编辑" className="main-pickup" checkedChildren="开" unCheckedChildren="关" checked={pickup} onChange={this.pickupChange} /> |
| | | {pickup ? <Button onClick={() => setTimeout(() => {this.checkData()}, 10)} loading={loading} className="submit-table" type="link">提交</Button> : null} |
| | | <Table |
| | | components={components} |
| | | style={setting.style} |
| | | size={setting.size || 'middle'} |
| | | bordered={setting.bordered !== 'false'} |
| | | columns={this.state.columns} |
| | | columns={_columns} |
| | | dataSource={_data} |
| | | loading={this.props.loading} |
| | | scroll={{ x: '100%', y: height }} |
| | |
| | | pagination={_pagination} |
| | | /> |
| | | {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null} |
| | | {pickup && setting.addable === 'true' ? <Button onClick={this.addLine} style={{display: 'block', width: '100%', color: '#26C281'}} icon="plus" type="link"></Button> : null} |
| | | </div> |
| | | ) |
| | | } |