| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Collapse, Form, Input, Col, Icon, InputNumber, Select, Radio, Popover, Menu, Drawer } from 'antd' |
| | | import { Collapse, Form, Input, Col, Icon, InputNumber, Select, Radio, Drawer } from 'antd' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import zhCN from '@/locales/zh-CN/mob.js' |
| | | import enUS from '@/locales/en-US/mob.js' |
| | | import ColorSketch from '@/mob/colorsketch' |
| | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | comIds: [], |
| | | fontColor: '#000000', |
| | | backgroundColor: '#ffffff', |
| | | bgimages: [], |
| | | marginTop: '', |
| | | marginTopVal: '', |
| | | marginBottom: '', |
| | | marginBottomVal: '', |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | if (!is(fromJS(this.props.editElem), fromJS(nextProps.editElem))) { |
| | | this.setState({ |
| | | card: null |
| | | }, () => { |
| | | if (!nextProps.editElem) return |
| | | let _card = fromJS(nextProps.editElem).toJS() |
| | | let bgImg = _card.backgroundImage || '' |
| | | |
| | | if (bgImg && /^linear-gradient/.test(bgImg)) { |
| | | bgImg = bgImg.replace('linear-gradient(', '') |
| | | bgImg = bgImg.replace(')', '') |
| | | } else if (bgImg && /^url/.test(bgImg)) { |
| | | bgImg = bgImg.replace('url(', '') |
| | | bgImg = bgImg.replace(')', '') |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card, |
| | | fontColor: _card.color || '#000000', |
| | | backgroundColor: _card.backgroundColor || '#ffffff', |
| | | backgroundImage: bgImg, |
| | | marginTop: _card.marginTop ? _card.marginTop : '', |
| | | marginTopVal: _card.marginTop ? parseInt(_card.marginTop) : '', |
| | | marginBottom: _card.marginBottom ? _card.marginBottom : '', |
| | | marginBottomVal: _card.marginBottomVal ? parseInt(_card.marginBottomVal) : '' |
| | | }) |
| | | }) |
| | | } |
| | | backgroundImage: '', |
| | | options: [], |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | updateStyle = (style) => { |
| | | const { card } = this.state |
| | | componentDidMount () { |
| | | MKEmitter.addListener('changeStyle', this.initStyle) |
| | | } |
| | | |
| | | this.props.updateStyle({componentId: card.componentId, classId: card.classId, uuid: card.uuid, style}) |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('changeStyle', this.initStyle) |
| | | } |
| | | |
| | | initStyle = (comIds, options, style = {}) => { |
| | | let backgroundImage = '' |
| | | if (style.backgroundImage) { |
| | | if (/^url/ig.test(style.backgroundImage)) { |
| | | backgroundImage = style.backgroundImage.replace(/^url\(/ig, '').replace(/\)$/ig, '') |
| | | } else if (/^linear-gradient/ig.test(style.backgroundImage)) { |
| | | backgroundImage = style.backgroundImage.replace(/^linear-gradient\(/ig, '').replace(/\)$/ig, '') |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | comIds: comIds, |
| | | card: fromJS(style).toJS(), |
| | | options: options, |
| | | backgroundImage |
| | | }) |
| | | } |
| | | |
| | | onCloseDrawer = () => { |
| | | this.setState({ |
| | | visible: false, |
| | | comIds: [], |
| | | card: null, |
| | | options: [], |
| | | backgroundImage: '' |
| | | }) |
| | | } |
| | | |
| | | updateStyle = (style) => { |
| | | const { comIds, card } = this.state |
| | | |
| | | let _style = { |
| | | ...card, |
| | | ...style |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _style, |
| | | }) |
| | | |
| | | MKEmitter.emit('submitStyle', comIds, _style) |
| | | } |
| | | |
| | | /** |
| | |
| | | * @description 修改背景颜色 ,颜色控件 |
| | | */ |
| | | changeBackgroundColor = (val) => { |
| | | this.setState({ |
| | | backgroundColor: val |
| | | }) |
| | | this.updateStyle({backgroundColor: val}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改字体颜色 ,手动输入 |
| | | */ |
| | | changeBackgroundColorInput = (e) => { |
| | | this.setState({ |
| | | backgroundColor: e.target.value |
| | | }) |
| | | } |
| | | |
| | | imgChange = (list) => { |
| | |
| | | } |
| | | |
| | | changeBackgroundImageInput = (e) => { |
| | | this.setState({ |
| | | backgroundImage: e.target.value |
| | | }) |
| | | } |
| | | |
| | | submitBackgroundImage = (e) => { |
| | | let val = e.target.value |
| | | val = val.replace(/^\s*|\s*$/ig, '') |
| | | |
| | |
| | | } else if (/^#|,/ig.test(val)) { |
| | | val = `linear-gradient(${val})` |
| | | } |
| | | |
| | | this.setState({backgroundImage: e.target.value}) |
| | | this.updateStyle({backgroundImage: val}) |
| | | } |
| | | |
| | | submitBorder = (val, type) => { |
| | | this.updateStyle({[type]: val}) |
| | | submitBorder = (val) => { |
| | | let border = '0px' |
| | | if (!/,\s0\)$/.test(val)) { |
| | | border = `1px solid ${val}` |
| | | } |
| | | this.updateStyle({border: border}) |
| | | } |
| | | |
| | | changeBorderRadius = (val) => { |
| | | let value = parseFloat(val) |
| | | |
| | | if (isNaN(value) || value < 0 || value > 500) return |
| | | |
| | | this.updateStyle({borderRadius: `${value}px`}) |
| | | } |
| | | |
| | | changeMarginTop = (e) => { |
| | | changeBorderRadius = (e) => { |
| | | let val = e.target.value |
| | | let _val = parseInt(val) |
| | | |
| | | this.setState({ |
| | | marginTop: val |
| | | }) |
| | | |
| | | if (isNaN(_val)) return |
| | | |
| | | this.setState({ |
| | | marginTopVal: _val |
| | | }) |
| | | this.updateStyle({borderRadius: val}) |
| | | } |
| | | |
| | | submitMarginTop = (val) => { |
| | | this.setState({ |
| | | marginTop: val |
| | | }) |
| | | this.updateStyle({marginTop: val}) |
| | | } |
| | | changeMarginOrPadding = (val, type) => { |
| | | val = parseInt(val) |
| | | |
| | | changeMarginBottom = (e) => { |
| | | let val = e.target.value |
| | | let _val = parseInt(val) |
| | | if (isNaN(val)) { |
| | | val = 0 |
| | | } |
| | | |
| | | this.setState({ |
| | | marginBottom: val |
| | | }) |
| | | |
| | | if (isNaN(_val)) return |
| | | |
| | | this.setState({ |
| | | marginBottomVal: _val |
| | | }) |
| | | } |
| | | |
| | | submitMarginBottom = (val) => { |
| | | this.setState({ |
| | | marginBottom: val |
| | | }) |
| | | this.updateStyle({marginBottom: val}) |
| | | this.updateStyle({[type]: `${val}px`}) |
| | | } |
| | | |
| | | render () { |
| | | const { card, fontColor, backgroundColor, backgroundImage, bgimages, marginTop, marginTopVal, marginBottom, marginBottomVal } = this.state |
| | | const { card, options, backgroundImage, bgimages } = this.state |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | |
| | | |
| | | return ( |
| | | <Drawer |
| | | title="样式修改" |
| | | title={ |
| | | <div className="header-logo"> |
| | | <img src="http://cloud.mk9h.cn/Content/images/upload/2020-03-26/2020032615132185788026_xiazai.png" alt=""/> |
| | | </div> |
| | | } |
| | | placement="left" |
| | | width="300" |
| | | className="menu-style-drawer" |
| | | closable={true} |
| | | maskStyle={{opacity: 0.2}} |
| | | onClose={this.onCloseDrawer} |
| | | maskStyle={{opacity: 0.1}} |
| | | visible={this.state.visible} |
| | | > |
| | | <div className="mob-controller"> |
| | | <div className="menu-style-controller"> |
| | | <Form {...formItemLayout}> |
| | | {card ? <Collapse expandIconPosition="right" defaultActiveKey={card.items[0]} accordion={true}> |
| | | {card.items.includes('font') ? <Panel header="字体" key="font"> |
| | | {card ? <Collapse expandIconPosition="right" destroyInactivePanel={true} defaultActiveKey={options[0]} accordion={true}> |
| | | {options.includes('font') ? <Panel header="字体" key="font"> |
| | | <Col span={12}> |
| | | <Form.Item colon={false} label={<Icon title="字体大小" type="font-size" />}> |
| | | <InputNumber defaultValue={card.fontSize || 14} min={12} max={100} precision={0} onChange={this.changeFontSize} /> |
| | | <InputNumber defaultValue={card.fontSize} min={12} max={100} precision={0} onChange={this.changeFontSize} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <ColorSketch value={card.color || '#000000'} onChange={this.changeFontColor} /> |
| | | <Input value={fontColor} onChange={this.changeFontColorInput} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | | {card.items.includes('background') ? <Panel header="背景" key="background"> |
| | | {options.includes('background') ? <Panel header="背景" key="background"> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="背景颜色" type="bg-colors" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <ColorSketch color={card.backgroundColor || '#ffffff'} changeColor={this.changeBackgroundColor} /> |
| | | <Input value={backgroundColor} onChange={this.changeBackgroundColorInput} /> |
| | | <ColorSketch value={card.backgroundColor || '#ffffff'} onChange={this.changeBackgroundColor} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/> |
| | | <Input placeholder="" value={backgroundImage} autoComplete="off" onBlur={this.submitBackgroundImage} onPressEnter={this.submitBackgroundImage} onChange={this.changeBackgroundImageInput} /> |
| | | <Input placeholder="" value={backgroundImage} autoComplete="off" onChange={this.changeBackgroundImageInput} /> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | | {card.items.includes('border') ? <Panel header="边框" key="border"> |
| | | {options.includes('border') ? <Panel header="边框" key="border"> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="外边框" type="border-outer" />} |
| | | label={<Icon title="边框" type="border-outer" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Input placeholder="" defaultValue={card.border || ''} autoComplete="off" onBlur={(e) => this.submitBorder(e.target.value, 'border')} onPressEnter={(e) => this.submitBorder(e.target.value, 'border')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="左边框" type="border-left" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Input placeholder="" defaultValue={card.borderLeft || ''} autoComplete="off" onBlur={(e) => this.submitBorder(e.target.value, 'borderLeft')} onPressEnter={(e) => this.submitBorder(e.target.value, 'borderLeft')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="右边框" type="border-right" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Input placeholder="" defaultValue={card.borderRight || ''} autoComplete="off" onBlur={(e) => this.submitBorder(e.target.value, 'borderRight')} onPressEnter={(e) => this.submitBorder(e.target.value, 'borderRight')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="上边框" type="border-top" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Input placeholder="" defaultValue={card.borderTop || ''} autoComplete="off" onBlur={(e) => this.submitBorder(e.target.value, 'borderTop')} onPressEnter={(e) => this.submitBorder(e.target.value, 'borderTop')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="下边框" type="border-bottom" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <Input placeholder="" defaultValue={card.borderBottom || ''} autoComplete="off" onBlur={(e) => this.submitBorder(e.target.value, 'borderBottom')} onPressEnter={(e) => this.submitBorder(e.target.value, 'borderBottom')}/> |
| | | <ColorSketch defaultValue={card.border ? card.border.replace(/^1px solid /ig, '').replace('0px', 'transparent') : 'transparent'} onChange={this.submitBorder} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | |
| | | label={<Icon title="圆角" type="radius-setting" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <InputNumber defaultValue={card.borderRadius || 0} min={0} max={500} precision={0} onChange={this.changeBorderRadius}/> |
| | | <Radio.Group onChange={this.changeBorderRadius} defaultValue={card.borderRadius || ''}> |
| | | <Radio value="0px">无</Radio> |
| | | <Radio value="2px">2px</Radio> |
| | | <Radio value="4px">4px</Radio> |
| | | <Radio value="25%">25%</Radio> |
| | | <Radio value="50%">50%</Radio> |
| | | </Radio.Group> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | | {card.items.includes('margin') ? <Panel header="外边距" key="margin"> |
| | | {options.includes('margin') ? <Panel header="外边距" key="margin"> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="上边距" type="vertical-align-top"/>} |
| | | label={<Icon title="上边距" type="arrow-up"/>} |
| | | > |
| | | <Popover placement="bottom" overlayClassName="margin-popover" content={ |
| | | marginTopVal !== '' ? |
| | | <Menu> |
| | | <Menu.Item onClick={() => this.submitMarginTop(`${marginTopVal}px`)}>{marginTopVal} px</Menu.Item> |
| | | <Menu.Item onClick={() => this.submitMarginTop(`${marginTopVal}vh`)}>{marginTopVal} vh</Menu.Item> |
| | | </Menu> : null |
| | | } trigger="hover"> |
| | | <Input value={marginTop} onChange={this.changeMarginTop}/> |
| | | </Popover> |
| | | <InputNumber defaultValue={card.marginTop || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginTop')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="下边距" type="vertical-align-bottom"/>} |
| | | label={<Icon title="下边距" type="arrow-down"/>} |
| | | > |
| | | <Popover placement="bottom" overlayClassName="margin-popover" content={ |
| | | marginBottomVal !== '' ? |
| | | <Menu> |
| | | <Menu.Item onClick={() => this.submitMarginBottom(`${marginBottomVal}px`)}>{marginBottomVal} px</Menu.Item> |
| | | <Menu.Item onClick={() => this.submitMarginBottom(`${marginBottomVal}vh`)}>{marginBottomVal} vh</Menu.Item> |
| | | </Menu> : null |
| | | } trigger="hover"> |
| | | <Input value={marginBottom} onChange={this.changeMarginBottom}/> |
| | | </Popover> |
| | | <InputNumber defaultValue={card.marginBottom || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginBottom')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="左边距" type="arrow-left"/>} |
| | | > |
| | | <InputNumber defaultValue={card.marginLeft || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginLeft')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="右边距" type="arrow-right"/>} |
| | | > |
| | | <InputNumber defaultValue={card.marginRight || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'marginRight')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | | {options.includes('padding') ? <Panel header="内边距" key="padding"> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="上边距" type="arrow-up"/>} |
| | | > |
| | | <InputNumber defaultValue={card.paddingTop || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingTop')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="下边距" type="arrow-down"/>} |
| | | > |
| | | <InputNumber defaultValue={card.paddingBottom || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingBottom')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="左边距" type="arrow-left"/>} |
| | | > |
| | | <InputNumber defaultValue={card.paddingLeft || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingLeft')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="右边距" type="arrow-right"/>} |
| | | > |
| | | <InputNumber defaultValue={card.paddingRight || 0} min={0} max={1000} precision={0} onChange={(val) => this.changeMarginOrPadding(val, 'paddingRight')}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |