17个文件已修改
13个文件已添加
3个文件已删除
| | |
| | | .ant-modal.popview-modal { |
| | | top: 70px; |
| | | .ant-modal-body { |
| | | min-height: 250px; |
| | | min-height: 200px; |
| | | max-height: calc(100vh - 210px); |
| | | overflow-y: auto; |
| | | } |
| | |
| | | top: 70px; |
| | | } |
| | | .ant-modal-body { |
| | | min-height: 250px; |
| | | min-height: 200px; |
| | | max-height: calc(100vh - 210px); |
| | | overflow-y: auto; |
| | | } |
| | |
| | | |
| | | if (this.props['data-__meta']) { |
| | | initVal = this.props['data-__meta'].initialValue || null |
| | | } else if (this.props.defaultValue) { |
| | | initVal = this.props.defaultValue || null |
| | | } |
| | | |
| | | if (this.props.Item && this.props.Item.encryption === 'true') { |
New file |
| | |
| | | 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 asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const Editor = asyncComponent(() => import('@/components/editor')) |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | visible: false, |
| | | html: null |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | trigger = () => { |
| | | const { config } = this.props |
| | | |
| | | this.setState({ |
| | | visible: true, |
| | | html: config.html || null |
| | | }) |
| | | } |
| | | |
| | | verifySubmit = () => { |
| | | const { config } = this.props |
| | | const { html } = this.state |
| | | |
| | | this.setState({ |
| | | visible: false |
| | | }) |
| | | this.props.updateConfig({...config, html}) |
| | | } |
| | | |
| | | onChange = (val) => { |
| | | this.setState({ |
| | | html: val |
| | | }) |
| | | } |
| | | |
| | | render () { |
| | | const { config } = this.props |
| | | const { visible, dict, html } = this.state |
| | | |
| | | if (!config) return null |
| | | |
| | | 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} |
| | | <Modal |
| | | wrapClassName="popview-modal model-menu-edit-content-form" |
| | | title="内容编辑" |
| | | visible={visible} |
| | | width={950} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <Editor defaultValue={html} onChange={this.onChange} /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-edit-content-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-form { |
| | | color: purple; |
| | | } |
| | | } |
| | | .model-menu-edit-content-form { |
| | | .normal-braft-editor { |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 4px; |
| | | overflow-x: hidden; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import {connect} from 'react-redux' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Popover } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | |
| | | import MKEmitter from '@/utils/events.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 NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent')) |
| | | const WrapComponent = asyncIconComponent(() => import('./wrapsetting')) |
| | | const EditorContent = asyncIconComponent(() => import('./editorcontent')) |
| | | const BraftContent = asyncComponent(() => import('@/tabviews/custom/components/share/braftContent')) |
| | | |
| | | class TableCardEditComponent extends Component { |
| | | static propTpyes = { |
| | | card: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | card: null, |
| | | back: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { card } = this.props |
| | | |
| | | if (card.isNew) { |
| | | let _card = { |
| | | uuid: card.uuid, |
| | | type: card.type, |
| | | floor: card.floor, |
| | | tabId: card.tabId || '', |
| | | parentId: card.parentId || '', |
| | | dataName: card.dataName || '', |
| | | format: 'object', // 组件属性 - 数据格式 |
| | | pageable: false, // 组件属性 - 是否可分页 |
| | | switchable: false, // 组件属性 - 数据是否可切换 |
| | | width: card.width || 24, |
| | | name: card.name, |
| | | subtype: card.subtype, |
| | | setting: { interType: 'system' }, |
| | | wrap: { name: card.name, width: card.width || 24, encryption: 'true' }, |
| | | style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, |
| | | headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' }, |
| | | columns: [], |
| | | scripts: [], |
| | | html: '' |
| | | } |
| | | |
| | | if (card.config) { |
| | | let config = fromJS(card.config).toJS() |
| | | |
| | | _card.wrap = config.wrap |
| | | _card.wrap.name = card.name |
| | | _card.style = config.style |
| | | _card.headerStyle = config.headerStyle |
| | | _card.html = config.html |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | this.props.updateConfig(_card) |
| | | } else { |
| | | this.setState({ |
| | | card: fromJS(card).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) || (!this.props.menu && nextProps.menu) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 卡片行外层信息更新(数据源,样式等) |
| | | */ |
| | | updateComponent = (component) => { |
| | | this.setState({ |
| | | card: component |
| | | }) |
| | | |
| | | component.width = component.wrap.width |
| | | component.name = component.wrap.name |
| | | |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { card } = this.state |
| | | |
| | | if (comIds[0] !== card.uuid) return |
| | | |
| | | let _card = {} |
| | | if (comIds.length === 1) { |
| | | _card = {...card, style} |
| | | } else { |
| | | return |
| | | } |
| | | |
| | | this.setState({ |
| | | card: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | /** |
| | | * @description 更新搜索条件配置信息 |
| | | */ |
| | | updateconfig = (config) => { |
| | | this.setState({ |
| | | card: config |
| | | }) |
| | | this.props.updateConfig(config) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.card) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.state |
| | | return ( |
| | | <div className="menu-normal-editor-box" style={{...card.style}} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader defaultshow="hidden" hideSearch="true" config={card} updateComponent={this.updateComponent}/> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="normaltable" card={card}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <UserComponent config={card}/> |
| | | <Icon className="close" title="删除组件" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} /> |
| | | <EditorContent config={card} updateConfig={this.updateComponent}/> |
| | | {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> |
| | | <BraftContent |
| | | value={card.wrap.datatype !== 'static' ? '<p class="empty-content">富文本</p>' : card.html} |
| | | encryption="false" |
| | | /> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | const mapStateToProps = (state) => { |
| | | return { |
| | | menu: state.customMenu |
| | | } |
| | | } |
| | | |
| | | const mapDispatchToProps = () => { |
| | | return {} |
| | | } |
| | | |
| | | export default connect(mapStateToProps, mapDispatchToProps)(TableCardEditComponent) |
New file |
| | |
| | | .menu-normal-editor-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 100px; |
| | | |
| | | .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); |
| | | } |
| | | .empty-content { |
| | | text-align: center; |
| | | font-size: 30px; |
| | | margin: 0; |
| | | line-height: 90px; |
| | | color: #bcbcbc; |
| | | } |
| | | } |
| | | .menu-normal-table-edit-box::after { |
| | | display: block; |
| | | content: ' '; |
| | | clear: both; |
| | | } |
| | | .menu-normal-table-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import SettingForm from './settingform' |
| | | import './index.scss' |
| | | |
| | | class DataSource extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.any, |
| | | updateConfig: PropTypes.func |
| | | } |
| | | |
| | | state = { |
| | | dict: localStorage.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" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title="富文本设置" |
| | | visible={visible} |
| | | width={700} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.verifySubmit} |
| | | onCancel={() => { this.setState({ visible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <SettingForm |
| | | dict={dict} |
| | | wrap={wrap} |
| | | config={config} |
| | | inputSubmit={this.verifySubmit} |
| | | wrappedComponentRef={(inst) => this.verifyRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DataSource |
New file |
| | |
| | | .model-menu-setting-wrap { |
| | | display: inline-block; |
| | | |
| | | >.anticon-edit { |
| | | color: #1890ff; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd' |
| | | |
| | | import './index.scss' |
| | | |
| | | class SettingForm extends Component { |
| | | static propTpyes = { |
| | | dict: PropTypes.object, // 字典项 |
| | | config: PropTypes.object, // 卡片行信息 |
| | | wrap: PropTypes.object, // 数据源配置 |
| | | inputSubmit: PropTypes.func // 回车事件 |
| | | } |
| | | |
| | | state = { |
| | | roleList: [], |
| | | datatype: this.props.wrap.datatype || 'dynamic' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | let roleList = sessionStorage.getItem('sysRoles') |
| | | if (roleList) { |
| | | try { |
| | | roleList = JSON.parse(roleList) |
| | | } catch { |
| | | roleList = [] |
| | | } |
| | | } else { |
| | | roleList = [] |
| | | } |
| | | |
| | | this.setState({roleList}) |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | // 表单提交时检查输入值是否正确 |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (!err) { |
| | | resolve(values) |
| | | } else { |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = (e) => { |
| | | e.preventDefault() |
| | | |
| | | if (this.props.inputSubmit) { |
| | | this.props.inputSubmit() |
| | | } |
| | | } |
| | | |
| | | changeDataType = (e) => { |
| | | this.setState({datatype: e.target.value}) |
| | | } |
| | | |
| | | render() { |
| | | const { wrap, config } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { roleList, datatype } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 8 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="model-menu-setting-form"> |
| | | <Form {...formItemLayout}> |
| | | <Row gutter={24}> |
| | | <Col span={12}> |
| | | <Form.Item label="标题"> |
| | | {getFieldDecorator('title', { |
| | | initialValue: wrap.title || '' |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="用于组件间的区分。"> |
| | | <Icon type="question-circle" /> |
| | | 组件名称 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('name', { |
| | | initialValue: wrap.name, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '组件名称!' |
| | | } |
| | | ] |
| | | })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="栅格布局,每行等分为24列。"> |
| | | <Icon type="question-circle" /> |
| | | 宽度 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('width', { |
| | | initialValue: wrap.width || 24, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: this.props.dict['form.required.input'] + '宽度!' |
| | | } |
| | | ] |
| | | })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label={ |
| | | <Tooltip placement="topLeft" title="选择静态值,无需配置数据源。"> |
| | | <Icon type="question-circle" /> |
| | | 数据来源 |
| | | </Tooltip> |
| | | }> |
| | | {getFieldDecorator('datatype', { |
| | | initialValue: datatype |
| | | })( |
| | | <Radio.Group onChange={this.changeDataType}> |
| | | <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', { |
| | | 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) |
New file |
| | |
| | | .model-menu-setting-form { |
| | | position: relative; |
| | | |
| | | .anticon-question-circle { |
| | | color: #c49f47; |
| | | margin-right: 3px; |
| | | } |
| | | .ant-input-number { |
| | | width: 100%; |
| | | } |
| | | .color-sketch-block { |
| | | position: relative; |
| | | top: 7px; |
| | | } |
| | | } |
| | |
| | | const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | return (<TableCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'table' && card.subtype === 'normaltable') { |
| | | return (<NormalTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | |
| | | line: '折线图', |
| | | pie: '饼图', |
| | | table: '表格', |
| | | editor: '富文本', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | _config.search = config.search || [] |
| | | _config.cols = config.cols || [] |
| | | _config.plot = config.plot || {} |
| | | _config.html = config.html || '' |
| | | |
| | | _config.width = _config.wrap.width || _config.plot.width || config.width || 24 |
| | | |
| | |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) |
| | | const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | return (<NormalTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'group' && card.subtype === 'normalgroup') { |
| | | return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | |
| | | search: '搜索', |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | |
| | | return ( |
| | | <div className="model-datasource"> |
| | | <Icon type="setting" onClick={() => this.editDataSource()} /> |
| | | <Icon type="setting" title="数据源" onClick={() => this.editDataSource()} /> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={'数据源配置'} |
| | |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalTable = asyncComponent(() => import('@/menu/components/table/normal-table')) |
| | | const NormalGroup = asyncComponent(() => import('@/menu/components/group/normal-group')) |
| | | const BraftEditor = asyncComponent(() => import('@/menu/components/editor/braft-editor')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | |
| | | return (<NormalTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'group' && card.subtype === 'normalgroup') { |
| | | return (<NormalGroup group={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'editor') { |
| | | return (<BraftEditor card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | return ( |
| | |
| | | search: '搜索', |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | |
| | | import TableCard from '@/assets/mobimg/table-card.png' |
| | | import NormalTable from '@/assets/mobimg/normal-table.png' |
| | | import Pie from '@/assets/mobimg/pie.png' |
| | | import Editor from '@/assets/mobimg/editor.png' |
| | | import Pie1 from '@/assets/mobimg/ring.png' |
| | | import Pie2 from '@/assets/mobimg/nightingale.png' |
| | | import Mainsearch from '@/assets/mobimg/mainsearch.png' |
| | |
| | | { type: 'menu', url: bar1, component: 'bar', subtype: 'bar1', title: '条形图', width: 24 }, |
| | | { type: 'menu', url: Pie, component: 'pie', subtype: 'pie', title: '饼图', width: 12 }, |
| | | { type: 'menu', url: Pie1, component: 'pie', subtype: 'ring', title: '环图', width: 12 }, |
| | | { type: 'menu', url: Editor, component: 'editor', subtype: 'brafteditor', title: '富文本', width: 24 }, |
| | | { type: 'menu', url: Pie2, component: 'pie', subtype: 'nightingale', title: '南丁格尔图', width: 12 }, |
| | | { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '分组', width: 24, forbid: ['billPrint'] }, |
| | | ] |
| | |
| | | |
| | | config.components.forEach(item => { |
| | | if (error) return |
| | | if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return |
| | | if ((item.subtype === 'propcard' || item.subtype === 'brafteditor') && item.wrap.datatype === 'static') return |
| | | |
| | | if (item.setting) { |
| | | if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Spin, notification } from 'antd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import Api from '@/api' |
| | | import UtilsDM from '@/utils/utils-datamanage.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import './index.scss' |
| | | |
| | | const BraftContent = asyncComponent(() => import('@/tabviews/custom/components/share/braftContent')) |
| | | const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader')) |
| | | |
| | | class BraftEditorContent extends Component { |
| | | static propTpyes = { |
| | | BID: PropTypes.any, // 父级Id |
| | | data: PropTypes.array, // 统一查询数据 |
| | | config: PropTypes.object, // 组件配置信息 |
| | | mainSearch: PropTypes.any, // 外层搜索条件 |
| | | menuType: PropTypes.any, // 菜单类型 |
| | | } |
| | | |
| | | state = { |
| | | BID: '', // 上级ID |
| | | config: null, // 图表配置信息 |
| | | loading: false, // 数据加载状态 |
| | | sync: false, // 是否统一请求数据 |
| | | data: {} // 数据 |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { data, initdata, BID } = this.props |
| | | let _config = fromJS(this.props.config).toJS() |
| | | |
| | | let _data = {} |
| | | let _sync = false |
| | | |
| | | if (_config.setting && _config.wrap.datatype !== 'static') { |
| | | _sync = _config.setting.sync === 'true' |
| | | |
| | | if (_sync && data) { |
| | | _data = data[_config.dataName] || {} |
| | | if (_data && Array.isArray(_data)) { |
| | | _data = _data[0] || {} |
| | | } |
| | | _sync = false |
| | | } else if (_sync && initdata) { |
| | | _data = initdata || {} |
| | | if (_data && Array.isArray(_data)) { |
| | | _data = _data[0] || {} |
| | | } |
| | | _sync = false |
| | | } |
| | | } else { |
| | | _data = {} |
| | | } |
| | | |
| | | this.setState({ |
| | | sync: _sync, |
| | | data: _data, |
| | | BID: BID || '', |
| | | config: _config, |
| | | arr_field: _config.columns.map(col => col.field).join(','), |
| | | }, () => { |
| | | if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') { |
| | | this.loadData() |
| | | } |
| | | }) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('reloadData', this.reloadData) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('reloadData', this.reloadData) |
| | | } |
| | | |
| | | /** |
| | | * @description 图表数据更新,刷新内容 |
| | | */ |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | const { sync, config } = this.state |
| | | |
| | | if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) { |
| | | let _data = {} |
| | | if (nextProps.data && nextProps.data[config.dataName]) { |
| | | _data = nextProps.data[config.dataName] |
| | | if (_data && Array.isArray(_data)) { |
| | | _data = _data[0] |
| | | } |
| | | } |
| | | |
| | | this.setState({sync: false, data: _data}) |
| | | } else if (nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) { |
| | | if (config.wrap.datatype !== 'static' && config.setting.syncRefresh === 'true') { |
| | | this.setState({}, () => { |
| | | this.loadData() |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | reloadData = (menuId) => { |
| | | const { config } = this.state |
| | | |
| | | if (menuId !== config.uuid) return |
| | | |
| | | this.loadData() |
| | | } |
| | | |
| | | async loadData () { |
| | | const { mainSearch, menuType } = this.props |
| | | const { config, arr_field, BID } = this.state |
| | | |
| | | if (config.wrap.datatype === 'static') { |
| | | this.setState({ |
| | | data: {}, |
| | | loading: false |
| | | }) |
| | | return |
| | | } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询 |
| | | this.setState({ |
| | | data: {}, |
| | | loading: false |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let searches = [] |
| | | if (mainSearch && mainSearch.length > 0) { // 主表搜索条件 |
| | | let keys = searches.map(item => item.key) |
| | | mainSearch.forEach(item => { |
| | | if (!keys.includes(item.key)) { |
| | | searches.push(item) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | loading: true |
| | | }) |
| | | |
| | | let _orderBy = config.setting.order || '' |
| | | let param = UtilsDM.getQueryDataParams(config.setting, arr_field, searches, _orderBy, 1, 1, BID, menuType) |
| | | |
| | | let result = await Api.genericInterface(param) |
| | | if (result.status) { |
| | | let _data = result.data && result.data[0] ? result.data[0] : {} |
| | | |
| | | this.setState({ |
| | | data: _data, |
| | | loading: false |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | loading: false |
| | | }) |
| | | notification.error({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 10 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { config, loading, data } = this.state |
| | | |
| | | return ( |
| | | <div className="custom-braft-editor-box" style={{...config.style}}> |
| | | {loading ? |
| | | <div className="loading-mask"> |
| | | <div className="ant-spin-blur"></div> |
| | | <Spin /> |
| | | </div> : null |
| | | } |
| | | <NormalHeader config={config}/> |
| | | <BraftContent |
| | | value={config.wrap.datatype !== 'static' ? (data[config.wrap.field] || '') : config.html} |
| | | encryption={config.wrap.datatype !== 'static' ? config.wrap.encryption : 'false'} |
| | | /> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default BraftEditorContent |
New file |
| | |
| | | .custom-braft-editor-box { |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | min-height: 20px; |
| | | position: relative; |
| | | |
| | | .card-row-list::after { |
| | | content: ' '; |
| | | display: block; |
| | | clear: both; |
| | | } |
| | | |
| | | .card-row-list { |
| | | .card-item-box { |
| | | background-color: #ffffff; |
| | | transition: all 0.3s; |
| | | } |
| | | >.active >.card-item-box { |
| | | border-color: #1890ff!important; |
| | | box-shadow: 0 0 4px #1890ff; |
| | | } |
| | | } |
| | | .card-row-list.radio, .card-row-list.checkbox { |
| | | >.ant-col:not(.active):not(.selected):hover { |
| | | >.card-item-box { |
| | | border-color: #69c0ff!important; |
| | | box-shadow: 0 0 4px #69c0ff!important; |
| | | } |
| | | } |
| | | } |
| | | .card-row-list.true { |
| | | >.ant-col:hover { |
| | | >.card-item-box { |
| | | z-index: 1; |
| | | transform: scale(1.05); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .card-item-box { |
| | | position: relative; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .loading-mask { |
| | | position: absolute; |
| | | left: 40px; |
| | | top: 0; |
| | | right: 40px; |
| | | bottom: 0px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | text-align: justify; |
| | | z-index: 1; |
| | | |
| | | .ant-spin-blur { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | opacity: 0.5; |
| | | background: #ffffff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .custom-braft-editor-box::after { |
| | | content: ' '; |
| | | display: block; |
| | | clear: both; |
| | | } |
| | |
| | | const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card')) |
| | | const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card')) |
| | | const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card')) |
| | | const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor')) |
| | | |
| | | class TabTransfer extends Component { |
| | | static propTpyes = { |
| | |
| | | if (item.type === 'tabs') return |
| | | |
| | | if (!item.setting || item.setting.interType !== 'system') return |
| | | if (!item.format || (item.subtype === 'propcard' && item.wrap.datatype === 'static')) return |
| | | if (!item.format) return |
| | | |
| | | if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') { |
| | | let param = this.getDefaultParam(item, _mainSearch) |
| | |
| | | <TableCard config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'editor') { |
| | | return ( |
| | | <Col span={item.width} key={item.uuid}> |
| | | <BraftEditor config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else { |
| | | return null |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | |
| | | import './index.scss' |
| | | |
| | | class BraftContent extends Component { |
| | | static propTpyes = { |
| | | value: PropTypes.any, // 内容 |
| | | encryption: PropTypes.any, // 是否解码 |
| | | } |
| | | |
| | | state = { |
| | | html: '' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { encryption, value } = this.props |
| | | let html = value |
| | | |
| | | if (encryption === 'true' && html) { |
| | | try { |
| | | html = window.decodeURIComponent(window.atob(html)) |
| | | } catch { |
| | | html = value |
| | | } |
| | | } |
| | | |
| | | this.setState({html}) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps(nextProps) { |
| | | if (!is(fromJS(this.props), fromJS(nextProps))) { |
| | | const { encryption, value } = nextProps |
| | | let html = value |
| | | |
| | | if (encryption === 'true' && html) { |
| | | try { |
| | | html = window.decodeURIComponent(window.atob(html)) |
| | | } catch { |
| | | html = value |
| | | } |
| | | } |
| | | |
| | | this.setState({html}) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { html } = this.state |
| | | return ( |
| | | <div className="braft-content" 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card')) |
| | | const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card')) |
| | | const NormalGroup = asyncComponent(() => import('@/tabviews/custom/components/group/normal-group')) |
| | | const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor')) |
| | | |
| | | class TabTransfer extends Component { |
| | | static propTpyes = { |
| | |
| | | if (item.type === 'tabs' || item.type === 'group') return |
| | | |
| | | if (!item.setting || item.setting.interType !== 'system') return |
| | | if (!item.format || (item.subtype === 'propcard' && item.wrap.datatype === 'static')) return |
| | | if (!item.format) return |
| | | |
| | | if (item.dataName && (!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true' && item.setting.sync === 'true') { |
| | | let param = this.getDefaultParam(item, _mainSearch) |
| | |
| | | <NormalGroup config={item} bids={bids} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'editor') { |
| | | return ( |
| | | <Col span={item.width} key={item.uuid}> |
| | | <BraftEditor config={item} data={data} BID={BID} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else { |
| | | return null |
| | | } |
| | |
| | | const MainSearch = asyncComponent(() => import('@/tabviews/zshare/topSearch')) |
| | | const NormalTable = asyncComponent(() => import('./components/table/normal-table')) |
| | | const NormalGroup = asyncComponent(() => import('./components/group/normal-group')) |
| | | const BraftEditor = asyncComponent(() => import('./components/editor/braft-editor')) |
| | | const SettingComponent = asyncComponent(() => import('@/tabviews/zshare/settingcomponent')) |
| | | const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage')) |
| | | |
| | |
| | | return component |
| | | } |
| | | |
| | | if ((component.subtype === 'propcard' || component.subtype === 'brafteditor') && component.wrap.datatype === 'static') { |
| | | component.format = '' |
| | | } |
| | | |
| | | if (!component.setting) return component // 不使用系统函数时 |
| | | if (!component.format || (component.subtype === 'propcard' && component.wrap.datatype === 'static')) return component // 没有动态数据 数据格式 array 或 object |
| | | if (!component.format) return component // 没有动态数据 数据格式 array 或 object |
| | | if (component.setting.interType !== 'system') { // 不使用系统函数时 |
| | | component.setting.sync = 'false' |
| | | component.setting.laypage = component.setting.laypage === 'true' |
| | |
| | | <NormalGroup config={item} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'editor') { |
| | | return ( |
| | | <Col span={item.width} key={item.uuid}> |
| | | <BraftEditor config={item} data={data} BID={_bid} mainSearch={mainSearch} menuType={menuType} /> |
| | | </Col> |
| | | ) |
| | | } else { |
| | | return null |
| | | } |
| | |
| | | const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card')) |
| | | const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table')) |
| | | const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor')) |
| | | |
| | | class BillPrint extends Component { |
| | | state = { |
| | |
| | | if (component.search) component.search = [] |
| | | component.data = [] // 初始化数据为空 |
| | | |
| | | if ((component.subtype === 'propcard' || component.subtype === 'brafteditor') && component.wrap.datatype === 'static') { |
| | | component.format = '' |
| | | } |
| | | |
| | | if (!component.setting) return component // 不使用系统函数时 |
| | | if (!component.format || (component.subtype === 'propcard' && component.wrap.datatype === 'static')) return component // 没有动态数据 数据格式 array 或 object |
| | | if (!component.format) return component // 没有动态数据 数据格式 array 或 object |
| | | if (component.setting.interType !== 'system') { // 不使用系统函数时 |
| | | component.setting.sync = 'false' |
| | | return component |
| | |
| | | let _results = results.filter(Boolean) |
| | | |
| | | let comps = components.map(item => { |
| | | if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return item |
| | | if (!item.format) return item |
| | | |
| | | _results.forEach(res => { |
| | | if (res.componentId === item.uuid && res.data) { |
| | |
| | | <NormalTable config={item} initdata={item.data} mainSearch={[]} menuType="" /> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'editor') { |
| | | return ( |
| | | <Col span={item.width} key={item.uuid}> |
| | | <BraftEditor config={item} initdata={item.data} mainSearch={[]} menuType="" /> |
| | | </Col> |
| | | ) |
| | | } else { |
| | | return null |
| | | } |
| | |
| | | |
| | | config.components.forEach(item => { |
| | | if (error) return |
| | | if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return |
| | | if ((item.subtype === 'propcard' || item.subtype === 'brafteditor') && item.wrap.datatype === 'static') return |
| | | |
| | | if (item.setting) { |
| | | if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) { |