| | |
| | | options: fields |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'nameField', |
| | | label: Formdict['model.name'] + Formdict['model.form.field'], |
| | | initVal: card.nameField || '', |
| | | required: false, |
| | | options: [{uuid: 'empty', field: '', label: '空'}, ...fields] |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'Width', |
| | | min: 20, |
| | |
| | | readonly: false |
| | | }, |
| | | { |
| | | type: 'select', |
| | | type: 'radio', |
| | | key: 'lenWidRadio', |
| | | label: '长宽比', |
| | | initVal: card.lenWidRadio || '1:1', |
| | |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'picSort', |
| | | label: '图片排列', |
| | | initVal: card.picSort || '1', |
| | | tooltip: '同一单元格内,含有多张图片时的列数。', |
| | | required: false, |
| | | options: [{ |
| | | value: '1', |
| | | text: '1' |
| | | }, { |
| | | value: '2', |
| | | text: '2' |
| | | }, { |
| | | value: '3', |
| | | text: '3' |
| | | }, { |
| | | value: '4', |
| | | text: '4' |
| | | }] |
| | | }, |
| | | { |
| | | type: 'radio', |
| | | key: 'scale', |
| | | label: Formdict['header.form.clickscale'], |
| | | initVal: card.scale || 'false', |
| | |
| | | const columnTypeOptions = { |
| | | text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'blacklist', 'perspective', 'rowspan'], |
| | | number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum'], |
| | | link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist'], |
| | | link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist', 'nameField'], |
| | | textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'blacklist'], |
| | | picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio'], |
| | | picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'picSort'], |
| | | colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'], |
| | | custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'], |
| | | action: ['label', 'type', 'Align', 'Width'] |
| | |
| | | getPopupContainer={() => document.getElementById('columnwinter')} |
| | | > |
| | | {item.options.map((option, index) => |
| | | <Select.Option key={`${index}`} value={option.value || option.field}> |
| | | <Select.Option key={`${option.value || option.field}${index}`} value={option.value || option.field}> |
| | | {option.text || option.label} |
| | | </Select.Option> |
| | | )} |
| | |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider, DragSource, DropTarget } from 'react-dnd' |
| | | import { Table, Form, Popover, Icon, Modal } from 'antd' |
| | | import { Table, Form, Popover, Icon, Modal, message } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | |
| | | const { confirm } = Modal |
| | | const coldict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const EditColumn = asyncIconComponent(() => import('./editColumn')) |
| | | const MarkColumn = asyncIconComponent(() => import('./markcolumn')) |
| | | const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent')) |
| | | |
| | | class HeaderCol extends Component { |
| | |
| | | }) |
| | | } |
| | | |
| | | updateMarks = (vals) => { |
| | | const { column } = this.props |
| | | this.props.updateCol({...column, marks: vals}) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | |
| | | if (!nextProps.column) return false |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { connectDragSource, connectDropTarget, moveCol, addElement, editColumn, deleteCol, index, column, align, fields, children, ...restProps } = this.props |
| | | const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, deleteCol, index, column, align, fields, children, ...restProps } = this.props |
| | | |
| | | if (index !== undefined) { |
| | | return connectDragSource( |
| | | connectDropTarget(<th {...restProps} index={index} style={{ cursor: 'move', textAlign: align }}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | {column && (column.type === 'custom' || column.type === 'colspan' || column.type === 'action') ? |
| | | {column && ['custom', 'colspan', 'action'].includes(column.type) ? |
| | | <Icon className="plus" title="添加" type="plus" onClick={() => this.props.addElement(column)} /> : null |
| | | } |
| | | <Icon className="edit" title="编辑" type="edit" onClick={() => this.props.editColumn(column)} /> |
| | | <Icon className="close" title="删除" type="delete" onClick={this.deleteCol} /> |
| | | {column && ['text', 'number'].includes(column.type) ? <MarkColumn dict={coldict} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null } |
| | | </div> |
| | | } trigger="hover"> |
| | | {children} |
| | |
| | | } |
| | | <Icon className="edit" title="编辑" type="edit" onClick={() => this.props.editColumn(column)} /> |
| | | <Icon className="close" title="删除" type="delete" onClick={this.deleteCol} /> |
| | | {column && ['text', 'number'].includes(column.type) ? <MarkColumn dict={coldict} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null } |
| | | </div> |
| | | } trigger="hover"> |
| | | {children} |
| | |
| | | return ( |
| | | <td style={{...style, minWidth: column.Width || 100}} className={className}> |
| | | {column.field} |
| | | {column.marks && column.marks.length > 0 ? <Icon className="profile" type="ant-design"/> : null} |
| | | </td> |
| | | ) |
| | | } else { |
| | |
| | | state = { |
| | | data: [{uuid: Utils.getuuid()}], |
| | | columns: [], |
| | | fields: [] |
| | | fields: [], |
| | | lineMarks: [] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | |
| | | this.setState({ |
| | | columns: fromJS(config.cols).toJS(), |
| | | fields: fromJS(config.columns).toJS() |
| | | fields: fromJS(config.columns).toJS(), |
| | | lineMarks: config.lineMarks ? fromJS(config.lineMarks).toJS() : [] |
| | | }) |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | updateLineMarks = (vals) => { |
| | | this.setState({ |
| | | lineMarks: vals |
| | | }, () => { |
| | | this.props.updatecolumn({...this.props.config, lineMarks: vals}) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列复制 |
| | | */ |
| | | copycolumn = () => { |
| | | const { columns } = this.state |
| | | |
| | | let oInput = document.createElement('input') |
| | | let val = { |
| | | copyType: 'columns', |
| | | columns: columns |
| | | } |
| | | |
| | | oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val))) |
| | | document.body.appendChild(oInput) |
| | | oInput.select() |
| | | document.execCommand('Copy') |
| | | oInput.className = 'oInput' |
| | | oInput.style.display = 'none' |
| | | |
| | | message.success('复制成功。') |
| | | |
| | | document.body.removeChild(oInput) |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { fields, card } = this.state |
| | | const { fields, card, lineMarks } = this.state |
| | | const components = { |
| | | header: { |
| | | cell: DragableHeaderCol |
| | |
| | | }), |
| | | onHeaderCell: () => ({ |
| | | column: cell, |
| | | fields: fields, |
| | | align: cell.Align, |
| | | updateCol: this.updateCol, |
| | | addElement: this.addElement, |
| | | editColumn: this.editColumn, |
| | | deleteCol: this.deleteCol, |
| | |
| | | onHeaderCell: () => ({ |
| | | index, |
| | | column: col, |
| | | fields: fields, |
| | | align: col.Align, |
| | | moveCol: this.moveCol, |
| | | updateCol: this.updateCol, |
| | | addElement: this.addElement, |
| | | editColumn: this.editColumn, |
| | | deleteCol: this.deleteCol, |
| | |
| | | |
| | | return ( |
| | | <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType}`}> |
| | | <div className="col-control"> |
| | | <Icon title="复制" type="copy" onClick={this.copycolumn} /> |
| | | <MarkColumn dict={coldict} columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} /> |
| | | </div> |
| | | <DndProvider> |
| | | <Table |
| | | rowKey="uuid" |
| | |
| | | .normal-table-columns { |
| | | position: relative; |
| | | .ant-table-body { |
| | | overflow-x: auto; |
| | | padding-bottom: 20px; |
| | | tr td:not(.ant-table-selection-column) { |
| | | position: relative; |
| | | padding: 12px 8px; |
| | | background: #ffffff; |
| | | >.profile { |
| | | position: absolute; |
| | | top: 2px; |
| | | right: 2px; |
| | | color: purple; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | tr:hover td { |
| | | background: #ffffff!important; |
| | |
| | | } |
| | | } |
| | | } |
| | | .col-control { |
| | | position: absolute; |
| | | z-index: 2; |
| | | right: 0; |
| | | top: -25px; |
| | | >i, >div > i { |
| | | font-size: 16px; |
| | | margin-right: 10px; |
| | | cursor: pointer; |
| | | } |
| | | >.anticon-copy { |
| | | color: #26C281; |
| | | } |
| | | >div >.profile { |
| | | color: purple; |
| | | } |
| | | } |
| | | } |
| | | .normal-table-columns.false { |
| | | .ant-pagination { |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import MarkForm from './markform' |
| | | import './index.scss' |
| | | import { minkeIconSystem } from '@/utils/option.js' |
| | | import '@/assets/css/table.scss' |
| | | |
| | | const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) |
| | | |
| | | class MarkColumn extends Component { |
| | | static propTpyes = { |
| | | columns: PropTypes.array, // 显示列 |
| | | dict: PropTypes.object, // 字典项 |
| | | marks: PropTypes.object, |
| | | onSubmit: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | marks: null, |
| | | columns: null, |
| | | visible: false, |
| | | markColumns: [ |
| | | { |
| | | title: '对比字段', |
| | | dataIndex: 'field', |
| | | width: '16%', |
| | | editable: true, |
| | | inputType: 'cascader', |
| | | options: [], |
| | | render: text => { |
| | | return ( |
| | | <div>{text[0]} VS {text[2] ? text[2] : '静态值'}</div> |
| | | ) |
| | | } |
| | | }, |
| | | { |
| | | title: '对比方式', |
| | | dataIndex: 'match', |
| | | width: '16%', |
| | | editable: true, |
| | | inputType: 'select', |
| | | options: [ |
| | | { value: '=', text: '=' }, |
| | | { value: '!=', text: '!=' }, |
| | | { value: '>', text: '>' }, |
| | | { value: '<', text: '<' }, |
| | | { value: 'like', text: 'like' } |
| | | ] |
| | | }, |
| | | { |
| | | title: '对比值', |
| | | dataIndex: 'contrastValue', |
| | | width: '16%', |
| | | editable: true, |
| | | required: false, |
| | | inputType: 'input' |
| | | }, |
| | | { |
| | | title: '颜色', |
| | | dataIndex: 'color', |
| | | inputType: 'color', |
| | | editable: true, |
| | | width: '16%', |
| | | render: text => { |
| | | return (<div style={{width: '80px', height: '23px', background: text}}></div>) |
| | | } |
| | | }, |
| | | { |
| | | title: '标记方式', |
| | | dataIndex: 'signType', |
| | | width: '16%', |
| | | editable: true, |
| | | inputType: 'cascader', |
| | | options: [], |
| | | render: text => { |
| | | let sign = { |
| | | 'font': '文字颜色', |
| | | 'background': '背景', |
| | | 'underline': '下划线', |
| | | 'line-through': '中划线', |
| | | 'icon': '图标' |
| | | } |
| | | |
| | | return ( |
| | | <div>{sign[text[0]]} {text[3] ? <Icon type={text[3]} /> : null}</div> |
| | | ) |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | |
| | | markChange = (values) => { |
| | | let _marks = fromJS(this.state.marks).toJS() |
| | | |
| | | if (values.uuid) { |
| | | _marks = _marks.map(item => { |
| | | if (item.uuid === values.uuid) { |
| | | return values |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | } else { |
| | | values.uuid = Utils.getuuid() |
| | | _marks.push(values) |
| | | } |
| | | |
| | | this.setState({ |
| | | marks: _marks |
| | | }) |
| | | } |
| | | |
| | | handleDelete = (record) => { |
| | | const { marks } = this.state |
| | | |
| | | let _marks = marks.filter(item => item.uuid !== record.uuid) |
| | | |
| | | this.setState({ marks: _marks }) |
| | | } |
| | | |
| | | resetMark = () => { |
| | | const { marks, columns, type } = this.props |
| | | |
| | | let options = columns.map(col => { |
| | | return { |
| | | value: col.field, |
| | | label: col.label, |
| | | isLeaf: false, |
| | | children: [ |
| | | { |
| | | value: 'static', |
| | | label: '静态值' |
| | | }, |
| | | { |
| | | value: 'dynamic', |
| | | label: '动态值', |
| | | children: columns.map(cell => { |
| | | return { |
| | | value: cell.field, |
| | | label: cell.label |
| | | } |
| | | }) |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | |
| | | let icons = [ |
| | | { |
| | | value: 'direction', |
| | | label: '方向性图标', |
| | | children: minkeIconSystem.direction.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | }, |
| | | { |
| | | value: 'hint', |
| | | label: '提示建议性图标', |
| | | children: minkeIconSystem.hint.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | }, |
| | | { |
| | | value: 'edit', |
| | | label: '编辑类图标', |
| | | children: minkeIconSystem.edit.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | }, |
| | | { |
| | | value: 'data', |
| | | label: '数据类图标', |
| | | children: minkeIconSystem.data.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | }, |
| | | { |
| | | value: 'trademark', |
| | | label: '品牌和标识', |
| | | children: minkeIconSystem.trademark.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | }, |
| | | { |
| | | value: 'normal', |
| | | label: '网站通用图标', |
| | | children: minkeIconSystem.normal.map(cell => { |
| | | return { |
| | | value: cell, |
| | | label: (<Icon type={cell} />) |
| | | } |
| | | }) |
| | | } |
| | | ] |
| | | let signs = [ |
| | | { |
| | | value: 'font', |
| | | label: '文字颜色' |
| | | }, |
| | | { |
| | | value: 'background', |
| | | label: '背景' |
| | | }, |
| | | { |
| | | value: 'underline', |
| | | label: '下划线' |
| | | }, |
| | | { |
| | | value: 'line-through', |
| | | label: '中划线' |
| | | }, |
| | | { |
| | | value: 'icon', |
| | | label: '图标', |
| | | children: [ |
| | | { |
| | | value: 'front', |
| | | label: '内容前', |
| | | children: icons |
| | | }, |
| | | { |
| | | value: 'back', |
| | | label: '内容后', |
| | | children: icons |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | |
| | | if (type === 'line') { |
| | | signs.pop() |
| | | } |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | marks: marks ? fromJS(marks).toJS() : [], |
| | | markColumns: this.state.markColumns.map(col => { |
| | | if (col.dataIndex === 'field') { |
| | | col.options = options |
| | | } else if (col.dataIndex === 'signType') { |
| | | col.options = signs |
| | | } |
| | | |
| | | return col |
| | | }), |
| | | options, |
| | | signs |
| | | }) |
| | | } |
| | | |
| | | markSubmit = () => { |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | |
| | | let marks = this.state.marks.map(item => { |
| | | if (item.signType[0] === 'background') { |
| | | try { |
| | | let colors = item.color.match(/\d+/g) |
| | | if ((colors[0] * 0.299 + colors[1] * 0.578 + colors[2] * 0.114) * colors[3] < 192) { |
| | | item.fontColor = '#ffffff' |
| | | } else { |
| | | item.fontColor = '' |
| | | } |
| | | } catch { |
| | | item.fontColor = '' |
| | | } |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | this.props.onSubmit(marks) |
| | | } |
| | | |
| | | render() { |
| | | const { dict } = this.props |
| | | const { marks, markColumns, visible, options, signs } = this.state |
| | | |
| | | return ( |
| | | <div style={{display: 'inline-block'}}> |
| | | <Icon className="profile" title="标记" type="ant-design" onClick={this.resetMark} /> |
| | | <Modal |
| | | wrapClassName="model-table-column-mark-modal" |
| | | title={'标记设置'} |
| | | visible={visible} |
| | | width={'75vw'} |
| | | maskClosable={false} |
| | | style={{minWidth: '900px', maxWidth: '1200px'}} |
| | | okText={dict['model.submit']} |
| | | onOk={this.markSubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <MarkForm dict={dict} signs={signs} columns={options} markChange={this.markChange}/> |
| | | <EditTable data={marks} columns={markColumns} onChange={(marks) => this.setState({marks})}/> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default MarkColumn |
New file |
| | |
| | | #mark-column-box-modal { |
| | | .ant-form-item-label .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | table tr td { |
| | | word-wrap: break-word; |
| | | word-break: break-word; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | |
| | | .mingke-table .ant-empty { |
| | | margin: 20px 8px!important; |
| | | } |
| | | .mingke-table { |
| | | td { |
| | | position: relative; |
| | | } |
| | | } |
| | | .errorval { |
| | | display: inline-block; |
| | | width: 30px; |
| | | } |
| | | .operation-btn { |
| | | display: inline-block; |
| | | font-size: 16px; |
| | | padding: 0 5px; |
| | | cursor: pointer; |
| | | } |
| | | .ant-tabs-tabpane { |
| | | position: relative; |
| | | .excel-col-add { |
| | | position: absolute; |
| | | right: 0; |
| | | top: 90px; |
| | | } |
| | | } |
| | | |
| | | .ant-table-tbody tr.background td { |
| | | background: unset!important; |
| | | } |
| | | .background { |
| | | .baseboard { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | } |
| | | .content { |
| | | position: relative; |
| | | } |
| | | } |
| | | |
| | | .mk-table-line.background { |
| | | .baseboard { |
| | | background: unset!important; |
| | | } |
| | | } |
| | | |
| | | .ant-form-item { |
| | | white-space: nowrap; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Select, Button, Input, Icon, Cascader, Tooltip } from 'antd' |
| | | |
| | | import ColorSketch from '@/mob/colorsketch' |
| | | import './index.scss' |
| | | |
| | | class UniqueForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | columns: PropTypes.array, // 列名集合 |
| | | signs: PropTypes.array, // 标记类型 |
| | | markChange: PropTypes.func // 修改函数 |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | this.props.markChange(values) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { columns, signs } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} className="normal-table-mark-form"> |
| | | <Row gutter={24}> |
| | | <Col span={6}> |
| | | <Form.Item label={'对比字段'}> |
| | | {getFieldDecorator('field', { |
| | | initialValue: [], |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '对比字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader options={columns} placeholder=""/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item label={'对比方式'}> |
| | | {getFieldDecorator('match', { |
| | | initialValue: '=', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '对比方式!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select> |
| | | <Select.Option value="="> = </Select.Option> |
| | | <Select.Option value="!="> != </Select.Option> |
| | | <Select.Option value=">"> > </Select.Option> |
| | | <Select.Option value="<"> < </Select.Option> |
| | | <Select.Option value="like"> like </Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item label={<Tooltip placement="topLeft" title="对比静态值时,需要填写对比值,默认为空。"> |
| | | <Icon type="question-circle" /> |
| | | {'对比值'} |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('contrastValue', { |
| | | initialValue: '' |
| | | })(<Input placeholder="" autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item label="颜色"> |
| | | {getFieldDecorator('color', { |
| | | initialValue: 'rgba(0, 0, 0, 0.85)', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '颜色!' |
| | | } |
| | | ] |
| | | })( |
| | | <ColorSketch /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item label="标记方式"> |
| | | {getFieldDecorator('signType', { |
| | | initialValue: [], |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '标记方式!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader options={signs} placeholder=""/> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={18} style={{textAlign: 'right', marginBottom: 10}}> |
| | | <Button onClick={this.handleConfirm} type="primary" className="mk-green"> |
| | | 添加 |
| | | </Button> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(UniqueForm) |
New file |
| | |
| | | .normal-table-mark-form { |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | .color-sketch-block { |
| | | position: relative; |
| | | top: 5px; |
| | | .color-sketch-block-box { |
| | | width: 100%; |
| | | } |
| | | .color-sketch-value { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Tabs, Table, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd' |
| | | import { Form, Tabs, Popconfirm, Icon, notification, Modal, Typography, Spin } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | |
| | | { |
| | | title: 'SQL', |
| | | dataIndex: 'sql', |
| | | width: '65%', |
| | | render: (text) => ( |
| | | <Paragraph copyable ellipsis={{ rows: 4, expandable: true }}>{text}</Paragraph> |
| | | ) |
| | | width: '72%', |
| | | render: (text) => { |
| | | let title = text.match(/^\s*\/\*.+\*\//) |
| | | title = title && title[0] ? title[0] : '' |
| | | text = title ? text.replace(title, '') : text |
| | | |
| | | return ( |
| | | <div> |
| | | {title ? <span style={{color: '#a50'}}>{title}</span> : null} |
| | | <Paragraph copyable ellipsis={{ rows: 4, expandable: true }}>{text}</Paragraph> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | { |
| | | title: '状态', |
| | | dataIndex: 'status', |
| | | width: '15%', |
| | | width: '13%', |
| | | render: (text, record) => record.status === 'false' ? |
| | | ( |
| | | <div> |
| | |
| | | { |
| | | title: '操作', |
| | | align: 'center', |
| | | width: '20%', |
| | | width: '15%', |
| | | dataIndex: 'operation', |
| | | render: (text, record) => |
| | | (<div> |
| | | (<div style={{textAlign: 'center'}}> |
| | | <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span> |
| | | <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> |
| | | <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> |
| | | <span className="operation-btn" title={this.props.dict['model.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span> |
| | | <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | |
| | | |
| | | let _setting = fromJS(config.setting).toJS() |
| | | |
| | | // if (_setting.varMark === undefined) { |
| | | // _setting.varMark = this.getMark(Marks) |
| | | // } |
| | | |
| | | this.setState({ |
| | | columns: fromJS(config.columns).toJS(), |
| | | setting: _setting, |
| | |
| | | }) |
| | | |
| | | this.getsysScript() |
| | | } |
| | | |
| | | getMark = (varMarks) => { |
| | | let m = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] |
| | | let i = 0 |
| | | let n = 25 |
| | | |
| | | let name = '' |
| | | while (!name) { |
| | | name = `${m[n]}${m[i]}_` |
| | | if (varMarks.includes(name) && n > 0) { |
| | | i++ |
| | | if (i >= 26) { |
| | | n-- |
| | | i = 0 |
| | | } |
| | | name = '' |
| | | } |
| | | } |
| | | |
| | | return name |
| | | } |
| | | |
| | | getsysScript = () => { |
| | |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | handleUpDown = (record, direction) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | let index = 0 |
| | | |
| | | scripts = scripts.filter((item, i) => { |
| | | if (item.uuid === record.uuid) { |
| | | index = i |
| | | } |
| | | |
| | | return item.uuid !== record.uuid |
| | | }) |
| | | if ((index === 0 && direction === 'up') || (index === scripts.length && direction === 'down')) { |
| | | return |
| | | } |
| | | |
| | | if (direction === 'up') { |
| | | scripts.splice(index - 1, 0, record) |
| | | } else { |
| | | scripts.splice(index + 1, 0, record) |
| | | } |
| | | |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | scriptsChange = (values) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | |
| | |
| | | return new Promise((resolve, reject) => { |
| | | this.sqlverify(resolve, reject, false, scripts) |
| | | }) |
| | | } |
| | | |
| | | changeScripts = (scripts) => { |
| | | this.setState({ scripts }) |
| | | } |
| | | |
| | | scriptSubmit = (values) => { |
| | |
| | | scriptSubmit={this.scriptSubmit} |
| | | wrappedComponentRef={(inst) => this.scriptsForm = inst} |
| | | /> |
| | | <Table |
| | | bordered |
| | | rowKey="uuid" |
| | | className="custom-table" |
| | | dataSource={scripts} |
| | | columns={scriptsColumns} |
| | | pagination={false} |
| | | /> |
| | | <EditTable data={scripts} actions={[]} columns={scriptsColumns} onChange={this.changeScripts}/> |
| | | </TabPane> |
| | | </Tabs> |
| | | </div> |
| | |
| | | reg: new RegExp('@' + item.field + '@', 'ig') |
| | | }) |
| | | } |
| | | } else if (item.type === 'text' || item.type === 'select') { |
| | | item.field.split(',').forEach(field => { |
| | | _regoptions.push({ |
| | | var: new RegExp('@' + field, 'ig'), |
| | | reg: new RegExp('@' + field + '@', 'ig') |
| | | }) |
| | | }) |
| | | } else { |
| | | _regoptions.push({ |
| | | var: new RegExp('@' + item.field, 'ig'), |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import md5 from 'md5' |
| | | import { connect } from 'react-redux' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Table, Typography, Icon, Col } from 'antd' |
| | | |
| | | import { modifyTabview } from '@/store/action' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import '@/assets/css/table.scss' |
| | | import './index.scss' |
| | | |
| | | const { Paragraph } = Typography |
| | | |
| | | class BodyRow extends React.Component { |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props.data), fromJS(nextProps.data)) || !is(fromJS(this.props.className), fromJS(nextProps.className)) |
| | | } |
| | | |
| | | render() { |
| | | let { lineMarks, data, className, ...resProps } = this.props |
| | | let style = {} |
| | | |
| | | if (lineMarks && lineMarks.length > 0) { |
| | | lineMarks.some(mark => { |
| | | let originVal = data[mark.field[0]] + '' |
| | | let contrastVal = '' |
| | | let result = false |
| | | |
| | | if (mark.field[1] === 'static') { |
| | | contrastVal = mark.contrastValue + '' |
| | | } else { |
| | | contrastVal = data[mark.field[2]] + '' |
| | | } |
| | | |
| | | if (mark.match === '=') { |
| | | result = originVal === contrastVal |
| | | } else if (mark.match === '!=') { |
| | | result = originVal !== contrastVal |
| | | } else if (mark.match === 'like') { |
| | | result = originVal.indexOf(contrastVal) > -1 |
| | | } else if (mark.match === '>') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) { |
| | | result = true |
| | | } |
| | | } else if (mark.match === '<') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) { |
| | | result = true |
| | | } |
| | | } |
| | | |
| | | if (result) { |
| | | if (mark.signType[0] === 'font') { |
| | | style.color = mark.color |
| | | } else if (mark.signType[0] === 'background') { |
| | | style.background = mark.color |
| | | if (mark.fontColor) { |
| | | style.color = mark.fontColor |
| | | } |
| | | className += className + ' background' |
| | | } else if (mark.signType[0] === 'underline') { |
| | | style.textDecoration = 'underline' |
| | | style.color = mark.color |
| | | } else if (mark.signType[0] === 'line-through') { |
| | | style.textDecoration = 'line-through' |
| | | style.color = mark.color |
| | | } |
| | | } |
| | | |
| | | return result |
| | | }) |
| | | } |
| | | |
| | | return <tr {...resProps} className={className} style={style}/> |
| | | } |
| | | } |
| | | |
| | | class BodyCell extends React.Component { |
| | | getMark = (record, marks, style, content) => { |
| | | marks.some(mark => { |
| | | let originVal = record[mark.field[0]] + '' |
| | | let contrastVal = '' |
| | | let result = false |
| | | |
| | | if (mark.field[1] === 'static') { |
| | | contrastVal = mark.contrastValue + '' |
| | | } else { |
| | | contrastVal = record[mark.field[2]] + '' |
| | | } |
| | | |
| | | if (mark.match === '=') { |
| | | result = originVal === contrastVal |
| | | } else if (mark.match === '!=') { |
| | | result = originVal !== contrastVal |
| | | } else if (mark.match === 'like') { |
| | | result = originVal.indexOf(contrastVal) > -1 |
| | | } else if (mark.match === '>') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal > contrastVal) { |
| | | result = true |
| | | } |
| | | } else if (mark.match === '<') { |
| | | try { |
| | | originVal = parseFloat(originVal) |
| | | contrastVal = parseFloat(contrastVal) |
| | | } catch { |
| | | originVal = NaN |
| | | } |
| | | |
| | | if (!isNaN(originVal) && !isNaN(contrastVal) && originVal < contrastVal) { |
| | | result = true |
| | | } |
| | | } |
| | | |
| | | if (result) { |
| | | if (mark.signType[0] === 'font') { |
| | | style.color = mark.color |
| | | } else if (mark.signType[0] === 'background') { |
| | | style.background = mark.color |
| | | if (mark.fontColor) { |
| | | style.color = mark.fontColor |
| | | } |
| | | } else if (mark.signType[0] === 'underline') { |
| | | style.textDecoration = 'underline' |
| | | style.color = mark.color |
| | | } else if (mark.signType[0] === 'line-through') { |
| | | style.textDecoration = 'line-through' |
| | | style.color = mark.color |
| | | } else if (mark.signType[0] === 'icon') { |
| | | let icon = (<Icon style={{color: mark.color}} type={mark.signType[3]} />) |
| | | if (mark.signType[1] === 'front') { |
| | | content = <span>{icon} {content}</span> |
| | | } else { |
| | | content = <span>{content} {icon}</span> |
| | | } |
| | | } |
| | | } |
| | | return result |
| | | }) |
| | | |
| | | return content |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !nextProps.record || !is(fromJS(this.props.record), fromJS(nextProps.record)) |
| | | } |
| | | |
| | | render() { |
| | | let { col, record, className, style, triggerLink, ...resProps } = this.props |
| | | |
| | | if (!col) return (<td {...resProps} className={className} style={style}/>) |
| | | |
| | | if (col.type === 'text') { |
| | | 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) { |
| | | style = style || {} |
| | | content = this.getMark(record, col.marks, style, content) |
| | | } |
| | | if (col.blur) { |
| | | content = md5(content) |
| | | } |
| | | |
| | | if (col.rowspan === 'true') { |
| | | resProps.rowSpan = record['$$' + col.field] |
| | | } |
| | | |
| | | if (col.linkThdMenu || col.linkurl) { |
| | | content = ( |
| | | <div> |
| | | <div className="link-menu" onDoubleClick={() => this.triggerLink(col, record)}></div> |
| | | {content} |
| | | </div> |
| | | ) |
| | | } |
| | | |
| | | resProps.children = content |
| | | } else if (col.type === 'number') { |
| | | let content = '' |
| | | try { |
| | | content = parseFloat(record[col.field]) |
| | | if (isNaN(content)) { |
| | | content = '' |
| | | } |
| | | } catch { |
| | | content = '' |
| | | } |
| | | |
| | | if (content !== '') { |
| | | let decimal = col.decimal || 0 |
| | | if (col.format === 'percent') { |
| | | content = content * 100 |
| | | decimal = decimal > 2 ? decimal - 2 : 0 |
| | | } |
| | | |
| | | 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) { |
| | | style = style || {} |
| | | content = this.getMark(record, col.marks, style, content) |
| | | } |
| | | |
| | | if (col.blur) { |
| | | content = md5(content) |
| | | } |
| | | |
| | | if (col.linkThdMenu || col.linkurl) { |
| | | content = ( |
| | | <div> |
| | | <div className="link-menu" onDoubleClick={() => this.triggerLink(col, record)}></div> |
| | | {content} |
| | | </div> |
| | | ) |
| | | } |
| | | |
| | | resProps.children = content |
| | | } else if (col.type === 'picture') { |
| | | let photos = '' |
| | | if (record[col.field]) { |
| | | photos = `${record[col.field]}` |
| | | photos = photos.split(',') |
| | | } |
| | | |
| | | let cols = 24 / (col.picSort || 1) |
| | | let paddingTop = '100%' |
| | | |
| | | if (col.lenWidRadio === '16:9') { |
| | | paddingTop = '56.25%' |
| | | } else if (col.lenWidRadio === '3:2') { |
| | | paddingTop = '66.67%' |
| | | } else if (col.lenWidRadio === '4:3') { |
| | | paddingTop = '75%' |
| | | } |
| | | |
| | | resProps.children = ( |
| | | <div> |
| | | {photos.map((url, i) => ( |
| | | <Col key={i} span={cols}> |
| | | <div className="ant-mk-picture" style={{paddingTop, backgroundImage: `url('${url}')`}}></div> |
| | | </Col> |
| | | ))} |
| | | </div> |
| | | ) |
| | | } else if (col.type === 'textarea') { |
| | | let content = '' |
| | | if (record[col.field] !== undefined) { |
| | | content = `${record[col.field]}` |
| | | } |
| | | |
| | | if (content) { |
| | | content = col.prefix + content + col.postfix |
| | | } |
| | | |
| | | if (col.blur) { |
| | | content = md5(content) |
| | | } |
| | | |
| | | resProps.children = ( |
| | | <div> |
| | | {content ? <Paragraph copyable ellipsis={{ rows: 3, expandable: true }}>{content}</Paragraph> : null } |
| | | </div> |
| | | ) |
| | | } else if (col.type === 'link') { |
| | | let content = '' |
| | | let _href = record[col.field] || '' |
| | | |
| | | if (col.nameField) { |
| | | content = record[col.nameField] || '' |
| | | } |
| | | |
| | | if (!content && _href) { |
| | | content = _href |
| | | } else if (!_href) { |
| | | content = '' |
| | | } |
| | | |
| | | if (col.joint === 'true' && _href) { |
| | | let _quary = `id=${record.$$uuid}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}` |
| | | let _param = '' |
| | | |
| | | try { |
| | | _param = window.btoa(_quary) |
| | | } catch { |
| | | _param = window.btoa(window.encodeURIComponent(_quary)) |
| | | } |
| | | |
| | | if (/\?/ig.test(_href)) { |
| | | _href += '&' + _param |
| | | } else { |
| | | _href += '?' + _param |
| | | } |
| | | } |
| | | |
| | | if (col.blur) { |
| | | content = md5(content) |
| | | } |
| | | |
| | | resProps.children = ( |
| | | <div> |
| | | {content && _href ? <a href={_href} target="_blank" rel="noopener noreferrer">{content}</a> : null } |
| | | </div> |
| | | ) |
| | | } |
| | | |
| | | if (resProps.rowSpan === 0) return null |
| | | return (<td {...resProps} className={className} style={style}/>) |
| | | } |
| | | } |
| | | |
| | | class NormalTable extends Component { |
| | | static propTpyes = { |
| | | tableId: PropTypes.string, // 列表Id |
| | | statFValue: PropTypes.any, // 合计字段数据 |
| | | pageSize: PropTypes.any, // 每页数据 |
| | | MenuName: PropTypes.any, // 菜单名称 |
| | | dict: PropTypes.object, // 字典项 |
| | | MenuID: PropTypes.string, // 菜单Id |
| | | setting: PropTypes.object, // 表格全局设置:tableType(表格是否可选、单选、多选)、columnfixed(列固定)、actionfixed(按钮固定) |
| | | pickup: PropTypes.any, // 数据收起 |
| | | columns: PropTypes.array, // 表格列 |
| | | lineMarks: PropTypes.array, // 行标记 |
| | | fields: PropTypes.array, // 组件字段集 |
| | | BID: PropTypes.any, // 主表Id |
| | | ContainerId: PropTypes.any, // 标签页外层Id |
| | | BData: PropTypes.any, // 主表数据 |
| | | data: PropTypes.any, // 表格数据 |
| | | total: PropTypes.any, // 总数 |
| | | loading: PropTypes.bool, // 表格加载中 |
| | | refreshdata: PropTypes.func, // 表格中排序列、页码的变化时刷新 |
| | | handleTableId: PropTypes.func, // 数据切换 |
| | | chgSelectData: PropTypes.func, // 数据切换 |
| | | refreshbyaction: PropTypes.func, // 按钮执行完成后刷新 |
| | | } |
| | | |
| | | state = { |
| | | selectedRowKeys: [], // 表格中选中行 |
| | | pageIndex: 1, // 初始页面索引 |
| | | pageSize: 10, // 每页数据条数 |
| | | columns: null, // 显示列 |
| | | imgShow: false, // 图片放大模态框 |
| | | imgSrc: '', // 图片路径 |
| | | activeIndex: null, // 标记当前选中行 |
| | | rowspans: null // 行合并字段信息 |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { menuType, memberLevel, pageSize } = this.props |
| | | let columns = fromJS(this.props.columns).toJS() |
| | | let _columns = [] |
| | | let radio = 5 // 虚化比例 |
| | | let _format = false // 是否虚化处理 |
| | | let rowspans = [] |
| | | |
| | | if (window.GLOB.dataFormat && menuType !== 'HS' && memberLevel) { |
| | | _format = true |
| | | |
| | | if (memberLevel >= 30) { |
| | | radio = 20 |
| | | } else if (memberLevel >= 20) { |
| | | radio = 10 |
| | | } |
| | | } |
| | | |
| | | columns.forEach(item => { |
| | | if (item.hidden === true || item.Hide === 'true') return |
| | | let cell = null |
| | | |
| | | if (item.type === 'colspan') { |
| | | cell = {title: item.label, children: []} |
| | | |
| | | item.subcols.forEach(col => { |
| | | if (col.rowspan === 'true') { |
| | | rowspans.push(col.field) |
| | | } |
| | | if (_format && !Math.floor(Math.random() * radio)) { |
| | | col.blur = true |
| | | } |
| | | |
| | | if (col.marks && col.marks.length === 0) { |
| | | col.marks = '' |
| | | } |
| | | |
| | | cell.children.push({ |
| | | align: col.Align, |
| | | title: col.label, |
| | | dataIndex: col.field || col.uuid, |
| | | key: col.uuid, |
| | | width: col.Width || 120, |
| | | onCell: record => ({ |
| | | record, |
| | | col: item, |
| | | triggerLink: this.triggerLink |
| | | }) |
| | | }) |
| | | }) |
| | | } else { |
| | | if (item.rowspan === 'true') { |
| | | rowspans.push(item.field) |
| | | } |
| | | if (_format && !Math.floor(Math.random() * radio)) { |
| | | item.blur = true |
| | | } |
| | | |
| | | if (item.marks && item.marks.length === 0) { |
| | | item.marks = '' |
| | | } |
| | | |
| | | cell = { |
| | | align: item.Align, |
| | | dataIndex: item.field || item.uuid, |
| | | title: item.label, |
| | | sorter: item.field && item.IsSort === 'true', |
| | | width: item.Width || 120, |
| | | onCell: record => ({ |
| | | record, |
| | | col: item, |
| | | triggerLink: this.triggerLink |
| | | }) |
| | | } |
| | | } |
| | | |
| | | _columns.push(cell) |
| | | }) |
| | | |
| | | if (rowspans.length === 0) { |
| | | rowspans = null |
| | | } |
| | | |
| | | this.setState({ |
| | | columns: _columns, |
| | | pageSize: pageSize ? pageSize : 10, |
| | | rowspans |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('resetTable', this.resetTable) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('resetTable', this.resetTable) |
| | | } |
| | | |
| | | updateStatus = (type, positon, btn) => { |
| | | if (type === 'refresh') { |
| | | this.props.refreshbyaction(positon, btn) |
| | | } |
| | | } |
| | | |
| | | // 字段透视 |
| | | triggerLink = (item, record) => { |
| | | const { tabviews, MenuID, setting } = this.props |
| | | |
| | | if (item.linkThdMenu) { |
| | | let tabmenu = item.linkThdMenu |
| | | |
| | | tabmenu.param = { |
| | | searchkey: item.field, |
| | | searchval: record[item.field] || '', |
| | | BID: record[setting.primaryKey] |
| | | } |
| | | |
| | | tabmenu.selected = true |
| | | |
| | | let index = 0 |
| | | let isexit = false |
| | | let tabs = tabviews.map((tab, i) => { |
| | | tab.selected = false |
| | | |
| | | if (tab.MenuID === MenuID) { |
| | | index = i |
| | | } else if (tab.MenuID === tabmenu.MenuID) { |
| | | tab.param = tabmenu.param |
| | | tab.selected = true |
| | | isexit = true |
| | | } |
| | | |
| | | return tab |
| | | }) |
| | | |
| | | if (!isexit) { |
| | | tabs.splice(index + 1, 0, tabmenu) |
| | | } |
| | | |
| | | this.props.modifyTabview(tabs) |
| | | } else { |
| | | let src = item.linkurl |
| | | |
| | | if (item.linkurl.indexOf('paramsmain/') > -1) { |
| | | try { |
| | | let _url = item.linkurl.split('paramsmain/')[0] + 'paramsmain/' |
| | | let _param = JSON.parse(window.decodeURIComponent(window.atob(item.linkurl.split('paramsmain/')[1]))) |
| | | let dataparam = { |
| | | searchkey: item.field, |
| | | searchval: record[item.field] || '', |
| | | BID: record[setting.primaryKey] |
| | | } |
| | | _param.UserID = sessionStorage.getItem('UserID') |
| | | _param.LoginUID = sessionStorage.getItem('LoginUID') |
| | | _param.User_Name = sessionStorage.getItem('User_Name') |
| | | _param.param = dataparam |
| | | src = _url + window.btoa(window.encodeURIComponent(JSON.stringify(_param))) |
| | | } catch { |
| | | console.warn('菜单参数解析错误!') |
| | | } |
| | | } |
| | | |
| | | window.open(src) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | onSelectChange = selectedRowKeys => { |
| | | const { setting } = this.props |
| | | |
| | | let index = '' |
| | | let _activeIndex = null |
| | | if (selectedRowKeys.length > 0) { |
| | | index = selectedRowKeys.slice(-1)[0] |
| | | } |
| | | |
| | | if (setting.tableType === 'checkbox') { |
| | | _activeIndex = index === '' ? null : index |
| | | } |
| | | |
| | | this.changedata(index) |
| | | |
| | | this.setState({ selectedRowKeys, activeIndex: _activeIndex }) |
| | | |
| | | let selects = this.props.data.filter((item, _index) => selectedRowKeys.includes(_index)) |
| | | |
| | | this.props.chgSelectData(selects) |
| | | } |
| | | |
| | | /** |
| | | * @description 点击整行,触发切换, 判断是否可选,单选或多选,进行对应操作 |
| | | */ |
| | | changeRow = (record, index) => { |
| | | const { setting, pickup } = this.props |
| | | |
| | | if (!setting.tableType || pickup) return |
| | | |
| | | let newkeys = fromJS(this.state.selectedRowKeys).toJS() |
| | | |
| | | if (setting.tableType === 'radio') { |
| | | newkeys = [index] |
| | | this.changedata(index) |
| | | this.setState({ selectedRowKeys: newkeys }) |
| | | } else { |
| | | let _index = '' |
| | | if (newkeys.includes(index)) { |
| | | newkeys = newkeys.filter(item => item !== index) |
| | | if (newkeys.length > 0) { |
| | | _index = newkeys.slice(-1)[0] |
| | | } |
| | | this.changedata(_index) |
| | | } else { |
| | | _index = index |
| | | newkeys.push(index) |
| | | this.changedata(index) |
| | | } |
| | | |
| | | this.setState({ selectedRowKeys: newkeys, activeIndex: _index !== '' ? _index : null }) |
| | | } |
| | | |
| | | let selects = this.props.data.filter((item, _index) => newkeys.includes(_index)) |
| | | |
| | | this.props.chgSelectData(selects) |
| | | } |
| | | |
| | | changeTable = (pagination, filters, sorter) => { |
| | | this.setState({ |
| | | pageIndex: pagination.current, |
| | | pageSize: pagination.pageSize, |
| | | selectedRowKeys: [], |
| | | activeIndex: null |
| | | }) |
| | | this.props.refreshdata(pagination, filters, sorter) |
| | | } |
| | | |
| | | changedata = (index) => { |
| | | const { data, setting } = this.props |
| | | |
| | | let _id = '' |
| | | let _data = '' |
| | | |
| | | if (data && data.length > 0 && index !== '') { |
| | | _id = data[index][setting.primaryKey] || '' |
| | | _data = data[index] || '' |
| | | } |
| | | |
| | | this.props.handleTableId(this.props.tableId, _id, _data) |
| | | } |
| | | |
| | | resetTable = (id, repage) => { |
| | | const { MenuID, tableId } = this.props |
| | | |
| | | if (id !== (MenuID + tableId)) return |
| | | |
| | | if (repage === 'false') { |
| | | this.setState({ |
| | | selectedRowKeys: [], |
| | | activeIndex: null |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | pageIndex: 1, |
| | | selectedRowKeys: [], |
| | | activeIndex: null |
| | | }) |
| | | } |
| | | } |
| | | |
| | | handleRowspan = (data) => { |
| | | const { rowspans } = this.state |
| | | |
| | | if (!rowspans || data.length === 0) return data |
| | | |
| | | data = fromJS(data).toJS() |
| | | data = data.reverse() |
| | | data.forEach((item, index) => { |
| | | if (index === 0) { |
| | | rowspans.forEach(cell => { |
| | | item['$' + cell] = 1 |
| | | }) |
| | | } else { |
| | | let preItem = data[index - 1] |
| | | rowspans.forEach((cell, i) => { |
| | | if (i === 0) { |
| | | if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) { |
| | | item['$' + cell] = preItem['$' + cell] + 1 |
| | | } else { |
| | | item['$' + cell] = 1 |
| | | } |
| | | } else { |
| | | if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) { |
| | | item['$' + cell] = preItem['$' + cell] + 1 |
| | | } else { |
| | | item['$' + cell] = 1 |
| | | } |
| | | if (item['$' + cell] > item['$' + rowspans[i - 1]]) { |
| | | item['$' + cell] = 1 |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | data = data.reverse() |
| | | data.forEach((item, index) => { |
| | | if (index === 0) { |
| | | rowspans.forEach(cell => { |
| | | item['$$' + cell] = item['$' + cell] |
| | | }) |
| | | } else { |
| | | let preItem = data[index - 1] |
| | | rowspans.forEach(cell => { |
| | | if (preItem['$' + cell] > 1) { |
| | | item['$$' + cell] = 0 |
| | | } else { |
| | | item['$$' + cell] = item['$' + cell] |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | |
| | | render() { |
| | | const { setting, pickup, statFValue, lineMarks } = this.props |
| | | const { selectedRowKeys, activeIndex } = this.state |
| | | |
| | | // 设置表格选择属性:单选、多选、不可选 |
| | | let rowSelection = null |
| | | if (setting.tableType) { |
| | | rowSelection = { |
| | | selectedRowKeys, |
| | | type: (setting.tableType === 'radio') ? 'radio' : 'checkbox', |
| | | onChange: this.onSelectChange |
| | | } |
| | | } |
| | | |
| | | const components = { |
| | | body: { |
| | | row: BodyRow, |
| | | cell: BodyCell |
| | | } |
| | | } |
| | | |
| | | // 数据收起时,过滤已选数据 |
| | | let _data = this.props.data ? this.props.data : [] |
| | | |
| | | if (pickup) { |
| | | _data = _data.filter((item, index) => selectedRowKeys.includes(index)) |
| | | } |
| | | |
| | | _data = this.handleRowspan(_data) |
| | | |
| | | let _pagination = false |
| | | if (setting.laypage !== 'false' && setting.laypage !== false) { |
| | | _pagination = { |
| | | current: this.state.pageIndex, |
| | | pageSize: this.state.pageSize, |
| | | pageSizeOptions: ['10', '25', '50', '100', '500', '1000'], |
| | | showSizeChanger: true, |
| | | total: this.props.total || 0, |
| | | showTotal: (total, range) => `${range[0]}-${range[1]} ${this.props.dict['main.pagination.of']} ${total} ${this.props.dict['main.pagination.items']}` |
| | | } |
| | | } |
| | | |
| | | let _footer = '' |
| | | |
| | | if (statFValue && statFValue.length > 0) { |
| | | _footer = statFValue.map(f => `${f.label}(合计):${f.value}`).join(';') |
| | | } |
| | | |
| | | return ( |
| | | <div className="normal-custom-table"> |
| | | <Table |
| | | size="middle" |
| | | components={components} |
| | | bordered={setting.bordered !== 'false'} |
| | | rowSelection={rowSelection} |
| | | columns={this.state.columns} |
| | | dataSource={_data} |
| | | loading={this.props.loading} |
| | | scroll={{ x: '100%', y: false }} |
| | | onRow={(record, index) => { |
| | | return { |
| | | lineMarks, |
| | | data: record, |
| | | className: index === activeIndex ? ' mk-row-active ' : '', |
| | | onClick: () => {this.changeRow(record, index)} |
| | | } |
| | | }} |
| | | onChange={this.changeTable} |
| | | pagination={_pagination} |
| | | /> |
| | | {_footer ? <div className={'normal-table-footer ' + (_pagination ? 'pagination' : '')}>{_footer}</div> : null} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | menuType: state.editLevel, |
| | | tabviews: state.tabviews, |
| | | memberLevel: state.memberLevel |
| | | } |
| | | } |
| | | |
| | | const mapDispatchToProps = (dispatch) => { |
| | | return { |
| | | modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews)) |
| | | } |
| | | } |
| | | |
| | | export default connect(mapStateToProps, mapDispatchToProps)(NormalTable) |
New file |
| | |
| | | .normal-custom-table { |
| | | position: relative; |
| | | padding: 0 0px 30px; |
| | | |
| | | .normal-table-footer { |
| | | padding: 10px 0px; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | } |
| | | .normal-table-footer.pagination { |
| | | position: absolute; |
| | | bottom: 40px; |
| | | } |
| | | >.ant-table-wrapper { |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | table { |
| | | max-width: 100%; |
| | | width: 100%; |
| | | .ant-table-thead { |
| | | tr { |
| | | th { |
| | | position: relative; |
| | | } |
| | | } |
| | | } |
| | | .ant-table-selection-column { |
| | | width: 60px; |
| | | min-width: 60px; |
| | | max-width: 60px; |
| | | } |
| | | .ant-table-tbody > tr.ant-table-row-selected:not(.background) td { |
| | | background-color: #c4ebfd; |
| | | } |
| | | .ant-table-tbody > tr.ant-table-row-selected:not(.background):hover .ant-table-column-sort { |
| | | background-color: #c4ebfd; |
| | | } |
| | | .ant-table-tbody > tr.background td { |
| | | background-color: unset!important; |
| | | } |
| | | .ant-table-tbody > tr.mk-row-active:not(.background) td { |
| | | background-color: #91d5ff; |
| | | } |
| | | .ant-table-tbody > tr.ant-table-row-selected.mk-row-active:not(.background):hover .ant-table-column-sort { |
| | | background-color: #91d5ff; |
| | | } |
| | | .ant-table-tbody > tr td .anticon.font { |
| | | background-color: unset; |
| | | } |
| | | } |
| | | .ant-table-body { |
| | | overflow-x: auto!important; |
| | | table { |
| | | .ant-table-tbody > tr > td { |
| | | vertical-align: top; |
| | | |
| | | .ant-mk-picture { |
| | | background-position: center center; |
| | | background-size: cover; |
| | | margin: 2px; |
| | | } |
| | | .action-col { |
| | | .ant-btn > .anticon + span { |
| | | margin-left: 3px; |
| | | } |
| | | button { |
| | | border: 0; |
| | | background-color: transparent; |
| | | color: #1890ff; |
| | | box-shadow: none; |
| | | padding: 0 5px; |
| | | .anticon-loading { |
| | | display: none; |
| | | } |
| | | } |
| | | > div { |
| | | margin: 0 3px; |
| | | } |
| | | > button { |
| | | margin: 0 3px; |
| | | } |
| | | .ant-btn.ant-btn-loading:not(.ant-btn-circle):not(.ant-btn-circle-outline):not(.ant-btn-icon-only) { |
| | | padding-left: 0px; |
| | | } |
| | | } |
| | | } |
| | | .ant-table-tbody > tr > td[rowspan] { |
| | | vertical-align: middle; |
| | | } |
| | | .ant-table-tbody > tr > td.ant-table-column-has-actions { |
| | | position: relative; |
| | | .link-menu { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | right: 0px; |
| | | bottom: 0px; |
| | | opacity: 0; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .content { |
| | | position: relative; |
| | | z-index: 1; |
| | | word-wrap: break-word; |
| | | word-break: break-word; |
| | | } |
| | | } |
| | | .ant-table-tbody > tr > td .content { |
| | | p { |
| | | margin-bottom: 2px; |
| | | } |
| | | span { |
| | | display: inline-block; |
| | | margin-right: 5px; |
| | | } |
| | | } |
| | | .ant-table-tbody > tr > td .button { |
| | | .ant-btn { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .ant-table-body::-webkit-scrollbar { |
| | | width: 8px; |
| | | height: 10px; |
| | | } |
| | | ::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | ::-webkit-scrollbar-track {/*滚动条里面轨道*/ |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | .fix-header { |
| | | .ant-table-body { |
| | | min-height: unset |
| | | } |
| | | .ant-table-placeholder { |
| | | display: none; |
| | | } |
| | | .ant-table-wrapper { |
| | | display: none; |
| | | } |
| | | .ant-affix .ant-table-wrapper { |
| | | display: block; |
| | | } |
| | | } |
| | | } |
| | | .image-scale-modal { |
| | | width: 70vw; |
| | | min-height: 80vh; |
| | | top: 10vh; |
| | | .ant-modal-body { |
| | | min-height: calc(80vh - 110px); |
| | | line-height: calc(80vh - 160px); |
| | | text-align: center; |
| | | } |
| | | .ant-modal-footer { |
| | | text-align: center; |
| | | span { |
| | | display: inline-block; |
| | | color: #1890ff; |
| | | padding: 5px 15px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // 通用组件 |
| | | const MainAction = asyncSpinComponent(() => import('@/tabviews/zshare/actionList')) |
| | | const MainTable = asyncSpinComponent(() => import('@/tabviews/zshare/normalTable')) |
| | | const MainTable = asyncSpinComponent(() => import('@/tabviews/custom/components/share/normalTable')) |
| | | |
| | | class NormalTable extends Component { |
| | | static propTpyes = { |
| | |
| | | this.setState({ |
| | | data: result.data.map((item, index) => { |
| | | item.key = index |
| | | item.$$uuid = item[setting.primaryKey] || '' |
| | | return item |
| | | }), |
| | | total: result.total, |
| | |
| | | fields={config.columns} |
| | | total={this.state.total} |
| | | MenuID={this.props.MenuID} |
| | | lineMarks={config.lineMarks} |
| | | loading={this.state.loading} |
| | | refreshdata={this.refreshbytable} |
| | | statFValue={this.state.statFValue} |
| | |
| | | import { is, fromJS } from 'immutable' |
| | | import { Table, Affix, Typography, Modal, Icon } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import { modifyTabview } from '@/store/action' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import MKEmitter from '@/utils/events.js' |
| | |
| | | imgSrc: '', // 图片路径 |
| | | lineMarks: null, // 行标记 |
| | | activeIndex: null, // 标记当前选中行 |
| | | rowspan: null // 行合并字段信息 |
| | | rowspans: null // 行合并字段信息 |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | let _columns = [] |
| | | let radio = 5 // 虚化比例 |
| | | let _format = false // 是否虚化处理 |
| | | let rowspan = null |
| | | let rowspans = [] |
| | | |
| | | if (window.GLOB.dataFormat && menuType !== 'HS' && memberLevel) { |
| | | _format = true |
| | |
| | | |
| | | item.subcols.forEach(col => { |
| | | if (col.rowspan === 'true') { |
| | | rowspan = col |
| | | rowspans.push(col.field) |
| | | } |
| | | if (_format && !Math.floor(Math.random() * radio)) { |
| | | col.blur = true |
| | |
| | | } |
| | | } else { |
| | | if (item.rowspan === 'true') { |
| | | rowspan = item |
| | | rowspans.push(item.field) |
| | | } |
| | | if (_format && !Math.floor(Math.random() * radio)) { |
| | | item.blur = true |
| | |
| | | _columns.push(cell) |
| | | }) |
| | | |
| | | if (rowspans.length === 0) { |
| | | rowspans = null |
| | | } |
| | | |
| | | this.setState({ |
| | | columns: _columns, |
| | | pageSize: pageSize ? pageSize : 10, |
| | | lineMarks: lineMarks, |
| | | rowspan: rowspan |
| | | lineMarks, |
| | | rowspans |
| | | }) |
| | | } |
| | | |
| | |
| | | </div> |
| | | ), |
| | | props: { |
| | | rowSpan: record.$$rowspan, |
| | | rowSpan: record['$$' + item.field], |
| | | } |
| | | } |
| | | } |
| | |
| | | </div> |
| | | ), |
| | | props: { |
| | | rowSpan: record.$$rowspan, |
| | | rowSpan: record['$$' + item.field], |
| | | } |
| | | } |
| | | } |
| | |
| | | } else if (item.type === 'picture') { |
| | | let photos = '' |
| | | if (item.field && record.hasOwnProperty(item.field)) { |
| | | photos = record[item.field].split(',') |
| | | photos = record[item.field] + '' |
| | | photos = photos.split(',') |
| | | } else { |
| | | photos = '' |
| | | } |
| | |
| | | } else if (col.type === 'picture') { |
| | | let photos = [] |
| | | try { |
| | | photos = record[col.field].split(',') |
| | | photos = record[col.field] + '' |
| | | photos = photos.split(',') |
| | | } catch { |
| | | photos = [] |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | handleRowspan = (data) => { |
| | | const { rowspans } = this.state |
| | | |
| | | if (!rowspans || data.length === 0) return data |
| | | |
| | | data = fromJS(data).toJS() |
| | | data = data.reverse() |
| | | data.forEach((item, index) => { |
| | | if (index === 0) { |
| | | rowspans.forEach(cell => { |
| | | item['$' + cell] = 1 |
| | | }) |
| | | } else { |
| | | let preItem = data[index - 1] |
| | | rowspans.forEach((cell, i) => { |
| | | if (i === 0) { |
| | | if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) { |
| | | item['$' + cell] = preItem['$' + cell] + 1 |
| | | } else { |
| | | item['$' + cell] = 1 |
| | | } |
| | | } else { |
| | | if ((item[cell] || item[cell] === 0) && preItem[cell] === item[cell]) { |
| | | item['$' + cell] = preItem['$' + cell] + 1 |
| | | } else { |
| | | item['$' + cell] = 1 |
| | | } |
| | | if (item['$' + cell] > item['$' + rowspans[i - 1]]) { |
| | | item['$' + cell] = 1 |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | data = data.reverse() |
| | | data.forEach((item, index) => { |
| | | if (index === 0) { |
| | | rowspans.forEach(cell => { |
| | | item['$$' + cell] = item['$' + cell] |
| | | }) |
| | | } else { |
| | | let preItem = data[index - 1] |
| | | rowspans.forEach(cell => { |
| | | if (preItem['$' + cell] > 1) { |
| | | item['$$' + cell] = 0 |
| | | } else { |
| | | item['$$' + cell] = item['$' + cell] |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | return data |
| | | } |
| | | |
| | | render() { |
| | | const { setting, pickup, statFValue } = this.props |
| | | const { selectedRowKeys, lineMarks, activeIndex, rowspan } = this.state |
| | | const { selectedRowKeys, lineMarks, activeIndex } = this.state |
| | | |
| | | // 设置表格选择属性:单选、多选、不可选 |
| | | let rowSelection = null |
| | |
| | | _data = _data.filter((item, index) => selectedRowKeys.includes(index)) |
| | | } |
| | | |
| | | if (rowspan) { |
| | | let marks = {} |
| | | let premark = {val: '', mark: ''} |
| | | _data = _data.map(item => { |
| | | if (item[rowspan.field]) { |
| | | if (item[rowspan.field] !== premark.val) { |
| | | premark = {val: item[rowspan.field], mark: Utils.getuuid()} |
| | | |
| | | marks[premark.mark] = 1 |
| | | item.$$mark = premark.mark |
| | | } else { |
| | | marks[premark.mark]++ |
| | | item.$$mark = premark.mark |
| | | } |
| | | } else { |
| | | item.$$rowspan = 1 |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | _data = _data.map(item => { |
| | | if (item.$$mark) { |
| | | item.$$rowspan = marks[item.$$mark] |
| | | marks[item.$$mark] = 0 |
| | | } |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | _data = this.handleRowspan(_data) |
| | | |
| | | let _pagination = false |
| | | if (setting.laypage !== 'false' && setting.laypage !== false) { |
| | | _pagination = { |
| | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | config: null, // 页面配置 |
| | | tableFields: [], // 表格显示列 |
| | | tableFields: [], // 已选的常用表 |
| | | formlist: null, // 搜索条件、按钮、显示列表单字段 |
| | | menuloading: false, // 菜单保存中 |
| | | menucloseloading: false, // 菜单关闭时,选择保存 |
| | | loading: false, // 加载中,页面spin |
| | | closeVisible: false, // 关闭模态框 |
| | | tables: [], // 可用表名 |
| | | originMenu: null, // 原始菜单 |
| | | originActions: null, // 原始按钮信息,使用已有用户模板 |
| | | delActions: [], // 删除按钮列表 |
| | |
| | | import { DndProvider } from 'react-dnd' |
| | | import HTML5Backend from 'react-dnd-html5-backend' |
| | | import moment from 'moment' |
| | | import { Button, Card, Modal, Collapse, notification, Select, List, Icon, Empty, Popover, Switch } from 'antd' |
| | | import { Button, Card, Modal, Collapse, notification, Icon, Popover, Switch } from 'antd' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getModalForm } from '@/templates/zshare/formconfig' |
| | | import { queryTableSql } from '@/utils/option.js' |
| | | |
| | | import ModalForm from '@/templates/zshare/modalform' |
| | | import DragElement from './dragelement' |
| | | import SourceElement from './dragelement/source' |
| | | import SettingForm from './settingform' |
| | | import GroupForm from './groupform' |
| | | import EditCard from './editcard' |
| | | import MenuForm from './menuform' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import EditComponent from '@/templates/zshare/editcomponent' |
| | | import { BaseConfig, SearchItems } from './source' |
| | | import './index.scss' |
| | | |
| | | const { Panel } = Collapse |
| | | const { Option } = Select |
| | | const { confirm } = Modal |
| | | const CommonDict = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS |
| | | const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent')) |
| | | const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent')) |
| | | |
| | | class ComModalConfig extends Component { |
| | | static propTpyes = { |
| | |
| | | state = { |
| | | menu: null, // 上级菜单,三级菜单或标签 |
| | | dict: CommonDict, // 字典 |
| | | tableFields: [], // 已选的常用表 |
| | | config: null, // 页面配置,包括模板类型、模态框设置、添加表名、表单列表 |
| | | visible: false, // 表单编辑模态框,显示控制 |
| | | tableVisible: false, // 数据表字段列表模态框,显示控制 |
| | | tableColumns: [], // 表格字段名列表 |
| | | fields: null, // 表单,可选字段(去重后) |
| | | modalformlist: null, // 基本信息表单字段 |
| | | formlist: null, // 表单编辑模态框,可编辑字段 |
| | | card: null, // 编辑元素 |
| | |
| | | closeloading: false, // 菜单保存中 |
| | | settingVisible: false, // 全局配置模态框 |
| | | closeVisible: false, // 关闭模态框 |
| | | tables: [], // 可用表名 |
| | | selectedTables: [], // 已选表名 |
| | | originConfig: null, // 原始菜单 |
| | | groupVisible: false, // 全局配置模态框 |
| | | curgroup: null, // 当前组,新建或编辑 |
| | | sources: null, // 表单类型 |
| | | sqlVerifing: false, // sql验证 |
| | | openEdition: '', // 编辑版本标记,防止多人操作 |
| | | showField: false // 显示表单字段值 |
| | |
| | | menu: _menu, |
| | | source: _source, |
| | | config: _config, |
| | | selectedTables: _config.tables || [], |
| | | originConfig: fromJS(_config).toJS(), |
| | | modalformlist: [ |
| | | { |
| | |
| | | readonly: true |
| | | } |
| | | ] |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 获取数据表信息 |
| | | * 1、获取系统中全部表名 |
| | | * 2、根据已选表名,获取表格字段列表 |
| | | */ |
| | | componentDidMount () { |
| | | let param = { |
| | | func: 'sPC_Get_SelectedList', |
| | | LText: queryTableSql, |
| | | obj_name: 'data', |
| | | arr_field: 'TbName,Remark' |
| | | } |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 云端数据验证 |
| | | |
| | | Api.getSystemConfig(param).then(res => { |
| | | if (res.status) { |
| | | this.setState({ |
| | | tables: res.data |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | let deffers = this.state.selectedTables.map(item => { |
| | | return new Promise(resolve => { |
| | | Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => { |
| | | res.TBName = item.TbName |
| | | resolve(res) |
| | | }) |
| | | }) |
| | | }) |
| | | |
| | | // 获取字段后数据处理,根据类型分为text、number、datetime、date |
| | | Promise.all(deffers).then(response => { |
| | | let _columns = [] |
| | | response.forEach(res => { |
| | | if (res.status) { |
| | | let tabmsg = { |
| | | tableName: res.TBName, |
| | | columns: res.FDName.map(item => { |
| | | let _type = item.FieldType.toLowerCase() |
| | | let _decimal = 0 |
| | | if (/^nvarchar/.test(_type)) { |
| | | _type = 'text' |
| | | } else if (/^int/.test(_type)) { |
| | | _type = 'number' |
| | | } else if (/^decimal/.test(_type)) { |
| | | _decimal = _type.split(',')[1] |
| | | _decimal = parseInt(_decimal) |
| | | _type = 'number' |
| | | } else if (/^datetime/.test(_type)) { |
| | | _type = 'datetime' |
| | | } else if (/^date/.test(_type)) { |
| | | _type = 'date' |
| | | } else { |
| | | _type = 'text' |
| | | } |
| | | |
| | | return { |
| | | field: item.FieldName, |
| | | label: item.FieldDec, |
| | | type: _type, |
| | | decimal: _decimal |
| | | } |
| | | }) |
| | | } |
| | | _columns.push(tabmsg) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | this.setState({ |
| | | tableColumns: _columns |
| | | }) |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | let _LongParam = '' |
| | | let _config = {...config, tables: this.state.selectedTables} |
| | | let _config = fromJS(config).toJS() |
| | | |
| | | try { |
| | | _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config))) |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description 通过表字段添加表单 |
| | | * 1、检查是否已选表名,为选时警告提示 |
| | | * 2、表字段名通过map去重 |
| | | * 3、检查表单中的已选字段,并标记已选 |
| | | * @description 更新常用表信息,快捷添加后更新配置信息 |
| | | */ |
| | | queryField = () => { |
| | | const {selectedTables, tableColumns, config} = this.state |
| | | if (selectedTables.length === 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请选择表名!', |
| | | duration: 10 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let columns = new Map() |
| | | tableColumns.forEach(table => { |
| | | table.columns.forEach(column => { |
| | | columns.set(column.field, column) |
| | | }) |
| | | }) |
| | | |
| | | if (config.groups.length > 1) { |
| | | config.groups.forEach(group => { |
| | | group.sublist.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | columns.set(item.field, {...item, selected: true}) |
| | | } |
| | | }) |
| | | }) |
| | | } else { |
| | | config.fields.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | columns.set(item.field, {...item, selected: true}) |
| | | } |
| | | }) |
| | | } |
| | | updatetable = (config, fields) => { |
| | | const { tableFields } = this.state |
| | | |
| | | this.setState({ |
| | | tableVisible: true, |
| | | fields: [...columns.values()] |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 选择字段后提交 |
| | | * 1、没有可选字段时,直接关闭 |
| | | * 2、获取已选字段 |
| | | * 3、与已有字段对比 |
| | | * 4、添加新增字段 |
| | | */ |
| | | addFieldSubmit = () => { |
| | | if (!this.state.fields || this.state.fields.length === 0) { |
| | | this.setState({ |
| | | tableVisible: false |
| | | }) |
| | | } |
| | | |
| | | let _config = fromJS(this.state.config).toJS() |
| | | |
| | | let cards = this.refs.searchcard.state.selectCards |
| | | let columns = new Map() |
| | | cards.forEach(card => { |
| | | columns.set(card.field, card) |
| | | }) |
| | | |
| | | if (_config.groups.length > 1) { |
| | | _config.groups.forEach(group => { |
| | | let items = [] |
| | | group.sublist.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | let cell = columns.get(item.field) |
| | | |
| | | if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加 |
| | | items.push(item) |
| | | } else if (cell.selected) { // 数据类型修改时,重置类型及初始值 |
| | | item.type = cell.type |
| | | item.initval = '' |
| | | items.push(item) |
| | | } |
| | | columns.delete(item.field) |
| | | } else if (!item.origin) { // 过滤示例项 |
| | | items.push(item) |
| | | } |
| | | }) |
| | | group.sublist = items |
| | | }) |
| | | |
| | | let _columns = [...columns.values()] |
| | | |
| | | let _additems = _columns.map(item => { // 循环添加新增字段 |
| | | return { |
| | | uuid: Utils.getuuid(), |
| | | label: item.label, |
| | | field: item.field, |
| | | initval: '', |
| | | type: item.type, |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | dataSource: '', |
| | | orderType: 'asc', |
| | | decimal: 0, |
| | | readonly: 'false', |
| | | required: 'true' |
| | | } |
| | | }) |
| | | _config.groups[_config.groups.length - 1].sublist = [..._config.groups.slice(-1)[0].sublist, ..._additems] |
| | | |
| | | } else { |
| | | let items = [] |
| | | _config.fields.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | let cell = columns.get(item.field) |
| | | |
| | | if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加 |
| | | items.push(item) |
| | | } else if (cell.selected) { // 数据类型修改时,重置类型及初始值 |
| | | item.type = cell.type |
| | | item.initval = '' |
| | | items.push(item) |
| | | } |
| | | columns.delete(item.field) |
| | | } else if (!item.origin) { // 过滤示例项 |
| | | items.push(item) |
| | | } |
| | | }) |
| | | |
| | | let _columns = [...columns.values()] |
| | | |
| | | _columns.forEach(item => { // 循环添加新增字段 |
| | | if (item.selected) { |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | label: item.label, |
| | | field: item.field, |
| | | initval: '', |
| | | type: item.type, |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | dataSource: '', |
| | | orderType: 'asc', |
| | | readonly: 'false', |
| | | required: 'true' |
| | | } |
| | | |
| | | items.push(newcard) |
| | | } |
| | | }) |
| | | |
| | | _config.fields = items |
| | | } |
| | | |
| | | this.setState({ |
| | | config: _config |
| | | }) |
| | | notification.success({ |
| | | top: 92, |
| | | message: '添加成功', |
| | | duration: 2 |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 添加表名 |
| | | * 1、获取表信息 |
| | | * 2、检验是否已经添加,已添加时跳过 |
| | | * 3、通过表名获取字段集,并设置数据类型 |
| | | */ |
| | | onTableChange = (value) => { |
| | | const {tables, selectedTables, tableColumns} = this.state |
| | | |
| | | let _table = tables.filter(item => item.TbName === value)[0] |
| | | let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0] |
| | | |
| | | if (isSelected) return |
| | | |
| | | this.setState({ |
| | | selectedTables: [...selectedTables, _table] |
| | | }) |
| | | Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => { |
| | | if (res.status) { |
| | | let tabmsg = { |
| | | tableName: _table.name, |
| | | columns: res.FDName.map(item => { |
| | | let _type = item.FieldType.toLowerCase() |
| | | let _decimal = 0 |
| | | if (/^nvarchar/.test(_type)) { |
| | | _type = 'text' |
| | | } else if (/^int/.test(_type)) { |
| | | _type = 'number' |
| | | } else if (/^decimal/.test(_type)) { |
| | | _decimal = _type.split(',')[1] |
| | | _decimal = parseInt(_decimal) |
| | | _type = 'number' |
| | | } else if (/^datetime/.test(_type)) { |
| | | _type = 'datetime' |
| | | } else if (/^date/.test(_type)) { |
| | | _type = 'date' |
| | | } else { |
| | | _type = 'text' |
| | | } |
| | | |
| | | return { |
| | | field: item.FieldName, |
| | | label: item.FieldDec, |
| | | type: _type, |
| | | decimal: _decimal |
| | | } |
| | | }) |
| | | } |
| | | this.setState({ |
| | | tableColumns: [...tableColumns, tabmsg] |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 删除表名,删除对应字段集 |
| | | */ |
| | | deleteTable = (table) => { |
| | | const {selectedTables, tableColumns} = this.state |
| | | |
| | | this.setState({ |
| | | selectedTables: selectedTables.filter(item => item.TbName !== table.TbName), |
| | | tableColumns: tableColumns.filter(item => item.tableName !== table.TbName) |
| | | config: config, |
| | | tableFields: fields ? fields : tableFields |
| | | }) |
| | | } |
| | | |
| | |
| | | /** |
| | | * @description 编辑功能完成更新,包括解冻按钮、粘贴、替换等 |
| | | */ |
| | | updateConfig = (res) => { |
| | | updateEditConfig = (res) => { |
| | | if (res.type === 'paste') { |
| | | this.setState({ |
| | | config: res.content |
| | | }) |
| | | this.handleForm(res.newform) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 更新配置信息 |
| | | */ |
| | | updateconfig = (config) => { |
| | | this.setState({ |
| | | config: config |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | |
| | | <DndProvider backend={HTML5Backend}> |
| | | <div className="tools"> |
| | | <Collapse accordion defaultActiveKey="1" bordered={false}> |
| | | <Panel header={dict['header.menu.basedata']} key="0" id="modal-basedata"> |
| | | <Panel forceRender={true} header={dict['header.menu.basedata']} key="0" id="modal-basedata"> |
| | | <MenuForm |
| | | dict={dict} |
| | | formlist={this.state.modalformlist} |
| | | /> |
| | | <div className="ant-col ant-form-item-label"> |
| | | <label title={dict['header.menu.table.add']}> |
| | | {dict['header.menu.table.add']} |
| | | </label> |
| | | </div> |
| | | <Select |
| | | showSearch |
| | | showArrow={false} |
| | | className="tables" |
| | | style={{ width: '100%' }} |
| | | optionFilterProp="children" |
| | | value={dict['header.menu.table.placeholder']} |
| | | onChange={this.onTableChange} |
| | | getPopupContainer={() => document.getElementById('modal-basedata')} |
| | | filterOption={(input, option) => { |
| | | return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 |
| | | }} |
| | | > |
| | | {this.state.tables.map((table, index) => ( |
| | | <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option> |
| | | ))} |
| | | </Select> |
| | | {this.state.selectedTables.length > 0 && <List |
| | | size="small" |
| | | bordered |
| | | dataSource={this.state.selectedTables} |
| | | renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}> |
| | | {item.Remark + ' (' + item.TbName + ')'} |
| | | <Icon type="close" onClick={() => this.deleteTable(item)}/> |
| | | <div className="bottom-mask"></div> |
| | | </List.Item>} |
| | | />} |
| | | {/* 表名添加 */} |
| | | <TableComponent |
| | | config={config} |
| | | containerId="modal-basedata" |
| | | updatetable={this.updatetable} |
| | | /> |
| | | </Panel> |
| | | <Panel header={dict['header.menu.form']} key="1"> |
| | | <div className="search-element"> |
| | |
| | | return (<SourceElement key={index} content={item}/>) |
| | | })} |
| | | </div> |
| | | <Button type="primary" block onClick={() => this.queryField()}>{dict['header.menu.form.add']}</Button> |
| | | <FieldsComponent |
| | | config={config} |
| | | type="form" |
| | | tableFields={this.state.tableFields} |
| | | updatefield={this.updateconfig} |
| | | /> |
| | | <Button type="primary" block onClick={() => this.handleGroup()}>{dict['header.menu.group.add']}</Button> |
| | | </Panel> |
| | | </Collapse> |
| | |
| | | <div className="setting"> |
| | | <Card title={dict['header.menu.form.configurable']} bordered={false} extra={ |
| | | <div> |
| | | <EditComponent dict={dict} type="form" config={this.state.config} refresh={this.updateConfig}/> |
| | | <EditComponent dict={dict} type="form" config={this.state.config} refresh={this.updateEditConfig}/> |
| | | <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{dict['model.save']}</Button> |
| | | <Button onClick={this.cancelConfig}>{dict['model.back']}</Button> |
| | | </div> |
| | |
| | | inputSubmit={this.handleSubmit} |
| | | wrappedComponentRef={(inst) => this.formRef = inst} |
| | | /> |
| | | </Modal> |
| | | <Modal |
| | | wrapClassName="modal-fields" |
| | | title={dict['model.edit']} |
| | | visible={this.state.tableVisible} |
| | | width={'65vw'} |
| | | maskClosable={false} |
| | | style={{minWidth: '900px', maxWidth: '1200px'}} |
| | | onOk={this.addFieldSubmit} |
| | | cancelText={dict['model.close']} |
| | | onCancel={() => { this.setState({ tableVisible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | {this.state.fields && this.state.fields.length > 0 ? |
| | | <EditCard data={this.state.fields} ref="searchcard" type="search" /> : null |
| | | } |
| | | {(!this.state.fields || this.state.fields.length === 0) && |
| | | <Empty /> |
| | | } |
| | | </Modal> |
| | | <Modal |
| | | title={dict['model.edit']} |
| | |
| | | if (modaltype === 'columns' || modaltype === 'colspan') { |
| | | this.columnFormRef.handleConfirm().then(res => { |
| | | let fieldrepet = false // 字段重复 |
| | | let labelrepet = false // 提示文字重复 |
| | | let rowspanLabel = '' // 已存在的行合并字段 |
| | | |
| | | _columnlist = _columnlist.filter(item => !item.origin || item.uuid === res.uuid) // 去除初始列 |
| | | _columnlist = _columnlist.map(item => { |
| | | if (item.uuid !== res.uuid && res.field && item.field) { |
| | | if (item.field === res.field) { |
| | | fieldrepet = true |
| | | } else if (item.label === res.label) { |
| | | labelrepet = true |
| | | } else if (res.rowspan === 'true' && item.rowspan === 'true') { |
| | | rowspanLabel = item.label |
| | | } |
| | | } |
| | | |
| | |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['model.field.exist'] + ' !', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (labelrepet) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: this.state.dict['model.name.exist'] + ' !', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (rowspanLabel) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: `已存在行合并字段《${rowspanLabel}》!`, |
| | | duration: 5 |
| | | }) |
| | | return |
| | |
| | | columns.set(item.field, {...item, selected: true, datatype: _datatype}) |
| | | } |
| | | }) |
| | | } else if (type === 'form') { |
| | | if (config.groups.length > 1) { |
| | | config.groups.forEach(group => { |
| | | group.sublist.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | let _datatype = columns.get(item.field).datatype |
| | | columns.set(item.field, {...item, selected: true, datatype: _datatype}) |
| | | } |
| | | }) |
| | | }) |
| | | } else { |
| | | config.fields.forEach(item => { |
| | | if (columns.has(item.field)) { |
| | | let _datatype = columns.get(item.field).datatype |
| | | columns.set(item.field, {...item, selected: true, datatype: _datatype}) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // 显示字段集弹窗 |
| | |
| | | items.push(newcard) |
| | | } |
| | | }) |
| | | config.search = items |
| | | } else if (type === 'columns') { |
| | | config.columns.forEach(item => { |
| | | if (columnsMap.has(item.field)) { |
| | |
| | | items.push(newcard) |
| | | } |
| | | }) |
| | | config.columns = items |
| | | } else if (type === 'fields') { |
| | | config.columns.forEach(item => { |
| | | if (columnsMap.has(item.field)) { |
| | |
| | | items.push(newcard) |
| | | } |
| | | }) |
| | | } else if (type === 'form') { |
| | | if (config.groups.length > 1) { |
| | | config.groups.forEach(group => { |
| | | group.sublist.forEach(item => { |
| | | if (columnsMap.has(item.field)) { |
| | | let cell = columnsMap.get(item.field) |
| | | |
| | | if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加 |
| | | items.push(item) |
| | | } else if (cell.selected) { // 数据类型修改时,重置类型及初始值 |
| | | item.type = cell.type |
| | | item.initval = '' |
| | | items.push(item) |
| | | } |
| | | columnsMap.delete(item.field) |
| | | } else if (!item.origin) { // 过滤示例项 |
| | | items.push(item) |
| | | } |
| | | }) |
| | | group.sublist = items |
| | | }) |
| | | |
| | | let _columns = [...columnsMap.values()] |
| | | |
| | | let _additems = _columns.map(item => { // 循环添加新增字段 |
| | | return { |
| | | uuid: Utils.getuuid(), |
| | | label: item.label, |
| | | field: item.field, |
| | | initval: '', |
| | | type: item.type, |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | dataSource: '', |
| | | orderType: 'asc', |
| | | decimal: item.decimal, |
| | | readonly: 'false', |
| | | required: 'true' |
| | | } |
| | | }) |
| | | config.groups[config.groups.length - 1].sublist = [...config.groups.slice(-1)[0].sublist, ..._additems] |
| | | } else { |
| | | config.fields.forEach(item => { |
| | | if (columnsMap.has(item.field)) { |
| | | let cell = columnsMap.get(item.field) |
| | | |
| | | if (cell.selected && cell.type === item.type) { // 数据选择状态及类型未修改时,直接添加 |
| | | items.push(item) |
| | | } else if (cell.selected) { // 数据类型修改时,重置类型及初始值 |
| | | item.type = cell.type |
| | | item.initval = '' |
| | | items.push(item) |
| | | } |
| | | columnsMap.delete(item.field) |
| | | } else if (!item.origin) { // 过滤示例项 |
| | | items.push(item) |
| | | } |
| | | }) |
| | | |
| | | let _columns = [...columnsMap.values()] |
| | | |
| | | _columns.forEach(item => { // 循环添加新增字段 |
| | | if (item.selected) { |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | label: item.label, |
| | | field: item.field, |
| | | initval: '', |
| | | type: item.type, |
| | | resourceType: '0', |
| | | setAll: 'false', |
| | | options: [], |
| | | dataSource: '', |
| | | decimal: item.decimal, |
| | | orderType: 'asc', |
| | | readonly: 'false', |
| | | required: 'true' |
| | | } |
| | | |
| | | items.push(newcard) |
| | | } |
| | | }) |
| | | |
| | | config.fields = items |
| | | } |
| | | } |
| | | |
| | | let _config = null |
| | | |
| | | if (type === 'search') { |
| | | _config = {...this.props.config, search: items} |
| | | |
| | | this.props.updatefield(_config) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | | message: '操作成功', |
| | | duration: 2 |
| | | }) |
| | | } else if (type === 'columns') { |
| | | _config = {...this.props.config, columns: items} |
| | | |
| | | this.props.updatefield(_config) |
| | | if (type === 'search' || type === 'columns' || type === 'form') { |
| | | this.props.updatefield(config) |
| | | |
| | | notification.success({ |
| | | top: 92, |
| | |
| | | let rules = [] |
| | | if (item.key === 'field' || item.key === 'datefield') { |
| | | rules = [{ |
| | | pattern: openType === 'text' ? formRule.field.multipattern : formRule.field.pattern, |
| | | pattern: (openType === 'text' || openType === 'select') ? formRule.field.multipattern : formRule.field.pattern, |
| | | message: formRule.field.message |
| | | }, { |
| | | max: formRule.field.max, |
| | |
| | | import moment from 'moment' |
| | | |
| | | import Api from '@/api' |
| | | import options from '@/store/options.js' |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | tables: [], // 系统表 |
| | | tableFields: [], // 已选表字段集 |
| | | tableFields: [], // 已选表字段集 |
| | | selectedTables: [], // 已选表 |
| | | searchlist: null, // 搜索条件集 |
| | | visible: false // 模态框控制 |
| | | } |
| | | |
| | | /** |
| | |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 云端数据验证 |
| | | |
| | | Api.getSystemConfig(param).then(res => { |
| | | if (options.cloudServiceApi) { // 且存在云端地址 |
| | | param.rduri = options.cloudServiceApi |
| | | param.userid = sessionStorage.getItem('CloudUserID') || '' |
| | | param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' |
| | | } |
| | | |
| | | Api.getSystemCacheConfig(param).then(res => { |
| | | if (res.status) { |
| | | this.setState({ |
| | | tables: res.data |
| | |
| | | gettableFields = () => { |
| | | let deffers = this.state.selectedTables.map(item => { |
| | | return new Promise(resolve => { |
| | | Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => { |
| | | let param = {func: 'sPC_Get_FieldName', TBName: item.TbName} |
| | | if (options.cloudServiceApi) { // 且存在云端地址 |
| | | param.rduri = options.cloudServiceApi |
| | | param.userid = sessionStorage.getItem('CloudUserID') || '' |
| | | param.LoginUID = sessionStorage.getItem('CloudLoginUID') || '' |
| | | } |
| | | |
| | | Api.getSystemCacheConfig(param).then(res => { |
| | | res.TBName = item.TbName |
| | | resolve(res) |
| | | }) |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Row, Col, Icon, Button, notification, Select, Table, Popconfirm, Typography } from 'antd' |
| | | import { Form, Row, Col, Icon, Button, notification, Select, Popconfirm, Typography } from 'antd' |
| | | import moment from 'moment' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | // import SettingUtils from '../utils.jsx' |
| | | import Api from '@/api' |
| | | import CodeMirror from '@/templates/zshare/codemirror' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const { Paragraph } = Typography |
| | | const EditTable = asyncComponent(() => import('@/templates/zshare/editTable')) |
| | | |
| | | class CustomForm extends Component { |
| | | static propTpyes = { |
| | |
| | | { |
| | | title: 'SQL', |
| | | dataIndex: 'sql', |
| | | width: '70%', |
| | | render: (text) => ( |
| | | <Paragraph copyable ellipsis={{ rows: 5, expandable: true }}>{text}</Paragraph> |
| | | ) |
| | | width: '73%', |
| | | render: (text) => { |
| | | let title = text.match(/^\s*\/\*.+\*\//) |
| | | title = title && title[0] ? title[0] : '' |
| | | text = title ? text.replace(title, '') : text |
| | | |
| | | return ( |
| | | <div> |
| | | {title ? <span style={{color: '#a50'}}>{title}</span> : null} |
| | | <Paragraph copyable ellipsis={{ rows: 4, expandable: true }}>{text}</Paragraph> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | { |
| | | title: '状态', |
| | | dataIndex: 'status', |
| | | width: '10%', |
| | | width: '12%', |
| | | render: (text, record) => record.status === 'false' ? |
| | | ( |
| | | <div> |
| | |
| | | { |
| | | title: '操作', |
| | | align: 'center', |
| | | width: '20%', |
| | | width: '15%', |
| | | dataIndex: 'operation', |
| | | render: (text, record) => |
| | | (<div> |
| | | (<div style={{textAlign: 'center'}}> |
| | | <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span> |
| | | <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span> |
| | | <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span> |
| | | <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><Icon type="swap" /></span> |
| | | <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | handleCancel = () => { |
| | | this.setState({ |
| | |
| | | } |
| | | } |
| | | |
| | | handleUpDown = (record, direction) => { |
| | | let scripts = fromJS(this.state.scripts).toJS() |
| | | let index = 0 |
| | | |
| | | scripts = scripts.filter((item, i) => { |
| | | if (item.uuid === record.uuid) { |
| | | index = i |
| | | } |
| | | |
| | | return item.uuid !== record.uuid |
| | | }) |
| | | if ((index === 0 && direction === 'up') || (index === scripts.length && direction === 'down')) { |
| | | return |
| | | } |
| | | |
| | | if (direction === 'up') { |
| | | scripts.splice(index - 1, 0, record) |
| | | } else { |
| | | scripts.splice(index + 1, 0, record) |
| | | } |
| | | |
| | | changeScripts = (scripts) => { |
| | | this.setState({scripts}) |
| | | this.props.scriptsUpdate(scripts) |
| | | } |
| | |
| | | } |
| | | |
| | | return ( |
| | | <div> |
| | | <Form {...formItemLayout} className="modal-menu-setting-script"> |
| | | <div className="modal-menu-setting-script"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | {setting.tableName ? <Col span={8}> |
| | | <Form.Item label={'表名'} style={{whiteSpace: 'nowrap', margin: 0}}> |
| | |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | <Table |
| | | bordered |
| | | rowKey="uuid" |
| | | className="custom-table" |
| | | dataSource={scripts} |
| | | columns={scriptsColumns} |
| | | pagination={false} |
| | | /> |
| | | <EditTable data={scripts} actions={[]} columns={scriptsColumns} onChange={this.changeScripts}/> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | height: 350px; |
| | | } |
| | | } |
| | | div.ant-typography { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | |
| | | const { data, actions } = this.props |
| | | let columns = fromJS(this.props.columns).toJS() |
| | | |
| | | columns.push({ |
| | | title: eTDict['model.operation'], |
| | | dataIndex: 'operation', |
| | | width: '140px', |
| | | render: (text, record) => { |
| | | const { editingKey } = this.state |
| | | const editable = this.isEditing(record) |
| | | return editable ? ( |
| | | <span style={{textAlign: 'center', display: 'block'}}> |
| | | <EditableContext.Consumer> |
| | | {form => ( |
| | | <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}> |
| | | {eTDict['model.save']} |
| | | </span> |
| | | )} |
| | | </EditableContext.Consumer> |
| | | <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{eTDict['model.cancel']}</span> |
| | | </span> |
| | | ) : ( |
| | | <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')}> |
| | | {!actions || actions.includes('edit') ? <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span> : null} |
| | | {(!actions || actions.includes('del')) && editingKey === '' ? <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | | title={eTDict['model.query.delete']} |
| | | onConfirm={() => this.handleDelete(record.uuid) |
| | | }> |
| | | <span className="danger"><Icon type="delete" /></span> |
| | | </Popconfirm> : null} |
| | | {(!actions || actions.includes('del')) && editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null} |
| | | </div> |
| | | ) |
| | | } |
| | | }) |
| | | if (!actions || actions.length > 0) { |
| | | columns.push({ |
| | | title: eTDict['model.operation'], |
| | | dataIndex: 'operation', |
| | | width: '140px', |
| | | render: (text, record) => { |
| | | const { editingKey } = this.state |
| | | const editable = this.isEditing(record) |
| | | return editable ? ( |
| | | <span style={{textAlign: 'center', display: 'block'}}> |
| | | <EditableContext.Consumer> |
| | | {form => ( |
| | | <span onClick={() => this.save(form, record.uuid)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}> |
| | | {eTDict['model.save']} |
| | | </span> |
| | | )} |
| | | </EditableContext.Consumer> |
| | | <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.uuid)}>{eTDict['model.cancel']}</span> |
| | | </span> |
| | | ) : ( |
| | | <div className={'edit-operation-btn' + (editingKey !== '' ? ' disabled' : '')}> |
| | | {!actions || actions.includes('edit') ? <span className="primary" onClick={() => {editingKey === '' && this.edit(record.uuid)}}><Icon type="edit" /></span> : null} |
| | | {(!actions || actions.includes('del')) && editingKey === '' ? <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | | title={eTDict['model.query.delete']} |
| | | onConfirm={() => this.handleDelete(record.uuid) |
| | | }> |
| | | <span className="danger"><Icon type="delete" /></span> |
| | | </Popconfirm> : null} |
| | | {(!actions || actions.includes('del')) && editingKey !== '' ? <span className="danger"><Icon type="delete" /></span> : null} |
| | | </div> |
| | | ) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | data: data || [], |
| | |
| | | cell: EditableCell |
| | | } |
| | | } |
| | | if (!actions || actions.includes('down') || actions.includes('up')) { |
| | | if (!actions || actions.length === 0 || actions.includes('down') || actions.includes('up')) { |
| | | components.body.row = DragableBodyRow |
| | | } |
| | | |
| | |
| | | key: 'rowspan', |
| | | label: '行合并', |
| | | initVal: card.rowspan || 'false', |
| | | tooltip: '相邻行信息相同时,单元格合并。注:为防止表格信息错乱,行合并只能添加一个字段。', |
| | | tooltip: '相邻行信息相同时,单元格合并。', |
| | | required: false, |
| | | options: [{ |
| | | value: 'true', |
| | |
| | | voucherDetail: [], |
| | | systemScripts: [], |
| | | columnsFields: [], |
| | | unionFields: [], |
| | | uniqueColumns: [ |
| | | { |
| | | title: '名称', |
| | |
| | | _verify.uniques = _verify.uniques || [] |
| | | _verify.contrasts = _verify.contrasts || [] |
| | | _verify.accountdate = _verify.accountdate || 'false' |
| | | _verify.accountfield = _verify.accountfield || '' |
| | | _verify.customverifys = _verify.customverifys || [] |
| | | _verify.billcodes = _verify.billcodes || [] |
| | | _verify.voucher = _verify.voucher || {enabled: false} |
| | |
| | | } |
| | | } |
| | | |
| | | let unionFields = fromJS(_fields).toJS() |
| | | |
| | | if (hasColumn) { |
| | | columns.forEach(_f => { |
| | | if (!_f.field || fieldArr.includes(_f.field.toLowerCase())) return |
| | | |
| | | fieldArr.push(_f.field.toLowerCase()) |
| | | |
| | | unionFields.push(_f) |
| | | _usefulfields.push(_f.field) |
| | | |
| | | if (_f.datatype) { // 自定义字段 |
| | |
| | | col.options = _columns |
| | | } |
| | | return col |
| | | }) |
| | | }), |
| | | unionFields |
| | | }) |
| | | }) |
| | | } |
| | |
| | | { |
| | | obj_name: 'voucherDetail', |
| | | arr_field: 'ModularDetailCode,CodeName,BID,VoucherTypeTwo,IDefine1', |
| | | LText: window.btoa(window.encodeURIComponent(`select distinct ModularDetailCode,ModularDetailCode+ModularDetailName as CodeName,ModularCode as BID, VoucherTypeTwo, IDefine1 from sModularDetail where Deleted=0 and VoucherTypeTwo!='' and Appkey=case when Appkey='' then '' else @Appkey@ end order by ModularDetailCode`)) |
| | | LText: window.btoa(window.encodeURIComponent(`select distinct ModularDetailCode,ModularDetailCode+ModularDetailName as CodeName,ModularCode as BID, VoucherTypeTwo, IDefine1 from sModularDetail where Deleted=0 and VoucherTypeTwo!='' |
| | | and Appkey=@Appkey@ union |
| | | select distinct a.ModularDetailCode,a.ModularDetailCode+ModularDetailName as CodeName,ModularCode as BID, VoucherTypeTwo, IDefine1 |
| | | from (select * from sModularDetail where Deleted=0 and VoucherTypeTwo!='' and Appkey='') a |
| | | left join (select distinct ModularDetailCode from sModularDetail where Deleted=0 and VoucherTypeTwo!='' |
| | | and Appkey=@Appkey@) m on a.ModularDetailCode=m.ModularDetailCode where m.ModularDetailCode is null order by ModularDetailCode` |
| | | )) |
| | | }, |
| | | { |
| | | obj_name: 'noteCodes', |
| | |
| | | |
| | | this.setState({ |
| | | verify: {...verify, [key]: value} |
| | | }) |
| | | } |
| | | |
| | | changeAccField = (val) => { |
| | | const { verify } = this.state |
| | | |
| | | this.setState({ |
| | | verify: {...verify, accountfield: val} |
| | | }) |
| | | } |
| | | |
| | |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } else if (verify.accountdate === 'true' && !verify.accountfield) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '开启账期时,需要选择验证公司!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let _loading = false |
| | |
| | | |
| | | render() { |
| | | const { card } = this.props |
| | | const { verify, fields, uniqueColumns, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes } = this.state |
| | | const { verify, fields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Col> |
| | | {verify.accountdate === 'true' ? <Col span={8}> |
| | | <Form.Item label={'验证公司'} required> |
| | | <Select defaultValue={verify.accountfield || ''} onChange={this.changeAccField}> |
| | | {unionFields.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}> |
| | | {option.label} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={8}> |
| | | <Form.Item label={'失效验证'}> |
| | | <Radio.Group value={verify.invalid} onChange={(e) => {this.onOptionChange(e, 'invalid')}}> |
| | |
| | | |
| | | newsearches[item.key] = item.value ? item.value[0] + ' 00:00:00.000' : '' |
| | | newsearches[item.key + '1'] = item.value ? _endval + ' 00:00:00.000' : '' |
| | | } else if (item.type === 'text') { |
| | | } else if (item.type === 'text' || item.type === 'select') { |
| | | item.key.split(',').forEach(field => { // 综合搜索,所字段拼接 |
| | | newsearches[field] = item.value |
| | | }) |
| | |
| | | if (item.forbid || !item.value || (item.type === 'multiselect' && item.value.length === 0)) return |
| | | |
| | | searchText += (searchText !== '' ? ' AND ' : '') |
| | | if (item.type === 'text') { |
| | | if (item.type === 'text' || item.type === 'select') { // 综合搜索,文本或下拉,所有字段拼接 |
| | | let str = item.match === '=' ? '' : '%' |
| | | let fields = item.key.split(',').map(field => { // 综合搜索,所字段拼接 |
| | | let fields = item.key.split(',').map(field => { |
| | | return field + ' ' + item.match + ' \'' + str + item.value + str + '\'' |
| | | }) |
| | | |
| | | searchText += '(' + fields.join(' OR ') + ')' |
| | | } else if (item.type === 'select') { |
| | | let str = item.match === '=' ? '' : '%' |
| | | |
| | | searchText += item.key + ' ' + item.match + ' \'' + str + item.value + str + '\'' |
| | | } else if (item.type === 'multiselect') { |
| | | |
| | | searchText += `'${item.value}' ` + item.match + ' \'%\'+' + item.key + '+\'%\'' |
| | |
| | | item.value = item.value ? item.value.join(',') : item.value |
| | | |
| | | options.push(item) |
| | | } else if (item.type === 'text') { |
| | | } else if (item.type === 'text' || item.type === 'select') { |
| | | item.key.split(',').forEach(field => { // 综合搜索,所字段拼接 |
| | | let cell = JSON.parse(JSON.stringify(item)) |
| | | cell.key = field |
| | | |
| | | options.push(item) |
| | | options.push(cell) |
| | | }) |
| | | } else { |
| | | options.push(item) |
| | |
| | | options.push({ |
| | | key: item.key + '1', |
| | | value: '0' |
| | | }) |
| | | } else if (search.type === 'text' || search.type === 'select') { |
| | | item.key.split(',').forEach(field => { |
| | | let cell = JSON.parse(JSON.stringify(item)) |
| | | cell.key = field |
| | | |
| | | options.push(cell) |
| | | }) |
| | | } else { |
| | | options.push(item) |
| | |
| | | if (verify.accountdate === 'true') { |
| | | _sql += ` |
| | | /* 账期验证 */ |
| | | exec s_FIBVoucherDateCheck @ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT |
| | | exec s_FIBVoucherDateCheck @OrgCode=${verify.accountfield ? '@' + verify.accountfield : '\'\''}, @ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT |
| | | if @ErrorCode!='' |
| | | GOTO aaa |
| | | ` |