From 9f3a0655391c42dc7fb9a3cfa6d8fc4ca935bd9d Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期二, 29 十二月 2020 18:29:37 +0800 Subject: [PATCH] 2020-12-29 --- src/menu/components/share/pastecomponent/index.jsx | 175 +++++++++++++++++++ src/menu/components/card/table-card/index.jsx | 9 src/templates/zshare/pasteform/index.jsx | 11 src/menu/components/card/cardcomponent/index.jsx | 14 + src/menu/components/share/pastecomponent/index.scss | 0 src/menu/pastecontroller/index.jsx | 193 +++++++++++++++++++++ src/menu/components/card/data-card/index.jsx | 4 src/menu/components/chart/antv-pie/index.jsx | 4 src/menu/components/search/main-search/index.jsx | 4 src/templates/zshare/editcomponent/index.jsx | 2 src/menu/components/chart/antv-bar/index.jsx | 4 src/menu/pastecontroller/index.scss | 0 src/menu/components/card/table-card/cardcomponent/index.jsx | 5 src/menu/components/share/copycomponent/index.jsx | 46 +++++ src/menu/components/card/prop-card/index.jsx | 29 ++ src/menu/components/table/normal-table/index.jsx | 4 src/menu/components/share/copycomponent/index.scss | 0 src/menu/components/tabs/antv-tabs/index.jsx | 17 + src/views/menudesign/index.jsx | 17 + 19 files changed, 521 insertions(+), 17 deletions(-) diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx index 1fb88ef..b16e051 100644 --- a/src/menu/components/card/cardcomponent/index.jsx +++ b/src/menu/components/card/cardcomponent/index.jsx @@ -4,6 +4,7 @@ import { Modal, Popover, Icon, Switch, Col } 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' @@ -13,12 +14,14 @@ import './index.scss' const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) class CardBoxComponent extends Component { static propTpyes = { offset: PropTypes.any, // 鍋忕Щ閲� cards: PropTypes.object, // 鍗$墖琛岄厤缃俊鎭� card: PropTypes.object, // 鍗$墖閰嶇疆淇℃伅 + move: PropTypes.func, // 鍗$墖绉诲姩 deleteElement: PropTypes.func, // 鍗$墖鍒犻櫎 updateElement: PropTypes.func // 鑿滃崟閰嶇疆鏇存柊 } @@ -233,8 +236,17 @@ <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" type="edit" onClick={() => this.setState({settingVisible: true})} /> + <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)}> + <Icon type="swap" id={card.uuid}/> + </Popover> : null} {cards.subtype === 'propcard' ? <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> : null} {card.setting.type === 'multi' ? <Switch size="small" onClick={this.changeSide} defaultChecked /> : null} </div> diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx index aec0a96..95244bc 100644 --- a/src/menu/components/card/data-card/index.jsx +++ b/src/menu/components/card/data-card/index.jsx @@ -17,6 +17,8 @@ const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) const CardComponent = asyncComponent(() => import('../cardcomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) @@ -381,6 +383,8 @@ <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="datacard" card={card}/> + <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx index aefe5b6..0040e4d 100644 --- a/src/menu/components/card/prop-card/index.jsx +++ b/src/menu/components/card/prop-card/index.jsx @@ -16,6 +16,8 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting')) const CardComponent = asyncComponent(() => import('../cardcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) @@ -304,8 +306,27 @@ } } + 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}) + this.props.updateConfig(card) + } + render() { - const { menu } = this.props const { card } = this.state let offset = 0 @@ -326,7 +347,9 @@ <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" /> - {menu ? <WrapComponent config={card} MenuType={menu.MenuType} updateConfig={this.updateComponent} /> : null} + <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" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> @@ -336,7 +359,7 @@ } trigger="hover"> <Icon type="tool" /> </Popover> - {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} MenuType={menu ? menu.MenuType : ''} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + {card.subcards.map((subcard, index) => (<CardComponent key={subcard.uuid} offset={!index ? offset : 0} cards={card} card={subcard} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} </div> ) } diff --git a/src/menu/components/card/table-card/cardcomponent/index.jsx b/src/menu/components/card/table-card/cardcomponent/index.jsx index 7cf24f4..09b052e 100644 --- a/src/menu/components/card/table-card/cardcomponent/index.jsx +++ b/src/menu/components/card/table-card/cardcomponent/index.jsx @@ -4,6 +4,7 @@ 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' @@ -13,6 +14,7 @@ import './index.scss' const CardCellComponent = asyncComponent(() => import('../../cardcellcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) class CardBoxComponent extends Component { static propTpyes = { @@ -171,7 +173,8 @@ <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" type="edit" onClick={() => this.setState({settingVisible: true})} /> + <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" /> <Icon className="close" title="鍒犻櫎鍗$墖" type="delete" onClick={() => this.props.deleteElement(card)} /> </div> diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx index eae5304..7486c33 100644 --- a/src/menu/components/card/table-card/index.jsx +++ b/src/menu/components/card/table-card/index.jsx @@ -16,6 +16,8 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting')) const CardComponent = asyncComponent(() => import('./cardcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) @@ -308,7 +310,6 @@ } render() { - const { menu } = this.props const { card } = this.state return ( @@ -318,7 +319,9 @@ <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 ? <WrapComponent config={card} MenuType={menu.MenuType} updateConfig={this.updateComponent} /> : null} + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="tablecard" card={card}/> + <PasteComponent config={card} options={['cardcell', 'search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> @@ -328,7 +331,7 @@ <Icon type="tool" /> </Popover> <div style={{minHeight: card.wrap.height - 90}}> - {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} MenuType={menu ? menu.MenuType : ''} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} + {card.subcards.map(subcard => (<CardComponent key={subcard.uuid} cards={card} card={subcard} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))} </div> {card.setting.laypage === 'true' ? <Pagination size="small" total={50} /> : null} </div> diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx index 14f13f7..95f9131 100644 --- a/src/menu/components/chart/antv-bar/index.jsx +++ b/src/menu/components/chart/antv-bar/index.jsx @@ -19,6 +19,8 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) @@ -861,6 +863,8 @@ <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> + <CopyComponent type="line" card={card}/> + <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx index 3535bbb..b5d947d 100644 --- a/src/menu/components/chart/antv-pie/index.jsx +++ b/src/menu/components/chart/antv-pie/index.jsx @@ -17,6 +17,8 @@ const SettingComponent = asyncIconComponent(() => import('@/menu/datasource')) const ChartCompileForm = asyncIconComponent(() => import('./chartcompile')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) @@ -432,6 +434,8 @@ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> <ChartCompileForm config={card} dict={this.state.dict} plotchange={this.updateComponent}/> + <CopyComponent type="pie" card={card}/> + <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx index 87bbadc..12b5278 100644 --- a/src/menu/components/search/main-search/index.jsx +++ b/src/menu/components/search/main-search/index.jsx @@ -20,6 +20,8 @@ const { confirm } = Modal const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) class MainSearchComponent extends Component { static propTpyes = { @@ -353,6 +355,8 @@ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞" onClick={this.addSearch} type="plus" /> <WrapComponent config={card} updateConfig={this.updateComponent}/> + <CopyComponent type="mainsearch" card={card}/> + <PasteComponent config={card} options={['search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> </div> diff --git a/src/menu/components/share/copycomponent/index.jsx b/src/menu/components/share/copycomponent/index.jsx new file mode 100644 index 0000000..a4c90ed --- /dev/null +++ b/src/menu/components/share/copycomponent/index.jsx @@ -0,0 +1,46 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Icon, message } from 'antd' +import './index.scss' + +class CopyComponent extends Component { + static propTpyes = { + btnlog: PropTypes.array, + handlelog: PropTypes.func + } + + trigger = () => { + const { card, type } = this.props + let copycard = fromJS(card).toJS() + copycard.copyType = type + + let _val = '' + + try { + _val = window.btoa(window.encodeURIComponent(JSON.stringify(copycard))) + } catch { + message.warning('澶嶅埗澶辫触锛岃閲嶈瘯锛�') + _val = '' + } + + if (_val) { + let oInput = document.createElement('input') + oInput.value = _val + document.body.appendChild(oInput) + oInput.select() + document.execCommand('Copy') + document.body.removeChild(oInput) + + message.success('澶嶅埗鎴愬姛銆�') + } + } + + render () { + return ( + <Icon type="copy" title="澶嶅埗" style={{color: '#26C281'}} onClick={this.trigger} /> + ) + } +} + +export default CopyComponent \ No newline at end of file diff --git a/src/menu/components/share/copycomponent/index.scss b/src/menu/components/share/copycomponent/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/menu/components/share/copycomponent/index.scss diff --git a/src/menu/components/share/pastecomponent/index.jsx b/src/menu/components/share/pastecomponent/index.jsx new file mode 100644 index 0000000..95ffb34 --- /dev/null +++ b/src/menu/components/share/pastecomponent/index.jsx @@ -0,0 +1,175 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Icon, Modal, notification } from 'antd' + +import Utils from '@/utils/utils.js' +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + config: PropTypes.object, // 缁勪欢閰嶇疆 + updateConfig: PropTypes.func + } + + state = { + visible: false + } + + handleMenuClick = () => { + this.setState({visible: true}) + } + + resetconfig = (item) => { + item.uuid = Utils.getuuid() + + if (item.copyType === 'cardcell') { + item.setting = item.setting || {} + item.setting.width = item.setting.width || 6 + + if (item.elements) { + item.elements = item.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + if (item.backElements) { + item.backElements = item.backElements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + } else if (item.copyType === 'table') { + let loopCol = (col) => { + col.subcols = col.subcols.map(c => { + c.uuid = Utils.getuuid() + + if (c.type === 'colspan' && c.subcols) { + c = loopCol(c) + } else if (c.type === 'custom' && c.elements) { + c.elements = c.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } else if (c.type === 'action' && c.elements) { + c.elements = c.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + return c + }) + + return col + } + + if (item.type === 'colspan' && item.subcols) { + item = loopCol(item) + } else if (item.type === 'custom' && item.elements) { + item.elements = item.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } else if (item.type === 'action' && item.elements) { + item.elements = item.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + } + + return item + } + + pasteSubmit = () => { + const { options } = this.props + this.pasteFormRef.handleConfirm().then(res => { + if (!options.includes(res.copyType)) { + notification.warning({ + top: 92, + message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', + duration: 5 + }) + return + } + + let type = res.copyType + let config = fromJS(this.props.config).toJS() + + res = this.resetconfig(res) + delete res.copyType + + if (type === 'action') { + config.action = config.action || [] + config.action = config.action.filter(item => !item.origin) + + config.action.push(res) + } else if (type === 'search' || type === 'form') { + config.search = config.search || [] + config.search = config.search.filter(item => !item.origin) + + let keys = config.search.map(item => item.field.toLowerCase()) + + if (type === 'form') { + if (['number', 'switch', 'textarea', 'checkcard', 'fileupload', 'hint', 'color', 'funcvar'].includes(res.type)) { + res.type = 'text' + } else if (res.type === 'radio') { + res.type = 'select' + } else if (res.type === 'checkbox') { + res.type = 'multiselect' + } else if (res.type === 'datetime') { + res.type = 'date' + } + } + + if (res.field && keys.includes(res.field.toLowerCase())) { + notification.warning({ + top: 92, + message: '鎼滅储瀛楁宸插瓨鍦紒', + duration: 5 + }) + return + } + + config.search.push(res) + } else if (type === 'cardcell') { + config.subcards.push(res) + } + + this.props.updateConfig(config) + this.setState({visible: false}) + + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + }) + } + + render() { + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/menu/components/share/pastecomponent/index.scss b/src/menu/components/share/pastecomponent/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/menu/components/share/pastecomponent/index.scss diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx index 7d72415..fbf625e 100644 --- a/src/menu/components/table/normal-table/index.jsx +++ b/src/menu/components/table/normal-table/index.jsx @@ -18,6 +18,8 @@ const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent')) const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent')) const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent')) const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent')) const ColumnComponent = asyncComponent(() => import('./columns')) const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) @@ -328,6 +330,8 @@ <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="normaltable" card={card}/> + <PasteComponent config={card} options={['action', 'search', 'form']} updateConfig={this.updateComponent} /> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> diff --git a/src/menu/components/tabs/antv-tabs/index.jsx b/src/menu/components/tabs/antv-tabs/index.jsx index 720b8b4..7aaaeef 100644 --- a/src/menu/components/tabs/antv-tabs/index.jsx +++ b/src/menu/components/tabs/antv-tabs/index.jsx @@ -15,6 +15,8 @@ import './index.scss' const SettingComponent = asyncIconComponent(() => import('../tabsetting')) +const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) +const PasteController = asyncIconComponent(() => import('@/menu/pastecontroller')) const TabLabelComponent = asyncComponent(() => import('../tablabelform')) const TabComponents = asyncComponent(() => import('../tabcomponents')) @@ -238,6 +240,19 @@ this.props.updateConfig(tabs) } + insert = (item, tab) => { + let tabs = fromJS(this.state.tabs).toJS() + + tabs.subtabs.forEach(stab => { + if (stab.uuid === tab.uuid) { + stab.components.push(item) + } + }) + + this.setState({tabs}) + this.props.updateConfig(tabs) + } + render() { const { tabs, dict, labelvisible, editab } = this.state @@ -249,6 +264,7 @@ <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={() => this.editTab(tab)} /> + <PasteController type="tab" Tab={tab} insert={this.insert} /> <Icon className="close" title="delete" type="close" onClick={() => this.delTab(tab)} /> </div> } trigger="hover"> @@ -263,6 +279,7 @@ <div className="mk-popover-control"> <Icon className="plus" title="娣诲姞鏍囩" type="plus" onClick={this.tabAdd} /> <SettingComponent config={tabs} updateConfig={this.updateComponent} /> + <CopyComponent type="tabs" card={tabs}/> <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> </div> diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx new file mode 100644 index 0000000..1578179 --- /dev/null +++ b/src/menu/pastecontroller/index.jsx @@ -0,0 +1,193 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { Icon, Modal, Button, notification } from 'antd' + +import Utils from '@/utils/utils.js' +import asyncComponent from '@/utils/asyncComponent' +import './index.scss' + +const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform')) + +class PasteController extends Component { + static propTpyes = { + type: PropTypes.any, // 缁勪欢绫诲瀷 + Tab: PropTypes.any, // 鏍囩锛屾坊鍔犺彍鍗曠粍浠舵椂涓虹┖ + insert: PropTypes.func + } + + state = { + visible: false + } + + handleMenuClick = () => { + this.setState({visible: true}) + } + + resetconfig = (item, Tab) => { + item.uuid = Utils.getuuid() + item.floor = Tab ? (Tab.floor + 1) : 1 + + if (Tab) { + item.tabId = Tab.uuid + item.parentId = Tab.parentId + } + + if (item.type === 'tabs') { + item.subtabs.forEach(tab => { + tab.uuid = Utils.getuuid() + tab.parentId = item.uuid + + if (item.floor >= 3) { + tab.components = tab.components.filter(cell => cell.type !== 'tabs') + } + + tab.components = tab.components.map(cell => { + cell = this.resetconfig(cell, tab) + return cell + }) + }) + } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { + item.subcards.forEach(card => { + card.uuid = Utils.getuuid() + if (card.elements) { + card.elements = card.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + if (card.backElements) { + card.backElements = card.backElements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + }) + } else if (item.type === 'table' && item.subtype === 'normaltable' && item.cols) { + let loopCol = (col) => { + col.subcols = col.subcols.map(c => { + c.uuid = Utils.getuuid() + + if (c.type === 'colspan' && c.subcols) { + c = loopCol(c) + } else if (c.type === 'custom' && c.elements) { + c.elements = c.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } else if (c.type === 'action' && c.elements) { + c.elements = c.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + return c + }) + + return col + } + + item.cols = item.cols.map(col => { + col.uuid = Utils.getuuid() + + if (col.type === 'colspan' && col.subcols) { + col = loopCol(col) + } else if (col.type === 'custom' && col.elements) { + col.elements = col.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } else if (col.type === 'action' && col.elements) { + col.elements = col.elements.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + return col + }) + } + + if (item.btnlog) { + item.btnlog = [] + } + + if (item.action) { + item.action = item.action.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + if (item.search) { + item.search = item.search.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + if (item.columns) { + item.columns = item.columns.map(cell => { + cell.uuid = Utils.getuuid() + return cell + }) + } + + return item + } + + pasteSubmit = () => { + const { Tab } = this.props + this.pasteFormRef.handleConfirm().then(res => { + if (!['tabs', 'datacard', 'propcard', 'mainsearch', 'normaltable', 'tablecard', 'line', 'bar', 'pie'].includes(res.copyType)) { + notification.warning({ + top: 92, + message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�', + duration: 5 + }) + return + } else if (Tab && Tab.floor === 3 && res.type === 'tabs') { + notification.warning({ + top: 92, + message: '鏍囩椤垫渶澶氫负涓夐噸缁撴瀯锛�', + duration: 5 + }) + return + } + + res = this.resetconfig(res, Tab) + + delete res.copyType + + this.props.insert(res, Tab) + this.setState({visible: false}) + + notification.success({ + top: 92, + message: '绮樿创鎴愬姛锛�', + duration: 2 + }) + }) + } + + render() { + const { type } = this.props + const { visible } = this.state + + return ( + <div style={{display: 'inline-block'}}> + {type !== 'menu' ? <Icon type="snippets" style={{color: 'purple'}} onClick={() => {this.setState({visible: true})}} /> : null} + {type === 'menu' ? <Button type="link" style={{padding: '5px'}} icon="snippets" onClick={() => {this.setState({visible: true})}}>绮樿创</Button> : null} + <Modal + title="绮樿创" + visible={visible} + width={600} + maskClosable={false} + onOk={this.pasteSubmit} + onCancel={() => {this.setState({visible: false})}} + destroyOnClose + > + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst} inputSubmit={this.pasteSubmit}/> + </Modal> + </div> + ) + } +} + +export default PasteController \ No newline at end of file diff --git a/src/menu/pastecontroller/index.scss b/src/menu/pastecontroller/index.scss new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/menu/pastecontroller/index.scss diff --git a/src/templates/zshare/editcomponent/index.jsx b/src/templates/zshare/editcomponent/index.jsx index 18bc492..769e66a 100644 --- a/src/templates/zshare/editcomponent/index.jsx +++ b/src/templates/zshare/editcomponent/index.jsx @@ -312,7 +312,7 @@ onCancel={() => {this.setState({pasteVisible: false})}} destroyOnClose > - <PasteForm dict={dict} wrappedComponentRef={(inst) => this.pasteFormRef = inst}/> + <PasteForm wrappedComponentRef={(inst) => this.pasteFormRef = inst}/> </Modal> </div> ) diff --git a/src/templates/zshare/pasteform/index.jsx b/src/templates/zshare/pasteform/index.jsx index b843b94..016a03f 100644 --- a/src/templates/zshare/pasteform/index.jsx +++ b/src/templates/zshare/pasteform/index.jsx @@ -1,14 +1,13 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import { Form, Row, Col, Input, notification } from 'antd' -import Utils from '@/utils/utils.js' import './index.scss' const { TextArea } = Input class MainSearch extends Component { static propTpyes = { - dict: PropTypes.object // 瀛楀吀椤� + inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 } componentDidMount () { @@ -38,10 +37,6 @@ duration: 5 }) _config = '' - } - - if (_config && _config.uuid) { // 姣忔绮樿创鏃舵洿鏂癐D锛岄槻姝㈤噸澶嶇矘璐存椂id閲嶅 - _config.uuid = Utils.getuuid() } if (_config) { @@ -76,10 +71,10 @@ rules: [ { required: true, - message: this.props.dict['form.required.input'] + '閰嶇疆淇℃伅!' + message: '璇疯緭鍏ラ厤缃俊鎭�!' } ] - })(<TextArea autoSize={{ minRows: 6, maxRows: 6 }} />)} + })(<TextArea autoSize={{ minRows: 6, maxRows: 6 }} onPressEnter={() => this.props.inputSubmit && this.props.inputSubmit()}/>)} </Form.Item> </Col> </Row> diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx index ab016ad..dd9c02a 100644 --- a/src/views/menudesign/index.jsx +++ b/src/views/menudesign/index.jsx @@ -30,6 +30,7 @@ const SourceWrap = asyncComponent(() => import('@/menu/modelsource')) const MenuShell = asyncComponent(() => import('@/menu/menushell')) const BgController = asyncComponent(() => import('@/menu/bgcontroller')) +const PasteController = asyncComponent(() => import('@/menu/pastecontroller')) const PaddingController = asyncComponent(() => import('@/menu/padcontroller')) const StyleController = asyncComponent(() => import('@/menu/stylecontroller')) const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller')) @@ -48,6 +49,7 @@ MenuNo: '', tableFields: [], delButtons: [], + copyButtons: [], activeKey: 'basedata', menuloading: false, oriConfig: null, @@ -85,6 +87,7 @@ componentDidMount () { MKEmitter.addListener('delButtons', this.delButtons) + MKEmitter.addListener('copyButtons', this.copyButtons) MKEmitter.addListener('changePopview', this.initPopview) } @@ -96,11 +99,15 @@ return } MKEmitter.removeListener('delButtons', this.delButtons) + MKEmitter.removeListener('copyButtons', this.copyButtons) MKEmitter.removeListener('changePopview', this.initPopview) } delButtons = (items) => { this.setState({delButtons: [...this.state.delButtons, ...items]}) + } + copyButtons = (items) => { + this.setState({copyButtons: [...this.state.copyButtons, ...items]}) } initPopview = (card, btn) => { @@ -608,6 +615,15 @@ this.props.modifyCustomMenu(config) } + insert = (item) => { + let config = fromJS(this.state.config).toJS() + + config.components.push(item) + + this.setState({config}) + this.props.modifyCustomMenu(config) + } + /** * @description 鏇存柊甯哥敤琛ㄤ俊鎭紝蹇嵎娣诲姞鍚庢洿鏂伴厤缃俊鎭� */ @@ -677,6 +693,7 @@ <div> {config && config.MenuName} </div> } bordered={false} extra={ <div> + <PasteController type="menu" Tab={null} insert={this.insert} /> {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null} <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button> <Button type="default" onClick={this.closeView}>{dict['mob.return']}</Button> -- Gitblit v1.8.0