From ca788834ea15d6dd43bf0923757ca1d46d00ebc4 Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期一, 12 七月 2021 23:17:26 +0800 Subject: [PATCH] 2021-07-12 --- src/menu/datasource/verifycard/settingform/index.scss | 8 src/menu/components/card/balcony/index.jsx | 300 +++++++++++++++ src/utils/utils-datamanage.js | 2 src/menu/components/card/balcony/wrapsetting/settingform/index.scss | 36 + src/menu/components/share/styleInput/index.scss | 11 src/menu/components/card/balcony/wrapsetting/settingform/index.jsx | 301 +++++++++++++++ src/menu/components/share/styleInput/index.jsx | 117 ++++++ src/menu/datasource/verifycard/settingform/index.jsx | 25 + src/utils/utils-custom.js | 74 +++ src/menu/components/card/balcony/wrapsetting/index.scss | 7 src/menu/pastecontroller/index.jsx | 2 src/menu/components/card/balcony/index.scss | 77 ++++ src/tabviews/custom/index.jsx | 4 src/menu/components/card/balcony/wrapsetting/index.jsx | 83 ++++ src/menu/components/card/data-card/wrapsetting/settingform/index.jsx | 27 + src/menu/menushell/card.jsx | 3 src/menu/components/card/data-card/wrapsetting/index.jsx | 4 src/menu/menushell/index.jsx | 1 src/menu/popview/index.jsx | 2 src/menu/modulesource/option.jsx | 1 20 files changed, 1,065 insertions(+), 20 deletions(-) diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx new file mode 100644 index 0000000..acb1fd6 --- /dev/null +++ b/src/menu/components/card/balcony/index.jsx @@ -0,0 +1,300 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Icon, Popover, Modal } from 'antd' + +import asyncComponent from '@/utils/asyncComponent' +import asyncIconComponent from '@/utils/asyncIconComponent' +import { resetStyle } from '@/utils/utils-custom.js' +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('./wrapsetting')) +const CardCellComponent = asyncComponent(() => import('../cardcellcomponent')) +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 ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent')) +const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) + +const { confirm } = Modal + +class BalconyEditComponent 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 ismob = sessionStorage.getItem('appType') === 'mob' + 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: { interType: 'system' }, + wrap: { name: card.name, width: card.width || 24, linkType: 'static', position: 'relative', datatype: 'static' }, + style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' }, + columns: [], + scripts: [], + elements: [], + } + + if (card.config) { + let config = fromJS(card.config).toJS() + + _card.wrap = config.wrap + _card.wrap.name = card.name + _card.style = config.style + + _card.elements = _card.elements.map(elem => { + elem.uuid = Utils.getuuid() + return elem + }) + } + 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)) + } + + /** + * @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) + } + }) + cell.backElements && cell.backElements.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: { width: 6, type: 'simple'}, + style: { + borderWidth: '1px', borderColor: '#e8e8e8', + paddingTop: '15px', paddingBottom: '15px', paddingLeft: '15px', paddingRight: '15px', + marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' + }, + backStyle: {}, + elements: [], + backElements: [] + } + + 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 + }) + newcard.backElements = newcard.backElements.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}) + 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 + + let _style = resetStyle(card.style) + + return ( + <div className="menu-balcony-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> + <NormalHeader defaultshow="hidden" config={card} updateComponent={this.updateComponent}/> + <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" /> + <WrapComponent config={card} updateConfig={this.updateComponent} /> + <CopyComponent type="balcony" card={card}/> + <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} /> + <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" /> + <ClockComponent config={card} updateConfig={this.updateComponent}/> + <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> + <CardCellComponent cards={card} cardCell={card} elements={card.elements} updateElement={this.updateCard}/> + </div> + ) + } +} + +export default BalconyEditComponent \ No newline at end of file diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss new file mode 100644 index 0000000..1e071bd --- /dev/null +++ b/src/menu/components/card/balcony/index.scss @@ -0,0 +1,77 @@ +.menu-balcony-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-color: #ffffff; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + min-height: 20px; + } + + .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-balcony-edit-box::after { + display: block; + content: ' '; + clear: both; +} +.menu-balcony-edit-box:hover { + z-index: 1; + box-shadow: 0px 0px 4px #1890ff; +} diff --git a/src/menu/components/card/balcony/wrapsetting/index.jsx b/src/menu/components/card/balcony/wrapsetting/index.jsx new file mode 100644 index 0000000..a8332db --- /dev/null +++ b/src/menu/components/card/balcony/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 BalconyWrapSetting 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="鍗$墖璁剧疆" + 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 BalconyWrapSetting \ No newline at end of file diff --git a/src/menu/components/card/balcony/wrapsetting/index.scss b/src/menu/components/card/balcony/wrapsetting/index.scss new file mode 100644 index 0000000..04372e6 --- /dev/null +++ b/src/menu/components/card/balcony/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/card/balcony/wrapsetting/settingform/index.jsx b/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx new file mode 100644 index 0000000..3cc7bf6 --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/settingform/index.jsx @@ -0,0 +1,301 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { fromJS } from 'immutable' +import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select, Cascader } from 'antd' + +import MenuUtils from '@/utils/utils-custom.js' +import StyleInput from '@/menu/components/share/styleInput' +import './index.scss' + +class SettingForm extends Component { + static propTpyes = { + dict: PropTypes.object, + config: PropTypes.object, + wrap: PropTypes.object, + inputSubmit: PropTypes.func + } + + state = { + roleList: [], + modules: [], + supmodules: [], + appType: sessionStorage.getItem('appType'), + linkType: this.props.wrap.linkType, + position: this.props.wrap.position, + } + + UNSAFE_componentWillMount () { + let roleList = sessionStorage.getItem('sysRoles') + if (roleList) { + try { + roleList = JSON.parse(roleList) + } catch { + roleList = [] + } + } else { + roleList = [] + } + + let menu = fromJS(window.GLOB.customMenu).toJS() + + let modules = MenuUtils.getLinkModules(menu.components) + if (!modules) { + modules = [] + } + + let _menu = fromJS(window.GLOB.customMenu).toJS() + + let supmodules = MenuUtils.getSupModules(_menu.components, '') + if (!supmodules) { + supmodules = [] + } + + this.setState({roleList, modules, supmodules}) + } + + 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 } = this.props + const { getFieldDecorator } = this.props.form + const { roleList, modules, supmodules, linkType, position } = 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={ + <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> + <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> + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="缁勪欢涓庡叾浠栫粍浠朵箣闂寸殑鎺у埗绫诲瀷锛岀嫭绔嬭〃绀轰笌鍏朵粬娌℃湁鍏宠仈銆�"> + <Icon type="question-circle" /> + 鍙楁帶绫诲瀷 + </Tooltip> + }> + {getFieldDecorator('linkType', { + initialValue: wrap.linkType || 'static' + })( + <Radio.Group onChange={(e) => this.setState({linkType: e.target.value})}> + <Radio value="static">鐙珛</Radio> + <Radio value="sync">鍚屾</Radio> + <Radio value="sup">涓婄骇</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {linkType === 'sup' ? <Col span={12}> + <Form.Item label="涓婄骇缁勪欢"> + {getFieldDecorator('supModule', { + initialValue: wrap.supModule, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '涓婄骇缁勪欢!' + } + ] + })( + <Cascader options={supmodules} expandTrigger="hover" placeholder="" /> + )} + </Form.Item> + </Col> : null} + {linkType === 'sync' ? <Col span={12}> + <Form.Item label="鍚屾缁勪欢"> + {getFieldDecorator('syncModule', { + initialValue: wrap.syncModule, + rules: [ + { + required: true, + message: this.props.dict['form.required.select'] + '鍚屾缁勪欢!' + } + ] + })( + <Cascader options={modules} expandTrigger="hover" placeholder="" /> + )} + </Form.Item> + </Col> : null} + {linkType === 'sync' ? <Col span={12}> + <Form.Item label="鍏ㄩ��"> + {getFieldDecorator('checkAll', { + initialValue: wrap.checkAll || 'hidden' + })( + <Radio.Group> + <Radio key="hidden" value="hidden"> 闅愯棌 </Radio> + <Radio key="show" value="show"> 鏄剧ず </Radio> + </Radio.Group> + )} + </Form.Item> + </Col> : null} + <Col span={12}> + <Form.Item label={ + <Tooltip placement="topLeft" title="浣跨敤鍥哄畾瀹氫綅鏃讹紝璇峰湪娴嬭瘯鐜涓煡鐪嬪畾浣嶆晥鏋溿��"> + <Icon type="question-circle" /> + 浣嶇疆 + </Tooltip> + }> + {getFieldDecorator('position', { + initialValue: wrap.position || 'relative' + })( + <Radio.Group onChange={(e) => this.setState({position: e.target.value})}> + <Radio value="relative">鐩稿瀹氫綅</Radio> + <Radio value="fixed">鍥哄畾瀹氫綅</Radio> + </Radio.Group> + )} + </Form.Item> + </Col> + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濅笂"> + {getFieldDecorator('top', { + initialValue: wrap.top || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濆彸"> + {getFieldDecorator('right', { + initialValue: wrap.right || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濅笅"> + {getFieldDecorator('bottom', { + initialValue: wrap.bottom || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="璺濆乏"> + {getFieldDecorator('left', { + initialValue: wrap.left || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="瀹為檯瀹藉害"> + {getFieldDecorator('realwidth', { + initialValue: wrap.realwidth || '' + })(<StyleInput options={['px', 'vh', 'vw', '%']} />)} + </Form.Item> + </Col> : null} + {position === 'fixed' ? <Col span={12}> + <Form.Item label="鍙樻崲"> + {getFieldDecorator('transform', { + initialValue: wrap.transform || '' + })( + <Select> + <Select.Option key='1' value={''}>鏃�</Select.Option> + <Select.Option key='2' value={'translateY(-50%)'}>涓婄Щ50%</Select.Option> + <Select.Option key='3' value={'translateY(50%)'}>涓嬬Щ50%</Select.Option> + <Select.Option key='5' value={'translateX(-50%)'}>宸︾Щ50%</Select.Option> + <Select.Option key='4' value={'translateX(50%)'}>鍙崇Щ50%</Select.Option> + </Select> + )} + </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/card/balcony/wrapsetting/settingform/index.scss b/src/menu/components/card/balcony/wrapsetting/settingform/index.scss new file mode 100644 index 0000000..9644e12 --- /dev/null +++ b/src/menu/components/card/balcony/wrapsetting/settingform/index.scss @@ -0,0 +1,36 @@ +.model-menu-setting-form { + position: relative; + + .anticon-question-circle { + color: #c49f47; + margin-right: 3px; + } + .ant-input-number { + width: 100%; + } + .css { + padding-top: 10px; + .css-class { + position: absolute; + right: 13px; + top: -15px; + z-index: 1; + button { + height: 25px; + } + } + .ant-form-item { + margin-bottom: 0; + } + .ant-form-item-label { + width: 16%; + } + .ant-form-item-control-wrapper { + width: 84%; + .code-mirror-wrap .code-mirror-area .CodeMirror { + height: 100px; + min-height: 100px; + } + } + } +} \ No newline at end of file diff --git a/src/menu/components/card/data-card/wrapsetting/index.jsx b/src/menu/components/card/data-card/wrapsetting/index.jsx index 81346a6..8877617 100644 --- a/src/menu/components/card/data-card/wrapsetting/index.jsx +++ b/src/menu/components/card/data-card/wrapsetting/index.jsx @@ -8,7 +8,7 @@ import SettingForm from './settingform' import './index.scss' -class DataSource extends Component { +class CardWrapSetting extends Component { static propTpyes = { config: PropTypes.any, updateConfig: PropTypes.func @@ -80,4 +80,4 @@ } } -export default DataSource \ No newline at end of file +export default CardWrapSetting \ No newline at end of file diff --git a/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx b/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx index 3465f70..d1c8eb0 100644 --- a/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx +++ b/src/menu/components/card/data-card/wrapsetting/settingform/index.jsx @@ -6,15 +6,16 @@ class SettingForm extends Component { static propTpyes = { - dict: PropTypes.object, // 瀛楀吀椤� - config: PropTypes.object, // 鍗$墖琛屼俊鎭� - wrap: PropTypes.object, // 鏁版嵁婧愰厤缃� - inputSubmit: PropTypes.func // 鍥炶溅浜嬩欢 + dict: PropTypes.object, + config: PropTypes.object, + wrap: PropTypes.object, + inputSubmit: PropTypes.func } state = { roleList: [], appType: sessionStorage.getItem('appType'), + cardType: this.props.wrap.cardType, MenuType: '' } @@ -63,7 +64,7 @@ render() { const { wrap, config } = this.props const { getFieldDecorator } = this.props.form - const { roleList, MenuType, appType } = this.state + const { roleList, MenuType, appType, cardType } = this.state const formItemLayout = { labelCol: { @@ -163,10 +164,22 @@ {getFieldDecorator('cardType', { initialValue: wrap.cardType || '' })( - <Radio.Group style={{whiteSpace: 'nowrap'}}> + <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({cardType: e.target.value})}> <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 === 'datacard' && appType === 'mob' && cardType === 'checkbox' ? <Col span={12}> + <Form.Item label="鍏ㄩ��"> + {getFieldDecorator('checkAll', { + initialValue: wrap.checkAll || 'hidden' + })( + <Radio.Group> + <Radio key="hidden" value="hidden"> 闅愯棌 </Radio> + <Radio key="show" value="show"> 鏄剧ず </Radio> </Radio.Group> )} </Form.Item> @@ -189,7 +202,7 @@ )} </Form.Item> </Col> : null} - {config.subtype !== 'tablecard' ? <Col span={12}> + {config.subtype !== 'tablecard' && appType !== 'mob' ? <Col span={12}> <Form.Item label={ <Tooltip placement="topLeft" title="榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��"> <Icon type="question-circle" /> diff --git a/src/menu/components/share/styleInput/index.jsx b/src/menu/components/share/styleInput/index.jsx new file mode 100644 index 0000000..4233217 --- /dev/null +++ b/src/menu/components/share/styleInput/index.jsx @@ -0,0 +1,117 @@ +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import { is, fromJS } from 'immutable' +import { Select, Input } from 'antd' + +import './index.scss' + +const { Option } = Select + +class StyleInput extends Component { + static propTpyes = { + defaultValue: PropTypes.any, + options: PropTypes.any, + value: PropTypes.any, + onChange: PropTypes.func, + } + + state = { + value: '', + unit: '', + options: null + } + + UNSAFE_componentWillMount () { + const { value, options } = this.props + + let val = '' + let unit = '' + + if (value !== undefined) { + val = value + } + + unit = options[0] + + if (val) { + if (val.indexOf('px') > -1) { + unit = 'px' + } else if (val.indexOf('%') > -1) { + unit = '%' + } else if (val.indexOf('vw') > -1) { + unit = 'vw' + } else if (val.indexOf('vh') > -1) { + unit = 'vh' + } + } + + let _val = parseFloat(val) + + if (isNaN(_val)) { + _val = '' + } + + this.setState({value: _val, options: options, unit}) + } + + shouldComponentUpdate (nextProps, nextState) { + return !is(fromJS(this.state), fromJS(nextState)) + } + + /** + * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆 + */ + componentWillUnmount () { + this.setState = () => { + return + } + } + + changeValue = (e) => { + const { unit } = this.state + let val = e.target.value + + if (/\d+\.$/.test(val)) { + this.setState({ + value: val + }) + return + } + let _val = parseFloat(val) + + if (isNaN(_val)) { + _val = '' + } + + this.setState({ + value: _val, + }) + + this.props.onChange(_val ? `${_val}${unit}` : '') + } + + changeUnit = (val) => { + const { value } = this.state + + this.setState({unit: val}) + this.props.onChange(value ? `${value}${val}` : '') + } + + render () { + const { value, options, unit } = this.state + + return ( + <div className="style-input-wrap"> + <Input value={value} addonAfter={ + options.length > 1 ? + <Select value={unit} onChange={this.changeUnit}> + {options.map(item => <Option key={item} value={item}>{item}</Option>)} + </Select> : + <div className="single-unit">{unit}</div> + } onChange={this.changeValue}/> + </div> + ) + } +} + +export default StyleInput \ No newline at end of file diff --git a/src/menu/components/share/styleInput/index.scss b/src/menu/components/share/styleInput/index.scss new file mode 100644 index 0000000..b058a37 --- /dev/null +++ b/src/menu/components/share/styleInput/index.scss @@ -0,0 +1,11 @@ +.style-input-wrap { + line-height: 32px; + .ant-select { + width: 60px!important; + } + .single-unit { + width: 38px; + text-align: left; + color: rgba(255, 255, 255, 0.65); + } +} diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx index dc66b36..d7916a3 100644 --- a/src/menu/datasource/verifycard/settingform/index.jsx +++ b/src/menu/datasource/verifycard/settingform/index.jsx @@ -8,6 +8,8 @@ import CodeMirror from '@/templates/zshare/codemirror' import './index.scss' +const { TextArea } = Input + class SettingForm extends Component { static propTpyes = { dict: PropTypes.object, // 瀛楀吀椤� @@ -249,7 +251,7 @@ })(<Input placeholder={''} autoComplete="off" />)} </Form.Item> </Col> : null} - {interType === 'outer' ? <Col span={8}> + {interType === 'outer' ? <Col className="outer-interface" span={24}> <Form.Item label="鎺ュ彛鍦板潃"> {getFieldDecorator('interface', { initialValue: setting.interface || '', @@ -259,7 +261,18 @@ message: this.props.dict['form.required.input'] + '鎺ュ彛鍦板潃!' } ] - })(<Input placeholder={''} autoComplete="off" />)} + })(<TextArea rows={2}/>)} + </Form.Item> + </Col> : null} + {interType === 'outer' ? <Col className="outer-interface" span={24}> + <Form.Item label={<Tooltip placement="topLeft" title="姝e紡绯荤粺鎺ュ彛鍦板潃锛屼负绌烘椂浣跨敤鎺ュ彛鍦板潃"> + <Icon type="question-circle" /> + 姝e紡鍦板潃 + </Tooltip> + }> + {getFieldDecorator('proInterface', { + initialValue: setting.proInterface || '' + })(<TextArea rows={2}/>)} </Form.Item> </Col> : null} {interType === 'outer' ? <Col span={8}> @@ -340,7 +353,7 @@ </Radio.Group>)} </Form.Item> </Col> : null} - {config.type !== 'navbar' ? <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}> <Icon type="question-circle" /> @@ -408,7 +421,7 @@ )} </Form.Item> </Col> : null} - {config.type !== 'navbar' ? <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'浼樺厛浣跨敤鍚岀骇鐨勬悳绱㈡潯浠剁粍浠讹紝鍚岀骇鎼滅储涓嶅瓨鍦ㄦ椂锛屼緷娆″悜涓婇�夊彇锛屼笌褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵竴鍚岀敤浣滄暟鎹繃婊わ紙褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵紭鍏堬級銆�'}> <Icon type="question-circle" /> @@ -425,7 +438,7 @@ )} </Form.Item> </Col> : null} - {config.type !== 'navbar' && useMSearch === 'true' ? <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' && useMSearch === 'true' ? <Col span={8}> <Form.Item label={ <Tooltip placement="topLeft" title={'澶栧眰鎼滅储鏉′欢鏀瑰彉鏃讹紝鏄惁鍒锋柊褰撳墠缁勪欢鏁版嵁銆�'}> <Icon type="question-circle" /> @@ -442,7 +455,7 @@ )} </Form.Item> </Col> : null} - {config.type !== 'navbar' ? <Col span={8}> + {config.type !== 'navbar' && config.type !== 'balcony' ? <Col span={8}> <Form.Item label="鍒濆鍖栨暟鎹�"> {getFieldDecorator('onload', { initialValue: setting.onload || 'true' diff --git a/src/menu/datasource/verifycard/settingform/index.scss b/src/menu/datasource/verifycard/settingform/index.scss index 5bd14b5..d0943f6 100644 --- a/src/menu/datasource/verifycard/settingform/index.scss +++ b/src/menu/datasource/verifycard/settingform/index.scss @@ -24,4 +24,12 @@ .ant-radio-group { white-space: nowrap; } + .outer-interface { + .ant-form-item-label { + width: 10.5%; + } + .ant-form-item-control-wrapper { + width: 89.5%; + } + } } \ No newline at end of file diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx index a482a9d..b12b583 100644 --- a/src/menu/menushell/card.jsx +++ b/src/menu/menushell/card.jsx @@ -12,6 +12,7 @@ const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) +const Balcony = asyncComponent(() => import('@/menu/components/card/balcony')) const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) @@ -90,6 +91,8 @@ return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } else if (card.type === 'code') { return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) + } else if (card.type === 'balcony') { + return (<Balcony card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) } } return ( diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx index b1427ac..308e390 100644 --- a/src/menu/menushell/index.jsx +++ b/src/menu/menushell/index.jsx @@ -100,6 +100,7 @@ dashboard: '浠〃鐩�', scatter: '鏁g偣鍥�', tree: '鏍戝舰鍒楄〃', + balcony: '娴姩鍗�', card: '鍗$墖' } let i = 1 diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx index 99e6ef6..e9e1833 100644 --- a/src/menu/modulesource/option.jsx +++ b/src/menu/modulesource/option.jsx @@ -29,6 +29,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: card2, component: 'balcony', subtype: 'balcony', title: '鍙诞鍔ㄥ崱', width: 24 }, { type: 'menu', url: form, component: 'form', subtype: 'stepform', 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'] }, diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx index 8283c68..7b3153c 100644 --- a/src/menu/pastecontroller/index.jsx +++ b/src/menu/pastecontroller/index.jsx @@ -66,7 +66,7 @@ return cell }) } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { card.uuid = Utils.getuuid() if (card.elements) { if (sessionStorage.getItem('editMenuType') === 'popview') { diff --git a/src/menu/popview/index.jsx b/src/menu/popview/index.jsx index 0abb17e..a80ddd5 100644 --- a/src/menu/popview/index.jsx +++ b/src/menu/popview/index.jsx @@ -246,7 +246,7 @@ buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`) _sort++ }) - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { card.elements && card.elements.forEach(cell => { if (cell.eleType !== 'button') return this.checkBtn(cell) diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx index 01be5f2..e2180a4 100644 --- a/src/tabviews/custom/index.jsx +++ b/src/tabviews/custom/index.jsx @@ -570,7 +570,7 @@ } if (item.type === 'card') { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { let _hasheight = card.style.height && card.style.height !== 'auto' if (card.style.shadow) { // 鍗$墖闃村奖 @@ -625,7 +625,7 @@ }) }) } else if ((item.type === 'table' && item.subtype === 'tablecard') || item.type === 'carousel') { - item.subcards.forEach(card => { + item.subcards && item.subcards.forEach(card => { let _hasheight = card.style.height && card.style.height !== 'auto' card.elements = card.elements.filter(cell => { if (cell.eleType === 'button') { diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js index 840ce6d..43a7b75 100644 --- a/src/utils/utils-custom.js +++ b/src/utils/utils-custom.js @@ -166,6 +166,80 @@ } /** + * @description 鑾峰彇鍙叧鑱旀ā鍧� + */ + static getLinkModules (components) { + let modules = components.map(item => { + if ((item.type === 'card' && item.subtype === 'datacard') || (item.type === 'table' && item.subtype === 'normaltable')) { + return { + value: item.uuid, + label: item.name + } + } else if (item.type === 'tabs') { + let _item = { + value: item.uuid, + label: item.name, + children: item.subtabs.map(f_tab => { + let subItem = { + value: f_tab.uuid, + label: f_tab.label, + children: this.getLinkModules(f_tab.components) + } + + if (!subItem.children || subItem.children.length === 0) { + return {children: null} + } + return subItem + }) + } + + _item.children = _item.children.filter(t => t.children !== null) + + if (_item.children.length === 0) { + return {children: null} + } + + return _item + } else if (item.type === 'group') { + let _item = { + value: item.uuid, + label: item.name, + children: item.components.map(f_tab => { + if ((f_tab.type === 'card' && f_tab.subtype === 'datacard') || (f_tab.type === 'table' && f_tab.subtype === 'normaltable')) { + return { + value: f_tab.uuid, + label: f_tab.name + } + } + return { + children: null + } + }) + } + + _item.children = _item.children.filter(t => t.children !== null) + + if (_item.children.length === 0) { + return {children: null} + } + + return _item + } else { + return { + children: null + } + } + }) + + modules = modules.filter(mod => mod.children !== null) + + if (modules.length === 0) { + return null + } + return modules + } + + /** * @description 鑾峰彇鍒犻櫎鎸夐挳Id * @return {String} name */ diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js index b995699..d878668 100644 --- a/src/utils/utils-datamanage.js +++ b/src/utils/utils-datamanage.js @@ -65,7 +65,7 @@ if (setting.sysInterface === 'true' && window.GLOB.mainSystemApi) { param.rduri = window.GLOB.mainSystemApi } else if (setting.sysInterface !== 'true') { - param.rduri = setting.interface + param.rduri = window.GLOB.systemType === 'production' ? (setting.proInterface || setting.interface) : setting.interface } } -- Gitblit v1.8.0