| | |
| | | 'header.form.topPicBottomText': '上图下文', |
| | | 'header.form.leftPicRightText': '左图右文', |
| | | 'model.form.selectItem.error': '下拉选项设置错误!', |
| | | 'header.form.request.method': '请求方式', |
| | | 'header.form.readonly': '只读', |
| | | 'header.form.queryType': '查询类型', |
| | | 'header.form.query': '查询', |
| | |
| | | 'header.form.topPicBottomText': '上图下文', |
| | | 'header.form.leftPicRightText': '左图右文', |
| | | 'model.form.selectItem.error': '下拉选项设置错误!', |
| | | 'header.form.request.method': '请求方式', |
| | | 'header.form.readonly': '只读', |
| | | 'header.form.queryType': '查询类型', |
| | | 'header.form.query': '查询', |
| | |
| | | text: this.props.dict['header.form.requiredOnce'] |
| | | }], |
| | | insertUpdateOptions: [{ |
| | | value: '', |
| | | text: this.props.dict['model.empty'] |
| | | }, { |
| | | value: 'insert', |
| | | text: this.props.dict['header.form.action.insert'] |
| | | }, { |
| | |
| | | _options.push('execMode', 'intertype', 'innerFunc', 'Ot', 'execSuccess', 'execError') |
| | | } |
| | | } |
| | | } else if (_opentype === 'popview' && _opentype === 'tab') { |
| | | } else if (_opentype !== 'popview' && _opentype !== 'tab') { |
| | | if (_intertype === 'outer') { |
| | | _options.push('innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc') |
| | | } else if (_intertype === 'inner') { |
| | |
| | | values.OpenType = values.execMode |
| | | } |
| | | } else if (['pop', 'prompt', 'exec'].includes(values.OpenType) && values.verify) { |
| | | if (values.Ot === 'requiredOnce' && ['notRequired', 'requiredSgl', 'required'].includes(this.props.card.Ot)) { |
| | | values.verify.uniques = [] |
| | | } else if (this.props.card.Ot === 'requiredOnce' && ['notRequired', 'requiredSgl', 'required'].includes(values.Ot)) { |
| | | if ((values.Ot === 'requiredOnce' || this.props.card.Ot === 'requiredOnce') && this.props.card.Ot !== values.Ot) { |
| | | values.verify.uniques = [] |
| | | } |
| | | } |
| | |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import { Icon } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const Container = ({plus, list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => { |
| | | const Container = ({list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => { |
| | | const [cards, setCards] = useState(list) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | |
| | | drop() {} |
| | | }) |
| | | |
| | | const addaction = () => { |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = 'button' |
| | | newcard.sqlType = '' |
| | | newcard.Ot = 'requiredSgl' |
| | | newcard.OpenType = 'prompt' |
| | | newcard.icon = '' |
| | | newcard.class = 'primary' |
| | | newcard.intertype = 'system' |
| | | newcard.method = 'POST' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | | newcard.errorTime = 10 |
| | | newcard.verify = null |
| | | newcard.show = 'icon' |
| | | |
| | | let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0 |
| | | |
| | | const { index: overIndex } = findCard(`${targetId}`) |
| | | let targetIndex = overIndex |
| | | |
| | | targetIndex++ |
| | | |
| | | const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] }) |
| | | |
| | | handleList(_cards, newcard) |
| | | } |
| | | |
| | | return ( |
| | | <div ref={drop} className="ant-row"> |
| | | {cards.map(card => ( |
| | |
| | | doubleClickCard={doubleClickBtn} |
| | | /> |
| | | ))} |
| | | {plus !== 'false' ? <Icon type="plus" title="添加按钮" onClick={addaction}/> : null} |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | class ActionComponent extends Component { |
| | | static propTpyes = { |
| | | type: PropTypes.string, // 菜单类型,主表或子表 |
| | | plus: PropTypes.any, // 是否存在添加按钮,值为false时隐藏 |
| | | config: PropTypes.object, // 菜单配置信息 |
| | | setSubConfig: PropTypes.func, // 设置子配置信息 |
| | | updateaction: PropTypes.func // 菜单配置更新 |
| | |
| | | <p>{this.state.dict['model.tooltip.func.outface']}</p> |
| | | </div> |
| | | |
| | | let menulist = menu.fstMenuList ? menu.fstMenuList : [] |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let modules = this.getModules(menu.components, config.uuid) |
| | | |
| | | this.setState({ |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { config, plus } = this.props |
| | | const { config } = this.props |
| | | const { actionlist, visible, card, dict, profVisible } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-action-list"> |
| | | <div className={'model-menu-action-list length' + actionlist.length}> |
| | | <DragElement |
| | | plus={plus} |
| | | list={actionlist} |
| | | handleList={this.handleList} |
| | | handleMenu={this.handleAction} |
| | |
| | | <p>{this.state.dict['model.tooltip.func.outface']}</p> |
| | | </div> |
| | | |
| | | let menulist = [] |
| | | if (menu.fstMenuList) { |
| | | let trees = fromJS(menu.fstMenuList).toJS() |
| | | |
| | | menulist = trees.map(fst => { |
| | | fst.value = fst.MenuID |
| | | fst.label = fst.MenuName |
| | | fst.isLeaf = false |
| | | fst.children = fst.children.map(snd => { |
| | | snd.value = snd.MenuID |
| | | snd.label = snd.MenuName |
| | | |
| | | snd.children = snd.children.map(thd => { |
| | | thd.value = thd.MenuID |
| | | thd.label = thd.MenuName |
| | | thd.disabled = thd.MenuID === menu.MenuID |
| | | return thd |
| | | }) |
| | | return snd |
| | | }) |
| | | return fst |
| | | }) |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let modules = this.getModules(menu.components, cards.uuid) |
| | |
| | | newcard.icon = '' |
| | | newcard.class = 'primary' |
| | | newcard.intertype = 'system' |
| | | newcard.method = 'POST' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | |
| | | newcard.icon = '' |
| | | newcard.class = 'primary' |
| | | newcard.intertype = 'system' |
| | | newcard.method = 'POST' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | |
| | | /** |
| | | * @description 获取图表视图配置表单 |
| | | * @param {object} card // 图表对象 |
| | | * @param {Array} columns // 显示列 |
| | | * @param {Array} MenuType // 菜单类型 |
| | | */ |
| | | export function getBaseForm (card, MenuType) { |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | |
| | | required: false, |
| | | forbid: MenuType === 'billPrint', |
| | | options: roleList |
| | | }, |
| | | { |
| | | type: 'cascader', |
| | | key: 'linkmenu', |
| | | label: '关联菜单', |
| | | initVal: card.linkmenu || [], |
| | | tooltip: '在使用柱形图且未启用自定义设置时有效。', |
| | | required: false, |
| | | forbid: MenuType === 'billPrint', |
| | | options: menulist |
| | | } |
| | | ] |
| | | } |
| | |
| | | newcard.sysInterface = card.setting.sysInterface || '' |
| | | newcard.outerFunc = card.setting.outerFunc || '' |
| | | newcard.interface = card.setting.interface || '' |
| | | newcard.method = 'POST' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
| | |
| | | </Popover> |
| | | {menu && menu.MenuType !== 'billPrint' ? <ActionComponent |
| | | type="chart" |
| | | plus="false" |
| | | config={card} |
| | | updateaction={this.updateComponent} |
| | | /> : null} |
| | |
| | | /** |
| | | * @description 获取图表视图配置表单 |
| | | * @param {object} card // 图表对象 |
| | | * @param {Array} columns // 显示列 |
| | | * @param {Array} MenuType // 菜单类型 |
| | | */ |
| | | export function getBaseForm (card, MenuType, fstMenuList = []) { |
| | | export function getBaseForm (card, MenuType) { |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | |
| | | tooltip: '双击饼图,会打开关联的菜单。', |
| | | required: false, |
| | | forbid: MenuType === 'billPrint', |
| | | options: fstMenuList |
| | | options: menulist |
| | | } |
| | | ] |
| | | } |
| | |
| | | |
| | | class LineChartDrawerForm extends Component { |
| | | static propTpyes = { |
| | | menu: PropTypes.any, |
| | | MenuType: PropTypes.any, |
| | | dict: PropTypes.object, |
| | | plot: PropTypes.object, |
| | | config: PropTypes.object, |
| | |
| | | } |
| | | |
| | | showDrawer = () => { |
| | | const { config, menu } = this.props |
| | | const { config, MenuType } = this.props |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | view: 'normal', |
| | | plot: fromJS(config.plot).toJS(), |
| | | baseFormlist: getBaseForm(config.plot, menu.MenuType, menu.fstMenuList), |
| | | baseFormlist: getBaseForm(config.plot, MenuType), |
| | | formlist: getOptionForm(config.plot, config.columns) |
| | | }) |
| | | } |
| | |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | <ChartCompileForm config={card} menu={menu} dict={this.state.dict} plotchange={this.updateComponent}/> |
| | | {menu ? <ChartCompileForm config={card} MenuType={menu.MenuType} dict={this.state.dict} plotchange={this.updateComponent}/> : null} |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | <SettingComponent config={card} updateConfig={this.updateComponent}/> |
| | |
| | | newcard.icon = '' |
| | | newcard.class = 'primary' |
| | | newcard.intertype = 'system' |
| | | newcard.method = 'POST' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.popClose = 'never' |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, InputNumber, Select, Radio, Tooltip, Icon } from 'antd' |
| | | import { formRule } from '@/utils/option.js' |
| | | import TransferForm from '@/templates/zshare/transferform' |
| | | import './index.scss' |
| | | |
| | | class MainSearch extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | columns: PropTypes.array, |
| | | card: PropTypes.any, |
| | | inputSubmit: PropTypes.any // 回车提交事件 |
| | | } |
| | | |
| | | componentDidMount () { |
| | | try { |
| | | let _form = document.getElementById('label') |
| | | if (_form && _form.select) { |
| | | _form.select() |
| | | } |
| | | } catch { |
| | | console.warn('表单focus失败!') |
| | | } |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | let targetKeys = this.refs['column-transfer'].state.targetKeys |
| | | |
| | | delete values.type // 删除type,此处值为'合并列'文字 |
| | | |
| | | let subfield = [] // 用于查看合并列字段 |
| | | this.props.columns.forEach(col => { |
| | | if (col.field && targetKeys.includes(col.uuid)) { |
| | | subfield.push(col.field) |
| | | } |
| | | }) |
| | | subfield = subfield.join(', ') |
| | | |
| | | let _card = {...this.props.card, ...values, sublist: targetKeys, subfield: subfield} |
| | | |
| | | delete _card.focus |
| | | |
| | | resolve(_card) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 6 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 18 } |
| | | } |
| | | } |
| | | return ( |
| | | <Form {...formItemLayout} className="commontable-cospan-column-form" id="columncolspan"> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['model.name']}> |
| | | {getFieldDecorator('label', { |
| | | initialValue: card.label, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + this.props.dict['model.name'] + '!' |
| | | }, |
| | | { |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['model.form.type']}> |
| | | {getFieldDecorator('type', { |
| | | initialValue: this.props.dict['model.form.colspan'], |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + this.props.dict['model.form.type'] + '!' |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={true}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['model.form.align']}> |
| | | {getFieldDecorator('Align', { |
| | | initialValue: card.Align, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + this.props.dict['model.form.align'] + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | getPopupContainer={() => document.getElementById('columncolspan')} |
| | | > |
| | | <Select.Option value="left">{this.props.dict['model.form.alignLeft']}</Select.Option> |
| | | <Select.Option value="right">{this.props.dict['model.form.alignRight']}</Select.Option> |
| | | <Select.Option value="center">{this.props.dict['model.form.alignCenter']}</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['model.form.columnWidth']}> |
| | | {getFieldDecorator('Width', { |
| | | initialValue: card.Width, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + this.props.dict['model.form.columnWidth'] + '!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={1000} precision={0} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择显示分组,表格会展开添加分组的子列,此时排列方式会失效。"> |
| | | <Icon type="question-circle" /> |
| | | 显示分组 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('unfold', { |
| | | initialValue: card.unfold || 'false' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">{this.props.dict['model.true']}</Radio> |
| | | <Radio value="false">{this.props.dict['model.false']}</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['model.hidden']}> |
| | | {getFieldDecorator('Hide', { |
| | | initialValue: card.Hide || 'false', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + this.props.dict['model.hidden'] + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">{this.props.dict['model.true']}</Radio> |
| | | <Radio value="false">{this.props.dict['model.false']}</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={this.props.dict['header.form.order']}> |
| | | {getFieldDecorator('order', { |
| | | initialValue: card.order, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + this.props.dict['header.form.order'] + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | getPopupContainer={() => document.getElementById('columncolspan')} |
| | | > |
| | | <Select.Option value="vertical">{this.props.dict['header.form.vertical']}</Select.Option> |
| | | <Select.Option value="horizontal">{this.props.dict['header.form.horizontal']}</Select.Option> |
| | | <Select.Option value="vertical2">{this.props.dict['header.form.vertical2']}</Select.Option> |
| | | <Select.Option value="topPicBottomText">{this.props.dict['header.form.topPicBottomText']}</Select.Option> |
| | | <Select.Option value="leftPicRightText">{this.props.dict['header.form.leftPicRightText']}</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <TransferForm columns={this.props.columns} ref="column-transfer" selected={card.sublist}/> |
| | | </Col> |
| | | </Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(MainSearch) |
New file |
| | |
| | | .commontable-cospan-column-form { |
| | | min-height: 190px; |
| | | .ant-form-item { |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon, Cascader } from 'antd' |
| | | |
| | | import { formRule } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | const columnTypeOptions = { |
| | | text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'perspective', 'rowspan'], |
| | | number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum'], |
| | | link: ['label', 'field', 'type', 'nameField', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist'], |
| | | textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'fieldlength', 'blacklist'], |
| | | picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight'] |
| | | } |
| | | |
| | | class MainSearch extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | formlist: PropTypes.any, |
| | | card: PropTypes.any, |
| | | inputSubmit: PropTypes.any // 回车提交事件 |
| | | } |
| | | |
| | | state = { |
| | | formlist: null, |
| | | type: '', |
| | | menulist: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | let _menulist = this.props.formlist.filter(form => form.key === 'linkmenu')[0] || '' |
| | | |
| | | let _options = JSON.parse(JSON.stringify(columnTypeOptions[card.type])) |
| | | if (card.type === 'text' || card.type === 'number') { |
| | | if (card.perspective !== 'linkurl') { |
| | | _options.push('linkmenu') |
| | | } else { |
| | | _options.push('linkurl') |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | type: card.type, |
| | | menulist: _menulist.options || [], |
| | | formlist: this.props.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 初次添加的显示列元素,聚焦提示文字 |
| | | */ |
| | | componentDidMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.focus) { |
| | | try { |
| | | let _form = document.getElementById('label') |
| | | _form.select() |
| | | } catch { |
| | | console.warn('表单focus失败!') |
| | | } |
| | | } |
| | | } |
| | | |
| | | typeChange = (key, value) => { |
| | | const { card } = this.props |
| | | if (key === 'type') { |
| | | let _options = JSON.parse(JSON.stringify(columnTypeOptions[value])) |
| | | |
| | | if (card.type === 'text' || card.type === 'number') { |
| | | if (card.perspective !== 'linkurl') { |
| | | _options.push('linkmenu') |
| | | } else { |
| | | _options.push('linkurl') |
| | | } |
| | | } |
| | | |
| | | let fieldlength = 50 |
| | | |
| | | if (value !== 'text') { |
| | | fieldlength = 512 |
| | | } |
| | | |
| | | this.setState({ |
| | | type: value, |
| | | formlist: this.props.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | | }) |
| | | }, () => { |
| | | if (this.props.form.getFieldValue('fieldlength') !== undefined) { |
| | | this.props.form.setFieldsValue({fieldlength: fieldlength}) |
| | | } |
| | | }) |
| | | } else if (key === 'format' && value === 'percent') { |
| | | this.props.form.setFieldsValue({postfix: '%'}) |
| | | } |
| | | } |
| | | |
| | | changeRadio = (key, value) => { |
| | | if (key === 'perspective') { |
| | | let _options = JSON.parse(JSON.stringify(columnTypeOptions[this.state.type])) |
| | | |
| | | if (value !== 'linkurl') { |
| | | _options.push('linkmenu') |
| | | } else { |
| | | _options.push('linkurl') |
| | | } |
| | | |
| | | this.setState({ |
| | | formlist: this.props.formlist.map(item => { |
| | | item.hidden = !_options.includes(item.key) |
| | | |
| | | return item |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | getFields() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const fields = [] |
| | | this.state.formlist.forEach((item, index) => { |
| | | if (item.hidden) return |
| | | |
| | | if (item.type === 'text') { // 文本搜索 |
| | | let rules = [] |
| | | if (item.key === 'field' || item.key === 'nameField') { |
| | | rules = [{ |
| | | pattern: formRule.field.pattern, |
| | | message: formRule.field.message |
| | | }, { |
| | | max: formRule.field.max, |
| | | message: formRule.field.maxMessage |
| | | }] |
| | | } else if (item.key !== 'linkurl') { |
| | | rules = [{ |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | }] |
| | | } |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | }, |
| | | ...rules |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'number') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | } |
| | | ] |
| | | })(item.unlimit ? <InputNumber /> : |
| | | <InputNumber min={item.min} max={item.max} precision={item.decimal} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉搜索 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onChange={(value) => {this.typeChange(item.key, value)}} |
| | | getPopupContainer={() => document.getElementById('columnwinter')} |
| | | > |
| | | {item.options.map((option, index) => |
| | | <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}> |
| | | {option.text} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'radio') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}> |
| | | { |
| | | item.options.map(option => { |
| | | return ( |
| | | <Radio key={option.value} value={option.value}>{option.text}</Radio> |
| | | ) |
| | | }) |
| | | } |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'multiselect') { // 多选 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || [] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | mode="multiple" |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {item.options.map((option, i) => |
| | | <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'cascader') { // 多选 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || [] |
| | | })( |
| | | <Cascader |
| | | options={this.state.menulist} |
| | | placeholder="" |
| | | getPopupContainer={() => document.getElementById('columnwinter')} |
| | | /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } |
| | | }) |
| | | return fields |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | values.uuid = this.props.card.uuid |
| | | values.marks = this.props.card.marks || '' |
| | | |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 6 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 18 } |
| | | } |
| | | } |
| | | return ( |
| | | <Form {...formItemLayout} className="commontable-column-form" id="columnwinter"> |
| | | <Row gutter={24}>{this.getFields()}</Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(MainSearch) |
New file |
| | |
| | | .commontable-column-form { |
| | | min-height: 190px; |
| | | .ant-form-item { |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | position: relative; |
| | | left: -3px; |
| | | } |
| | | .ant-cascader-menus { |
| | | padding: 5px 0px; |
| | | .ant-cascader-menu:last-child { |
| | | padding-right: 3px; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React from 'react' |
| | | import { useDrag, useDrop } from 'react-dnd' |
| | | import { Icon, Popover } from 'antd' |
| | | import './index.scss' |
| | | |
| | | const Card = ({ id, card, showfield, moveCard, findCard, editCard, delCard, markCard }) => { |
| | | const originalIndex = findCard(id).index |
| | | const [{ isDragging }, drag] = useDrag({ |
| | | item: { type: 'columns', id, originalIndex }, |
| | | collect: monitor => ({ |
| | | isDragging: monitor.isDragging(), |
| | | }), |
| | | }) |
| | | const [, drop] = useDrop({ |
| | | accept: 'columns', |
| | | canDrop: () => true, |
| | | drop: (item) => { |
| | | const { id: draggedId, originalIndex } = item |
| | | |
| | | if (originalIndex === undefined) { |
| | | item.dropTargetId = id |
| | | } else if (draggedId && draggedId !== id) { |
| | | const { index: overIndex } = findCard(id) |
| | | moveCard(draggedId, overIndex) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | const opacity = isDragging ? 0 : 1 |
| | | |
| | | return ( |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} /> |
| | | <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} /> |
| | | {['text', 'number'].includes(card.type) && !card.origin ? <Icon className="profile" title="mark" type="ant-design" onClick={() => markCard(id)} /> : null} |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="page-card" style={{ flex: card.Width, opacity: opacity}}> |
| | | <div ref={node => drag(drop(node))}> |
| | | <span className="ant-table-header-column"> |
| | | <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}> |
| | | <span className="ant-table-column-title">{card.label}</span> |
| | | {card.IsSort === 'true' ? |
| | | <span className="ant-table-column-sorter"> |
| | | <Icon type="caret-up" /> |
| | | <Icon type="caret-down" /> |
| | | </span> : null |
| | | } |
| | | </div> |
| | | {showfield ? |
| | | <div className="ant-table-column-fields"> |
| | | <span className="ant-table-column-title">{card.type === 'colspan' ? card.subfield : card.field}</span> |
| | | </div> : null |
| | | } |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </Popover> |
| | | ) |
| | | } |
| | | export default Card |
New file |
| | |
| | | import React, { useState } from 'react' |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import { Icon, Popover } from 'antd' |
| | | import Utils from '@/utils/utils.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const Container = ({list, setting, gridBtn, showfield, placeholder, handleList, handleMenu, handleGridBtn, deleteMenu, markMenu }) => { |
| | | const [cards, setCards] = useState(list) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | | const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) |
| | | handleList(_cards) |
| | | } |
| | | |
| | | if (!is(fromJS(cards), fromJS(list))) { |
| | | setCards(list) |
| | | } |
| | | |
| | | const findCard = id => { |
| | | const card = cards.filter(c => `${c.uuid}` === id)[0] |
| | | return { |
| | | card, |
| | | index: cards.indexOf(card), |
| | | } |
| | | } |
| | | |
| | | const editCard = id => { |
| | | const { card } = findCard(id) |
| | | delete card.focus // 兼容早期的合并列 |
| | | |
| | | handleMenu(card) |
| | | } |
| | | |
| | | |
| | | const delCard = id => { |
| | | const { card } = findCard(id) |
| | | deleteMenu(card) |
| | | } |
| | | |
| | | const markCard = id => { |
| | | const { card } = findCard(id) |
| | | markMenu(card) |
| | | } |
| | | |
| | | const [, drop] = useDrop({ |
| | | accept: 'columns', |
| | | drop(item) { |
| | | if (item.hasOwnProperty('originalIndex')) { |
| | | return |
| | | } |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.Align = 'left' |
| | | newcard.label = 'label' |
| | | newcard.field = '' |
| | | newcard.Hide = 'false' |
| | | newcard.contrastType = 'static' |
| | | newcard.IsSort = 'true' |
| | | newcard.type = item.subType |
| | | newcard.Width = 120 |
| | | if (item.subType === 'colspan') { |
| | | newcard.sublist = [] |
| | | newcard.subfield = [] |
| | | newcard.IsSort = 'false' |
| | | newcard.order = 'vertical' |
| | | } |
| | | |
| | | let targetId = '' |
| | | |
| | | if (item.dropTargetId) { |
| | | targetId = item.dropTargetId |
| | | delete item.dropTargetId |
| | | } else if (cards.length > 0) { |
| | | targetId = cards[cards.length - 1].uuid |
| | | } |
| | | |
| | | const { index: overIndex } = findCard(`${targetId}`) |
| | | const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | |
| | | handleList(_cards, newcard) |
| | | } |
| | | }) |
| | | |
| | | let columns = [] |
| | | let _colCards = [] |
| | | |
| | | // 过滤合并列 |
| | | let _hideCol = [] |
| | | |
| | | if (!showfield) { |
| | | cards.forEach(col => { |
| | | if (col.type === 'colspan' && col.sublist) { |
| | | _hideCol.push(...col.sublist) |
| | | } |
| | | }) |
| | | } |
| | | cards.forEach(col => { |
| | | if (_hideCol.includes(col.uuid)) return |
| | | |
| | | _colCards.push(col) |
| | | }) |
| | | |
| | | // 显示列分行 |
| | | if (_colCards.length > 10) { |
| | | let number = Math.ceil(_colCards.length / Math.ceil(_colCards.length / 10)) |
| | | for (let i = 0, len = _colCards.length; i < len; i += number) { |
| | | columns.push(_colCards.slice(i, i + number)) |
| | | } |
| | | } else { |
| | | columns.push(_colCards) |
| | | } |
| | | |
| | | return ( |
| | | <div ref={drop} className="ant-row"> |
| | | {columns.map((column, i) => ( |
| | | <div key={i} className="column-box"> |
| | | {/* 多选 */} |
| | | {i === 0 && column.length > 0 && setting.tableType === 'checkbox' ? |
| | | <div className="page-card" style={{flex: 60}}> |
| | | <span className="ant-checkbox-inner"></span> |
| | | </div> : null |
| | | } |
| | | {/* 单选 */} |
| | | {i === 0 && column.length > 0 && setting.tableType === 'radio' ? |
| | | <div className="page-card" style={{flex: 60}}></div> : null |
| | | } |
| | | {column.map(card => ( |
| | | <Card |
| | | key={card.uuid} |
| | | id={card.uuid} |
| | | card={card} |
| | | showfield={showfield} |
| | | moveCard={moveCard} |
| | | editCard={editCard} |
| | | delCard={delCard} |
| | | markCard={markCard} |
| | | findCard={findCard} |
| | | /> |
| | | ))} |
| | | {i === (columns.length - 1) && gridBtn && gridBtn.display ? |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="edit" type="edit" onClick={handleGridBtn}/> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="page-card" style={{flex: gridBtn.Width}}> |
| | | <div style={{cursor: 'default'}}> |
| | | <span className="ant-table-header-column"> |
| | | <div className="ant-table-column-sorters" title={gridBtn.label} style={{textAlign: gridBtn.Align}}> |
| | | <span className="ant-table-column-title">{gridBtn.label}</span> |
| | | </div> |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </Popover> : null |
| | | } |
| | | </div> |
| | | ))} |
| | | |
| | | {cards.length === 0 ? |
| | | <div className="common-drawarea-placeholder"> |
| | | {placeholder} |
| | | </div> : null |
| | | } |
| | | </div> |
| | | ) |
| | | } |
| | | export default Container |
New file |
| | |
| | | .common-drawarea-placeholder { |
| | | width: 100%; |
| | | line-height: 65px; |
| | | text-align: center; |
| | | color: #bcbcbc; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Select, InputNumber, Radio } from 'antd' |
| | | import { formRule } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class MainSearch extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | card: PropTypes.any, |
| | | inputSubmit: PropTypes.any // 回车提交事件 |
| | | } |
| | | |
| | | state = { |
| | | formlist: [ |
| | | { |
| | | type: 'text', |
| | | key: 'label', |
| | | label: this.props.dict['model.name'], |
| | | initVal: this.props.card.label, |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'select', |
| | | key: 'Align', |
| | | label: this.props.dict['model.form.align'], |
| | | initVal: this.props.card.Align, |
| | | required: true, |
| | | options: [{ |
| | | MenuID: 'left', |
| | | text: this.props.dict['model.form.alignLeft'] |
| | | }, { |
| | | MenuID: 'right', |
| | | text: this.props.dict['model.form.alignRight'] |
| | | }, { |
| | | MenuID: 'center', |
| | | text: this.props.dict['model.form.alignCenter'] |
| | | }] |
| | | }, |
| | | { |
| | | type: 'number', |
| | | key: 'Width', |
| | | decimal: 0, |
| | | label: this.props.dict['model.form.columnWidth'], |
| | | initVal: this.props.card.Width, |
| | | required: true |
| | | }, |
| | | // { |
| | | // type: 'select', |
| | | // key: 'style', |
| | | // label: this.props.dict['model.form.style'], |
| | | // initVal: this.props.card.style, |
| | | // required: true, |
| | | // options: [{ |
| | | // MenuID: 'button', |
| | | // text: this.props.dict['header.form.button'] |
| | | // }, { |
| | | // MenuID: 'text', |
| | | // text: this.props.dict['model.form.href'] |
| | | // }] |
| | | // }, |
| | | // { |
| | | // type: 'select', |
| | | // key: 'show', |
| | | // label: this.props.dict['header.form.order'], |
| | | // initVal: this.props.card.show, |
| | | // required: true, |
| | | // options: [{ |
| | | // MenuID: 'horizontal', |
| | | // text: this.props.dict['header.form.horizontal'] |
| | | // }, { |
| | | // MenuID: 'vertical', |
| | | // text: this.props.dict['header.form.vertical'] |
| | | // }] |
| | | // } |
| | | ] |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | getFields() { |
| | | const { getFieldDecorator } = this.props.form |
| | | const fields = [] |
| | | this.state.formlist.forEach((item, index) => { |
| | | if (item.type === 'text') { // 文本搜索 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | }, |
| | | { |
| | | max: formRule.input.max, |
| | | message: formRule.input.message |
| | | } |
| | | ] |
| | | })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'number') { // 文本搜索 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.input'] + item.label + '!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={1000} precision={item.decimal} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'select') { // 下拉搜索 |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | getPopupContainer={() => document.getElementById('gridbtncolumnwinter')} |
| | | > |
| | | {item.options.map(option => |
| | | <Select.Option id={option.MenuID} title={option.text} key={option.MenuID} value={option.MenuID}> |
| | | {option.text} |
| | | </Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'radio') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.label}> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal, |
| | | rules: [ |
| | | { |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | } |
| | | ] |
| | | })( |
| | | <Radio.Group> |
| | | { |
| | | item.options.map(option => { |
| | | return ( |
| | | <Radio key={option.MenuID} value={option.MenuID}>{option.text}</Radio> |
| | | ) |
| | | }) |
| | | } |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } |
| | | }) |
| | | return fields |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve({...this.props.card, ...values}) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 6 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 18 } |
| | | } |
| | | } |
| | | return ( |
| | | <Form {...formItemLayout} className="commontable-gridbtn-column-form" id="gridbtncolumnwinter"> |
| | | <Row gutter={24}>{this.getFields()}</Row> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(MainSearch) |
New file |
| | |
| | | .commontable-gridbtn-column-form { |
| | | min-height: 190px; |
| | | .ant-form-item { |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal, notification, Switch, message, Spin } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getColumnForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import ColumnForm from './columnform' |
| | | import ColspanForm from './colspanform' |
| | | import GridBtnForm from './gridbtnform' |
| | | import DragElement from './dragcolumn' |
| | | import MarkColumn from './markcolumn' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | class ColumnComponent extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 配置信息 |
| | | updatecolumn: PropTypes.func // 更新 |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | columnlist: null, // 显示列 |
| | | loading: false, // 查询显示列联动菜单 |
| | | showField: false, // 显示列字段 |
| | | modaltype: '', // 模态框控制 |
| | | card: null // 编辑中元素 |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列初始化 |
| | | */ |
| | | UNSAFE_componentWillMount () { |
| | | this.setState({ |
| | | columnlist: fromJS(this.props.config.cols).toJS() |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 监听到显示列复制时,触发显示列编辑 |
| | | */ |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | const { config } = this.props |
| | | const { columnlist } = this.state |
| | | |
| | | if (!is(fromJS(nextProps.config.cols), fromJS(config.cols)) && !is(fromJS(nextProps.config.cols), fromJS(columnlist))) { |
| | | this.setState({columnlist: fromJS(nextProps.config.cols).toJS()}) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列顺序调整,或拖拽添加 |
| | | */ |
| | | handleList = (list, card) => { |
| | | const { config } = this.props |
| | | |
| | | if (card) { |
| | | this.setState({columnlist: list}) |
| | | this.handleColumn(card) |
| | | } else { |
| | | this.setState({columnlist: list}, ()=> { |
| | | this.props.updatecolumn({...config, cols: list}) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列与合并列编辑,获取表单信息 |
| | | */ |
| | | handleColumn = (card) => { |
| | | if (card.type !== 'colspan') { |
| | | let menulist = sessionStorage.getItem('fstMenuList') |
| | | if (menulist) { |
| | | try { |
| | | menulist = JSON.parse(menulist) |
| | | } catch { |
| | | menulist = [] |
| | | } |
| | | } else { |
| | | menulist = [] |
| | | } |
| | | |
| | | this.setState({ |
| | | modaltype: 'cols', |
| | | card: card, |
| | | formlist: getColumnForm(card, menulist) |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | modaltype: 'colspan', |
| | | card: card |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 设置标志 |
| | | */ |
| | | markElement = (card) => { |
| | | this.setState({ |
| | | modaltype: 'mark', |
| | | card: card |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 操作列编辑 |
| | | */ |
| | | handleGridBtn = () => { |
| | | this.setState({ |
| | | modaltype: 'gridbtn' |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 取消保存,如果元素为新添元素,则从序列中删除 |
| | | */ |
| | | editModalCancel = () => { |
| | | const { card } = this.state |
| | | |
| | | if (card && card.focus) { |
| | | let _columnlist = fromJS(this.state.columnlist).toJS() |
| | | |
| | | _columnlist = _columnlist.filter(item => item.uuid !== card.uuid) |
| | | |
| | | this.setState({ |
| | | card: null, |
| | | modaltype: '', |
| | | columnlist: _columnlist |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | card: null, |
| | | modaltype: '' |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 搜索修改后提交保存 |
| | | * 1、去除系统默认显示列 |
| | | * 2、字段及提示文字重复校验 |
| | | * 3、更新下拉菜单可选集合 |
| | | * 4、下拉菜单数据源语法验证 |
| | | */ |
| | | handleSubmit = () => { |
| | | const { config } = this.props |
| | | const { modaltype, card } = this.state |
| | | |
| | | let _columnlist = fromJS(this.state.columnlist).toJS() |
| | | |
| | | if (modaltype === 'cols' || 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 |
| | | } |
| | | } |
| | | |
| | | if (item.uuid === res.uuid) { |
| | | return res |
| | | } else { |
| | | return item |
| | | } |
| | | }) |
| | | |
| | | if (fieldrepet) { |
| | | 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 |
| | | } |
| | | |
| | | if (!card.focus && (card.type !== res.type || (res.field && card.field !== res.field))) { |
| | | let refers = [] |
| | | _columnlist.forEach(column => { |
| | | if (column.marks && column.marks.filter(mark => mark.field === card.field || mark.contrastField === card.field).length > 0) { |
| | | refers.push(column.label) |
| | | } |
| | | if (column.type === 'colspan') { |
| | | let _length = column.sublist.length |
| | | column.sublist = column.sublist.filter(cell => cell !== card.uuid) |
| | | |
| | | if (column.sublist.length < _length) { |
| | | let subfield = [] // 合并列字段 |
| | | _columnlist.forEach(col => { |
| | | if (col.field && column.sublist.includes(col.uuid)) { |
| | | subfield.push(col.field) |
| | | } |
| | | }) |
| | | column.subfield = subfield.join(', ') |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (refers.length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '显示列《' + refers.join('、') + '》标记中含有该字段,此次修改会导致标记失效,请修改相应的标记设置!', |
| | | duration: 5 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | card: null, |
| | | columnlist: _columnlist, |
| | | modaltype: '' |
| | | }, ()=> { |
| | | this.props.updatecolumn({...config, cols: _columnlist}) |
| | | }) |
| | | }) |
| | | } else if (modaltype === 'gridbtn') { |
| | | this.gridBtnFormRef.handleConfirm().then(res => { |
| | | this.setState({ |
| | | modaltype: '' |
| | | }) |
| | | |
| | | this.props.updatecolumn({...config, gridBtn: res}) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列删除 |
| | | */ |
| | | deleteElement = (card) => { |
| | | const { config } = this.props |
| | | const { dict } = this.state |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: dict['model.confirm'] + dict['model.delete'] + ` - ${card.label} ?`, |
| | | onOk() { |
| | | let _columnlist = fromJS(_this.state.columnlist).toJS() |
| | | |
| | | _columnlist = _columnlist.filter(item => item.uuid !== card.uuid) |
| | | |
| | | if (card.field) { |
| | | let refers = [] |
| | | _columnlist.forEach(column => { |
| | | if (column.marks && column.marks.filter(mark => mark.field === card.field || mark.contrastField === card.field).length > 0) { |
| | | refers.push(column.label) |
| | | } |
| | | if (column.type === 'colspan') { |
| | | let _length = column.sublist.length |
| | | column.sublist = column.sublist.filter(cell => cell !== card.uuid) |
| | | |
| | | if (column.sublist.length < _length) { |
| | | let subfield = [] // 合并列字段 |
| | | _columnlist.forEach(col => { |
| | | if (col.field && column.sublist.includes(col.uuid)) { |
| | | subfield.push(col.field) |
| | | } |
| | | }) |
| | | column.subfield = subfield.join(', ') |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (refers.length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '显示列《' + refers.join('、') + '》标记中含有该字段,删除会导致标记失效,请修改相应的标记设置!', |
| | | duration: 5 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | _this.setState({ |
| | | columnlist: _columnlist |
| | | }, ()=> { |
| | | _this.props.updatecolumn({...config, cols: _columnlist}) |
| | | }) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列复制 |
| | | */ |
| | | copycolumn = () => { |
| | | const { columnlist } = this.state |
| | | |
| | | let oInput = document.createElement('input') |
| | | let val = { |
| | | copyType: 'columns', |
| | | columns: columnlist |
| | | } |
| | | |
| | | 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) |
| | | } |
| | | |
| | | /** |
| | | * @description 显示列字段名显示或隐藏控制 |
| | | */ |
| | | onFieldChange = () => { |
| | | const { showField, columnlist } = this.state |
| | | |
| | | if (!showField) { |
| | | let fields = [] |
| | | columnlist.forEach(col => { |
| | | if (col.field) { |
| | | fields.push(col.field) |
| | | } |
| | | }) |
| | | |
| | | fields = fields.join(',') |
| | | |
| | | let textArea = document.createElement('textarea') |
| | | textArea.value = fields |
| | | document.body.appendChild(textArea) |
| | | textArea.select() |
| | | |
| | | try { |
| | | document.execCommand('copy') |
| | | document.body.removeChild(textArea) |
| | | } catch (err) { |
| | | document.body.removeChild(textArea) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | showField: !showField |
| | | }) |
| | | } |
| | | |
| | | markSubmit = () => { |
| | | const { config } = this.props |
| | | const { card } = this.state |
| | | let _columnlist = fromJS(this.state.columnlist).toJS() |
| | | let _marks = this.refs.markRef.state.marks |
| | | |
| | | if (_marks.length === 0) { |
| | | _marks = '' |
| | | } |
| | | |
| | | _columnlist = _columnlist.map(item => { |
| | | if (item.uuid === card.uuid) { |
| | | item.marks = _marks |
| | | } |
| | | |
| | | return item |
| | | }) |
| | | |
| | | this.setState({ |
| | | card: null, |
| | | columnlist: _columnlist, |
| | | modaltype: '' |
| | | }, ()=> { |
| | | this.props.updatecolumn({...config, cols: _columnlist}) |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { config } = this.props |
| | | const { modaltype, columnlist, dict, card } = this.state |
| | | |
| | | return ( |
| | | <div className="model-custom-table-column-list"> |
| | | {columnlist && columnlist.length > 0 ? |
| | | <Icon className="column-copy" title="copy" type="copy" onClick={this.copycolumn} /> : null |
| | | } |
| | | <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={this.onFieldChange} /> |
| | | <DragElement |
| | | list={columnlist} |
| | | setting={config.setting} |
| | | gridBtn={config.gridBtn} |
| | | handleList={this.handleList} |
| | | handleMenu={this.handleColumn} |
| | | deleteMenu={this.deleteElement} |
| | | markMenu={this.markElement} |
| | | handleGridBtn={this.handleGridBtn} |
| | | showfield={this.state.showField} |
| | | placeholder={this.state.dict['header.form.column.placeholder']} |
| | | /> |
| | | {/* 显示列编辑 */} |
| | | <Modal |
| | | title={dict['header.modal.column.edit']} |
| | | visible={modaltype === 'cols'} |
| | | width={800} |
| | | maskClosable={false} |
| | | onOk={this.handleSubmit} |
| | | onCancel={this.editModalCancel} |
| | | destroyOnClose |
| | | > |
| | | <ColumnForm |
| | | dict={dict} |
| | | card={card} |
| | | inputSubmit={this.handleSubmit} |
| | | formlist={this.state.formlist} |
| | | wrappedComponentRef={(inst) => this.columnFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | {/* 合并列编辑 */} |
| | | <Modal |
| | | title={dict['model.form.colspan'] + '-' + dict['model.edit']} |
| | | visible={modaltype === 'colspan'} |
| | | width={800} |
| | | maskClosable={false} |
| | | onOk={this.handleSubmit} |
| | | onCancel={this.editModalCancel} |
| | | destroyOnClose |
| | | > |
| | | <ColspanForm |
| | | dict={dict} |
| | | card={card} |
| | | inputSubmit={this.handleSubmit} |
| | | columns={columnlist} |
| | | wrappedComponentRef={(inst) => this.columnFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | {/* 操作列编辑 */} |
| | | <Modal |
| | | title={dict['header.modal.gridbtn.edit']} |
| | | visible={modaltype === 'gridbtn'} |
| | | width={800} |
| | | maskClosable={false} |
| | | onOk={this.handleSubmit} |
| | | onCancel={this.editModalCancel} |
| | | destroyOnClose |
| | | > |
| | | <GridBtnForm |
| | | dict={dict} |
| | | inputSubmit={this.handleSubmit} |
| | | card={config.gridBtn} |
| | | wrappedComponentRef={(inst) => this.gridBtnFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | {/* 按钮使用系统存储过程时,验证信息模态框 */} |
| | | <Modal |
| | | wrapClassName="model-table-column-mark-modal" |
| | | title={'标记设置'} |
| | | visible={modaltype === 'mark'} |
| | | width={'75vw'} |
| | | maskClosable={false} |
| | | style={{minWidth: '900px', maxWidth: '1200px'}} |
| | | okText={dict['model.submit']} |
| | | onOk={this.markSubmit} |
| | | onCancel={() => { this.setState({ modaltype: '' }) }} |
| | | destroyOnClose |
| | | > |
| | | <MarkColumn |
| | | ref="markRef" |
| | | card={card} |
| | | dict={dict} |
| | | columns={columnlist} |
| | | /> |
| | | </Modal> |
| | | {this.state.loading && <Spin size="large" />} |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default ColumnComponent |
New file |
| | |
| | | .model-custom-table-column-list { |
| | | position: relative; |
| | | padding: 0px 0px 50px; |
| | | |
| | | .ant-switch { |
| | | position: absolute; |
| | | right: 5px; |
| | | top: -25px; |
| | | } |
| | | .column-copy { |
| | | position: absolute; |
| | | font-size: 16px; |
| | | right: 70px; |
| | | top: -22px; |
| | | color: #26C281; |
| | | cursor: pointer; |
| | | } |
| | | > .ant-row { |
| | | background: #fafafa; |
| | | border-radius: 4px; |
| | | min-height: 47px; |
| | | border: 1px solid #e8e8e8; |
| | | .column-box { |
| | | display: flex; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .column-box:not(:first-child) { |
| | | border-top: 1px solid #e8e8e8; |
| | | } |
| | | .page-card { |
| | | position: relative; |
| | | padding: 0px; |
| | | min-height: 45px; |
| | | > div { |
| | | padding: 12px 0px 0px; |
| | | cursor: move; |
| | | height: 100%; |
| | | .ant-table-column-sorters { |
| | | padding: 0px 8px 12px; |
| | | // white-space: nowrap; |
| | | } |
| | | .ant-table-column-fields { |
| | | padding: 0px 8px 5px; |
| | | } |
| | | } |
| | | .ant-table-column-sorter { |
| | | position: relative; |
| | | display: inline-block; |
| | | width: 24px; |
| | | font-size: 12px; |
| | | color: #bfbfbf; |
| | | .anticon-caret-up { |
| | | position: relative; |
| | | left: 10px; |
| | | top: -3px; |
| | | } |
| | | .anticon-caret-down { |
| | | position: relative; |
| | | left: -2px; |
| | | top: 3px; |
| | | } |
| | | } |
| | | .ant-checkbox-inner { |
| | | margin-top: 14px; |
| | | margin-left: calc(50% - 8px); |
| | | } |
| | | } |
| | | .page-card:not(:last-child) { |
| | | border-right: 1px solid #e8e8e8; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .model-table-column-mark-modal { |
| | | .ant-modal { |
| | | top: 50px; |
| | | padding-bottom: 5px; |
| | | .ant-modal-body { |
| | | max-height: calc(100vh - 190px); |
| | | min-height: 350px; |
| | | overflow-y: auto; |
| | | } |
| | | .ant-modal-body::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | .ant-modal-body::-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); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Table, Popconfirm, Icon } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | |
| | | import MarkForm from './markform' |
| | | import './index.scss' |
| | | import '@/assets/css/table.scss' |
| | | |
| | | class MarkColumn extends Component { |
| | | static propTpyes = { |
| | | columns: PropTypes.array, // 显示列 |
| | | dict: PropTypes.object, // 字典项 |
| | | card: PropTypes.object, |
| | | } |
| | | |
| | | state = { |
| | | marks: null, |
| | | columns: null, |
| | | markColumns: [ |
| | | { |
| | | title: '字段', |
| | | dataIndex: 'field', |
| | | width: '20%', |
| | | render: (text, record) => { |
| | | let item = this.props.columns.filter(col => col.field === record.field)[0] |
| | | if (item) { |
| | | return item.label + '(' + item.field + ')' |
| | | } else { |
| | | return '' |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | title: '对比类型', |
| | | dataIndex: 'contrastType', |
| | | width: '15%', |
| | | render: (text, record) => { |
| | | if (record.contrastType === 'static') { |
| | | return '静态' |
| | | } else { |
| | | return '动态' |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | title: '对比值/字段', |
| | | dataIndex: 'contrastValue', |
| | | width: '20%', |
| | | render: (text, record) => { |
| | | if (record.contrastType === 'static') { |
| | | return '对比值: ' + text |
| | | } else { |
| | | let item = this.props.columns.filter(col => col.field === record.contrastField)[0] |
| | | if (item) { |
| | | return '字段: ' + item.label + '(' + item.field + ')' |
| | | } else { |
| | | return '' |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | title: '对比方式', |
| | | dataIndex: 'match', |
| | | width: '12%' |
| | | }, |
| | | { |
| | | title: '标记效果', |
| | | dataIndex: 'signType', |
| | | width: '13%', |
| | | render: (text, record) => { |
| | | let item = this.props.columns.filter(col => col.field === record.field)[0] |
| | | if (!item) return '' |
| | | |
| | | let content = '' |
| | | if (item.type === 'text') { |
| | | content = '文本' |
| | | } else { |
| | | content = Math.ceil(Math.random() * 100) * 10 |
| | | } |
| | | |
| | | let _outerclass = '' |
| | | if (record.signType === 'font') { |
| | | _outerclass = 'font ' + record.color[1] |
| | | } else if (record.signType === 'background') { |
| | | _outerclass = 'background ' + record.color[1] |
| | | } else if (record.signType === 'card') { |
| | | _outerclass = 'background ' + record.color[1] |
| | | content = '效果在卡片中可见' |
| | | } else if (record.signType === 'icon') { |
| | | if (record.position === 'front') { |
| | | content = <div><Icon className={'font ' + record.color[1]} type={record.icon} /> {content} </div> |
| | | } else { |
| | | content = <div> {content} <Icon className={'font ' + record.color[1]} type={record.icon} /> </div> |
| | | } |
| | | } |
| | | |
| | | return <div className={_outerclass}> |
| | | <div className="baseboard"></div> |
| | | <div className="content"> |
| | | {content} |
| | | </div> |
| | | </div> |
| | | } |
| | | }, |
| | | { |
| | | title: '操作', |
| | | align: 'center', |
| | | dataIndex: 'operation', |
| | | render: (text, record) => |
| | | ( |
| | | <div> |
| | | <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> |
| | | <Popconfirm |
| | | overlayClassName="popover-confirm" |
| | | title={this.props.dict['model.query.delete']} |
| | | onConfirm={() => this.handleDelete(record) |
| | | }> |
| | | <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span> |
| | | </Popconfirm> |
| | | </div> |
| | | ) |
| | | } |
| | | ] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { columns, card } = this.props |
| | | |
| | | this.setState({ |
| | | columns: columns.filter(col => col.type === 'text' || col.type === 'number'), |
| | | marks: card.marks ? fromJS(card.marks).toJS() : [] |
| | | }) |
| | | } |
| | | |
| | | 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 }) |
| | | } |
| | | |
| | | handleEdit = (record) => { |
| | | this.markForm.edit(record) |
| | | |
| | | let node = document.getElementById('mark-column-box-modal').parentNode |
| | | |
| | | if (node && node.scrollTop) { |
| | | let inter = Math.ceil(node.scrollTop / 10) |
| | | |
| | | let timer = setInterval(() => { |
| | | if (node.scrollTop - inter > 0) { |
| | | node.scrollTop = node.scrollTop - inter |
| | | } else { |
| | | node.scrollTop = 0 |
| | | clearInterval(timer) |
| | | } |
| | | }, 10) |
| | | } |
| | | } |
| | | |
| | | handleUpDown = (record, direction) => { |
| | | let _marks = fromJS(this.state.marks).toJS() |
| | | let index = 0 |
| | | |
| | | _marks = _marks.filter((item, i) => { |
| | | if (item.uuid === record.uuid) { |
| | | index = i |
| | | } |
| | | |
| | | return item.uuid !== record.uuid |
| | | }) |
| | | if ((index === 0 && direction === 'up') || (index === _marks.length && direction === 'down')) { |
| | | return |
| | | } |
| | | |
| | | if (direction === 'up') { |
| | | _marks.splice(index - 1, 0, record) |
| | | } else { |
| | | _marks.splice(index + 1, 0, record) |
| | | } |
| | | |
| | | this.setState({ |
| | | marks: _marks |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.props |
| | | const { marks, markColumns, columns } = this.state |
| | | |
| | | return ( |
| | | <div id="mark-column-box-modal" className=""> |
| | | <MarkForm |
| | | dict={this.props.dict} |
| | | card={card} |
| | | columns={columns} |
| | | markChange={this.markChange} |
| | | wrappedComponentRef={(inst) => this.markForm = inst} |
| | | /> |
| | | <Table |
| | | bordered |
| | | rowKey="uuid" |
| | | className="mingke-table" |
| | | dataSource={marks} |
| | | rowClassName={(record) => record.signType === 'line' ? 'mk-table-line background ' + record.color[1] : ''} |
| | | columns={markColumns} |
| | | pagination={false} |
| | | /> |
| | | </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, InputNumber, Radio, Icon, Cascader, Tooltip } from 'antd' |
| | | |
| | | import { minkeColorSystem, minkeIconSystem } from '@/utils/option.js' |
| | | import './index.scss' |
| | | |
| | | class UniqueForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | card: PropTypes.object, // 字段信息 |
| | | columns: PropTypes.array, // 列名集合 |
| | | markChange: PropTypes.func // 修改函数 |
| | | } |
| | | |
| | | state = { |
| | | editItem: null, // 编辑元素 |
| | | contrastType: 'static', |
| | | originField: this.props.card, |
| | | signType: 'background', |
| | | selectIcon: '', |
| | | options: JSON.parse(JSON.stringify(minkeColorSystem)), |
| | | icons: minkeIconSystem.direction |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | this.setState({ |
| | | options: this.state.options.map(option => { |
| | | option.children = option.children.map(cell => { |
| | | cell.label = <div className={'background ' + cell.value}>{cell.value}</div> |
| | | |
| | | return cell |
| | | }) |
| | | return option |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | edit = (record) => { |
| | | const { columns } = this.props |
| | | let item = columns.filter(col => col.field === record.field)[0] |
| | | |
| | | let _type = 'background ' |
| | | if (record.signType === 'icon' || record.signType === 'font') { |
| | | _type = 'font ' |
| | | } |
| | | |
| | | this.setState({ |
| | | originField: item || '', |
| | | editItem: record, |
| | | contrastType: record.contrastType || '', |
| | | signType: record.signType || '', |
| | | selectIcon: record.icon || '', |
| | | options: this.state.options.map(option => { |
| | | option.children = option.children.map(cell => { |
| | | cell.label = <div className={_type + cell.value}>{record.icon ? <Icon type={record.icon} /> : cell.value}</div> |
| | | |
| | | return cell |
| | | }) |
| | | return option |
| | | }) |
| | | }, () => { |
| | | let fieldvalue = {} |
| | | Object.keys(record).forEach(key => { |
| | | if (this.props.form.getFieldValue(key) !== undefined) { |
| | | fieldvalue[key] = record[key] |
| | | } |
| | | }) |
| | | |
| | | this.props.form.setFieldsValue(fieldvalue) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 字段切换 |
| | | */ |
| | | fieldChange = (value) => { |
| | | const { columns } = this.props |
| | | let item = columns.filter(col => col.field === value)[0] |
| | | |
| | | this.setState({ |
| | | originField: item |
| | | }) |
| | | |
| | | if (this.state.contrastType !== 'static') { |
| | | this.props.form.setFieldsValue({contrastField: ''}) |
| | | } else { |
| | | this.props.form.setFieldsValue({contrastValue: ''}) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 对比值类型切换 |
| | | */ |
| | | changeType = (val) => { |
| | | this.setState({ |
| | | contrastType: val |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 标记类型切换 |
| | | */ |
| | | changeSignType = (val) => { |
| | | let _type = 'background ' |
| | | if (val === 'icon' || val === 'font') { |
| | | _type = 'font ' |
| | | } |
| | | |
| | | let newState = { |
| | | signType: val, |
| | | selectIcon: '' |
| | | } |
| | | |
| | | if (val !== 'icon') { |
| | | newState.options = this.state.options.map(option => { |
| | | option.children = option.children.map(cell => { |
| | | cell.label = <div className={_type + cell.value}>{cell.value}</div> |
| | | |
| | | return cell |
| | | }) |
| | | return option |
| | | }) |
| | | } |
| | | |
| | | this.setState(newState) |
| | | } |
| | | |
| | | /** |
| | | * @description 图标类型切换 |
| | | */ |
| | | changeIconType = (val) => { |
| | | this.setState({ |
| | | icons: minkeIconSystem[val], |
| | | selectIcon: '' |
| | | }) |
| | | this.props.form.setFieldsValue({icon: ''}) |
| | | } |
| | | |
| | | /** |
| | | * @description 切换图标 |
| | | */ |
| | | changeIcon = (val) => { |
| | | this.setState({ |
| | | selectIcon: val, |
| | | options: this.state.options.map(option => { |
| | | option.children = option.children.map(cell => { |
| | | cell.label = <div className={'font ' + cell.value}><Icon type={val} /></div> |
| | | |
| | | return cell |
| | | }) |
| | | return option |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | values.uuid = this.state.editItem ? this.state.editItem.uuid : '' |
| | | |
| | | this.props.markChange(values) |
| | | this.setState({ |
| | | editItem: null |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | render() { |
| | | const { columns } = this.props |
| | | const { originField, contrastType, signType, options, selectIcon, icons } = this.state |
| | | const { getFieldDecorator } = this.props.form |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | let contFields = columns.filter(col => originField.field !== col.field && originField.type === col.type) |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} id="model-mark-form-box" className="mingke-table"> |
| | | <Row gutter={24}> |
| | | <Col span={6}> |
| | | <Form.Item label={'字段'}> |
| | | {getFieldDecorator('field', { |
| | | initialValue: originField.field, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | onChange={this.fieldChange} |
| | | > |
| | | {columns.map(item => ( |
| | | <Select.Option key={item.uuid} title={item.label + '(' + item.field + ')'} value={item.field}>{item.label + '(' + item.field + ')'}</Select.Option> |
| | | ))} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={6}> |
| | | <Form.Item label={'对比类型'}> |
| | | {getFieldDecorator('contrastType', { |
| | | initialValue: 'static' |
| | | })( |
| | | <Radio.Group onChange={(e) => this.changeType(e.target.value)}> |
| | | <Radio value="static">静态</Radio> |
| | | <Radio value="dynamic">动态</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </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> |
| | | {originField.type === 'number' ? <Select.Option value=">"> > </Select.Option> : null} |
| | | {originField.type === 'number' ? <Select.Option value="<"> < </Select.Option> : null} |
| | | {originField.type === 'text' ? <Select.Option value="like"> like </Select.Option> : null} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {contrastType === 'static' ? <Col span={6}> |
| | | <Form.Item label={'对比值'}> |
| | | {getFieldDecorator('contrastValue', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '对比值!' |
| | | } |
| | | ] |
| | | })(originField.type === 'number' ? <InputNumber /> : <Input placeholder="" autoComplete="off" />)} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {contrastType === 'dynamic' ? <Col span={6}> |
| | | <Form.Item label={'对比字段'}> |
| | | {getFieldDecorator('contrastField', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '对比字段!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select |
| | | showSearch |
| | | filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
| | | > |
| | | {contFields.map(item => ( |
| | | <Select.Option key={item.uuid} title={item.label + '(' + item.field + ')'} value={item.field}>{item.label + '(' + item.field + ')'}</Select.Option> |
| | | ))} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={6}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="卡片类型,在卡片图表中起效"> |
| | | <Icon type="question-circle" /> |
| | | {'标记'} |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('signType', { |
| | | initialValue: 'background', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '标记方式!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select onChange={this.changeSignType}> |
| | | <Select.Option value="font">单元格(文字)</Select.Option> |
| | | <Select.Option value="background">单元格(背景)</Select.Option> |
| | | <Select.Option value="line">行</Select.Option> |
| | | <Select.Option value="icon">图标</Select.Option> |
| | | <Select.Option value="card">卡片</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {signType === 'icon' ? <Col span={6}> |
| | | <Form.Item label={'图标位置'}> |
| | | {getFieldDecorator('position', { |
| | | initialValue: 'back' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="front">前</Radio> |
| | | <Radio value="back">后</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {signType === 'icon' ? <Col span={6}> |
| | | <Form.Item label={'图标类型'}> |
| | | {getFieldDecorator('iconType', { |
| | | initialValue: 'direction' |
| | | })( |
| | | <Select onChange={this.changeIconType}> |
| | | <Select.Option value="direction">方向性图标</Select.Option> |
| | | <Select.Option value="hint">提示建议性图标</Select.Option> |
| | | <Select.Option value="edit">编辑类图标</Select.Option> |
| | | <Select.Option value="data">数据类图标</Select.Option> |
| | | <Select.Option value="trademark">品牌和标识</Select.Option> |
| | | <Select.Option value="normal">网站通用图标</Select.Option> |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {signType === 'icon' ? <Col span={6}> |
| | | <Form.Item label={'图标'}> |
| | | {getFieldDecorator('icon', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '图标!' |
| | | } |
| | | ] |
| | | })( |
| | | <Select onChange={this.changeIcon} getPopupContainer={() => document.getElementById('model-mark-form-box')}> |
| | | {icons.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {(signType === 'icon' && selectIcon) || signType !== 'icon' ? <Col span={6}> |
| | | <Form.Item label="颜色"> |
| | | {getFieldDecorator('color', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.select'] + '颜色!' |
| | | } |
| | | ] |
| | | })( |
| | | <Cascader |
| | | options={options} |
| | | placeholder="" |
| | | displayRender={(label, selectedOptions) => selectedOptions[0] ? selectedOptions[0].label + (selectedOptions[1] ? ' / ' + selectedOptions[1].value : '') : ''} |
| | | getPopupContainer={() => document.getElementById('model-mark-form-box')} |
| | | /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={signType === 'icon' ? (!selectIcon ? 24 : 18) : 12} 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 |
| | |
| | | #model-mark-form-box { |
| | | .ant-select-dropdown-menu-item { |
| | | .anticon { |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | } |
| | |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover, Modal } from 'antd' |
| | | |
| | | // import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | |
| | | import SearchComponent from '@/templates/sharecomponent/searchcomponent' |
| | | import './index.scss' |
| | | |
| | | const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) |
| | | const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent')) |
| | | const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent')) |
| | | const ColumnComponent = asyncComponent(() => import('./columncomponent')) |
| | | // const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting')) |
| | | // const SearchComponent = asyncComponent(() => import('@/menu/searchcomponent')) |
| | | |
| | |
| | | parentId: card.parentId || '', |
| | | format: 'array', // 组件属性 - 数据格式 |
| | | pageable: true, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | switchable: true, // 组件属性 - 数据是否可切换 |
| | | dataName: card.dataName || '', |
| | | width: 12, |
| | | search: [], |
| | | width: 24, |
| | | search: [ |
| | | { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'text', match: 'like' }, |
| | | { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'select', match: 'equal' }, |
| | | { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'date', match: 'greater' } |
| | | ], |
| | | action: [ |
| | | { origin: true, uuid: Utils.getuuid(), label: '添加', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green' }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '修改', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple' }, |
| | | { origin: true, uuid: Utils.getuuid(), label: '删除', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'red' } |
| | | ], |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, width: 12 }, |
| | | wrap: { name: card.name, width: 24 }, |
| | | style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, |
| | | headerStyle: { fontSize: '16px' }, |
| | | columns: [], |
| | | cols: [ |
| | | { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 }, |
| | | { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 }, |
| | | { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 } |
| | | ], |
| | | scripts: [] |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | addSearch = () => { |
| | | const { card } = this.state |
| | | let card = fromJS(this.state.card).toJS() |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = 'label' |
| | | newcard.initval = '' |
| | | newcard.type = 'select' |
| | | newcard.resourceType = '0' |
| | | newcard.options = [] |
| | | newcard.setAll = 'false' |
| | | newcard.orderType = 'asc' |
| | | newcard.display = 'dropdown' |
| | | newcard.type = 'text' |
| | | newcard.match = '=' |
| | | |
| | | // 注册事件-添加搜索 |
| | | MKEmitter.emit('addSearch', card.uuid, newcard) |
| | | card.search.push(newcard) |
| | | |
| | | this.setState({card}) |
| | | } |
| | | |
| | | addButton = () => { |
| | | const { card } = this.state |
| | | |
| | | let newcard = {} |
| | | newcard.uuid = Utils.getuuid() |
| | | newcard.focus = true |
| | | |
| | | newcard.label = 'label' |
| | | newcard.sqlType = '' |
| | | newcard.Ot = 'requiredSgl' |
| | | newcard.OpenType = 'pop' |
| | | newcard.icon = '' |
| | | newcard.class = 'green' |
| | | newcard.intertype = card.setting.interType || 'system' |
| | | newcard.innerFunc = card.setting.innerFunc || '' |
| | | newcard.sysInterface = card.setting.sysInterface || '' |
| | | newcard.outerFunc = card.setting.outerFunc || '' |
| | | newcard.interface = card.setting.interface || '' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | | newcard.errorTime = 10 |
| | | newcard.verify = null |
| | | newcard.show = 'button' |
| | | |
| | | // 注册事件-添加按钮 |
| | | MKEmitter.emit('addButton', card.uuid, newcard) |
| | | } |
| | | |
| | | /** |
| | | * @description 更新搜索条件配置信息 |
| | | */ |
| | | updatesearch = (config) => { |
| | | updateconfig = (config) => { |
| | | this.setState({ |
| | | card: config |
| | | }) |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | setSubConfig = (btn) => { |
| | | |
| | | } |
| | | updateaction = (config) => { |
| | | |
| | | } |
| | | |
| | | render() { |
| | | const { menu } = this.props |
| | | const { card } = this.state |
| | | |
| | | return ( |
| | | <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}}> |
| | | <SearchComponent config={card} updatesearch={this.updatesearch}/> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加卡片" onClick={this.addCard} type="plus" /> |
| | | <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> |
| | | {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="添加搜索" onClick={this.addSearch} type="plus-circle" /> : null} |
| | | {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="添加按钮" onClick={this.addButton} type="plus-square" /> : null} |
| | | {/* {menu ? <WrapComponent config={card} MenuType={menu.MenuType} updateConfig={this.updateComponent} /> : null} */} |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} |
| | | <SettingComponent config={card} updateConfig={this.updateComponent} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <SearchComponent config={card} updatesearch={this.updateconfig}/> |
| | | <ActionComponent |
| | | type="normaltable" |
| | | config={card} |
| | | updateaction={this.updateComponent} |
| | | /> |
| | | <ColumnComponent config={card} updatecolumn={this.updateconfig}/> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | background-size: cover; |
| | | min-height: 100px; |
| | | |
| | | .table-header { |
| | | position: relative; |
| | | height: 45px; |
| | | overflow: hidden; |
| | | padding-right: 35px; |
| | | |
| | | .table-title { |
| | | text-decoration: inherit; |
| | | font-weight: inherit; |
| | | font-style: inherit; |
| | | float: left; |
| | | line-height: 45px; |
| | | margin-left: 10px; |
| | | position: relative; |
| | | z-index: 1; |
| | | .model-table-search-list { |
| | | padding: 10px 0px 0px; |
| | | min-height: 65px; |
| | | >.anticon-question-circle { |
| | | display: none; |
| | | } |
| | | .page-card { |
| | | background: transparent; |
| | | } |
| | | } |
| | | .card-control { |
| | | position: absolute; |
| | | top: 0px; |
| | | left: 0px; |
| | | .anticon-tool { |
| | | right: auto; |
| | | left: 1px; |
| | | padding: 1px; |
| | | } |
| | | .model-table-search-list.length0 { |
| | | display: none; |
| | | } |
| | | .anticon-tool { |
| | | position: absolute; |
| | |
| | | padding: 5px; |
| | | background: rgba(255, 255, 255, 0.55); |
| | | } |
| | | |
| | | .card-item { |
| | | overflow-y: hidden; |
| | | position: relative; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 20px; |
| | | } |
| | | |
| | | .card-item:hover { |
| | | box-shadow: 0px 0px 2px #e8e8e8; |
| | | } |
| | | |
| | | .model-menu-card-cell-list .card-detail-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | .model-menu-action-list { |
| | | line-height: 40px; |
| | | .ant-row > .anticon-plus { |
| | | position: absolute; |
| | | right: -30px; |
| | | font-size: 16px; |
| | | } |
| | | padding: 15px 0px 10px; |
| | | } |
| | | .model-menu-action-list.length0 { |
| | | display: none; |
| | | } |
| | | .card-add-button { |
| | | text-align: right; |
| | |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Chart } from '@antv/g2' |
| | | import { connect } from 'react-redux' |
| | | import DataSet from '@antv/data-set' |
| | | import { Spin, Empty, Select, notification } from 'antd' |
| | | |
| | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import { modifyTabview } from '@/store/action' |
| | | import './index.scss' |
| | | |
| | | const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton')) |
| | |
| | | } |
| | | } |
| | | |
| | | if (plot.linkmenu && plot.linkmenu.length > 0) { |
| | | let menu_id = plot.linkmenu[plot.linkmenu.length - 1] |
| | | let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || '' |
| | | |
| | | chart.on('element:dblclick', (ev) => { |
| | | if (!menu) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '菜单已删除或没有访问权限!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | try { |
| | | let data = ev.data.data |
| | | let primaryId = '' |
| | | if (this.state.config.setting.primaryKey && data) { |
| | | primaryId = data[this.state.config.setting.primaryKey] || '' |
| | | } |
| | | |
| | | let newtab = { |
| | | ...menu, |
| | | selected: true, |
| | | param: { |
| | | BID: primaryId, |
| | | data: data |
| | | } |
| | | } |
| | | |
| | | let tabs = this.props.tabviews.filter(tab => { |
| | | tab.selected = false |
| | | return tab.MenuID !== newtab.MenuID |
| | | }) |
| | | |
| | | if (this.props.tabviews.length !== tabs.length) { |
| | | this.props.modifyTabview(fromJS(tabs).toJS()) |
| | | } |
| | | |
| | | this.setState({}, () => { |
| | | tabs.push(newtab) |
| | | this.props.modifyTabview(tabs) |
| | | }) |
| | | } catch { |
| | | console.warn('菜单打开失败!') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | chart.render() |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | export default LineChart |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | tabviews: state.tabviews, |
| | | permMenus: state.permMenus, |
| | | } |
| | | } |
| | | |
| | | const mapDispatchToProps = (dispatch) => { |
| | | return { |
| | | modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews)) |
| | | } |
| | | } |
| | | |
| | | export default connect(mapStateToProps, mapDispatchToProps)(LineChart) |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | tabviews: state.tabviews, |
| | |
| | | const { config } = this.props |
| | | let LText_field = [] |
| | | let diffUser = false |
| | | let LText = params.map((item, index) => { |
| | | let _LText = params.map((item, index) => { |
| | | let _script = item.script |
| | | |
| | | if (index === 0) { |
| | |
| | | |
| | | let param = { |
| | | func: 'sPC_Get_structured_data', |
| | | LText: LText.join(' union all '), |
| | | LText: _LText.join(' union all '), |
| | | LText_field: LText_field.join(' union all ') |
| | | } |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) |
| | | |
| | | param.LText1 = LText1 |
| | | param.LText = LText |
| | | param.LText2 = LText2 |
| | | param.LText_field = Utils.formatOptions(param.LText_field) |
| | | |
| | | if (config.cacheUseful === 'true') { |
| | |
| | | const { config } = this.state |
| | | let LText_field = [] |
| | | let diffUser = false |
| | | let LText = params.map((item, index) => { |
| | | let _LText = params.map((item, index) => { |
| | | let _script = item.script |
| | | |
| | | if (index === 0) { |
| | |
| | | return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` |
| | | }) |
| | | |
| | | // 把大接口sPC_Get_structured_data的ltext拆成三份,第一段:@LText1,第二段@LText,第三段@LText2 |
| | | let param = { |
| | | func: 'sPC_Get_structured_data', |
| | | LText: LText.join(' union all '), |
| | | LText: _LText.join(' union all '), |
| | | LText_field: LText_field.join(' union all '), |
| | | BID: this.state.BID || '' |
| | | } |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText) |
| | | |
| | | param.LText1 = LText1 |
| | | param.LText = LText |
| | | param.LText2 = LText2 |
| | | param.LText_field = Utils.formatOptions(param.LText_field) |
| | | |
| | | if (config.cacheUseful === 'true') { |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'add', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'notRequired', |
| | | position: 'toolbar', |
| | | execSuccess: 'grid', |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'update', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'requiredSgl', |
| | | position: 'grid', |
| | | position: 'toolbar', |
| | | execSuccess: 'grid', |
| | | execError: 'never', |
| | | errorTime: 15, |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'delete', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'required', |
| | | position: 'toolbar', |
| | | execSuccess: 'grid', |
| | |
| | | newcard.linkTab = '' |
| | | newcard.class = 'default' |
| | | newcard.intertype = 'inner' |
| | | newcard.method = 'POST' |
| | | newcard.position = 'toolbar' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | |
| | | newcard.icon = '' |
| | | newcard.class = 'default' |
| | | newcard.intertype = 'system' |
| | | newcard.method = 'POST' |
| | | newcard.position = 'toolbar' |
| | | newcard.execSuccess = 'grid' |
| | | newcard.execError = 'never' |
| | |
| | | if (!is(fromJS(nextProps.config.action), fromJS(this.props.config.action)) && !is(fromJS(nextProps.config.action), fromJS(actionlist))) { |
| | | let len = nextProps.config.action.length |
| | | let item = nextProps.config.action[len - 1] |
| | | if (item.copyType && item.focus) { |
| | | if (item && item.focus) { |
| | | this.handleAction(item) |
| | | } |
| | | this.setState({actionlist: fromJS(nextProps.config.action).toJS()}) |
| | |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import { Col } from 'antd' |
| | | import { Col, Button } from 'antd' |
| | | import Utils from '@/utils/utils.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | |
| | | /> |
| | | </Col> |
| | | ))} |
| | | |
| | | {cards.length > 0 ? <Col key="action" className="action" span={6}> |
| | | <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}> |
| | | <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8"> |
| | | </div> |
| | | <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16"> |
| | | <Button type="primary">搜索</Button> |
| | | <Button style={{ marginLeft: 8 }}>重置</Button> |
| | | <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div> |
| | | </div> |
| | | </div> |
| | | </Col> : null} |
| | | {cards.length === 0 ? |
| | | <div className="common-drawarea-placeholder"> |
| | | {placeholder} |
| | |
| | | if (!is(fromJS(nextProps.config.search), fromJS(this.props.config.search)) && !is(fromJS(nextProps.config.search), fromJS(searchlist))) { |
| | | let len = nextProps.config.search.length |
| | | let item = nextProps.config.search[len - 1] |
| | | if (item.copyType && item.focus) { |
| | | if (item && item.focus) { |
| | | this.handleSearch(item) |
| | | } |
| | | this.setState({searchlist: fromJS(nextProps.config.search).toJS()}) |
| | |
| | | const { dict, searchlist, visible, sqlVerifing, card } = this.state |
| | | |
| | | return ( |
| | | <div className="model-table-search-list"> |
| | | <div className={'model-table-search-list length' + searchlist.length}> |
| | | <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.search.guide']}> |
| | | <Icon type="question-circle" /> |
| | | </Tooltip> |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'add', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'notRequired', |
| | | position: 'toolbar', |
| | | execSuccess: 'grid', |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'update', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'requiredSgl', |
| | | position: 'grid', |
| | | execSuccess: 'grid', |
| | |
| | | origin: true, |
| | | uuid: Utils.getuuid(), |
| | | label: 'delete', |
| | | intertype: 'inner', |
| | | method: 'POST', |
| | | intertype: 'system', |
| | | Ot: 'required', |
| | | position: 'toolbar', |
| | | execSuccess: 'grid', |
| | |
| | | return window.btoa(_value) |
| | | } |
| | | |
| | | let len = value.length |
| | | // 注:LText 与 LText1 顺序颠倒 |
| | | return { |
| | | LText: encodesql(value.substring(5000, 10000)), |
| | | LText1: encodesql(value.substring(0, 5000)), |
| | | LText2: encodesql(value.substring(10000)) |
| | | if (len > 1000) { |
| | | let limit = Math.floor(len / 3) |
| | | return { |
| | | LText1: encodesql(value.substring(0, limit)), |
| | | LText: encodesql(value.substring(limit, limit * 2)), |
| | | LText2: encodesql(value.substring(limit * 2)) |
| | | } |
| | | } else { |
| | | return { |
| | | LText1: '', |
| | | LText: encodesql(value), |
| | | LText2: '' |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | let _config = fromJS(config).toJS() |
| | | delete _config.fstMenuList |
| | | delete _config.tableFields |
| | | |
| | | if (!is(fromJS(oriConfig), fromJS(_config))) { |
| | |
| | | } |
| | | |
| | | let _config = fromJS(config).toJS() |
| | | delete _config.fstMenuList |
| | | delete _config.tableFields |
| | | |
| | | let param = { |
| | |
| | | }) |
| | | } |
| | | |
| | | initMenuList = (msg) => { |
| | | let config = {...this.state.config, ...msg} |
| | | |
| | | this.setState({config}) |
| | | this.props.modifyCustomMenu(config) |
| | | } |
| | | |
| | | onEnabledChange = () => { |
| | | const { config } = this.state |
| | | |
| | |
| | | parentId={ParentId} |
| | | MenuName={MenuName} |
| | | MenuNo={MenuNo} |
| | | initMenuList={this.initMenuList} |
| | | updateConfig={this.updateConfig} |
| | | /> : null} |
| | | {config && MenuType === 'home' ? <HomeForm |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { fromJS } from 'immutable' |
| | | import { Form, Row, Col, Input, Select, notification, Radio, Icon, Tooltip, InputNumber } from 'antd' |
| | | |
| | | import Api from '@/api' |
| | |
| | | MenuName: PropTypes.string, |
| | | MenuNo: PropTypes.string, |
| | | parentId: PropTypes.string, |
| | | initMenuList: PropTypes.func, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { MenuId } = this.props |
| | | const { MenuId, config } = this.props |
| | | let _param = {func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'} |
| | | if (options.sysType !== 'cloud' && window.GLOB.systemType !== 'production') { |
| | | _param.linkurl = window.GLOB.linkurl |
| | |
| | | smenulist = item.children |
| | | } |
| | | }) |
| | | |
| | | this.props.initMenuList({fstMenuList: fromJS(menulist).toJS(), fstMenuId: thdMenu ? thdMenu.FstId : ''}) |
| | | sessionStorage.setItem('fstMenuList', JSON.stringify(menulist)) |
| | | this.props.updateConfig({...config, fstMenuId: thdMenu ? thdMenu.FstId : ''}) |
| | | |
| | | this.setState({ |
| | | fstMenuId: thdMenu ? thdMenu.FstId : '', |
| | |
| | | }) |
| | | } |
| | | |
| | | testFunc = () => { |
| | | let datas = [{ |
| | | name: 'a', |
| | | arr_field: 'MapCode,Country', |
| | | par_tablename: '', |
| | | type: '', |
| | | primaryKey: 'MapCode', |
| | | foreign_key: '', |
| | | sql: `select MapCode,Country from @tc1`, |
| | | script: `declare @tc1 table (MapCode nvarchar(50),Country nvarchar(50)) insert into @tc1 (MapCode,Country) select MapCode,Country from sMap where Province=''` |
| | | }, { |
| | | name: 'b', |
| | | arr_field: 'MapCode,Province,ParMapCode', |
| | | par_tablename: 'a', |
| | | type: 'array', |
| | | primaryKey: 'MapCode', |
| | | foreign_key: 'ParMapCode', |
| | | sql: `select MapCode,Province,ParMapCode from @tc2`, |
| | | script: `declare @tc2 table (MapCode nvarchar(50),Province nvarchar(50),ParMapCode nvarchar(50)) insert into @tc2 (MapCode,Province,ParMapCode) select MapCode,Province,ParMapCode from sMap where Province!='' and City=''` |
| | | }, { |
| | | name: 'c', |
| | | arr_field: 'MapCode,City,ParMapCode', |
| | | par_tablename: 'b', |
| | | type: 'array', |
| | | primaryKey: 'MapCode', |
| | | foreign_key: 'ParMapCode', |
| | | sql: `select MapCode,City,ParMapCode from @tc3`, |
| | | script: `declare @tc3 table (MapCode nvarchar(50),City nvarchar(50),ParMapCode nvarchar(50)) insert into @tc3 (MapCode,City,ParMapCode) select MapCode,City,ParMapCode from sMap where City!='' and Area=''` |
| | | }, { |
| | | name: 'd', |
| | | arr_field: 'MapCode,Area,ParMapCode', |
| | | par_tablename: 'c', |
| | | type: 'array', |
| | | primaryKey: 'MapCode', |
| | | foreign_key: 'ParMapCode', |
| | | sql: `select MapCode,Area,ParMapCode from sMap where Area!=''`, |
| | | script: `` |
| | | }] |
| | | |
| | | let LText = datas.map((item, index) => { |
| | | // item.par_tablename = '' |
| | | // item.foreign_key = '' |
| | | |
| | | let _orderBy = 'MapCode desc' |
| | | let _search = '' |
| | | let _sql = `select top 1000 ${item.arr_field} from (select ${item.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from (${item.sql}) tb ${_search}) tmptable order by tmptable.rows ` |
| | | |
| | | return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(item.script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort` |
| | | }) |
| | | |
| | | let LText_field = [] |
| | | datas.forEach(item => { |
| | | item.arr_field.split(',').forEach(cell => { |
| | | LText_field.push(`Select '${item.name}' as tablename,'${cell}' as fieldname,'nvarchar(50)' as field_type`) |
| | | }) |
| | | }) |
| | | |
| | | let param = { |
| | | func: 'sPC_Get_structured_data', |
| | | LText: LText.join(' union all '), |
| | | LText_field: LText_field.join(' union all ') |
| | | } |
| | | |
| | | param.LText = Utils.formatOptions(param.LText) |
| | | param.LText_field = Utils.formatOptions(param.LText_field) |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | |
| | | Api.getLocalConfig(param) |
| | | } |
| | | |
| | | // save = () => { |
| | | // html2canvas(document.getElementById('view')).then(canvas => { |
| | | // let imgUri = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream'); // 获取生成的图片的url |