import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Card, Spin, Empty } from 'antd'
|
|
import asyncComponent from '@/utils/asyncComponent'
|
import asyncExcelComponent from './asyncButtonComponent'
|
import MKEmitter from '@/utils/events.js'
|
import MkIcon from '@/components/mk-icon'
|
import '@/assets/css/table.scss'
|
import './index.scss'
|
|
const NormalButton = asyncComponent(() => import('@/tabviews/zshare/actionList/normalbutton'))
|
const PopupButton = asyncComponent(() => import('@/tabviews/zshare/actionList/popupbutton'))
|
const ExcelInButton = asyncExcelComponent(() => import('@/tabviews/zshare/actionList/excelInbutton'))
|
const ExcelOutButton = asyncExcelComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton'))
|
const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton'))
|
const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
|
const ChangeUserButton = asyncComponent(() => import('@/tabviews/zshare/actionList/changeuserbutton'))
|
const PrintButton = asyncComponent(() => import('@/tabviews/zshare/actionList/printbutton'))
|
|
class CardCell extends Component {
|
static propTpyes = {
|
type: PropTypes.any, // 卡片类型,添加按钮为 insert
|
BID: PropTypes.any, // 主表ID
|
BData: PropTypes.any, // 主表数据
|
MenuID: PropTypes.string, // 菜单ID
|
setting: PropTypes.object, // 页面设定
|
columns: PropTypes.array, // 显示列
|
card: PropTypes.object, // 卡片设置信息
|
data: PropTypes.object, // 卡片数据
|
selectKey: PropTypes.string, // 选择卡片的序号
|
colMap: PropTypes.any, // 显示列信息,用于设置标记
|
switchCard: PropTypes.func // 卡片切换
|
}
|
|
state = {
|
extra: null, // 顶部按钮信息
|
actions: null, // 底部按钮行
|
cardwidth: 0,
|
cardheight: 0,
|
plusSize: 0
|
}
|
|
UNSAFE_componentWillMount () {
|
this.getCardActions()
|
}
|
|
/**
|
* @description 数据切换,重新绑定按钮数据
|
*/
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
|
this.setState({}, () => {
|
this.getCardActions()
|
})
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
componentDidMount() {
|
if (this.insertRef) {
|
let _width = this.insertRef.offsetWidth
|
let _height = this.insertRef.offsetHeight
|
|
if (this.props.card.header) {
|
_height += 46
|
}
|
if (this.props.card.bottom) {
|
_height += 49
|
}
|
this.setState({
|
cardwidth: _width,
|
cardheight: _height,
|
plusSize: _width > _height ? _height / 2 : _width / 2
|
})
|
}
|
}
|
|
componentDidUpdate() {
|
if (this.insertRef) {
|
let _width = this.insertRef.offsetWidth
|
let _height = this.insertRef.offsetHeight
|
|
if (this.props.card.header) {
|
_height += 46
|
}
|
if (this.props.card.bottom) {
|
_height += 49
|
}
|
|
if (_height !== this.state.cardheight || _width !== this.state.cardwidth) {
|
this.setState({
|
cardwidth: _width,
|
cardheight: _height,
|
plusSize: _width > _height ? _height / 2 : _width / 2
|
})
|
}
|
}
|
}
|
|
/**
|
* @description 获取顶部及按钮行的按钮集
|
*/
|
getCardActions = () => {
|
const { card } = this.props
|
|
let extra = null
|
if (card.header && card.header.actions) {
|
let actions = card.header.actions.map(item => {
|
if (card.header.show === 'icon') {
|
item.show = 'icon'
|
} else {
|
item.show = 'button'
|
}
|
return item
|
})
|
|
actions = this.getActionList(actions)
|
extra = actions[0]
|
}
|
|
let _actions = null
|
if (card.bottom && card.bottom.actions) {
|
_actions = card.bottom.actions.map(item => {
|
if (card.bottom.show === 'icon') {
|
item.show = 'icon'
|
} else {
|
item.show = 'button'
|
}
|
return item
|
})
|
_actions = this.getActionList(_actions)
|
}
|
|
this.setState({
|
actions: _actions,
|
extra: extra
|
})
|
}
|
|
/**
|
* @description 获取按钮元素
|
*/
|
getActionList = (actions) => {
|
const { BData, setting, columns, data, MenuID } = this.props
|
|
return actions.map(item => {
|
if (['exec', 'prompt', 'pop'].includes(item.OpenType)) {
|
return (
|
<NormalButton
|
key={item.uuid}
|
BID={data.$$BID}
|
btn={item}
|
BData={BData}
|
setting={setting}
|
columns={columns}
|
selectedData={[data]}
|
/>
|
)
|
} else if (item.OpenType === 'popview') {
|
return (
|
<PopupButton
|
key={item.uuid}
|
BID={data.$$BID}
|
btn={item}
|
BData={BData}
|
setting={setting}
|
selectedData={[data]}
|
/>
|
)
|
} else if (item.OpenType === 'tab') {
|
return (
|
<TabButton
|
key={item.uuid}
|
btn={item}
|
MenuID={MenuID}
|
selectedData={[data]}
|
/>
|
)
|
} else if (item.OpenType === 'innerpage' || item.OpenType === 'outerpage') {
|
return (
|
<NewPageButton
|
key={item.uuid}
|
btn={item}
|
selectedData={[data]}
|
/>
|
)
|
} else if (item.OpenType === 'funcbutton') {
|
if (item.funcType === 'changeuser' || item.funcType === 'closetab') {
|
return (
|
<ChangeUserButton
|
key={item.uuid}
|
BID={data.$$BID}
|
btn={item}
|
setting={setting}
|
selectedData={[data]}
|
/>
|
)
|
} else if (item.funcType === 'print') {
|
return (
|
<PrintButton
|
key={item.uuid}
|
BID={data.$$BID}
|
btn={item}
|
BData={BData}
|
setting={setting}
|
columns={columns}
|
selectedData={[data]}
|
/>
|
)
|
}
|
}
|
|
return null
|
})
|
}
|
|
/**
|
* @description 卡片中元素标记设置
|
*/
|
getMark = (record, marks) => {
|
const { colMap } = this.props
|
let className = ''
|
let isIcon = false
|
let position = 'back'
|
let icon = ''
|
|
colMap && marks.some(mark => {
|
let originType = colMap.get(mark.field).type
|
|
let originVal = record.hasOwnProperty(mark.field) ? record[mark.field] : ''
|
let contrastVal = ''
|
if (mark.contrastType === 'static') {
|
contrastVal = mark.contrastValue
|
} else {
|
contrastVal = record.hasOwnProperty(mark.contrastField) ? record[mark.contrastField] : ''
|
}
|
|
if (originType === 'text') {
|
originVal = '' + originVal
|
contrastVal = '' + contrastVal
|
} else if (originType === 'number' && originVal !== '' && contrastVal !== '') {
|
try {
|
originVal = parseFloat(originVal)
|
contrastVal = parseFloat(contrastVal)
|
if (isNaN(originVal) || isNaN(contrastVal)) {
|
originVal = ''
|
}
|
} catch (e) {
|
originVal = ''
|
}
|
}
|
|
if (originVal === '' || contrastVal === '') return false
|
|
if (mark.match === '=' && originVal === contrastVal) {
|
className = mark.color[1]
|
} else if (mark.match === '!=' && originVal !== contrastVal) {
|
className = mark.color[1]
|
} else if (mark.match === 'like' && originVal.indexOf(contrastVal) > -1) {
|
className = mark.color[1]
|
} else if (mark.match === '>' && originVal > contrastVal) {
|
className = mark.color[1]
|
} else if (mark.match === '<' && originVal < contrastVal) {
|
className = mark.color[1]
|
}
|
|
if (!className) return false
|
|
if (mark.signType === 'font') {
|
className = 'font ' + className
|
} else if (mark.signType === 'icon') {
|
isIcon = true
|
if (mark.position === 'front') {
|
position = 'front'
|
}
|
icon = <MkIcon className={'font ' + className} type={mark.icon} />
|
className = ''
|
}
|
|
return true
|
})
|
|
return {
|
className: className,
|
isIcon: isIcon,
|
position: position,
|
icon: icon
|
}
|
}
|
|
/**
|
* @description 获取卡片内容
|
*/
|
getContent = (col) => {
|
const { data } = this.props
|
|
if (col.type === 'text') {
|
let content = ''
|
let className = ''
|
if (data.hasOwnProperty(col.field)) {
|
content = `${data[col.field]}`
|
}
|
|
content = content ? (col.prefix || '') + content + (col.postfix || '') : ''
|
|
if (col.marks) {
|
let result = this.getMark(data, col.marks)
|
|
if (result.className) {
|
className = result.className
|
} else if (result.isIcon) {
|
if (result.position === 'front') {
|
content = <span>{result.icon} {content}</span>
|
} else {
|
content = <span>{content} {result.icon}</span>
|
}
|
}
|
}
|
|
return (
|
<span className={className}>
|
{content}
|
</span>
|
)
|
} else if (col.type === 'number') {
|
let content = ''
|
let className = ''
|
|
if (data.hasOwnProperty(col.field)) {
|
try {
|
content = parseFloat(data[col.field])
|
if (isNaN(content)) {
|
content = ''
|
}
|
} catch (e) {
|
content = ''
|
}
|
}
|
|
if (content !== '') {
|
if (col.format === 'percent') {
|
content = content * 100
|
}
|
|
content = content.toFixed(col.decimal || 0)
|
|
if (col.format === 'thdSeparator') {
|
content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
|
}
|
|
content = (col.prefix || '') + content + (col.postfix || '')
|
}
|
|
if (col.marks) {
|
let result = this.getMark(data, col.marks)
|
|
if (result.className) {
|
className = result.className
|
} else if (result.isIcon) {
|
if (result.position === 'front') {
|
content = <span>{result.icon} {content}</span>
|
} else {
|
content = <span>{content} {result.icon}</span>
|
}
|
}
|
}
|
|
return (
|
<span className={className}>
|
{content}
|
</span>
|
)
|
} else if (col.type === 'link') {
|
let content = col.nameField ? data[col.nameField] : ''
|
let _href = data[col.field] || ''
|
|
if (!content && _href) {
|
content = _href
|
} else if (!_href) {
|
content = ''
|
}
|
|
if (col.joint === 'true' && _href) {
|
let _param = window.btoa('id=' + data[this.props.setting.primaryKey] + '&userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID'))
|
_href += '?' + _param
|
}
|
|
return (
|
<span>
|
{_href ? <a href={_href} target="_blank" rel="noopener noreferrer">{content}</a> : null}
|
</span>
|
)
|
}
|
}
|
|
/**
|
* @description 获取卡片中图片或图标设置
|
*/
|
getAvatar = () => {
|
const { card, data } = this.props
|
|
if (card.avatar.type === 'picture') {
|
if (card.avatar.field && data.hasOwnProperty(card.avatar.field) && data[card.avatar.field]) {
|
return <img src={data[card.avatar.field]} alt=""/>
|
} else {
|
return null
|
}
|
} else if (card.avatar.type === 'icon') {
|
let result = this.getMark(data, card.avatar.marks)
|
|
if (result.isIcon) {
|
return result.icon
|
} else {
|
return null
|
}
|
}
|
}
|
|
/**
|
* @description 卡片点击切换事件
|
*/
|
switchCard = () => {
|
const { card, data } = this.props
|
|
if (!card.switch) return
|
|
this.props.switchCard(data)
|
}
|
|
render() {
|
const { card, selectKey, data, type } = this.props
|
const { extra, actions, plusSize } = this.state
|
|
let title = null
|
if (card.header) {
|
if (card.header.column) {
|
title = this.getContent(card.header.column)
|
} else {
|
title = card.header.content
|
}
|
}
|
let style = {fontSize: plusSize + 'px'}
|
|
return (
|
<div className={'chart-card-box ' + card.outclass}>
|
{type !== 'insert' ? <Card
|
size="small"
|
className={'chart-card ' + (selectKey === data.key ? 'chart-card-selected' : '')}
|
title={title}
|
bordered={card.bordered}
|
extra={extra}
|
actions={actions}
|
>
|
<div className={'ant-card-meta' + (card.switch ? ' switch' : '')} style={card.flex ? {display: 'flex'} : null} onClick={this.switchCard}>
|
{card.avatar ?
|
<div className="ant-card-meta-avatar" style={card.avatar.class}>
|
<span className="ant-avatar ant-avatar-image" style={card.avatar.radius ? {borderRadius: '50%'} : null}>
|
{this.getAvatar()}
|
</span>
|
</div> : null
|
}
|
<div className="ant-card-meta-detail" style={card.flex ? {flex: 1} : null}>
|
{card.details.map((detail, i) => {
|
return (
|
<div className={detail.class} style={detail.style} key={i}>
|
{detail.column ? this.getContent(detail.column) : detail.content}
|
</div>
|
)
|
})}
|
</div>
|
</div>
|
</Card> : null}
|
{type === 'insert' ? <Card
|
size="small"
|
className="chart-card insert"
|
title={card.header ? ' ' : null}
|
bordered={card.bordered}
|
actions={card.bottom.actions ? [''] : null}
|
>
|
<div className="ant-card-meta" ref={(ref) => this.insertRef = ref} style={card.flex ? {display: 'flex'} : null}>
|
{card.avatar ? <div className="ant-card-meta-avatar" style={card.avatar.class}> </div> : null }
|
<div className="ant-card-meta-detail" style={card.flex ? {flex: 1} : null}>
|
{card.details.map((detail, i) => (<div className={detail.class} style={detail.style} key={i}></div>))}
|
</div>
|
</div>
|
<div className="mk-card-insert">
|
<NormalButton
|
BID={this.props.BID}
|
btn={{...card.insertAction, style}}
|
BData={this.props.BData}
|
setting={this.props.setting}
|
columns={this.props.columns}
|
selectedData={[]}
|
/>
|
</div>
|
</Card> : null}
|
</div>
|
)
|
}
|
}
|
|
class CardChart extends Component {
|
static propTpyes = {
|
BID: PropTypes.any, // 主表ID
|
BData: PropTypes.any, // 主表数据
|
MenuID: PropTypes.string, // 菜单ID
|
config: PropTypes.object, // 页面配置信息
|
columns: PropTypes.array, // 显示列
|
plot: PropTypes.object,
|
tableId: PropTypes.string,
|
loading: PropTypes.bool,
|
data: PropTypes.array,
|
}
|
|
state = {
|
card: null,
|
colMap: null,
|
selectKey: '',
|
actionList: null
|
}
|
|
/**
|
* @description 卡片初始化,设置卡片的配置信息
|
*/
|
UNSAFE_componentWillMount () {
|
const { plot, config } = this.props
|
let card = {}
|
|
let colMap = new Map() // 显示列
|
let actionMap = new Map() // 按钮组
|
let columns = fromJS(config.columns).toJS()
|
let actions = fromJS(config.action).toJS()
|
let insertAction = null
|
let actionList = []
|
|
columns.forEach(col => {
|
if (col.field) {
|
colMap.set(col.field, col)
|
}
|
})
|
|
if (plot.widthType === 'absolute') {
|
plot.cardWidth = 6
|
}
|
if (plot.avatar && plot.avatar.widthType === 'absolute') {
|
card.avatar.width = 32
|
}
|
|
actions.forEach(item => {
|
if ((item.Ot && item.Ot !== 'notRequired' && !['excelIn', 'excelOut'].includes(item.OpenType)) || item.funcType === 'changeuser') {
|
actionMap.set(item.uuid, item)
|
} else if (plot.extraAction && plot.extraAction === item.uuid && ['pop', 'prompt', 'exec'].includes(item.OpenType) && item.Ot === 'notRequired') {
|
item.show = 'icon'
|
insertAction = item
|
} else if (plot.actions && plot.actions.length > 0 && plot.actions.includes(item.uuid) && (item.OpenType === 'excelOut' || (item.OpenType === 'excelIn' && item.Ot === 'notRequired'))) {
|
item.show = 'icon'
|
actionList.push(item)
|
}
|
})
|
|
if (plot.subelement.includes('header')) {
|
card.header = { actions: [], show: plot.header.show }
|
if (plot.header.datatype === 'dynamic' && colMap.get(plot.header.field)) {
|
let col = fromJS(colMap.get(plot.header.field)).toJS()
|
if (col.marks) {
|
col.marks = col.marks.filter(mark => mark.signType === 'font' || mark.signType === 'icon')
|
}
|
card.header.column = col
|
} else if (plot.header.content) {
|
card.header.content = plot.header.content
|
}
|
|
if (plot.header.actions && plot.header.actions.length > 0) {
|
plot.header.actions.forEach(item => {
|
if (!actionMap.get(item.value)) return
|
card.header.actions.push(actionMap.get(item.value))
|
})
|
card.header.actions.length = 1
|
}
|
if (card.header.actions.length === 0) {
|
card.header.actions = null
|
}
|
}
|
|
if (plot.subelement.includes('avatar')) {
|
card.avatar = { type: plot.avatar.type, display: plot.avatar.display || 'inline' }
|
if (card.avatar.type === 'icon' && colMap.get(plot.avatar.field)) {
|
let col = fromJS(colMap.get(plot.avatar.field)).toJS()
|
let _marks = []
|
if (col.marks) {
|
_marks = col.marks.filter(mark => mark.signType === 'icon')
|
}
|
|
if (_marks.length === 0) {
|
card.avatar = null
|
} else {
|
card.avatar.marks = _marks
|
card.avatar.width = plot.avatar.size
|
card.avatar.class = {width: plot.avatar.size, paddingTop: plot.avatar.size, fontSize: plot.avatar.size + 'px'}
|
}
|
} else if (card.avatar.type === 'picture' && colMap.get(plot.avatar.field)) {
|
card.avatar.field = plot.avatar.field
|
card.avatar.width = plot.avatar.width
|
card.avatar.radius = plot.avatar.radius !== 'false'
|
|
let _width = card.avatar.width + '%'
|
|
card.avatar.class = {width: _width, paddingTop: _width}
|
}
|
}
|
|
card.details = []
|
if (plot.details.length > 0) {
|
card.details = plot.details.map(_item => {
|
let item = fromJS(_item).toJS()
|
|
if (item.datatype === 'dynamic' && colMap.get(item.field)) {
|
item.column = colMap.get(item.field)
|
} else {
|
item.datatype = 'static'
|
}
|
|
item.fontSize = item.fontSize || 14
|
item.height = item.height || 1
|
item.fontWeight = item.fontWeight || 'normal'
|
item.width = item.width + '%'
|
|
let _style = {}
|
_style.fontWeight = item.fontWeight
|
_style.width = item.width
|
_style.fontSize = item.fontSize + 'px'
|
_style.height = item.height * item.fontSize * 1.5
|
|
item.style = _style
|
|
let _class = 'mk-card-detail-item '
|
if (item.align) {
|
_class += item.align + ' '
|
}
|
|
_class += 'line' + item.height
|
item.class = _class
|
|
return item
|
})
|
}
|
|
if (plot.subelement.includes('bottom')) {
|
card.bottom = { actions: [], show: plot.bottom.show }
|
|
if (plot.bottom.actions && plot.bottom.actions.length > 0) {
|
plot.bottom.actions.forEach(item => {
|
if (!actionMap.get(item.value)) return
|
|
card.bottom.actions.push(actionMap.get(item.value))
|
})
|
}
|
|
if (card.bottom.actions.length === 0) {
|
card.bottom = null
|
}
|
}
|
|
card.outclass = ' ant-col ant-col-' + plot.cardWidth
|
card.bordered = plot.border !== 'hidden'
|
|
if (plot.bgfield && colMap.get(plot.bgfield)) {
|
let col = fromJS(colMap.get(plot.bgfield)).toJS()
|
let _marks = []
|
if (col.marks) {
|
_marks = col.marks.filter(mark => mark.signType === 'card')
|
}
|
|
if (_marks.length > 0) {
|
card.bgmarks = _marks
|
}
|
}
|
|
card.switch = plot.switch !== 'false'
|
|
if (insertAction && !insertAction.icon) {
|
insertAction.icon = 'plus'
|
}
|
|
card.insertAction = insertAction // 添加卡片
|
|
this.setState({card: card, colMap: colMap, actionList: actionList})
|
}
|
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
const { card } = this.state
|
|
if (card && card.switch && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
|
this.setState({selectKey: ''})
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
componentDidMount () {
|
const { plot } = this.props
|
const { card } = this.state
|
|
if (card.avatar) {
|
let _flex = false
|
let _cardWidth = 300
|
|
let _outWidth = document.body.offsetWidth - 260
|
if (this.cardRef.offsetWidth) {
|
_outWidth = this.cardRef.offsetWidth
|
}
|
_cardWidth = Math.floor(_outWidth * plot.cardWidth / 24 - 20)
|
|
if (card.avatar.display !== 'block') {
|
if (card.avatar.width < 90) {
|
_flex = true
|
}
|
} else if (card.avatar.width < _cardWidth * 0.9 && card.avatar.display !== 'block') {
|
_flex = true
|
}
|
|
this.setState({
|
card: {...this.state.card, flex: _flex}
|
})
|
}
|
}
|
|
/**
|
* @description 卡片切换
|
*/
|
switchCard = (data) => {
|
const { config } = this.props
|
|
let _id = data[config.setting.primaryKey] || ''
|
|
this.setState({selectKey: data.key})
|
|
MKEmitter.emit('changeTableLine', config.setting.ContainerId, this.props.tableId, _id, data)
|
}
|
|
render() {
|
const { plot, data, loading, BID, BData, MenuID, config, columns } = this.props
|
const { card, colMap, selectKey, actionList } = this.state
|
|
return (
|
<div className="card-row-box mingke-table" ref={(ref) => this.cardRef = ref} style={!plot.title ? {paddingTop: '15px'} : null}>
|
{loading ?
|
<div className="loading-mask">
|
<div className="ant-spin-blur"></div>
|
<Spin />
|
</div> : null
|
}
|
<div>
|
{plot.title ? <p className="chart-title">{plot.title}</p> : null}
|
<div style={{float: 'right', marginRight: 10}}>
|
{actionList && actionList.map(action => {
|
if (action.OpenType === 'excelIn') {
|
return (
|
<ExcelInButton
|
key={action.uuid}
|
BID={BID}
|
btn={action}
|
setting={config.setting}
|
/>
|
)
|
} else {
|
return (
|
<ExcelOutButton
|
key={action.uuid}
|
BID={BID}
|
btn={action}
|
setting={config.setting}
|
/>
|
)
|
}
|
})}
|
</div>
|
<div style={{clear: 'both'}}></div>
|
</div>
|
{data && data.length > 0 &&
|
data.map((item, i) => (
|
<CardCell
|
key={i}
|
BID={BID}
|
card={card}
|
data={item}
|
BData={BData}
|
MenuID={MenuID}
|
colMap={colMap}
|
columns={columns}
|
selectKey={selectKey}
|
setting={config.setting}
|
switchCard={this.switchCard}
|
/>
|
))
|
}
|
{!loading && card.insertAction ?
|
<CardCell
|
key="insert"
|
type="insert"
|
BID={BID}
|
card={card}
|
data={{key: 'insert'}}
|
BData={BData}
|
MenuID={MenuID}
|
setting={config.setting}
|
switchCard={() => {}}
|
/> : null
|
}
|
{(loading || !card.insertAction) && (!data || data.length === 0) ? <Empty description={false}/> : null}
|
<div className="clear"></div>
|
</div>
|
)
|
}
|
}
|
|
export default CardChart
|