New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Empty } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class BraftContent extends Component { |
| | | static propTpyes = { |
| | | html: PropTypes.any, |
| | | css: PropTypes.any, |
| | | } |
| | | |
| | | state = { |
| | | csselement: null |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { css } = this.props |
| | | |
| | | if (css) { |
| | | // let style = css.replace(/^[^}{]*{|}[^}{]*{/ig, (word) => { |
| | | // return word.replace(/}\n*/ig, `}\n#${mark}`).replace(/,/ig, `,#${mark} `) |
| | | // }) |
| | | // style = `\n/* 自定义 */\n#${mark} ${style}\n` |
| | | |
| | | let ele = document.createElement('style') |
| | | ele.innerHTML = css |
| | | document.getElementsByTagName('head')[0].appendChild(ele) |
| | | // document.getElementsByTagName('head')[0].prepend(ele) |
| | | |
| | | this.setState({csselement: ele}) |
| | | } |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (this.props.css !== nextProps.css) { |
| | | const { csselement } = this.state |
| | | |
| | | if (csselement && csselement.remove) { |
| | | csselement.remove() |
| | | } |
| | | if (nextProps.css) { |
| | | let ele = document.createElement('style') |
| | | ele.innerHTML = nextProps.css |
| | | document.getElementsByTagName('head')[0].appendChild(ele) |
| | | |
| | | this.setState({csselement: ele}) |
| | | } |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { html } = this.props |
| | | |
| | | if (!html) return <Empty style={{padding: '10px 0px'}} description={null}/> |
| | | |
| | | return ( |
| | | <div dangerouslySetInnerHTML={{ __html: html }}></div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | |
| | | export default BraftContent |
New file |
| | |
| | | .braft-content { |
| | | .media-wrap { |
| | | max-width: 100%; |
| | | } |
| | | img { |
| | | max-width: 100%; |
| | | } |
| | | video { |
| | | max-width: 100%; |
| | | } |
| | | table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border-spacing: 0; |
| | | margin: 10px 0px; |
| | | tr:first-child { |
| | | background-color: #f0f0f0; |
| | | } |
| | | td, th { |
| | | padding: 5px 14px; |
| | | font-size: 16px; |
| | | border: 1px solid #ddd; |
| | | } |
| | | } |
| | | } |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | import { Icon, Modal, Tabs } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | |
| | | import './index.scss' |
| | | |
| | | const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror')) |
| | | const { TabPane } = Tabs |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | html: null |
| | | html: '', |
| | | css: '' |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | html: config.html || null |
| | | html: config.html || '', |
| | | css: config.css || '' |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | const { html } = this.state |
| | | const { html, css } = this.state |
| | | |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, html}) |
| | | this.props.updateConfig({...config, html, css}) |
| | | } |
| | | |
| | | onChange = (val) => { |
| | | onHtmlChange = (val) => { |
| | | this.setState({ |
| | | html: val |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, html } = this.state |
| | | onCssChange = (val) => { |
| | | this.setState({ |
| | | css: val |
| | | }) |
| | | } |
| | | |
| | | if (!config) return null |
| | | render () { |
| | | const { visible, dict, html, css } = this.state |
| | | |
| | | return ( |
| | | <div className="model-menu-edit-content-wrap"> |
| | | {config.wrap.datatype === 'static' ? <Icon title="内容编辑" type="form" onClick={() => this.trigger()} /> : null} |
| | | {config.wrap.datatype !== 'static' ? <Icon title="内容编辑" style={{color: '#eeeeee', cursor: 'not-allowed'}} type="form"/> : null} |
| | | <div style={{display: 'inline-block'}}> |
| | | <Icon title="代码编辑" style={{color: 'purple'}} type="form" onClick={() => this.trigger()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal model-menu-edit-content-form" |
| | | wrapClassName="popview-modal code-sand-box-code-editor" |
| | | title="内容编辑" |
| | | visible={visible} |
| | | width={950} |
| | |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <CodeMirror value={html} onChange={this.onChange} /> |
| | | <Tabs> |
| | | <TabPane tab="HTML" key="HTML"> |
| | | <CodeMirror mode="text/xml" value={html} onChange={this.onHtmlChange} /> |
| | | </TabPane> |
| | | <TabPane tab="CSS" key="CSS"> |
| | | <CodeMirror mode="text/css" value={css} onChange={this.onCssChange} /> |
| | | </TabPane> |
| | | </Tabs> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | |
| | | .model-menu-edit-content-wrap { |
| | | display: inline-block; |
| | | .code-sand-box-code-editor.popview-modal { |
| | | .ant-modal-body { |
| | | padding-top: 0px; |
| | | .ant-tabs-bar { |
| | | margin: 0; |
| | | } |
| | | |
| | | >.anticon-form { |
| | | color: purple; |
| | | } |
| | | } |
| | | .model-menu-edit-content-form { |
| | | .normal-braft-editor { |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | overflow-x: hidden; |
| | | .code-mirror-wrap .code-mirror-area { |
| | | border-radius: 0; |
| | | |
| | | .CodeMirror { |
| | | height: 400px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const EditorCode = asyncIconComponent(() => import('./editorcode')) |
| | | const BraftContent = asyncComponent(() => import('@/tabviews/custom/components/share/braftContent')) |
| | | const CodeContent = asyncComponent(() => import('./codecontent')) |
| | | |
| | | class CodeSandBox extends Component { |
| | | static propTpyes = { |
| | |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <BraftContent |
| | | value={card.wrap.datatype !== 'static' ? '<p class="empty-content">富文本</p>' : card.html} |
| | | encryption="false" |
| | | /> |
| | | <CodeContent html={card.html} css={card.css}/> |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 100px; |
| | | min-height: 30px; |
| | | |
| | | .anticon-tool { |
| | | position: absolute; |
| | |
| | | |
| | | state = { |
| | | roleList: [], |
| | | datatype: this.props.wrap.datatype || 'dynamic' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | |
| | | } |
| | | } |
| | | |
| | | changeDataType = (e) => { |
| | | this.setState({datatype: e.target.value}) |
| | | } |
| | | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { wrap } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList, datatype } = this.state |
| | | const { roleList } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | |
| | | <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="用于组件间的区分。"> |
| | |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: datatype |
| | | initialValue: wrap.datatype || 'dynamic' |
| | | })( |
| | | <Radio.Group onChange={this.changeDataType}> |
| | | <Radio.Group> |
| | | <Radio value="dynamic">动态</Radio> |
| | | <Radio value="static">静态</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | {datatype === 'dynamic' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择动态值时,需设置文本字段才可生效。"> |
| | | <Icon type="question-circle" /> |
| | | 文本字段 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('field', { |
| | | initialValue: wrap.field || '' |
| | | })( |
| | | <Select> |
| | | {config.columns.map(option => |
| | | <Select.Option key={option.uuid} value={option.field}>{option.label}</Select.Option> |
| | | )} |
| | | </Select> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | {datatype === 'dynamic' ? <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="从数据源获取的数据是否需要解码。"> |
| | | <Icon type="question-circle" /> |
| | | 数据解码 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('encryption', { |
| | | initialValue: wrap.encryption || 'true' |
| | | })( |
| | | <Radio.Group> |
| | | <Radio value="true">是</Radio> |
| | | <Radio value="false">否</Radio> |
| | | </Radio.Group> |
| | | )} |
| | | </Form.Item> |
| | | </Col> : null} |
| | | <Col span={12}> |
| | | <Form.Item label="黑名单"> |
| | | {getFieldDecorator('blacklist', { |
| | |
| | | import {UnControlled as CodeMirror} from 'react-codemirror2' |
| | | import 'codemirror/mode/javascript/javascript' |
| | | import 'codemirror/mode/sql/sql' |
| | | import 'codemirror/mode/xml/xml' |
| | | import 'codemirror/mode/css/css' |
| | | import 'codemirror/addon/display/fullscreen.js' |
| | | |
| | | import 'codemirror/addon/display/fullscreen.css' |
| | |
| | | editor: null, // code对象 |
| | | defaultVal: '', // 初始值 |
| | | value: '', // 实时内容 |
| | | options: null, // mode : text/javascript、text/x-mysql ; theme : cobalt - 黑底 |
| | | options: null, // mode : text/xml, text/css, text/javascript、text/x-mysql ; theme : cobalt - 黑底 |
| | | fullScreen: false, |
| | | style: {fontSize: '18px', lineHeight: '32px'}, |
| | | display: true |