From 4a23b7a8f9c23d7903019e48869c8c3191fa0ffc Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期三, 17 三月 2021 09:29:29 +0800 Subject: [PATCH] 2021-03-17 --- src/menu/components/form/dragelement/source.jsx | 13 src/menu/components/form/cardcomponent/settingform/index.scss | 11 src/menu/components/form/cardcomponent/index.jsx | 229 ++++++++ src/templates/formtabconfig/index.jsx | 4 src/menu/components/form/normal-form/index.jsx | 301 +++++++++++ src/assets/mobimg/form.png | 0 src/templates/zshare/editcomponent/index.jsx | 6 src/menu/components/form/wrapsetting/index.scss | 7 src/templates/sharecomponent/fieldscomponent/index.jsx | 8 src/templates/modalconfig/index.jsx | 4 src/menu/components/form/cardcomponent/index.scss | 0 src/menu/components/form/dragelement/index.scss | 27 + src/menu/menushell/card.jsx | 3 src/menu/components/form/normal-form/index.scss | 92 +++ src/menu/modulesource/option.jsx | 2 src/menu/components/form/dragelement/card.jsx | 167 ++++++ src/menu/components/form/wrapsetting/settingform/index.jsx | 253 +++++++++ src/menu/components/form/cardcomponent/settingform/index.jsx | 194 +++++++ src/menu/components/form/dragelement/index.jsx | 157 +++++ src/menu/components/form/wrapsetting/settingform/index.scss | 11 src/tabviews/zshare/mutilform/index.jsx | 16 src/menu/components/form/wrapsetting/index.jsx | 83 +++ src/menu/modalconfig/index.scss | 4 src/menu/modalconfig/index.jsx | 4 src/menu/menushell/index.jsx | 1 25 files changed, 1,576 insertions(+), 21 deletions(-) diff --git a/src/assets/mobimg/form.png b/src/assets/mobimg/form.png new file mode 100644 index 0000000..6403b32 --- /dev/null +++ b/src/assets/mobimg/form.png Binary files differ diff --git a/src/menu/components/form/cardcomponent/index.jsx b/src/menu/components/form/cardcomponent/index.jsx new file mode 100644 index 0000000..5a3909e --- /dev/null +++ b/src/menu/components/form/cardcomponent/index.jsx @@ -0,0 +1,229 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Modal, Popover, Icon } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' + +import Utils from '@/utils/utils.js' +import MKEmitter from '@/utils/events.js' +import './index.scss' + +const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) + +class CardBoxComponent extends Component { + static propTpyes = { + cards: PropTypes.object, // 鍗$墖琛岄厤缃俊鎭� + card: PropTypes.object, // 鍗$墖閰嶇疆淇℃伅 + move: PropTypes.func, // 鍗$墖绉诲姩 + deleteElement: PropTypes.func, // 鍗$墖鍒犻櫎 + updateElement: PropTypes.func // 鑿滃崟閰嶇疆鏇存柊 + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, // 鍗$墖淇℃伅锛屽寘鎷鍙嶉潰 + formlist: null, // 璁剧疆琛ㄥ崟淇℃伅 + elements: null, // 缂栬緫缁� + visible: false, // 妯℃�佹鎺у埗 + settingVisible: false, + } + + /** + * @description 鎼滅储鏉′欢鍒濆鍖� + */ + UNSAFE_componentWillMount () { + const { card } = this.props + + this.setState({ + card: fromJS(card).toJS(), + elements: fromJS(card.elements).toJS(), + }) + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + const { cards } = this.props + + return !is(fromJS(cards), fromJS(nextProps.cards)) || !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + } + + getStyle = (comIds, style) => { + const { cards } = this.props + const { card } = this.state + + if (comIds.length !== 2 || comIds[0] !== cards.uuid || comIds[1] !== card.uuid) return + + let _card = fromJS(card).toJS() + _card.style = style + + this.setState({ + card: _card + }) + + this.props.updateElement(_card) + } + + updateCard = (elements) => { + const { card } = this.state + + let _card = {...card, elements: elements} + + this.setState({ + card: _card + }) + + this.props.updateElement(_card) + } + + addElement = () => { + const { cards } = this.props + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.eleType = 'text' + newcard.datatype = 'dynamic' + newcard.height = 1 + + // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌 + MKEmitter.emit('cardAddElement', [cards.uuid, card.uuid], newcard) + } + + addButton = () => { + const { cards } = this.props + const { card } = this.state + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.focus = true + + newcard.eleType = 'button' + newcard.label = 'button' + newcard.sqlType = '' + newcard.Ot = 'requiredSgl' + newcard.OpenType = 'prompt' + newcard.icon = '' + newcard.class = 'primary' + newcard.intertype = 'system' + newcard.execSuccess = 'grid' + newcard.execError = 'never' + newcard.popClose = 'never' + newcard.errorTime = 10 + newcard.verify = null + newcard.show = 'link' + + // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌 + MKEmitter.emit('cardAddElement', [cards.uuid, card.uuid], newcard) + } + + changeStyle = () => { + const { cards } = this.props + const { card } = this.state + + let options = ['background', 'border', 'padding', 'margin', 'shadow'] + + MKEmitter.emit('changeStyle', [cards.uuid, card.uuid], options, fromJS(card.style).toJS()) + } + + settingSubmit = () => { + const { card } = this.state + + this.settingRef.handleConfirm().then(res => { + this.setState({ + settingVisible: false, + card: {...card, setting: res} + }) + + this.props.updateElement({...card, setting: res}) + }) + } + + clickComponent = (e) => { + if ((sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'propcard') && this.props.cards.subtype === 'propcard') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card, this.props.cards, 'propcard') + } + } + + render() { + const { cards } = this.props + const { card, elements, settingVisible, dict } = this.state + + let _style = {...card.style} + + if (_style.shadow) { + _style.boxShadow = '0 0 4px ' + _style.shadow + } + _style.height = cards.style.height + + return ( + <div className="card-item" style={_style} onClick={this.clickComponent} id={card.uuid}> + <CardCellComponent cards={cards} cardCell={card} side="front" elements={elements} updateElement={this.updateCard}/> + <div className="card-control"> + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} type="plus" /> + <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> + <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.setState({settingVisible: true})} /> + <CopyComponent type="cardcell" card={card}/> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + {cards.subtype === 'propcard' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="plus" title="宸︾Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} /> + <Icon className="close" title="鍙崇Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} /> + </div> + } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}> + <Icon type="swap" id={card.uuid + 'swap'}/> + </Popover> : null} + {cards.subtype === 'propcard' ? <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + </div> + <Modal + wrapClassName="popview-modal" + title={'鍗$墖璁剧疆'} + visible={settingVisible} + width={700} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.settingSubmit} + onCancel={() => { this.setState({ settingVisible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + cards={cards} + setting={card.setting} + inputSubmit={this.settingSubmit} + wrappedComponentRef={(inst) => this.settingRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default CardBoxComponent \ No newline at end of file diff --git a/src/menu/components/form/cardcomponent/index.scss b/src/menu/components/form/cardcomponent/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/menu/components/form/cardcomponent/index.scss diff --git a/src/menu/components/form/cardcomponent/settingform/index.jsx b/src/menu/components/form/cardcomponent/settingform/index.jsx new file mode 100644 index 0000000..d8046cc --- /dev/null +++ b/src/menu/components/form/cardcomponent/settingform/index.jsx @@ -0,0 +1,194 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Radio, Tooltip, Icon, Input, Cascader, Select } from 'antd' + +import './index.scss' + +const { TextArea } = Input + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + cards: PropTypes.object, // 鍗$墖闆� + setting: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + type: this.props.setting.type || 'simple', + click: this.props.setting.click || '', + isApp: sessionStorage.getItem('appType') === 'pc', + menulist: [] + } + + UNSAFE_componentWillMount() { + const { isApp } = this.state + let menulist = null + + if (isApp) { + menulist = sessionStorage.getItem('appMenus') + } else { + menulist = sessionStorage.getItem('fstMenuList') + } + + if (menulist) { + try { + menulist = JSON.parse(menulist) + } catch { + menulist = [] + } + } else { + menulist = [] + } + + this.setState({menulist}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { setting, cards } = this.props + const { getFieldDecorator } = this.props.form + const { click, menulist, isApp } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + {cards.subtype === 'propcard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鍗$墖鐐瑰嚮鏃讹紝鍚戝叾浠栫粍浠朵紶閫掔殑BID鍊笺��"> + <Icon type="question-circle" /> + 涓婚敭鍊� + </Tooltip> + }> + {getFieldDecorator('primaryId', { + initialValue: setting.primaryId || '' + })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit}/>)} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label="鐐瑰嚮浜嬩欢"> + {getFieldDecorator('click', { + initialValue: click + })( + <Radio.Group onChange={(e) => this.setState({click: e.target.value})}> + <Radio value="">鏃�</Radio> + <Radio value="menu">鑿滃崟</Radio> + <Radio value="link">閾炬帴</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {!isApp && click === 'menu' ? <Col span={12}> + <Form.Item label="鑿滃崟"> + {getFieldDecorator('menu', { + initialValue: setting.menu || [], + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鑿滃崟!' + } + ] + })( + <Cascader options={menulist} placeholder=""/> + )} + </Form.Item> + </Col> : null} + {isApp && click === 'menu' ? <Col span={12}> + <Form.Item label="鍏宠仈鑿滃崟"> + {getFieldDecorator('menu', { + initialValue: setting.menu || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍏宠仈鑿滃崟!' + } + ] + })( + <Select + showSearch + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {menulist.map(option => + <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> : null} + {click === 'link' ? <Col span={24} className="textarea"> + <Form.Item label="閾炬帴"> + {getFieldDecorator('linkurl', { + initialValue: setting.linkurl || '', + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '閾炬帴!' + } + ] + })( <TextArea rows={2}/> )} + </Form.Item> + </Col> : null} + {isApp ? <Col span={12}> + <Form.Item label="鎵撳紑鏂瑰紡"> + {getFieldDecorator('open', { + initialValue: setting.open || 'blank' + })( + <Radio.Group> + <Radio value="blank">鏂扮獥鍙�</Radio> + <Radio value="self">褰撳墠绐楀彛</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {click !== '' ? <Col span={12}> + <Form.Item label="鍙傛暟鎷兼帴"> + {getFieldDecorator('joint', { + initialValue: setting.joint || 'true' + })( + <Radio.Group> + <Radio value="true">鏄�</Radio> + <Radio value="false">鍚�</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/menu/components/form/cardcomponent/settingform/index.scss b/src/menu/components/form/cardcomponent/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/menu/components/form/cardcomponent/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/menu/components/form/dragelement/card.jsx b/src/menu/components/form/dragelement/card.jsx new file mode 100644 index 0000000..a70c65d --- /dev/null +++ b/src/menu/components/form/dragelement/card.jsx @@ -0,0 +1,167 @@ +import React from 'react' +import { useDrag, useDrop } from 'react-dnd' +import { Icon, Select, DatePicker, Input, InputNumber, Button, Popover, Switch, Radio, Checkbox } from 'antd' +import moment from 'moment' + +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const { MonthPicker } = DatePicker +const { TextArea } = Input + +const Editor = asyncComponent(() => import('@/components/editor')) +const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) +const CheckCard = asyncComponent(() => import('@/templates/modalconfig/checkCard')) + +const Card = ({ id, card, cols, moveCard, findCard, editCard, closeCard, copyCard, showField }) => { + const originalIndex = findCard(id).index + const [{ isDragging }, drag] = useDrag({ + item: { type: 'form', id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + }) + const [, drop] = useDrop({ + accept: 'form', + 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 + + const edit = () => { + editCard(id) + } + + const close = () => { + closeCard(id) + } + + const copy = () => { + copyCard(id) + } + + let selectval = '' + if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { + if (card.initval) { + let _option = card.options.filter(option => option.Value === card.initval)[0] + if (_option) { + selectval = _option.Text || '' + } else { + selectval = '' + } + } else if (card.setAll === 'true') { + selectval = card.emptyText || '绌�' + } + } + let labelCol = 'ant-col-sm-8' + let wrapCol = 'ant-col-sm-16' + let isEntireLine = false + + if (card.entireLine === 'true' || ['textarea', 'hint', 'checkcard', 'brafteditor'].includes(card.type)) { + isEntireLine = true + } + + if (isEntireLine) { + if (cols === '2') { + labelCol = 'ant-col-sm-4' + wrapCol = 'ant-col-sm-20' + } else if (cols === '3') { + labelCol = 'ant-col-cuslabel' + wrapCol = 'ant-col-cuswrap' + } else if (cols === '4') { + labelCol = 'ant-col-sm-2' + wrapCol = 'ant-col-sm-22' + } + if (card.hidelabel === 'true') { + wrapCol = 'ant-col-sm-24' + } + } + + let formItem = null + if (card.type === 'text') { + formItem = (<Input style={{marginTop: '4px'}} value={card.initval} />) + } else if (card.type === 'number') { + formItem = (<InputNumber value={card.initval} precision={card.decimal} />) + } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') { + formItem = (<Select value={selectval}></Select>) + } else if (card.type === 'color') { + formItem = (<ColorSketch value={card.initval || 'transparent'}/>) + } else if (card.type === 'date') { + formItem = (<DatePicker value={card.initval ? moment().subtract(card.initval, 'days') : null} />) + } else if (card.type === 'datemonth') { + formItem = (<MonthPicker value={card.initval ? moment().subtract(card.initval, 'month') : null} />) + } else if (card.type === 'datetime') { + formItem = (<DatePicker showTime value={card.initval ? moment().subtract(card.initval, 'days') : null} />) + } else if (card.type === 'textarea') { + formItem = (<TextArea value={card.initval} autoSize={{ minRows: 2, maxRows: 6 }} />) + } else if (card.type === 'brafteditor') { + formItem = (<Editor />) + } else if (card.type === 'fileupload') { + formItem = (<Button style={{marginTop: '3px'}}><Icon type="upload" /> 鐐瑰嚮涓婁紶 </Button>) + } else if (card.type === 'funcvar') { + formItem = (<Input style={{marginTop: '4px'}} value={card.linkfield} />) + } else if (card.type === 'linkMain') { + formItem = (<Input style={{marginTop: '4px'}} />) + } else if (card.type === 'switch') { + formItem = (<Switch checkedChildren={card.openText || ''} unCheckedChildren={card.closeText || ''} style={{marginTop: '8px'}} checked={card.initval}/>) + } else if (card.type === 'radio') { + formItem = card.options && card.options.length > 0 ? (<Radio.Group value={card.initval}> + {card.options.map(cell => <Radio key={cell.key} value={cell.Value}>{cell.Text}</Radio>)} + </Radio.Group>) : (<Radio.Group value={1}> + <Radio value={1}>A</Radio> + <Radio value={2}>B</Radio> + <Radio value={3}>C</Radio> + <Radio value={4}>D</Radio> + </Radio.Group>) + } else if (card.type === 'checkbox') { + let _val = card.initval ? card.initval.split(',') : [] + formItem = card.options && card.options.length > 0 ? (<Checkbox.Group value={_val}> + {card.options.map(cell => <Checkbox key={cell.key} value={cell.Value}>{cell.Text}</Checkbox>)} + </Checkbox.Group>) : (<Checkbox.Group value={['A', 'C']}> + <Checkbox value="A">A</Checkbox> + <Checkbox value="B">B</Checkbox> + <Checkbox value="C">C</Checkbox> + <Checkbox value="D">D</Checkbox> + </Checkbox.Group>) + } else if (card.type === 'hint') { + formItem = <div style={{marginTop: '10px', color: 'rgba(0, 0, 0, 0.85)'}}>{card.message}</div> + } else if (card.type === 'checkcard') { + formItem = <CheckCard width={card.width} ratio={card.ratio} display={card.display} fields={card.fields} options={card.options} /> + } + + return ( + <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ + <div className="mk-popover-control"> + <Icon className="edit" type="edit" onClick={edit} /> + <Icon className="copy" type="copy" onClick={copy} /> + <Icon className="close" type="close" onClick={close} /> + </div> + } trigger="hover"> + <div className="page-card" style={{ opacity: opacity}}> + <div ref={node => drag(drop(node))}> + {<div className="ant-row ant-form-item"> + {card.hidelabel !== 'true' ? <div className={'ant-col ant-form-item-label ant-col-xs-24 ' + labelCol}> + {card.label ? <label className={card.required === 'true' ? 'required' : ''}>{card.tooltip ? + <Icon type="question-circle" /> : null} + {card.label}</label> : null} + </div> : null} + <div className={'ant-col ant-form-item-control-wrapper ant-col-xs-24 ' + wrapCol}> + {formItem} + {showField ? card.field : ''} + </div> + </div>} + </div> + </div> + </Popover> + ) +} +export default Card diff --git a/src/menu/components/form/dragelement/index.jsx b/src/menu/components/form/dragelement/index.jsx new file mode 100644 index 0000000..bcfe294 --- /dev/null +++ b/src/menu/components/form/dragelement/index.jsx @@ -0,0 +1,157 @@ +import React, { useState } from 'react' +import { useDrop } from 'react-dnd' +import { is, fromJS } from 'immutable' +import update from 'immutability-helper' +import { Col } from 'antd' +import Utils from '@/utils/utils.js' +import Card from './card' +import './index.scss' + +const Container = ({list, group, setting, placeholder, handleList, handleForm, closeForm, showField }) => { + const [cards, setCards] = useState(list) + const moveCard = (id, atIndex) => { + const { card, index } = findCard(id) + + if (!card) return + + const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) + + if (!group) { + handleList(_cards) + } else { + handleList(_cards, group) + } + } + + 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) + handleForm(card) + } + + const closeCard = id => { + const { card } = findCard(id) + closeForm(card) + } + + const copyCard = id => { + const { card, index: overIndex } = findCard(id) + + let _card = fromJS(card).toJS() + _card.uuid = Utils.getuuid() + _card.focus = true + + // 澶嶅埗鍒板壀鍒囨澘 + let oInput = document.createElement('input') + let val = JSON.parse(JSON.stringify(_card)) + val.copyType = 'form' + + 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' + document.body.removeChild(oInput) + + const _cards = update(cards, { $splice: [[overIndex + 1, 0, _card]] }) + + setCards(_cards) + + if (!group) { + handleList(_cards, null, null, _card) + } else { + handleList(_cards, group, null, _card) + } + } + + const [, drop] = useDrop({ + accept: 'form', + drop(item) { + if (item.hasOwnProperty('originalIndex') && group) { + const { card } = findCard(item.id) + if (!card) { + handleList(cards, group, item.id) + } + } + if (item.hasOwnProperty('originalIndex')) { + return + } + + let newcard = {} + newcard.uuid = Utils.getuuid() + newcard.label = 'label' + newcard.type = item.subType + newcard.resourceType = '0' + newcard.options = [] + newcard.readonly = 'false' + newcard.required = 'true' + newcard.focus = true + + 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}`) // cards涓虹┖鏃� overIndex 涓� -1 + const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) + + setCards(_cards) + + if (!group) { + handleList(_cards, null, null, newcard) + } else { + handleList(_cards, group, null, newcard) + } + } + }) + + let _cols = 24 / (setting.cols || 2) + + return ( + <div ref={drop} className="ant-row modal-fields-row"> + {cards.map(card => { + let isEntireLine = false + + if (card.entireLine === 'true' || ['textarea', 'hint', 'checkcard', 'brafteditor'].includes(card.type)) { + isEntireLine = true + } + + return <Col key={card.uuid} className={isEntireLine ? 'textarea' + setting.cols : ''} span={isEntireLine ? 24 : _cols}> + <Card + id={card.uuid} + cols={setting.cols} + card={card} + showField={showField} + moveCard={moveCard} + editCard={editCard} + closeCard={closeCard} + copyCard={copyCard} + findCard={findCard} + /> + </Col> + })} + {cards.length === 0 && + <div className="modal-drawarea-placeholder"> + {placeholder} + </div> + } + </div> + ) +} +export default Container diff --git a/src/menu/components/form/dragelement/index.scss b/src/menu/components/form/dragelement/index.scss new file mode 100644 index 0000000..d68b01a --- /dev/null +++ b/src/menu/components/form/dragelement/index.scss @@ -0,0 +1,27 @@ +.modal-source-item { + display: block; + box-shadow: 0px 0px 2px #bcbcbc; + padding: 0.4rem 0.7rem; + background-color: white; + margin: 0px 0px 10px; + cursor: move; + border-radius: 4px; +} +.modal-drawarea-placeholder { + width: 100%; + line-height: 65px; + text-align: center; + color: #bcbcbc; +} +.modal-fields-row { + padding-bottom: 35px; + .ant-col { + padding-left: 12px; + padding-right: 12px; + } + >.ant-col { + display: inline-block; + float: none; + vertical-align: top; + } +} \ No newline at end of file diff --git a/src/menu/components/form/dragelement/source.jsx b/src/menu/components/form/dragelement/source.jsx new file mode 100644 index 0000000..7d4af72 --- /dev/null +++ b/src/menu/components/form/dragelement/source.jsx @@ -0,0 +1,13 @@ +import React from 'react' +import { useDrag } from 'react-dnd' +import './index.scss' + +const SourceElement = ({content}) => { + const [, drag] = useDrag({ item: content }) + return ( + <div ref={drag} className="modal-source-item"> + {content.label} + </div> + ) +} +export default SourceElement \ No newline at end of file diff --git a/src/menu/components/form/normal-form/index.jsx b/src/menu/components/form/normal-form/index.jsx new file mode 100644 index 0000000..14e5ec9 --- /dev/null +++ b/src/menu/components/form/normal-form/index.jsx @@ -0,0 +1,301 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' +import { is, fromJS } from 'immutable' +import { Icon, Popover, Modal, Carousel } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' + +import MKEmitter from '@/utils/events.js' +import Utils from '@/utils/utils.js' +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import './index.scss' + +const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) +const WrapComponent = asyncIconComponent(() => import('@/menu/components/form/wrapsetting')) +const CardComponent = asyncComponent(() => import('../dragelement')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) +const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) + +const { confirm } = Modal + +class PropCardEditComponent extends Component { + static propTpyes = { + card: PropTypes.object, + deletecomponent: PropTypes.func, + updateConfig: PropTypes.func, + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + card: null, + back: false + } + + UNSAFE_componentWillMount () { + const { card } = this.props + + if (card.isNew) { + let _card = { + uuid: card.uuid, + type: card.type, + floor: card.floor, + tabId: card.tabId || '', + parentId: card.parentId || '', + format: 'object', // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡 + pageable: false, // 缁勪欢灞炴�� - 鏄惁鍙垎椤� + switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹� + dataName: card.dataName || '', + width: card.width || 24, + name: card.name, + subtype: card.subtype, + setting: { }, + wrap: { name: card.name, width: card.width || 24, datatype: 'static' }, + style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, + columns: [], + scripts: [], + subcards: [{ + uuid: Utils.getuuid(), + setting: {}, + style: {}, + fields: [], + }], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + + _card.subcards = config.subcards.map(scard => { + scard.uuid = Utils.getuuid() + scard.fields = scard.fields.map(elem => { + elem.uuid = Utils.getuuid() + return elem + }) + return scard + }) + } + this.setState({ + card: _card + }) + this.props.updateConfig(_card) + } else { + this.setState({ + card: fromJS(card).toJS() + }) + } + } + + componentDidMount () { + MKEmitter.addListener('submitStyle', this.getStyle) + MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) || (!this.props.menu && nextProps.menu) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + MKEmitter.removeListener('submitStyle', this.getStyle) + MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) + } + + updateComponentStyle = (parentId, keys, style) => { + const { card } = this.state + + if (card.uuid !== parentId) return + + let subcards = card.subcards.map(item => { + if (keys.includes(item.uuid)) { + item.style = {...item.style, ...style} + } + return item + }) + + this.setState({card: {...card, subcards: []}}, () => { + this.updateComponent({...card, subcards: subcards}) + }) + } + + /** + * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級 + */ + updateComponent = (component) => { + this.setState({ + card: component + }) + + component.width = component.wrap.width + component.name = component.wrap.name + + this.props.updateConfig(component) + } + + /** + * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 + */ + updateCard = (cell) => { + let card = fromJS(this.state.card).toJS() + + card.subcards = card.subcards.map(item => { + if (item.uuid === cell.uuid) return cell + return item + }) + + this.setState({card}) + + this.props.updateConfig(card) + } + + /** + * @description 鍗曚釜鍗$墖淇℃伅鏇存柊 + */ + deleteCard = (cell) => { + let card = fromJS(this.state.card).toJS() + let _this = this + + confirm({ + content: '纭畾鍒犻櫎琛ㄥ崟鍚楋紵', + onOk() { + card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid) + + let uuids = [] + cell.elements && cell.elements.forEach(c => { + if (c.eleType === 'button') { + uuids.push(c.uuid) + } + }) + MKEmitter.emit('delButtons', uuids) + + _this.setState({card}) + _this.props.updateConfig(card) + }, + onCancel() {} + }) + } + + changeStyle = () => { + const { card } = this.state + + MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) + } + + getStyle = (comIds, style) => { + const { card } = this.state + + if (comIds.length !== 1 || comIds[0] !== card.uuid) return + + let _card = {...card, style} + + this.setState({ + card: _card + }) + + this.props.updateConfig(_card) + } + + addCard = () => { + let card = fromJS(this.state.card).toJS() + + let newcard = { + uuid: Utils.getuuid(), + setting: {}, + style: {}, + elements: [], + } + + if (card.subcards.length > 0) { + newcard = fromJS(card.subcards.slice(-1)[0]).toJS() + newcard.uuid = Utils.getuuid() + newcard.elements = newcard.elements.map(elem => { + elem.uuid = Utils.getuuid() + return elem + }) + } + + card.subcards.push(newcard) + + this.setState({card}) + this.props.updateConfig(card) + } + + move = (item, direction) => { + let card = fromJS(this.state.card).toJS() + + let dragIndex = card.subcards.findIndex(c => c.uuid === item.uuid) + let hoverIndex = null + + if (direction === 'left') { + hoverIndex = dragIndex - 1 + } else { + hoverIndex = dragIndex + 1 + } + + if (hoverIndex === -1 || hoverIndex === card.subcards.length) return + + card.subcards.splice(hoverIndex, 0, ...card.subcards.splice(dragIndex, 1)) + + this.setState({card: {...card, subcards: []}}, () => { + this.setState({card}) + }) + this.props.updateConfig(card) + } + + clickComponent = (e) => { + if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { + e.stopPropagation() + MKEmitter.emit('clickComponent', this.state.card) + } + } + + render() { + const { card } = this.state + + return ( + <div className="menu-normal-form-edit-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> + <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" /> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="propcard" card={card}/> + <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <UserComponent config={card}/> + <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> + {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null} + {card.wrap.datatype === 'static' ? <Icon style={{color: '#eeeeee', cursor: 'not-allowed'}} type="setting"/> : null} + </div> + } trigger="hover"> + <Icon type="tool" /> + </Popover> + {card.subcards.length > 0 ? <Carousel dotPosition={card.wrap.dotPosition || 'bottom'} effect={card.wrap.effect || 'scrollx'}> + {card.subcards.map((subcard) => (<CardComponent key={subcard.uuid} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + </Carousel> : null} + </div> + ) + } +} + +const mapStateToProps = (state) => { + return { + menu: state.customMenu + } +} + +const mapDispatchToProps = () => { + return {} +} + +export default connect(mapStateToProps, mapDispatchToProps)(PropCardEditComponent) \ No newline at end of file diff --git a/src/menu/components/form/normal-form/index.scss b/src/menu/components/form/normal-form/index.scss new file mode 100644 index 0000000..f40fc16 --- /dev/null +++ b/src/menu/components/form/normal-form/index.scss @@ -0,0 +1,92 @@ +.menu-normal-form-edit-box { + position: relative; + box-sizing: border-box; + background: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 30px; + + .card-control { + position: absolute; + top: 0px; + left: 0px; + .anticon-tool { + right: auto; + left: 1px; + padding: 1px; + } + } + .anticon-tool { + position: absolute; + z-index: 2; + font-size: 16px; + right: 1px; + top: 1px; + cursor: pointer; + padding: 5px; + background: rgba(255, 255, 255, 0.55); + } + + .card-item { + overflow: hidden; + position: relative; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 20px; + height: 100%; + } + .ant-carousel:not(.ant-carousel-vertical) { + .slick-dots li button { + height: 8px; + } + } + .ant-carousel.ant-carousel-vertical { + .slick-dots li button { + width: 8px; + } + } + .ant-carousel { + .slick-dots li button { + background: #1890ff; + } + } + + .card-item:hover { + box-shadow: 0px 0px 2px #1890ff; + } + + .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; + } + } + .card-add-button { + text-align: right; + clear: left; + .anticon-plus { + font-size: 20px; + color: #26C281; + padding: 5px; + margin-right: 10px; + } + } +} +.menu-normal-form-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-normal-form-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/form/wrapsetting/index.jsx b/src/menu/components/form/wrapsetting/index.jsx new file mode 100644 index 0000000..81346a6 --- /dev/null +++ b/src/menu/components/form/wrapsetting/index.jsx @@ -0,0 +1,83 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Modal } from 'antd' + +import zhCN from '@/locales/zh-CN/model.js' +import enUS from '@/locales/en-US/model.js' +import SettingForm from './settingform' +import './index.scss' + +class DataSource extends Component { + static propTpyes = { + config: PropTypes.any, + updateConfig: PropTypes.func + } + + state = { + dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, + visible: false, + wrap: null + } + + UNSAFE_componentWillMount () { + const { config } = this.props + + this.setState({wrap: fromJS(config.wrap).toJS()}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) + } + + editDataSource = () => { + this.setState({ + visible: true + }) + } + + verifySubmit = () => { + const { config } = this.props + + this.verifyRef.handleConfirm().then(res => { + + this.setState({ + wrap: res, + visible: false + }) + this.props.updateConfig({...config, wrap: res}) + }) + } + + render () { + const { config } = this.props + const { visible, dict, wrap } = this.state + + return ( + <div className="model-menu-setting-wrap"> + <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} /> + <Modal + wrapClassName="popview-modal" + title={config.type === 'table' ? '琛ㄦ牸璁剧疆' : '鍗$墖璁剧疆'} + visible={visible} + width={800} + maskClosable={false} + okText={dict['model.submit']} + onOk={this.verifySubmit} + onCancel={() => { this.setState({ visible: false }) }} + destroyOnClose + > + <SettingForm + dict={dict} + wrap={wrap} + config={config} + inputSubmit={this.verifySubmit} + wrappedComponentRef={(inst) => this.verifyRef = inst} + /> + </Modal> + </div> + ) + } +} + +export default DataSource \ No newline at end of file diff --git a/src/menu/components/form/wrapsetting/index.scss b/src/menu/components/form/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/menu/components/form/wrapsetting/index.scss @@ -0,0 +1,7 @@ +.model-menu-setting-wrap { + display: inline-block; + + >.anticon-edit { + color: #1890ff; + } +} \ No newline at end of file diff --git a/src/menu/components/form/wrapsetting/settingform/index.jsx b/src/menu/components/form/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..08b58e2 --- /dev/null +++ b/src/menu/components/form/wrapsetting/settingform/index.jsx @@ -0,0 +1,253 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' + +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, // 瀛楀吀椤� + config: PropTypes.object, // 鍗$墖琛屼俊鎭� + wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + } + + state = { + roleList: [] + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + this.setState({roleList}) + } + + handleConfirm = () => { + // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭� + return new Promise((resolve, reject) => { + this.props.form.validateFieldsAndScroll((err, values) => { + if (!err) { + resolve(values) + } else { + reject(err) + } + }) + }) + } + + handleSubmit = (e) => { + e.preventDefault() + + if (this.props.inputSubmit) { + this.props.inputSubmit() + } + } + + render() { + const { wrap, config } = this.props + const { getFieldDecorator } = this.props.form + const { roleList } = this.state + + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 8 } + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 } + } + } + + return ( + <div className="model-menu-setting-form"> + <Form {...formItemLayout}> + <Row gutter={24}> + <Col span={12}> + <Form.Item label="鏍囬"> + {getFieldDecorator('title', { + initialValue: wrap.title || '' + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�"> + <Icon type="question-circle" /> + 缁勪欢鍚嶇О + </Tooltip> + }> + {getFieldDecorator('name', { + initialValue: wrap.name, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!' + } + ] + })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��"> + <Icon type="question-circle" /> + 瀹藉害 + </Tooltip> + }> + {getFieldDecorator('width', { + initialValue: wrap.width || 24, + rules: [ + { + required: true, + message: this.props.dict['form.required.input'] + '瀹藉害!' + } + ] + })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> + {config.subtype === 'propcard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��"> + <Icon type="question-circle" /> + 鏁版嵁鏉ユ簮 + </Tooltip> + }> + {getFieldDecorator('datatype', { + initialValue: wrap.datatype || 'dynamic' + })( + <Radio.Group> + <Radio value="dynamic">鍔ㄦ��</Radio> + <Radio value="static">闈欐��</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype === 'datacard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="鏁版嵁婧愪腑閫夋嫨鍒嗛〉鏃舵湁鏁堛��"> + <Icon type="question-circle" /> + 鍒嗛〉椋庢牸 + </Tooltip> + }> + {getFieldDecorator('pagestyle', { + initialValue: wrap.pagestyle || 'page' + })( + <Radio.Group> + <Radio value="page">椤电爜</Radio> + <Radio value="switch">宸﹀彸鍒囨崲</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype !== 'tablecard' ? <Col span={12}> + <Form.Item label="鍗$墖灞炴��"> + {getFieldDecorator('cardType', { + initialValue: wrap.cardType || '' + })( + <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio key="" value=""> 涓嶅彲閫� </Radio> + <Radio key="radio" value={'radio'}> 鍗曢�� </Radio> + {config.subtype !== 'propcard' ? <Radio key="checkbox" value={'checkbox'}> 澶氶�� </Radio> : null} + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype !== 'tablecard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="璁剧疆涓哄眳涓榻愭垨鍙冲榻愶紝鍙湪鍗$墖涓�1琛屾椂鏈夋晥銆�"> + <Icon type="question-circle" /> + 鍗$墖鎺掑垪 + </Tooltip> + }> + {getFieldDecorator('cardFloat', { + initialValue: wrap.cardFloat || 'left' + })( + <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio key="left" value="left"> 宸﹀榻� </Radio> + <Radio key="center" value="center"> 灞呬腑 </Radio> + <Radio key="right" value="right"> 鍙冲榻� </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype !== 'tablecard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��"> + <Icon type="question-circle" /> + 鍗$墖鏀惧ぇ + </Tooltip> + }> + {getFieldDecorator('scale', { + initialValue: wrap.scale || 'false' + })( + <Radio.Group> + <Radio key="false" value="false"> 鍚� </Radio> + <Radio key="true" value="true"> 鏄� </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + {config.subtype === 'tablecard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="琛ㄦ牸楂樺害锛岃秴鍑烘椂婊氬姩锛岄珮搴︿负绌烘椂鏍规嵁鍐呭鑷�傚簲銆�"> + <Icon type="question-circle" /> + 楂樺害 + </Tooltip> + }> + {getFieldDecorator('height', { + initialValue: wrap.height + })(<InputNumber min={100} max={2000} precision={0} onPressEnter={this.handleSubmit} />)} + </Form.Item> + </Col> : null} + {config.subtype === 'propcard' ? <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="閫夋嫨绫诲瀷涓恒�婇〉鐪�/椤佃剼銆嬫椂锛屾墦鍗扮殑姣忛〉閲岄兘浼氬甫鏈夎缁勪欢銆�"> + <Icon type="question-circle" /> + 缁勪欢绫诲瀷 + </Tooltip> + }> + {getFieldDecorator('printType', { + initialValue: wrap.printType || 'content' + })( + <Radio.Group> + <Radio value="content">鍐呭</Radio> + <Radio value="headerOrfooter">椤电湁/椤佃剼</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label="榛戝悕鍗�"> + {getFieldDecorator('blacklist', { + initialValue: wrap.blacklist || [] + })( + <Select + showSearch + mode="multiple" + filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} + > + {roleList.map(option => + <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option> + )} + </Select> + )} + </Form.Item> + </Col> + </Row> + </Form> + </div> + ) + } +} + +export default Form.create()(SettingForm) \ No newline at end of file diff --git a/src/menu/components/form/wrapsetting/settingform/index.scss b/src/menu/components/form/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..159130b --- /dev/null +++ b/src/menu/components/form/wrapsetting/settingform/index.scss @@ -0,0 +1,11 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } +} \ No newline at end of file diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx index 8150032..b89e539 100644 --- a/src/menu/menushell/card.jsx +++ b/src/menu/menushell/card.jsx @@ -14,6 +14,7 @@ const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) +const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) @@ -58,6 +59,8 @@ return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'pie') { return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'form') { + return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'tabs') { return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'card' && card.subtype === 'datacard') { diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx index 5f65129..05c87c4 100644 --- a/src/menu/menushell/index.jsx +++ b/src/menu/menushell/index.jsx @@ -92,6 +92,7 @@ editor: '瀵屾枃鏈�', code: '鑷畾涔�', carousel: '杞挱', + form: '琛ㄥ崟', card: '鍗$墖' } let i = 1 diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx index 155a031..c6fa855 100644 --- a/src/menu/modalconfig/index.jsx +++ b/src/menu/modalconfig/index.jsx @@ -259,7 +259,7 @@ if (_config.groups.length > 0) { _config.groups.forEach(group => { group.sublist = group.sublist.map(item => { - if (item.uuid !== res.uuid && item.field.toLowerCase() === res.field.toLowerCase()) { + if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { fieldrepet = true } else if (item.uuid !== res.uuid && item.label === res.label) { labelrepet = true @@ -274,7 +274,7 @@ }) } else { _config.fields = _config.fields.map(item => { - if (item.uuid !== res.uuid && item.field.toLowerCase() === res.field.toLowerCase()) { + if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { fieldrepet = true } else if (item.uuid !== res.uuid && item.label === res.label) { labelrepet = true diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss index 7dcf66e..be336b4 100644 --- a/src/menu/modalconfig/index.scss +++ b/src/menu/modalconfig/index.scss @@ -216,6 +216,10 @@ width: 100%; margin-top: 4px; } + .normal-braft-editor { + border: 1px solid #d9d9d9; + border-radius: 4px; + } } .ant-form-item-control-wrapper::after { content: ''; diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx index 112abf9..957a360 100644 --- a/src/menu/modulesource/option.jsx +++ b/src/menu/modulesource/option.jsx @@ -16,6 +16,7 @@ import Mainsearch from '@/assets/mobimg/mainsearch.png' import Carousel from '@/assets/mobimg/carousel.png' import Carousel1 from '@/assets/mobimg/carousel1.png' +import form from '@/assets/mobimg/form.png' // 缁勪欢閰嶇疆淇℃伅 export const menuOptions = [ @@ -23,6 +24,7 @@ { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', width: 24 }, { type: 'menu', url: card2, component: 'card', subtype: 'propcard', title: '灞炴�у崱', width: 24 }, + { type: 'menu', url: form, component: 'form', subtype: 'form', title: '琛ㄥ崟', width: 24 }, { type: 'menu', url: Carousel, component: 'carousel', subtype: 'datacard', title: '杞挱-鍔ㄦ�佹暟鎹�', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: Carousel1, component: 'carousel', subtype: 'propcard', title: '杞挱-闈欐�佹暟鎹�', width: 24, forbid: ['billPrint'] }, { type: 'menu', url: NormalTable, component: 'table', subtype: 'normaltable', title: '甯哥敤琛�', width: 24 }, diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx index 8cb2174..7010528 100644 --- a/src/tabviews/zshare/mutilform/index.jsx +++ b/src/tabviews/zshare/mutilform/index.jsx @@ -1391,14 +1391,14 @@ render() { const { cols } = this.state const formItemLayout = { - labelCol: { - xs: { span: 24 }, - sm: { span: 8 } - }, - wrapperCol: { - xs: { span: 24 }, - sm: { span: 16 } - } + // labelCol: { + // xs: { span: 24 }, + // sm: { span: 8 } + // }, + // wrapperCol: { + // xs: { span: 24 }, + // sm: { span: 16 } + // } } return ( diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx index 4493ddb..f07861f 100644 --- a/src/templates/formtabconfig/index.jsx +++ b/src/templates/formtabconfig/index.jsx @@ -905,7 +905,7 @@ if (_ismutil && group.sublist.length === 0) { _config.enabled = false } - let arr = group.sublist.filter(item => item.field.toLowerCase() === _primary) + let arr = group.sublist.filter(item => item.field && item.field.toLowerCase() === _primary) if (arr.length > 0) { _config.enabled = false @@ -1619,7 +1619,7 @@ let primaryrepeat = false config.groups.forEach(group => { - let arr = group.sublist.filter(item => item.field.toLowerCase() === _primary) + let arr = group.sublist.filter(item => item.field && item.field.toLowerCase() === _primary) if (arr.length > 0) { primaryrepeat = true diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx index 1db628e..d7e42bb 100644 --- a/src/templates/modalconfig/index.jsx +++ b/src/templates/modalconfig/index.jsx @@ -359,7 +359,7 @@ if (_config.groups.length > 0) { _config.groups.forEach(group => { group.sublist = group.sublist.map(item => { - if (item.uuid !== res.uuid && item.field.toLowerCase() === res.field.toLowerCase()) { + if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { fieldrepet = true } else if (item.uuid !== res.uuid && item.label === res.label) { labelrepet = true @@ -374,7 +374,7 @@ }) } else { _config.fields = _config.fields.map(item => { - if (item.uuid !== res.uuid && item.field.toLowerCase() === res.field.toLowerCase()) { + if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) { fieldrepet = true } else if (item.uuid !== res.uuid && item.label === res.label) { labelrepet = true diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx index a828bf7..43bb69b 100644 --- a/src/templates/sharecomponent/fieldscomponent/index.jsx +++ b/src/templates/sharecomponent/fieldscomponent/index.jsx @@ -70,7 +70,7 @@ if (config.groups.length > 1) { config.groups.forEach(group => { group.sublist.forEach(item => { - if (columns.has(item.field.toLowerCase())) { + if (item.field && columns.has(item.field.toLowerCase())) { let _datatype = columns.get(item.field.toLowerCase()).datatype columns.set(item.field.toLowerCase(), {...item, selected: true, datatype: _datatype}) } @@ -78,7 +78,7 @@ }) } else { config.fields.forEach(item => { - if (columns.has(item.field.toLowerCase())) { + if (item.field && columns.has(item.field.toLowerCase())) { let _datatype = columns.get(item.field.toLowerCase()).datatype columns.set(item.field.toLowerCase(), {...item, selected: true, datatype: _datatype}) } @@ -243,7 +243,7 @@ config.groups.forEach(group => { let _items = [] group.sublist.forEach(item => { - if (columnsMap.has(item.field.toLowerCase())) { + if (item.field && columnsMap.has(item.field.toLowerCase())) { let cell = columnsMap.get(item.field.toLowerCase()) if (cell.selected && cell.type === item.type) { // 鏁版嵁閫夋嫨鐘舵�佸強绫诲瀷鏈慨鏀规椂锛岀洿鎺ユ坊鍔� @@ -283,7 +283,7 @@ config.groups[config.groups.length - 1].sublist = [...config.groups.slice(-1)[0].sublist, ..._additems] } else { config.fields.forEach(item => { - if (columnsMap.has(item.field.toLowerCase())) { + if (item.field && columnsMap.has(item.field.toLowerCase())) { let cell = columnsMap.get(item.field.toLowerCase()) if (cell.selected && cell.type === item.type) { // 鏁版嵁閫夋嫨鐘舵�佸強绫诲瀷鏈慨鏀规椂锛岀洿鎺ユ坊鍔� diff --git a/src/templates/zshare/editcomponent/index.jsx b/src/templates/zshare/editcomponent/index.jsx index d10b9a9..154eadb 100644 --- a/src/templates/zshare/editcomponent/index.jsx +++ b/src/templates/zshare/editcomponent/index.jsx @@ -224,7 +224,7 @@ if (_config.groups.length > 0) { _config.groups.forEach(group => { group.sublist.forEach(item => { - fields.push(item.field.toLowerCase()) + item.field && fields.push(item.field.toLowerCase()) labels.push(item.label) }) if (group.default) { @@ -233,13 +233,13 @@ }) } else { _config.fields.forEach(item => { - fields.push(item.field.toLowerCase()) + item.field && fields.push(item.field.toLowerCase()) labels.push(item.label) }) _config.fields.push(res) } - if (fields.includes(res.field.toLowerCase())) { + if (res.field && fields.includes(res.field.toLowerCase())) { notification.warning({ top: 92, message: '瀛楁宸插瓨鍦紒', -- Gitblit v1.8.0