| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Icon, Modal } from 'antd' |
| | | import { Modal, Popover } from 'antd' |
| | | import { EditOutlined, CloseOutlined, PlusOutlined } from '@ant-design/icons' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import { getCardDetailForm } from '@/templates/zshare/formconfig' |
| | | |
| | | import MkIcon from '@/components/mk-icon' |
| | | import DragDetail from './dragdetail' |
| | | import CardDetailForm from './carddetailform' |
| | | import avatar from '@/assets/img/avatar.png' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | |
| | | } |
| | | |
| | | state = { |
| | | dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS, |
| | | visible: false, |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | modaltype: '', |
| | | formlist: null, |
| | | cardwidth: 0, |
| | | cardheight: 0, |
| | | cardcell: null // 卡片元素 |
| | | } |
| | | |
| | | componentDidMount () { |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | if (!is(fromJS(this.props.card), fromJS(nextProps.card))) { |
| | | |
| | | setTimeout(() => { |
| | | if (nextProps.card.extraAction && this.cardRef) { |
| | | if (this.cardRef.offsetWidth !== this.state.cardwidth || this.cardRef.offsetHeight !== this.state.cardheight) { |
| | | this.setState({ |
| | | cardwidth: this.cardRef.offsetWidth, |
| | | cardheight: this.cardRef.offsetHeight |
| | | }) |
| | | } |
| | | } |
| | | }, 200) |
| | | } |
| | | } |
| | | |
| | | |
| | | plotChange = (values) => { |
| | | const { card, config } = this.props |
| | |
| | | const { config } = this.props |
| | | if (!_cell) { |
| | | _cell = { |
| | | datatype: 'dynamic' |
| | | datatype: 'dynamic', |
| | | elemType: 'detail', |
| | | width: 100, |
| | | fontWeight: 'normal', |
| | | fontSize: 14 |
| | | } |
| | | } |
| | | |
| | | let _columns = config.columns.filter(col => ['text', 'number'].includes(col.type)) |
| | | let _columns = config.columns.filter(col => ['text', 'number', 'link', 'textarea'].includes(col.type)) |
| | | _columns = _columns.map(col => { |
| | | return { |
| | | uuid: col.uuid, |
| | |
| | | |
| | | this.setState({ |
| | | cardcell: _cell, |
| | | visible: true, |
| | | formlist: getCardDetailForm(_cell, _columns) |
| | | modaltype: 'detail', |
| | | formlist: getCardDetailForm(_cell, _columns, 'detail') |
| | | }) |
| | | } |
| | | |
| | | editHeader = () => { |
| | | const { config, card } = this.props |
| | | |
| | | let _columns = config.columns.filter(col => ['text', 'number'].includes(col.type)) |
| | | _columns = _columns.map(col => { |
| | | return { |
| | | uuid: col.uuid, |
| | | value: col.field, |
| | | text: col.label |
| | | } |
| | | }) |
| | | let _actions = config.action.filter(item => |
| | | (item.Ot && item.Ot !== 'notRequired' && !['excelIn', 'excelOut'].includes(item.OpenType)) || |
| | | item.funcType === 'changeuser' |
| | | ) |
| | | |
| | | let actionIds = [] |
| | | _actions = _actions.map(item => { |
| | | actionIds.push(item.uuid) |
| | | |
| | | return { |
| | | value: item.uuid, |
| | | icon: item.icon, |
| | | text: item.label |
| | | } |
| | | }) |
| | | |
| | | let _cell = fromJS(card.header).toJS() |
| | | if (_columns.filter(col => col.value === _cell.field).length === 0) { |
| | | _cell.field = '' |
| | | } |
| | | if (_cell.actions.length > 0) { |
| | | _cell.actions = _cell.actions.filter(item => actionIds.includes(item.value)) |
| | | } |
| | | |
| | | this.setState({ |
| | | cardcell: _cell, |
| | | modaltype: 'header', |
| | | formlist: getCardDetailForm(_cell, _columns, 'header', _actions) |
| | | }) |
| | | } |
| | | |
| | | editBottom = () => { |
| | | const { config, card } = this.props |
| | | |
| | | let _actions = config.action.filter(item => |
| | | (item.Ot && item.Ot !== 'notRequired' && !['excelIn', 'excelOut'].includes(item.OpenType)) || |
| | | item.funcType === 'changeuser' |
| | | ) |
| | | |
| | | let actionIds = [] |
| | | _actions = _actions.map(item => { |
| | | actionIds.push(item.uuid) |
| | | |
| | | return { |
| | | value: item.uuid, |
| | | icon: item.icon, |
| | | text: item.label |
| | | } |
| | | }) |
| | | |
| | | let _cell = fromJS(card.bottom).toJS() |
| | | |
| | | if (_cell.actions.length > 0) { |
| | | _cell.actions = _cell.actions.filter(item => actionIds.includes(item.value)) |
| | | } |
| | | |
| | | this.setState({ |
| | | cardcell: _cell, |
| | | modaltype: 'bottom', |
| | | formlist: getCardDetailForm(_cell, [], 'bottom', _actions) |
| | | }) |
| | | } |
| | | |
| | | editAvatar = () => { |
| | | const { config, card } = this.props |
| | | |
| | | let _columns = [] |
| | | config.columns.forEach(col => { |
| | | if (['picture'].includes(col.type)) { |
| | | _columns.push({ |
| | | type: 'picture', |
| | | uuid: col.uuid, |
| | | value: col.field, |
| | | text: col.label |
| | | }) |
| | | } else if (['text', 'number'].includes(col.type) && col.marks) { |
| | | let mark = col.marks.filter(_mark => _mark.signType === 'icon' && _mark.icon)[0] |
| | | if (mark) { |
| | | _columns.push({ |
| | | type: 'icon', |
| | | uuid: col.uuid, |
| | | value: col.field, |
| | | text: col.label, |
| | | icon: mark.icon, |
| | | color: mark.color[1] |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | let _cell = fromJS(card.avatar).toJS() |
| | | if (_columns.filter(col => col.value === _cell.field && col.type === _cell.type).length === 0) { |
| | | _cell.field = '' |
| | | _cell.content = '' |
| | | } |
| | | |
| | | this.setState({ |
| | | cardcell: _cell, |
| | | modaltype: 'avatar', |
| | | formlist: getCardDetailForm(_cell, _columns, 'avatar', []) |
| | | }) |
| | | } |
| | | |
| | | handleSubmit = () => { |
| | | const { card } = this.props |
| | | let _details = fromJS(card.details).toJS() |
| | | const { modaltype } = this.state |
| | | |
| | | this.detailFormRef.handleConfirm().then(res => { |
| | | if (!res.uuid) { |
| | | res.uuid = Utils.getuuid() |
| | | _details.push(res) |
| | | } else { |
| | | _details = _details.map(item => { |
| | | if (item.uuid === res.uuid) return res |
| | | return item |
| | | this.cardFormRef.handleConfirm().then(res => { |
| | | if (modaltype === 'detail') { |
| | | let _details = fromJS(this.props.card.details).toJS() |
| | | if (!res.uuid) { |
| | | res.uuid = Utils.getuuid() |
| | | _details.push(res) |
| | | } else { |
| | | _details = _details.map(item => { |
| | | if (item.uuid === res.uuid) return res |
| | | return item |
| | | }) |
| | | } |
| | | |
| | | this.setState({ |
| | | cardcell: null, |
| | | modaltype: '', |
| | | formlist: null |
| | | }) |
| | | this.plotChange({details: _details}) |
| | | } else if (modaltype === 'header') { |
| | | this.setState({ |
| | | cardcell: null, |
| | | modaltype: '', |
| | | formlist: null |
| | | }) |
| | | this.plotChange({header: res}) |
| | | } else if (modaltype === 'bottom') { |
| | | this.setState({ |
| | | cardcell: null, |
| | | modaltype: '', |
| | | formlist: null |
| | | }) |
| | | this.plotChange({bottom: res}) |
| | | } else if (modaltype === 'avatar') { |
| | | this.setState({ |
| | | cardcell: null, |
| | | modaltype: '', |
| | | formlist: null |
| | | }) |
| | | this.plotChange({avatar: res}) |
| | | } |
| | | |
| | | this.setState({ |
| | | cardcell: null, |
| | | visible: false, |
| | | formlist: null |
| | | }) |
| | | this.plotChange({details: _details}) |
| | | }) |
| | | } |
| | | |
| | | editModalCancel = () => { |
| | | this.setState({ |
| | | cardcell: null, |
| | | visible: false, |
| | | modaltype: '', |
| | | formlist: null |
| | | }) |
| | | } |
| | |
| | | |
| | | confirm({ |
| | | content: dict['model.confirm'] + dict['model.delete'] + ` - ${cell.content} ?`, |
| | | okText: dict['model.confirm'], |
| | | cancelText: dict['header.cancel'], |
| | | onOk() { |
| | | let _details = fromJS(card.details).toJS() |
| | | |
| | |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | |
| | | } |
| | | |
| | | deleteElem = (type) => { |
| | | const { dict } = this.state |
| | | let _this = this |
| | | |
| | | confirm({ |
| | | content: dict['model.confirm'] + dict['model.delete'] + '?', |
| | | onOk() { |
| | | let _subelement = fromJS(_this.props.card.subelement).toJS() |
| | | _subelement = _subelement.filter(_type => _type !== type) |
| | | |
| | | _this.plotChange({subelement: _subelement}) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | componentDidMount() { |
| | | const { card } = this.props |
| | | |
| | | if (card.extraAction && this.cardRef) { |
| | | this.setState({ |
| | | cardwidth: this.cardRef.offsetWidth, |
| | | cardheight: this.cardRef.offsetHeight |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidUpdate() { |
| | | const { card } = this.props |
| | | |
| | | if (card.extraAction && this.cardRef) { |
| | | if (this.cardRef.offsetWidth !== this.state.cardwidth || this.cardRef.offsetHeight !== this.state.cardheight) { |
| | | this.setState({ |
| | | cardwidth: this.cardRef.offsetWidth, |
| | | cardheight: this.cardRef.offsetHeight |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { card } = this.props |
| | | const { dict, visible, cardcell } = this.state |
| | | const { dict, modaltype, cardcell, cardwidth, cardheight } = this.state |
| | | let _width = '100%' |
| | | if (card.bottom && card.bottom.actions.length > 0) { |
| | | _width = Math.floor((100 / card.bottom.actions.length) * 10000) / 10000 + '%' |
| | | } |
| | | |
| | | if (card.widthType === 'absolute') { |
| | | card.cardWidth = 6 |
| | | } |
| | | if (card.avatar && card.avatar.widthType === 'absolute') { |
| | | card.avatar.width = 32 |
| | | } |
| | | |
| | | let outclass = 'ant-col-' + card.cardWidth |
| | | |
| | | if (card.background) { |
| | | outclass += ' background ' + card.background |
| | | } |
| | | if (card.border === 'hidden') { |
| | | outclass += ' without-border' |
| | | } else { |
| | | outclass += ' ant-card-bordered' |
| | | } |
| | | |
| | | let metastyle = {} |
| | | if (card.subelement.includes('avatar')) { |
| | | // 计算卡片宽度 |
| | | let _outWidth = document.body.offsetWidth - 260 |
| | | let _cardWidth = Math.floor(_outWidth * card.cardWidth / 24 - 20) |
| | | |
| | | if (card.avatar.type === 'picture') { |
| | | if (card.avatar.width < 90 && card.avatar.display !== 'block') { |
| | | metastyle.display = 'flex' |
| | | } |
| | | } else { |
| | | if (card.avatar.size < _cardWidth * 0.9 && card.avatar.display !== 'block') { |
| | | metastyle.display = 'flex' |
| | | } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className="line-card-edit-box"> |
| | | <div className="line-card-edit-box mingke-table"> |
| | | {card.title ? <p className="chart-title">{card.title}</p> : null} |
| | | <div |
| | | className={'ant-card ant-card-bordered chart-card' + (card.widthType === 'ratio' ? ' ant-col ant-col-' + card.cardWidth : '')} |
| | | style={card.widthType === 'absolute' ? { width: card.cardWidth } : null} |
| | | ref={(ref) => this.cardRef = ref} |
| | | className={'ant-card chart-card ant-col ' + outclass} |
| | | > |
| | | <div className="ant-card-head"> |
| | | <div className="ant-card-head-wrapper"> |
| | | <div className="ant-card-head-title">Card Title</div> |
| | | <div className="ant-card-extra"> |
| | | <span>Action</span> |
| | | {card.subelement.includes('header') ? |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <EditOutlined className="edit" onClick={this.editHeader} /> |
| | | <CloseOutlined className="close" onClick={() => this.deleteElem('header')} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="ant-card-head"> |
| | | <div className="ant-card-head-wrapper"> |
| | | <div className="ant-card-head-title">{card.header.content}</div> |
| | | {card.header.actions && card.header.actions.length > 0 ? |
| | | <div className="ant-card-extra"> |
| | | <span> |
| | | {['icon', 'all'].includes(card.header.show) ? <MkIcon type={card.header.actions[0].icon || 'dash'}/> : null} |
| | | {['text', 'all'].includes(card.header.show) ? card.header.actions[0].text : null} |
| | | </span> |
| | | </div> : null |
| | | } |
| | | </div> |
| | | </div> |
| | | </Popover> : null |
| | | } |
| | | <div className="ant-card-body"> |
| | | <div className="ant-card-meta" style={metastyle}> |
| | | <PlusOutlined onClick={() => this.editdetail()} /> |
| | | {card.subelement.includes('avatar') ? |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <EditOutlined className="edit" onClick={this.editAvatar} /> |
| | | <CloseOutlined className="close" onClick={() => this.deleteElem('avatar')} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <div className="ant-card-meta-avatar" style={card.avatar.type === 'icon' ? {width: card.avatar.width, paddingTop: card.avatar.width} : {width: card.avatar.width + '%', paddingTop: card.avatar.width + '%'}}> |
| | | <span className="ant-avatar ant-avatar-circle ant-avatar-image" style={{borderRadius: card.avatar.radius === 'true' ? '50%' : 0}}> |
| | | {card.avatar.type === 'picture' ? <img src={avatar} alt=""/> : null} |
| | | {card.avatar.type === 'icon' ? <MkIcon className={'font ' + card.avatar.color} style={{fontSize: card.avatar.size + 'px'}} type={card.avatar.icon} /> : null} |
| | | </span> |
| | | </div> |
| | | </Popover> : null |
| | | } |
| | | <div className="ant-card-meta-detail" style={metastyle.display ? {flex: 1} : null}> |
| | | <DragDetail |
| | | cardObj={card} |
| | | handleList={this.handleList} |
| | | handleMenu={this.editdetail} |
| | | deleteMenu={this.deletedetail} |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div className="ant-card-body"> |
| | | <div className="ant-card-meta"> |
| | | <Icon type="plus" onClick={() => this.editdetail()} /> |
| | | {card.cardType === 'card2' ? <div className="ant-card-meta-avatar"> |
| | | <span className="ant-avatar ant-avatar-circle ant-avatar-image" style={{width: 32, height: 32}}> |
| | | <img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" alt=""/> |
| | | </span> |
| | | </div> : null } |
| | | <DragDetail |
| | | list={card.details} |
| | | handleList={this.handleList} |
| | | handleMenu={this.editdetail} |
| | | deleteMenu={this.deletedetail} |
| | | /> |
| | | </div> |
| | | </div> |
| | | {card.cardType === 'card2' ? <ul className="ant-card-actions"> |
| | | <li style={{width: '33.3333%'}}> |
| | | <span> |
| | | <Icon type="setting"/> |
| | | </span> |
| | | </li> |
| | | <li style={{width: '33.3333%'}}> |
| | | <span> |
| | | <Icon type="edit"/> |
| | | </span> |
| | | </li> |
| | | <li style={{width: '33.3333%'}}> |
| | | <span> |
| | | <Icon type="edit"/> |
| | | </span> |
| | | </li> |
| | | </ul> : null} |
| | | {card.subelement.includes('bottom') ? |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <EditOutlined className="edit" onClick={this.editBottom} /> |
| | | <CloseOutlined className="close" onClick={() => this.deleteElem('bottom')} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <ul className="ant-card-actions"> |
| | | {card.bottom.actions.map((item, i) => (<li key={i} style={{width: _width}}> |
| | | <span> |
| | | {['icon', 'all'].includes(card.bottom.show) ? <MkIcon type={item.icon || 'dash'}/> : null} |
| | | {['text', 'all'].includes(card.bottom.show) ? item.text : null} |
| | | </span> |
| | | </li>))} |
| | | </ul> |
| | | </Popover> : null |
| | | } |
| | | </div> |
| | | {card.extraAction ? |
| | | <div className={'ant-card chart-card chart-card-insert ' + outclass} style={{ width: cardwidth, height: cardheight }} > |
| | | <PlusOutlined style={cardwidth > cardheight ? {fontSize: cardheight / 2 + 'px', lineHeight: cardheight + 'px'} : {fontSize: cardwidth / 2 + 'px', lineHeight: cardheight + 'px'}} /> |
| | | </div> : null |
| | | } |
| | | {/* 显示列编辑 */} |
| | | <Modal |
| | | title="编辑" |
| | | visible={visible} |
| | | visible={!!modaltype} |
| | | width={650} |
| | | maskClosable={false} |
| | | onOk={this.handleSubmit} |
| | |
| | | card={cardcell} |
| | | inputSubmit={this.handleSubmit} |
| | | formlist={this.state.formlist} |
| | | wrappedComponentRef={(inst) => this.detailFormRef = inst} |
| | | wrappedComponentRef={(inst) => this.cardFormRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |