| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | if (card.show === 'icon') { |
| | | btnElement = (<Button style={_style} type="link"><Icon type={card.icon}/></Button>) |
| | | } else if (card.show === 'link') { |
| | | btnElement = (<Button style={_style} type="link">{card.icon ? <Icon type={card.icon}/> : null}{card.label}</Button>) |
| | | btnElement = (<Button style={_style} type="link">{card.label}{card.icon ? <Icon type={card.icon}/> : null}</Button>) |
| | | } else { |
| | | btnElement = (<Button style={_style}> {card.label}{card.icon ? <Icon type={card.icon}/> : null} </Button>) |
| | | btnElement = (<Button style={_style}> {card.icon ? <Icon type={card.icon}/> : null}{card.label} </Button>) |
| | | } |
| | | |
| | | return ( |
| | |
| | | const { TextArea } = Input |
| | | const ColorSketch = asyncComponent(() => import('@/mob/colorsketch')) |
| | | const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent')) |
| | | const MkIcon = asyncComponent(() => import('@/components/mkIcon')) |
| | | |
| | | const cardTypeOptions = { |
| | | sequence: ['eleType', 'width'], |
| | |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'icon') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | | <Form.Item label={item.tooltip ? |
| | | <Tooltip placement="topLeft" title={item.tooltip}> |
| | | <Icon type="question-circle" /> |
| | | {item.label} |
| | | </Tooltip> : item.label |
| | | }> |
| | | {getFieldDecorator(item.key, { |
| | | initialValue: item.initVal || '', |
| | | rules: [{ |
| | | required: !!item.required, |
| | | message: this.props.dict['form.required.select'] + item.label + '!' |
| | | }] |
| | | })( |
| | | <MkIcon /> |
| | | )} |
| | | </Form.Item> |
| | | </Col> |
| | | ) |
| | | } else if (item.type === 'radio') { |
| | | fields.push( |
| | | <Col span={12} key={index}> |
| | |
| | | options: _options |
| | | }, |
| | | { |
| | | type: 'select', |
| | | type: 'icon', |
| | | key: 'icon', |
| | | label: '图标', |
| | | initVal: card.icon, |
| | | required: true, |
| | | options: [ |
| | | { value: 'question-circle', text: 'question-circle'}, |
| | | { value: 'alert', text: 'alert'}, |
| | | { value: 'cloud', text: 'cloud'}, |
| | | { value: 'eye', text: 'eye'}, |
| | | { value: 'eye-invisible', text: 'eye-invisible'}, |
| | | { value: 'android', text: 'android'}, |
| | | { value: 'apple', text: 'apple'}, |
| | | { value: 'windows', text: 'windows'}, |
| | | { value: 'ie', text: 'ie'}, |
| | | { value: 'chrome', text: 'chrome'}, |
| | | { value: 'github', text: 'github'}, |
| | | { value: 'aliwangwang', text: 'aliwangwang'}, |
| | | { value: 'dingding', text: 'dingding'}, |
| | | { value: 'wechat', text: 'wechat'}, |
| | | { value: 'alipay', text: 'alipay'}, |
| | | { value: 'weibo-square', text: 'weibo-square'}, |
| | | { value: 'weibo-circle', text: 'weibo-circle'}, |
| | | { value: 'taobao-circle', text: 'taobao-circle'}, |
| | | { value: 'weibo', text: 'weibo'}, |
| | | { value: 'twitter', text: 'twitter'}, |
| | | { value: 'youtube', text: 'youtube'}, |
| | | { value: 'alipay-circle', text: 'alipay-circle'}, |
| | | { value: 'taobao', text: 'taobao'}, |
| | | { value: 'skype', text: 'skype'}, |
| | | { value: 'qq', text: 'qq'}, |
| | | { value: 'gitlab', text: 'gitlab'}, |
| | | { value: 'zhihu', text: 'zhihu'}, |
| | | { value: 'slack', text: 'slack'}, |
| | | { value: 'sketch', text: 'sketch'}, |
| | | { value: 'yahoo', text: 'yahoo'}, |
| | | { value: 'reddit', text: 'reddit'}, |
| | | { value: 'dribbble', text: 'dribbble'}, |
| | | ] |
| | | required: true |
| | | }, |
| | | { |
| | | type: 'radio', |
| | |
| | | |
| | | let _style = {...card.style} |
| | | |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | if (side === 'back') { |
| | | _style = { |
| | | ...card.backStyle, |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | |
| | | let _style = {...card.style} |
| | | |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = cards.style.height |
| | | _style = resetStyle(_style) |
| | | |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { group } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [group.uuid], ['background', 'border', 'padding', 'margin'], group.style) |
| | | MKEmitter.emit('changeStyle', [group.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], group.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | let btnElement = null |
| | | let _style = resetStyle(card.style) |
| | | |
| | | if (card.show === 'icon') { |
| | | btnElement = ( |
| | | <Button |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { tabs } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [tabs.uuid], ['background', 'border', 'padding', 'margin'], tabs.style) |
| | | MKEmitter.emit('changeStyle', [tabs.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], tabs.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['height', 'background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | })( |
| | | <FileUpload config={{ |
| | | initval: '', |
| | | suffix: '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp', |
| | | suffix: '.jpg,.png,.gif,.pjp,.pjpeg,.jpeg,.jfif,.webp,.ico', |
| | | maxfile: 1, |
| | | fileType: 'picture' |
| | | }} /> |
| | |
| | | * @description 修改阴影颜色 ,颜色控件 |
| | | */ |
| | | changeShadowColor = (val) => { |
| | | this.updateStyle({shadow: val}) |
| | | const { card } = this.state |
| | | |
| | | let boxShadow = `${card.hShadow || '0px'} ${card.vShadow || '0px'} ${card.shadowBlur || '0px'} ${val}` |
| | | |
| | | this.updateStyle({shadowColor: val, boxShadow}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改阴影颜色 ,颜色控件 |
| | | */ |
| | | changeShadowBlur = (val) => { |
| | | const { card } = this.state |
| | | |
| | | let boxShadow = `${card.hShadow || '0px'} ${card.vShadow || '0px'} ${val || '0px'} ${card.shadowColor || 'transparent'}` |
| | | |
| | | this.updateStyle({shadowBlur: val, boxShadow}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改阴影颜色 ,颜色控件 |
| | | */ |
| | | changeHShadow = (val) => { |
| | | const { card } = this.state |
| | | |
| | | let boxShadow = `${val || '0px'} ${card.vShadow || '0px'} ${card.shadowBlur || '0px'} ${card.shadowColor || 'transparent'}` |
| | | |
| | | this.updateStyle({hShadow: val, boxShadow}) |
| | | } |
| | | |
| | | /** |
| | | * @description 修改阴影颜色 ,颜色控件 |
| | | */ |
| | | changeVShadow = (val) => { |
| | | const { card } = this.state |
| | | |
| | | let boxShadow = `${card.hShadow || '0px'} ${val || '0px'} ${card.shadowBlur || '0px'} ${card.shadowColor || 'transparent'}` |
| | | |
| | | this.updateStyle({vShadow: val, boxShadow}) |
| | | } |
| | | |
| | | imgChange = (val) => { |
| | |
| | | label={<Icon title="阴影颜色" type="bg-colors" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <ColorSketch value={card.shadow || 'transparent'} onChange={this.changeShadowColor} /> |
| | | <ColorSketch value={card.shadowColor || 'transparent'} onChange={this.changeShadowColor} /> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="模糊距离" type="column-width" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.shadowBlur || '0px'} options={['px']} onChange={this.changeShadowBlur}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="水平位置" type="arrow-right" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.hShadow || '0px'} options={['px']} onChange={this.changeHShadow}/> |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item |
| | | colon={false} |
| | | label={<Icon title="垂直位置" type="arrow-down" />} |
| | | labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } |
| | | > |
| | | <StyleInput defaultValue={card.vShadow || '0px'} options={['px']} onChange={this.changeVShadow}/> |
| | | </Form.Item> |
| | | </Col> |
| | | </Panel> : null} |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], card.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | |
| | | |
| | | return ( |
| | | <div className="menu-menubar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <NormalHeader config={card} updateComponent={this.updateComponent}/> |
| | | {card.wrap.title ? <NormalHeader config={card} updateComponent={this.updateComponent}/> : null} |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加菜单" onClick={this.addMenu} type="plus" /> |
| | |
| | | |
| | | let _style = {...card.style} |
| | | |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | _style = resetStyle(_style) |
| | | |
| | | return ( |
| | |
| | | changeStyle = () => { |
| | | const { card } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding'], card.style) |
| | | MKEmitter.emit('changeStyle', [card.uuid], ['font', 'background', 'border', 'padding', 'shadow'], card.style) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | _style.height = card.wrap.height |
| | | |
| | | return ( |
New file |
| | |
| | | import React, { Component } from 'react' |
| | | import { Tabs } from 'antd' |
| | | import { is, fromJS } from 'immutable' |
| | | import { DndProvider, DragSource, DropTarget } from 'react-dnd' |
| | | |
| | | // Drag & Drop node |
| | | class TabNode extends Component { |
| | | render() { |
| | | const { connectDragSource, connectDropTarget, children } = this.props |
| | | |
| | | return connectDragSource(connectDropTarget(children)) |
| | | } |
| | | } |
| | | |
| | | const cardTarget = { |
| | | drop(props, monitor) { |
| | | const dragKey = monitor.getItem().index |
| | | const hoverKey = props.index |
| | | |
| | | if (dragKey === hoverKey) { |
| | | return; |
| | | } |
| | | |
| | | props.moveTabNode(dragKey, hoverKey) |
| | | monitor.getItem().index = hoverKey |
| | | } |
| | | } |
| | | |
| | | const cardSource = { |
| | | beginDrag(props) { |
| | | return { |
| | | id: props.id, |
| | | index: props.index, |
| | | } |
| | | } |
| | | } |
| | | |
| | | const WrapTabNode = DropTarget('DND_NODE', cardTarget, connect => ({ |
| | | connectDropTarget: connect.dropTarget(), |
| | | }))( |
| | | DragSource('DND_NODE', cardSource, (connect, monitor) => ({ |
| | | connectDragSource: connect.dragSource(), |
| | | isDragging: monitor.isDragging(), |
| | | }))(TabNode) |
| | | ) |
| | | |
| | | class DraggableTabs extends Component { |
| | | state = { |
| | | order: [] |
| | | } |
| | | |
| | | moveTabNode = (dragKey, hoverKey) => { |
| | | const newOrder = this.state.order.slice() |
| | | const { children } = this.props |
| | | |
| | | React.Children.forEach(children, c => { |
| | | if (newOrder.indexOf(c.key) === -1) { |
| | | newOrder.push(c.key) |
| | | } |
| | | }) |
| | | |
| | | const dragIndex = newOrder.indexOf(dragKey) |
| | | const hoverIndex = newOrder.indexOf(hoverKey) |
| | | |
| | | newOrder.splice(dragIndex, 1) |
| | | newOrder.splice(hoverIndex, 0, dragKey) |
| | | |
| | | this.setState({ |
| | | order: newOrder |
| | | }) |
| | | this.props.tabsMove(newOrder) |
| | | } |
| | | |
| | | renderTabBar = (props, DefaultTabBar) => ( |
| | | <DefaultTabBar {...props}> |
| | | {node => ( |
| | | <WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}> |
| | | {node} |
| | | </WrapTabNode> |
| | | )} |
| | | </DefaultTabBar> |
| | | ) |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) || |
| | | !is(fromJS(nextProps.children), fromJS(this.props.children)) || |
| | | nextProps.tabPosition !== this.props.tabPosition || |
| | | nextProps.type !== this.props.type |
| | | } |
| | | |
| | | render() { |
| | | const { order } = this.state |
| | | const { children } = this.props |
| | | const tabs = [] |
| | | React.Children.forEach(children, c => { |
| | | tabs.push(c) |
| | | }) |
| | | |
| | | const orderTabs = tabs.slice().sort((a, b) => { |
| | | const orderA = order.indexOf(a.key) |
| | | const orderB = order.indexOf(b.key) |
| | | |
| | | if (orderA !== -1 && orderB !== -1) { |
| | | return orderA - orderB |
| | | } |
| | | if (orderA !== -1) { |
| | | return -1 |
| | | } |
| | | if (orderB !== -1) { |
| | | return 1 |
| | | } |
| | | |
| | | const ia = tabs.indexOf(a) |
| | | const ib = tabs.indexOf(b) |
| | | |
| | | return ia - ib |
| | | }) |
| | | |
| | | return ( |
| | | <DndProvider> |
| | | <Tabs renderTabBar={this.renderTabBar} {...this.props}> |
| | | {orderTabs} |
| | | </Tabs> |
| | | </DndProvider> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default DraggableTabs |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Tabs, Icon, Popover, Modal } from 'antd' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import DraggableTabs from './dragabletabs' |
| | | import { resetStyle } from '@/utils/utils-custom.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import Utils from '@/utils/utils.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/components/tabs/tabsetting')) |
| | | const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent')) |
| | | const PasteController = asyncIconComponent(() => import('@/menu/pastecontroller')) |
| | | const TabLabelComponent = asyncComponent(() => import('@/menu/components/tabs/tablabelform')) |
| | | const TabComponents = asyncComponent(() => import('../tabcomponents')) |
| | | |
| | | const { TabPane } = Tabs |
| | | const { confirm } = Modal |
| | | |
| | | class antvTabs extends Component { |
| | | static propTpyes = { |
| | | tabs: PropTypes.object, |
| | | deletecomponent: PropTypes.func, |
| | | updateConfig: PropTypes.func, |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | tabs: null, |
| | | editab: null, |
| | | labelvisible: false |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { tabs } = this.props |
| | | |
| | | if (tabs.isNew) { |
| | | let _tabs = { |
| | | uuid: tabs.uuid, |
| | | type: tabs.type, |
| | | floor: tabs.floor, |
| | | tabId: tabs.tabId || '', |
| | | parentId: tabs.parentId || '', |
| | | subtype: tabs.subtype, |
| | | width: 24, |
| | | name: tabs.name, |
| | | setting: {width: 24, position: 'top', tabStyle: 'line', name: tabs.name}, |
| | | style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' }, |
| | | subtabs: [ |
| | | { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 1', icon: '', components: [] }, |
| | | { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 2', icon: '', components: [] }, |
| | | { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 3', icon: '', components: [] } |
| | | ] |
| | | } |
| | | this.setState({ |
| | | tabs: _tabs |
| | | }) |
| | | this.props.updateConfig(_tabs) |
| | | } else { |
| | | this.setState({ |
| | | tabs: fromJS(tabs).toJS() |
| | | }) |
| | | } |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | componentDidMount () { |
| | | MKEmitter.addListener('submitStyle', this.getStyle) |
| | | MKEmitter.addListener('submitSearch', this.getSearch) |
| | | MKEmitter.addListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新,清除快捷键设置 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | MKEmitter.removeListener('submitStyle', this.getStyle) |
| | | MKEmitter.removeListener('submitSearch', this.getSearch) |
| | | MKEmitter.removeListener('tabsChange', this.handleTabsChange) |
| | | MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle) |
| | | } |
| | | |
| | | updateComponentStyle = (parentId, keys, style) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (tabs.subtabs.findIndex(tab => tab.uuid === parentId) === -1) return |
| | | |
| | | let _tabs = fromJS(tabs).toJS() |
| | | let _tabs_ = fromJS(tabs).toJS() |
| | | |
| | | let components = [] |
| | | _tabs.subtabs.forEach(tab => { |
| | | if (tab.uuid === parentId) { |
| | | components = tab.components.map(item => { |
| | | if (keys.includes(item.uuid)) { |
| | | item.style = {...item.style, ...style} |
| | | } |
| | | return item |
| | | }) |
| | | tab.components = [] |
| | | } |
| | | }) |
| | | |
| | | _tabs_.subtabs = _tabs_.subtabs.map(tab => { |
| | | if (tab.uuid === parentId) { |
| | | tab.components = components |
| | | } |
| | | return tab |
| | | }) |
| | | |
| | | this.setState({tabs: _tabs}, () => { |
| | | this.updateComponent(_tabs_) |
| | | }) |
| | | } |
| | | |
| | | changeStyle = () => { |
| | | const { tabs } = this.state |
| | | |
| | | MKEmitter.emit('changeStyle', [tabs.uuid], ['background', 'border', 'padding', 'margin', 'shadow'], tabs.style) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (comIds.length !== 1 || comIds[0] !== tabs.uuid) return |
| | | |
| | | let _card = {...tabs, style} |
| | | |
| | | this.setState({ |
| | | tabs: _card |
| | | }) |
| | | |
| | | this.props.updateConfig(_card) |
| | | } |
| | | |
| | | handleTabsChange = (parentId) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (parentId === tabs.parentId) { |
| | | MKEmitter.emit('tabsChange', tabs.uuid) |
| | | } |
| | | } |
| | | |
| | | updateComponent = (component) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (!is(fromJS(tabs.setting), fromJS(component.setting)) || !is(fromJS(tabs.style), fromJS(component.style))) { |
| | | // 注册事件-标签变化,通知标签内元素 |
| | | MKEmitter.emit('tabsChange', tabs.uuid) |
| | | } |
| | | |
| | | component.width = component.setting.width |
| | | component.name = component.setting.name |
| | | |
| | | this.setState({ |
| | | tabs: component |
| | | }) |
| | | this.props.updateConfig(component) |
| | | } |
| | | |
| | | updateTabComponent = (tab) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | |
| | | tabs.subtabs = tabs.subtabs.map(t => { |
| | | if (t.uuid === tab.uuid) { |
| | | return tab |
| | | } else { |
| | | return t |
| | | } |
| | | }) |
| | | |
| | | this.setState({tabs}) |
| | | this.props.updateConfig(tabs) |
| | | } |
| | | |
| | | tabAdd = (e) => { |
| | | const { tabs } = this.state |
| | | |
| | | e.stopPropagation() |
| | | |
| | | this.setState({ |
| | | editab: { |
| | | uuid: '', |
| | | parentId: tabs.uuid, |
| | | floor: tabs.floor, |
| | | label: '', |
| | | icon: '', |
| | | components: [] |
| | | }, |
| | | labelvisible: true |
| | | }) |
| | | } |
| | | |
| | | editTab = (tab) => { |
| | | this.setState({ |
| | | editab: tab, |
| | | labelvisible: true |
| | | }) |
| | | } |
| | | |
| | | tabLabelSubmit = () => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | let editab = fromJS(this.state.editab).toJS() |
| | | |
| | | this.tabLabelRef.handleConfirm().then(res => { |
| | | editab.label = res.label |
| | | editab.icon = res.icon |
| | | editab.hasSearch = res.hasSearch || '' |
| | | editab.blacklist = res.blacklist |
| | | |
| | | if (editab.uuid) { |
| | | tabs.subtabs = tabs.subtabs.map(t => { |
| | | if (t.uuid === editab.uuid) { |
| | | return editab |
| | | } else { |
| | | return t |
| | | } |
| | | }) |
| | | } else { |
| | | editab.uuid = Utils.getuuid() |
| | | tabs.subtabs.push(editab) |
| | | } |
| | | |
| | | this.setState({ |
| | | editab: null, |
| | | labelvisible: false, |
| | | tabs |
| | | }) |
| | | this.props.updateConfig(tabs) |
| | | }) |
| | | } |
| | | |
| | | delTab = (tab) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | const _this = this |
| | | |
| | | tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid) |
| | | |
| | | let uuids = MenuUtils.getDelButtonIds({...tab, type: 'group'}) |
| | | |
| | | confirm({ |
| | | title: '确定删除标签?', |
| | | content: '', |
| | | onOk() { |
| | | _this.setState({tabs}) |
| | | _this.props.updateConfig(tabs) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | moveSwitch = (order) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | let subtab = {} |
| | | tabs.subtabs.forEach(item => { |
| | | subtab[item.uuid] = item |
| | | }) |
| | | |
| | | tabs.subtabs = [] |
| | | |
| | | order.forEach(item => { |
| | | if (subtab[item]) { |
| | | tabs.subtabs.push(subtab[item]) |
| | | } |
| | | }) |
| | | |
| | | this.setState({tabs}) |
| | | this.props.updateConfig(tabs) |
| | | } |
| | | |
| | | insert = (item, tab) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | |
| | | tabs.subtabs.forEach(stab => { |
| | | if (stab.uuid === tab.uuid) { |
| | | stab.components.push(item) |
| | | } |
| | | }) |
| | | |
| | | this.setState({tabs}) |
| | | this.props.updateConfig(tabs) |
| | | } |
| | | |
| | | getSearch = (config) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (tabs.uuid !== config.uuid) return |
| | | |
| | | let _tabs = fromJS(tabs).toJS() |
| | | |
| | | _tabs.subtabs = _tabs.subtabs.map(t => { |
| | | if (t.uuid === config.tabId) { |
| | | t.search = config.search |
| | | } |
| | | return t |
| | | }) |
| | | |
| | | this.setState({ |
| | | tabs: _tabs |
| | | }) |
| | | this.props.updateConfig(_tabs) |
| | | } |
| | | |
| | | setSearch = (tab) => { |
| | | const { tabs } = this.state |
| | | let card = { |
| | | uuid: tabs.uuid, |
| | | tabId: tab.uuid, |
| | | search: tab.search |
| | | } |
| | | |
| | | if (!card.search) { |
| | | card.search = { |
| | | floor: 1, |
| | | setting: { type: 'title', field: '', title: '', focus: 'true', btn: 'hidden' }, |
| | | groups: [], |
| | | fields: [] |
| | | } |
| | | } |
| | | MKEmitter.emit('changeSearch', card) |
| | | } |
| | | |
| | | clickComponent = (e) => { |
| | | if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') { |
| | | e.stopPropagation() |
| | | MKEmitter.emit('clickComponent', this.state.tabs) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { tabs, dict, labelvisible, editab, appType } = this.state |
| | | let _style = resetStyle(tabs.style) |
| | | |
| | | return ( |
| | | <div className={'menu-tabs-edit-box ' + tabs.setting.display} style={_style} onClick={this.clickComponent} id={tabs.uuid}> |
| | | <DraggableTabs tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch}> |
| | | {tabs.subtabs.map(tab => ( |
| | | <TabPane tab={ |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="edit" title="edit" type="edit" onClick={() => this.editTab(tab)} /> |
| | | <PasteController type="tab" Tab={tab} insert={this.insert} /> |
| | | <Icon className="close" title="delete" type="close" onClick={() => this.delTab(tab)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span> |
| | | </Popover> |
| | | } key={tab.uuid}> |
| | | {appType === 'mob' && tabs.setting.position === 'top' && tabs.setting.display === 'inline-block' && tab.hasSearch === 'icon' ? |
| | | <Icon className="search-icon" onDoubleClick={() => this.setSearch(tab)} type="search" /> : null} |
| | | <TabComponents config={tab} handleList={this.updateTabComponent} deleteCard={this.deleteCard} /> |
| | | </TabPane> |
| | | ))} |
| | | </DraggableTabs> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <Icon className="plus" title="添加标签" type="plus" onClick={this.tabAdd} /> |
| | | <SettingComponent config={tabs} updateConfig={this.updateComponent} /> |
| | | <CopyComponent type="tabs" card={tabs}/> |
| | | <Icon className="style" title="调整样式" onClick={this.changeStyle} type="font-colors" /> |
| | | <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(tabs.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | </Popover> |
| | | <Modal |
| | | wrapClassName="popview-modal" |
| | | title={'标签编辑'} |
| | | visible={labelvisible} |
| | | width={600} |
| | | maskClosable={false} |
| | | okText={dict['model.submit']} |
| | | onOk={this.tabLabelSubmit} |
| | | onCancel={() => { this.setState({ labelvisible: false }) }} |
| | | destroyOnClose |
| | | > |
| | | <TabLabelComponent |
| | | dict={dict} |
| | | tab={editab} |
| | | setting={tabs.setting} |
| | | inputSubmit={this.tabLabelSubmit} |
| | | wrappedComponentRef={(inst) => this.tabLabelRef = inst} |
| | | /> |
| | | </Modal> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default antvTabs |
New file |
| | |
| | | .menu-tabs-edit-box { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | background: #ffffff; |
| | | background-position: center center; |
| | | background-repeat: no-repeat; |
| | | background-size: cover; |
| | | |
| | | >.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); |
| | | } |
| | | |
| | | .ant-tabs.ant-tabs-left, .ant-tabs.ant-tabs-bottom { |
| | | .tab-shell-inner { |
| | | padding-top: 25px; |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-tabpane-active { |
| | | min-height: 200px; |
| | | } |
| | | |
| | | .ant-tabs .ant-tabs-top-bar > .ant-tabs-nav-container { |
| | | >.ant-tabs-tab-next:not(.ant-tabs-tab-arrow-show) + .ant-tabs-nav-wrap > .ant-tabs-nav-scroll > .ant-tabs-nav { |
| | | width: 100%; |
| | | > div > .ant-tabs-tab-disabled { |
| | | float: right; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ant-tabs .ant-tabs-left-bar .ant-tabs-tab { |
| | | text-align: right; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 8px 24px; |
| | | } |
| | | } |
| | | .ant-tabs .ant-tabs-right-bar .ant-tabs-tab { |
| | | text-align: left; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 8px 24px; |
| | | } |
| | | } |
| | | .ant-tabs-tab { |
| | | padding: 0px!important; |
| | | text-align: center; |
| | | > span { |
| | | display: inline-block; |
| | | padding: 12px 16px; |
| | | } |
| | | } |
| | | .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar { |
| | | top: 0px; |
| | | } |
| | | .ant-tabs-card { |
| | | .ant-tabs-left-bar, .ant-tabs-right-bar { |
| | | .ant-tabs-tab { |
| | | > span { |
| | | padding: 0px 16px; |
| | | } |
| | | } |
| | | .ant-tabs-tab-active { |
| | | padding-left: 0px!important; |
| | | padding-right: 0px!important; |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-card-bar { |
| | | .ant-tabs-tab { |
| | | > span { |
| | | display: inline-block; |
| | | padding: 0px 16px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .search-icon { |
| | | position: absolute; |
| | | top: 10px; |
| | | right: 40px; |
| | | font-size: 18px; |
| | | cursor: pointer; |
| | | padding: 3px; |
| | | } |
| | | } |
| | | .menu-tabs-edit-box:hover { |
| | | z-index: 1; |
| | | box-shadow: 0px 0px 4px #1890ff; |
| | | } |
| | | |
| | | .mob-shell { |
| | | .menu-tabs-edit-box.flex { |
| | | >.ant-tabs.ant-tabs-top, >.ant-tabs.ant-tabs-bottom { |
| | | >.ant-tabs-bar { |
| | | >.ant-tabs-nav-container { |
| | | >.ant-tabs-nav-wrap { |
| | | >.ant-tabs-nav-scroll { |
| | | >.ant-tabs-nav { |
| | | display: block; |
| | | >div { |
| | | display: flex; |
| | | >.ant-tabs-tab { |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import React from 'react' |
| | | import { useDrag, useDrop } from 'react-dnd' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import './index.scss' |
| | | |
| | | const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar')) |
| | | const MainSearch = asyncComponent(() => import('@/menu/components/search/main-search')) |
| | | const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) |
| | | const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) |
| | | const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | const AntvTabs = asyncComponent(() => import('@/mob/components/tabs/antv-tabs')) |
| | | const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) |
| | | const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) |
| | | const NormalTree = asyncComponent(() => import('@/menu/components/tree/antd-tree')) |
| | | const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) |
| | | const CarouselPropCard = asyncComponent(() => import('@/menu/components/carousel/prop-card')) |
| | | const TableCard = asyncComponent(() => import('@/menu/components/card/table-card')) |
| | | const NormalForm = asyncComponent(() => import('@/menu/components/form/normal-form')) |
| | | 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 NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar')) |
| | | const CodeSandbox = asyncComponent(() => import('@/menu/components/code/sandbox')) |
| | | |
| | | const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => { |
| | | const originalIndex = findCard(id).index |
| | | const [{ isDragging }, drag] = useDrag({ |
| | | item: { type: 'menu', id, originalIndex, floor: card.floor }, |
| | | collect: monitor => ({ |
| | | isDragging: monitor.isDragging(), |
| | | }), |
| | | }) |
| | | const [, drop] = useDrop({ |
| | | accept: 'menu', |
| | | canDrop: () => true, |
| | | drop: (item) => { |
| | | const { id: draggedId, originalIndex, floor } = item |
| | | if (originalIndex === undefined) { |
| | | item.dropTargetId = id |
| | | } else if (draggedId && floor === card.floor) { |
| | | if (draggedId === id) return |
| | | const { index: originIndex } = findCard(draggedId) |
| | | |
| | | if (originIndex === -1) return |
| | | |
| | | const { index: overIndex } = findCard(id) |
| | | |
| | | moveCard(draggedId, overIndex) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | let style = { opacity: 1} |
| | | if (isDragging) { |
| | | style = { opacity: 0.3} |
| | | } |
| | | |
| | | const getCardComponent = () => { |
| | | if (card.type === 'bar' || card.type === 'line') { |
| | | return (<AntvBar card={card} updateConfig={updateConfig} deletecomponent={delCard} />) |
| | | } else if (card.type === 'search') { |
| | | return (<MainSearch card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'pie') { |
| | | return (<AntvPie card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'dashboard') { |
| | | return (<AntvDashboard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'tree') { |
| | | return (<NormalTree card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'scatter') { |
| | | return (<AntvScatter card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'form') { |
| | | return (<NormalForm card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'tabs') { |
| | | return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard} />) |
| | | } else if (card.type === 'card' && card.subtype === 'datacard') { |
| | | return (<DataCard card={card} updateConfig={updateConfig} deletecomponent={delCard} />) |
| | | } else if (card.type === 'card' && card.subtype === 'propcard') { |
| | | return (<PropCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'carousel' && card.subtype === 'datacard') { |
| | | return (<CarouselDataCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'carousel' && card.subtype === 'propcard') { |
| | | return (<CarouselPropCard card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'table' && card.subtype === 'tablecard') { |
| | | 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 === '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}/>) |
| | | } else if (card.type === 'menubar') { |
| | | return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } else if (card.type === 'code') { |
| | | return (<CodeSandbox card={card} updateConfig={updateConfig} deletecomponent={delCard}/>) |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}> |
| | | {getCardComponent()} |
| | | </div> |
| | | ) |
| | | } |
| | | export default Card |
New file |
| | |
| | | import React, { useState } from 'react' |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import { Empty, notification, Modal } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import MKEmitter from '@/utils/events.js' |
| | | import MenuUtils from '@/utils/utils-custom.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const { confirm } = Modal |
| | | |
| | | const Container = ({ config, handleList }) => { |
| | | const [cards, setCards] = useState(config.components) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | | const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) |
| | | handleList({...config, components: _cards}) |
| | | } |
| | | |
| | | if (!is(fromJS(cards), fromJS(config.components))) { |
| | | setCards(config.components) |
| | | } |
| | | |
| | | const findCard = id => { |
| | | const card = cards.filter(c => `${c.uuid}` === id)[0] |
| | | return { |
| | | card, |
| | | index: cards.indexOf(card), |
| | | } |
| | | } |
| | | |
| | | const updateConfig = (element) => { |
| | | handleList({...config, components: cards.map(item => item.uuid === element.uuid ? element : item)}) |
| | | } |
| | | |
| | | const deleteCard = (id) => { |
| | | const { card } = findCard(id) |
| | | |
| | | let hasComponent = false |
| | | if (card.type === 'tabs') { |
| | | card.subtabs.forEach(tab => { |
| | | if (tab.components.length > 0) { |
| | | hasComponent = true |
| | | } |
| | | }) |
| | | } |
| | | |
| | | let uuids = MenuUtils.getDelButtonIds(card) |
| | | |
| | | confirm({ |
| | | title: `确定删除《${card.name}》吗?`, |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | handleList({...config, components: cards.filter(item => item.uuid !== card.uuid)}) |
| | | |
| | | if (uuids.length === 0) return |
| | | |
| | | MKEmitter.emit('delButtons', uuids) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | const [, drop] = useDrop({ |
| | | accept: 'menu', |
| | | drop(item) { |
| | | if (item.hasOwnProperty('originalIndex') || item.added) { |
| | | return |
| | | } |
| | | item.added = true |
| | | |
| | | if (item.component === 'search') { // 搜索组件不可重复添加 |
| | | if (cards.filter(card => card.type === 'search').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '搜索条件不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | } else if (item.component === 'tabs' && config.floor === 3) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '标签页最多为三重结构!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let name = '' |
| | | let names = { |
| | | bbar: '柱状图', |
| | | line: '折线图', |
| | | tabs: '标签组', |
| | | pie: '饼图', |
| | | search: '搜索', |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | form: '表单', |
| | | dashboard: '仪表盘', |
| | | scatter: '散点图', |
| | | menubar: '菜单栏', |
| | | tree: '树形列表', |
| | | card: '卡片' |
| | | } |
| | | let i = 1 |
| | | |
| | | while (!name && names[item.component]) { |
| | | let _name = names[item.component] + i |
| | | if (config.components.filter(com => com.name === _name).length === 0) { |
| | | name = _name |
| | | } |
| | | i++ |
| | | } |
| | | |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | tabId: config.uuid, |
| | | parentId: config.parentId, |
| | | type: item.component, |
| | | subtype: item.subtype, |
| | | config: item.config, |
| | | width: item.width || 24, |
| | | dataName: Utils.getdataName(), |
| | | name: name, |
| | | floor: config.floor ? (config.floor + 1) : 2, // 组件的层级 |
| | | isNew: true // 新添加标志,用于初始化 |
| | | } |
| | | |
| | | let targetId = '' |
| | | |
| | | if (item.dropTargetId) { |
| | | targetId = item.dropTargetId |
| | | delete item.dropTargetId |
| | | } else if (cards.length > 0) { |
| | | targetId = cards.slice(-1)[0].uuid |
| | | } |
| | | |
| | | const { index: overIndex } = findCard(`${targetId}`) |
| | | const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | |
| | | handleList({...config, components: _cards}) |
| | | } |
| | | }) |
| | | |
| | | return ( |
| | | <div ref={drop} className="ant-row tab-shell-inner"> |
| | | {cards.map(card => ( |
| | | <Card |
| | | id={card.uuid} |
| | | key={card.uuid} |
| | | config={config} |
| | | card={card} |
| | | moveCard={moveCard} |
| | | delCard={deleteCard} |
| | | findCard={findCard} |
| | | updateConfig={updateConfig} |
| | | /> |
| | | ))} |
| | | {cards.length === 0 ? |
| | | <Empty description="请添加组件" /> : null |
| | | } |
| | | </div> |
| | | ) |
| | | } |
| | | export default Container |
New file |
| | |
| | | .tab-shell-inner { |
| | | margin: 0px; |
| | | |
| | | .anticon { |
| | | cursor: unset; |
| | | } |
| | | |
| | | .mk-component-card { |
| | | position: relative; |
| | | } |
| | | >.ant-empty { |
| | | padding: 60px 0px 70px; |
| | | } |
| | | } |
| | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | return ( |
| | | <div className="normal-topbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="normal-topbar-edit-box" style={card.style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <WrapComponent config={card} updateConfig={this.updateComponent} /> |
| | |
| | | const AntvPie = asyncComponent(() => import('@/menu/components/chart/antv-pie')) |
| | | const AntvDashboard = asyncComponent(() => import('@/menu/components/chart/antv-dashboard')) |
| | | const AntvScatter = asyncComponent(() => import('@/menu/components/chart/antv-scatter')) |
| | | const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs')) |
| | | const AntvTabs = asyncComponent(() => import('@/mob/components/tabs/antv-tabs')) |
| | | const DataCard = asyncComponent(() => import('@/menu/components/card/data-card')) |
| | | const PropCard = asyncComponent(() => import('@/menu/components/card/prop-card')) |
| | | const CarouselDataCard = asyncComponent(() => import('@/menu/components/carousel/data-card')) |
| | |
| | | card: '卡片', |
| | | navbar: '导航栏', |
| | | menubar: '菜单栏', |
| | | balcony: '浮动卡', |
| | | login: '登录' |
| | | } |
| | | let i = 1 |
| | |
| | | render() { |
| | | const { card } = this.state |
| | | |
| | | let _style = {...card.style} |
| | | if (_style.shadow) { |
| | | _style.boxShadow = '0 0 4px ' + _style.shadow |
| | | } |
| | | |
| | | return ( |
| | | <div className="normal-navbar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> |
| | | <div className="normal-navbar-edit-box" style={card.style} onClick={this.clickComponent} id={card.uuid}> |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <MenuComponent config={card} updateConfig={this.updateComponent} /> |
| | |
| | | dashboard: '仪表盘', |
| | | tree: '树形列表', |
| | | card: '卡片', |
| | | balcony: '浮动卡', |
| | | login: '登录' |
| | | } |
| | | let i = 1 |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Card, Col, Row, Icon, Menu, notification, Spin, Input, Tabs, Button, Tree, Empty } from 'antd' |
| | | import { Card, Col, Row, Icon, Menu, notification, Spin, Input, Tabs, Button, Tree, Empty, Select } from 'antd' |
| | | import md5 from 'md5' |
| | | |
| | | import Api from '@/api' |
| | | import Utils from '@/utils/utils.js' |
| | |
| | | export default class RoleManage extends Component { |
| | | static propTpyes = { |
| | | MenuNo: PropTypes.string, // 菜单参数 |
| | | MenuID: PropTypes.string // 菜单Id |
| | | MenuID: PropTypes.string // 菜单Id |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | loading: true, |
| | | loadingTree: false, |
| | | loadingAppTree: false, |
| | | roleList: null, |
| | | filterRoleList: [], |
| | | selectRoleId: '', |
| | | mainMenus: null, |
| | | menuTrees: null, |
| | |
| | | selectMenuTrees: null, |
| | | selectMenuOpenKeys: [], |
| | | primarykey: '', |
| | | tabKey: '', |
| | | submitloading: false, |
| | | initCheckKeys: null |
| | | initCheckKeys: null, |
| | | activeKey: 'manage', |
| | | appTrees: null, |
| | | appCheckedKeys: [], |
| | | appOpenKeys: [], |
| | | applist: [], |
| | | selectApp: null, |
| | | selectSubApp: null, |
| | | selectAppTrees: null, |
| | | selectAppOpenKeys: [], |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | if (result.status) { |
| | | this.setState({ |
| | | roleList: result.data |
| | | roleList: result.data, |
| | | filterRoleList: result.data || [] |
| | | }) |
| | | } else { |
| | | notification.warning({ |
| | |
| | | duration: 5 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | getAppList = () => { |
| | | let param = { |
| | | func: 's_get_kei' |
| | | } |
| | | |
| | | Api.getCloudConfig(param).then(result => { |
| | | if (result.status) { |
| | | let applist = result.data.map(item => { |
| | | item.sublist = item.data_detail || [] |
| | | item.sublist = item.sublist.map(cell => { |
| | | cell.ID = cell.d_id |
| | | return cell |
| | | }) |
| | | |
| | | return item |
| | | }) |
| | | let selectApp = applist[0] || null |
| | | |
| | | this.setState({ applist, selectApp }) |
| | | } else { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | |
| | | * @description 获取所有菜单节点,形成权限树 |
| | | */ |
| | | getAllMenuList = async () => { |
| | | const { selectRoleId, mainMenus, tabKey } = this.state |
| | | const { selectRoleId, mainMenus } = this.state |
| | | |
| | | let param = { |
| | | func: 's_rolemenu_get_FunMenu', |
| | | RoleID: selectRoleId, |
| | | SelectedType: tabKey |
| | | SelectedType: '' |
| | | } |
| | | |
| | | let result = await Api.getSystemConfig(param) |
| | |
| | | * @description 选择角色且存在权限树时,获取已分配结构 |
| | | */ |
| | | getSelectMenuList = async () => { |
| | | const { selectRoleId, menuTrees, tabKey } = this.state |
| | | if (!menuTrees) return |
| | | const { selectRoleId, menuTrees, activeKey } = this.state |
| | | if (!menuTrees || !selectRoleId || activeKey !== 'manage') return |
| | | |
| | | let param = { |
| | | func: 's_rolemenu_get_Menulist', |
| | | RoleID: selectRoleId |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingTree: true |
| | | }) |
| | | |
| | | let result = await Api.getSystemConfig(param) |
| | | |
| | | if (result.status) { |
| | | let _openKeys = [] |
| | | |
| | | if (tabKey === '') { |
| | | let _initKeys = result.data.map(item => item.MenuID) |
| | | _initKeys = Array.from(new Set(_initKeys)) |
| | | let _initKeys = result.data.map(item => item.MenuID) |
| | | _initKeys = Array.from(new Set(_initKeys)) |
| | | |
| | | selectMap = new Map() |
| | | this.getCheckedKeys(fromJS(menuTrees).toJS(), _initKeys) |
| | | selectMap = new Map() |
| | | this.getCheckedKeys(fromJS(menuTrees).toJS(), _initKeys) |
| | | |
| | | if (menuTrees[0]) { |
| | | if (menuTrees[0].key === 'PC' && menuTrees[0].children) { |
| | | this.getOpenNode(menuTrees[0].children[0], _openKeys) |
| | | } else { |
| | | this.getOpenNode(menuTrees[0], _openKeys) |
| | | } |
| | | if (menuTrees[0]) { |
| | | if (menuTrees[0].key === 'PC' && menuTrees[0].children) { |
| | | this.getOpenNode(menuTrees[0].children[0], _openKeys) |
| | | } else { |
| | | this.getOpenNode(menuTrees[0], _openKeys) |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingTree: false, |
| | | initCheckKeys: _initKeys, |
| | | checkedKeys: Array.from(selectMap.keys()), |
| | | menuOpenKeys: _openKeys |
| | | }) |
| | | } else { |
| | | let Keys = result.data.map(item => item.MenuID) |
| | | let _tree = this.getSelectTree(fromJS(menuTrees).toJS(), Keys) |
| | | |
| | | if (_tree[0]) { |
| | | if (_tree[0].key === 'PC' && _tree[0].children) { |
| | | this.getOpenNode(_tree[0].children[0], _openKeys) |
| | | } else { |
| | | this.getOpenNode(_tree[0], _openKeys) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingTree: false, |
| | | selectMenuTrees: _tree, |
| | | selectMenuOpenKeys: _openKeys |
| | | }) |
| | | } |
| | | |
| | | let _openkeys = [] |
| | | let Keys = result.data.map(item => item.MenuID) |
| | | let _tree = this.getSelectTree(fromJS(menuTrees).toJS(), Keys) |
| | | |
| | | if (_tree[0]) { |
| | | if (_tree[0].key === 'PC' && _tree[0].children) { |
| | | this.getOpenNode(_tree[0].children[0], _openkeys) |
| | | } else { |
| | | this.getOpenNode(_tree[0], _openkeys) |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingTree: false, |
| | | initCheckKeys: _initKeys, |
| | | checkedKeys: Array.from(selectMap.keys()), |
| | | menuOpenKeys: _openKeys, |
| | | selectMenuTrees: _tree, |
| | | selectMenuOpenKeys: _openkeys |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | loadingTree: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @description 选择角色且存在权限树时,获取已分配结构 |
| | | */ |
| | | getSelectAppNodeList = async () => { |
| | | const { selectRoleId, selectSubApp, selectApp, appTrees, activeKey } = this.state |
| | | |
| | | if (!appTrees || !selectRoleId || activeKey !== 'app' || !selectSubApp || !selectApp) return |
| | | |
| | | let param = { |
| | | func: 's_rolemenu_get_Menulist', |
| | | RoleID: selectRoleId, |
| | | TypeCharOne: selectApp.kei_no, |
| | | typename: selectSubApp.typename, |
| | | lang: selectSubApp.lang |
| | | } |
| | | |
| | | this.setState({ |
| | | loadingAppTree: true |
| | | }) |
| | | |
| | | let result = await Api.getSystemConfig(param) |
| | | |
| | | if (result.status) { |
| | | let _initKeys = result.data.map(item => item.MenuID) |
| | | _initKeys = Array.from(new Set(_initKeys)) |
| | | let _checkedKeys = [] |
| | | |
| | | let getCheckedKeys = (parents) => { |
| | | parents.forEach(item => { |
| | | if (_initKeys.includes(item.key)) { |
| | | if (item.children && item.children.length > 0) { |
| | | getCheckedKeys(item.children) |
| | | } else { |
| | | _checkedKeys.push(item.key) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | getCheckedKeys(appTrees) |
| | | |
| | | let _openKeys = [] |
| | | let getOpenNode = (parentNode) => { |
| | | if (parentNode && parentNode.children && parentNode.children.length > 0) { |
| | | _openKeys.push(parentNode.key) |
| | | parentNode.children.forEach(node => { |
| | | getOpenNode(node) |
| | | }) |
| | | } |
| | | } |
| | | getOpenNode(appTrees[0]) |
| | | |
| | | let Keys = result.data.map(item => item.MenuID) |
| | | let _tree = this.getSelectTree(fromJS(appTrees).toJS(), Keys) |
| | | |
| | | |
| | | let _openkeys = [] |
| | | let _getOpenNode = (parentNode) => { |
| | | if (parentNode && parentNode.children && parentNode.children.length > 0) { |
| | | _openkeys.push(parentNode.key) |
| | | parentNode.children.forEach(node => { |
| | | _getOpenNode(node) |
| | | }) |
| | | } |
| | | } |
| | | _getOpenNode(_tree[0]) |
| | | |
| | | this.setState({ |
| | | loadingAppTree: false, |
| | | appInitCheckKeys: _initKeys, |
| | | appCheckedKeys: _checkedKeys, |
| | | appOpenKeys: _openKeys, |
| | | selectAppTrees: _tree, |
| | | selectAppOpenKeys: _openkeys |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | loadingAppTree: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | |
| | | if (selectRoleId === role.RoleID) return |
| | | |
| | | this.setState({ |
| | | selectRoleId: role.RoleID, |
| | | loadingTree: true |
| | | selectRoleId: role.RoleID |
| | | }, () => { |
| | | this.getSelectMenuList() |
| | | this.getSelectAppNodeList() |
| | | }) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * @description 已分配与未分配切换 |
| | | * @description 节点选择事件 |
| | | */ |
| | | changeTab = (key) => { |
| | | const { selectRoleId } = this.state |
| | | |
| | | onAppCheck = (checkedKeys, info) => { |
| | | this.setState({ |
| | | tabKey: key === 'selected' ? key : '', |
| | | loadingTree: true |
| | | }, () => { |
| | | if (selectRoleId) { |
| | | this.getSelectMenuList() |
| | | } else { |
| | | this.setState({ |
| | | selectMenuTrees: [], |
| | | loadingTree: false |
| | | }) |
| | | } |
| | | appCheckedKeys: checkedKeys, |
| | | appHalfCheckedKeys: info.halfCheckedKeys, |
| | | appInitCheckKeys: null |
| | | }) |
| | | } |
| | | |
| | |
| | | |
| | | Api.getSystemConfig(param).then(result => { |
| | | if (result.status) { |
| | | if (!window.GLOB.mainSystemApi) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | }) |
| | | this.setState({ |
| | | submitloading: false, |
| | | loadingTree: true |
| | | }, () => { |
| | | this.getSelectMenuList() |
| | | }) |
| | | } else { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | }) |
| | | this.setState({ |
| | | submitloading: false |
| | | }, () => { |
| | | this.getSelectMenuList() |
| | | }) |
| | | if (window.GLOB.mainSystemApi) { |
| | | Api.getLocalConfig(localParam).then(res => { |
| | | if (res.status) { |
| | | notification.success({ |
| | | if (!res.status) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | this.setState({ |
| | | submitloading: false, |
| | | loadingTree: true |
| | | }, () => { |
| | | this.getSelectMenuList() |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | submitloading: false |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | } else { |
| | | this.setState({ |
| | | submitloading: false |
| | | }) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * @description 提交已选的权限 |
| | | */ |
| | | appRoleSubmit = () => { |
| | | const { selectApp, selectSubApp, appCheckedKeys, appHalfCheckedKeys, selectRoleId, appInitCheckKeys } = this.state |
| | | |
| | | let _keys = [] |
| | | |
| | | if (appInitCheckKeys) { |
| | | _keys = appInitCheckKeys |
| | | } else { |
| | | _keys = appCheckedKeys.concat(appHalfCheckedKeys) |
| | | } |
| | | |
| | | let param = { |
| | | func: 's_rolemenu_sub', |
| | | RoleID: selectRoleId, |
| | | TypeCharOne: selectApp.kei_no, |
| | | typename: selectSubApp.typename, |
| | | lang: selectSubApp.lang, |
| | | RoleMenu: _keys.map(key => { |
| | | return {MenuID: key} |
| | | }) |
| | | } |
| | | |
| | | let localParam = fromJS(param).toJS() |
| | | localParam.func = 's_rolemenu_sub_local' |
| | | |
| | | this.setState({ |
| | | submitloading: true |
| | | }) |
| | | |
| | | Api.getSystemConfig(param).then(result => { |
| | | if (result.status) { |
| | | notification.success({ |
| | | top: 92, |
| | | message: '保存成功', |
| | | duration: 2 |
| | | }) |
| | | this.setState({ |
| | | submitloading: false |
| | | }, () => { |
| | | this.getSelectAppNodeList() |
| | | }) |
| | | |
| | | if (window.GLOB.mainSystemApi) { |
| | | Api.getLocalConfig(localParam).then(res => { |
| | | if (!res.status) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | |
| | | loading: true, |
| | | loadingTree: false, |
| | | roleList: null, |
| | | filterRoleList: [], |
| | | selectRoleId: '', |
| | | mainMenus: null, |
| | | menuTrees: null, |
| | | checkedKeys: [], |
| | | appCheckedKeys: [], |
| | | menuOpenKeys: [], |
| | | selectMenuTrees: null, |
| | | selectMenuOpenKeys: [], |
| | | primarykey: '', |
| | | tabKey: '', |
| | | submitloading: false, |
| | | initCheckKeys: null |
| | | initCheckKeys: null, |
| | | appInitCheckKeys: null, |
| | | activeKey: 'manage', |
| | | appTrees: null, |
| | | appOpenKeys: [], |
| | | applist: [], |
| | | selectApp: null, |
| | | selectSubApp: null, |
| | | selectAppTrees: null, |
| | | selectAppOpenKeys: [] |
| | | }) |
| | | this.getRoleList() |
| | | this.getMainMenuList() |
| | | this.getAppList() |
| | | } |
| | | |
| | | filterRole = () => { |
| | | const { primarykey, roleList } = this.state |
| | | |
| | | let _roleList = [] |
| | | |
| | | if (roleList && roleList.length > 0) { |
| | | _roleList = roleList.filter(role => role.RoleName.toLowerCase().indexOf(primarykey.toLowerCase()) >= 0) |
| | | } |
| | | |
| | | this.setState({filterRoleList: _roleList}) |
| | | } |
| | | |
| | | getTreeList = () => { |
| | | const { selectApp, selectSubApp } = this.state |
| | | let param = { |
| | | func: 's_get_menus_roles_tree', |
| | | typecharone: selectApp.kei_no, |
| | | lang: selectSubApp.lang |
| | | } |
| | | |
| | | param.upid = md5(window.GLOB.appkey + selectApp.kei_no + selectSubApp.typename + selectSubApp.lang) |
| | | |
| | | this.setState({loadingAppTree: true}) |
| | | |
| | | Api.getCloudConfig(param).then(result => { |
| | | if (result.status) { |
| | | if (!result.data || result.data.length === 0) { |
| | | this.setState({loadingAppTree: false, appTrees: []}) |
| | | } else { |
| | | this.initTrees(result.data) |
| | | } |
| | | } else { |
| | | this.setState({loadingAppTree: false, appTrees: []}) |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | initTrees = (data) => { |
| | | let trees = [] |
| | | let map = new Map() |
| | | let _data = data.sort((a, b) => { |
| | | return a.sort - b.sort |
| | | }) |
| | | |
| | | _data.forEach(menu => { |
| | | if (menu.ParentID === 'top') { |
| | | trees.push({ |
| | | key: menu.MenuID, |
| | | title: menu.MenuName, |
| | | children: [] |
| | | }) |
| | | } else { |
| | | map.set(menu.MenuID, menu) |
| | | } |
| | | }) |
| | | |
| | | let reset = (m) => { |
| | | return m.map(n => { |
| | | [...map.keys()].forEach(key => { |
| | | if (map.get(key).ParentID === n.key) { |
| | | let c = map.get(key) |
| | | n.children.push({ |
| | | key: c.MenuID, |
| | | title: c.MenuName, |
| | | children: [] |
| | | }) |
| | | map.delete(key) |
| | | } |
| | | }) |
| | | if (n.children.length > 0) { |
| | | n.children = reset(n.children) |
| | | } |
| | | return n |
| | | }) |
| | | } |
| | | |
| | | trees = reset(trees) |
| | | |
| | | let expandedKeys = this.getExpandedKeys(trees, 0, []) |
| | | |
| | | this.setState({loadingAppTree: false, appTrees: trees, appOpenKeys: expandedKeys}, () => { |
| | | this.getSelectAppNodeList() |
| | | }) |
| | | } |
| | | |
| | | getExpandedKeys = (trees, i, keys) => { |
| | | if (i >= 3 || !trees[0]) return keys |
| | | |
| | | keys.push(trees[0].key) |
| | | |
| | | i++ |
| | | |
| | | if (trees[0].children && trees[0].children.length > 0) { |
| | | keys = this.getExpandedKeys(trees[0].children, i, keys) |
| | | } |
| | | |
| | | return keys |
| | | } |
| | | |
| | | changeType = (val) => { |
| | | this.setState({ |
| | | activeKey: val |
| | | }, () => { |
| | | this.getSelectMenuList() |
| | | this.getSelectAppNodeList() |
| | | }) |
| | | } |
| | | |
| | | changeApp = (val) => { |
| | | const { applist } = this.state |
| | | |
| | | let app = applist.filter(item => item.ID === val)[0] |
| | | |
| | | this.setState({selectApp: app, selectSubApp: null}) |
| | | } |
| | | |
| | | changeSubApp = (val) => { |
| | | const { selectApp } = this.state |
| | | |
| | | let subapp = selectApp.sublist.filter(item => item.ID === val)[0] |
| | | |
| | | this.setState({selectSubApp: subapp}, () => { |
| | | this.getTreeList() |
| | | }) |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | this.getRoleList() |
| | | this.getMainMenuList() |
| | | this.getAppList() |
| | | } |
| | | |
| | | componentDidMount () { |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { roleList, loading, loadingTree, primarykey, menuTrees, checkedKeys, menuOpenKeys, selectMenuTrees, tabKey, selectRoleId, selectMenuOpenKeys, submitloading } = this.state |
| | | |
| | | let _roleList = [] |
| | | |
| | | if (roleList && roleList.length > 0) { |
| | | _roleList = roleList.filter(role => role.RoleName.toLowerCase().indexOf(primarykey.toLowerCase()) >= 0) |
| | | } |
| | | const { activeKey, filterRoleList, applist, selectApp, selectSubApp, loading, loadingTree, loadingAppTree, primarykey, menuTrees, appTrees, checkedKeys, appCheckedKeys, menuOpenKeys, selectMenuTrees, selectAppTrees, selectRoleId, selectMenuOpenKeys, selectAppOpenKeys, submitloading, appOpenKeys } = this.state |
| | | |
| | | return ( |
| | | <div className="rolemanage"> |
| | | {loading && <Spin size="large" />} |
| | | <Row gutter={16}> |
| | | <Col span={5}> |
| | | <Card |
| | | className="role-list" |
| | | title={ |
| | | <span className="role-title"> |
| | | <Icon type="bank" /> |
| | | <span className="title">{this.state.dict['main.role.title']}</span> |
| | | <Search placeholder="" onSearch={value => this.setState({primarykey: value})} /> |
| | | </span> |
| | | } |
| | | bordered={false} |
| | | > |
| | | <Menu |
| | | onClick={this.handleClick} |
| | | mode="inline" |
| | | > |
| | | {_roleList.map((role, index) => |
| | | <Menu.Item key={index} onClick={() => this.changeRole(role)}>{role.RoleName}</Menu.Item> |
| | | )} |
| | | </Menu> |
| | | </Card> |
| | | </Col> |
| | | <Col span={19}> |
| | | <Tabs defaultActiveKey="all" tabBarExtraContent={!tabKey && selectRoleId ? <Button type="primary" loading={submitloading} onClick={this.roleSubmit}>提交</Button> : null} onChange={this.changeTab}> |
| | | <TabPane tab="菜单列表" key="all"> |
| | | {!loadingTree && menuTrees && menuTrees.length > 0 ? <Tree |
| | | checkable |
| | | selectable={false} |
| | | defaultExpandedKeys={menuOpenKeys} |
| | | autoExpandParent={true} |
| | | onCheck={this.onCheck} |
| | | checkedKeys={checkedKeys} |
| | | <Tabs activeKey={activeKey} type="card" onChange={this.changeType}> |
| | | <TabPane tab="管理系统" key="manage"> |
| | | <Row gutter={16}> |
| | | <Col span={5}> |
| | | <Card |
| | | className="role-list" |
| | | title={ |
| | | <span className="role-title"> |
| | | <Icon type="bank" /> |
| | | <span className="title">角色</span> |
| | | <Search placeholder="" value={primarykey} onChange={e => this.setState({primarykey: e.target.value})} onSearch={this.filterRole} /> |
| | | </span> |
| | | } |
| | | bordered={false} |
| | | > |
| | | {this.renderTreeNodes(menuTrees)} |
| | | </Tree> : null} |
| | | {!loadingTree && (!menuTrees || menuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingTree ? <Spin className="load-tree" /> : null} |
| | | </TabPane> |
| | | <TabPane tab="已授权菜单" key="selected"> |
| | | {!loadingTree && selectMenuTrees && selectMenuTrees.length > 0 ? <DirectoryTree multiple defaultExpandedKeys={selectMenuOpenKeys}> |
| | | {this.renderTreeNodes(selectMenuTrees)} |
| | | </DirectoryTree> : null} |
| | | {!loadingTree && (!selectMenuTrees || selectMenuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingTree ? <Spin className="load-tree" /> : null} |
| | | </TabPane> |
| | | </Tabs> |
| | | </Col> |
| | | </Row> |
| | | <Menu selectedKeys={[selectRoleId]} mode="inline"> |
| | | {filterRoleList.map((role) => |
| | | <Menu.Item key={role.RoleID} onClick={() => this.changeRole(role)}>{role.RoleName}</Menu.Item> |
| | | )} |
| | | </Menu> |
| | | </Card> |
| | | </Col> |
| | | <Col span={19}> |
| | | <Tabs defaultActiveKey="all"> |
| | | <TabPane tab="权限" key="all"> |
| | | {selectRoleId ? <Button className="submitBtn" type="primary" loading={submitloading} onClick={this.roleSubmit}>提交</Button> : null} |
| | | {!loadingTree && menuTrees && menuTrees.length > 0 ? <Tree |
| | | checkable |
| | | selectable={false} |
| | | defaultExpandedKeys={menuOpenKeys} |
| | | autoExpandParent={true} |
| | | onCheck={this.onCheck} |
| | | checkedKeys={checkedKeys} |
| | | > |
| | | {this.renderTreeNodes(menuTrees)} |
| | | </Tree> : null} |
| | | {!loadingTree && (!menuTrees || menuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingTree ? <Spin className="load-tree" /> : null} |
| | | </TabPane> |
| | | <TabPane tab="已授权" key="selected"> |
| | | {!loadingTree && selectMenuTrees && selectMenuTrees.length > 0 ? <DirectoryTree multiple defaultExpandedKeys={selectMenuOpenKeys}> |
| | | {this.renderTreeNodes(selectMenuTrees)} |
| | | </DirectoryTree> : null} |
| | | {!loadingTree && (!selectMenuTrees || selectMenuTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingTree ? <Spin className="load-tree" /> : null} |
| | | </TabPane> |
| | | </Tabs> |
| | | </Col> |
| | | </Row> |
| | | </TabPane> |
| | | <TabPane tab="应用" key="app"> |
| | | <div className="app-select"> |
| | | <div className="mk-form-item"> |
| | | <label>应用:</label> |
| | | <Select value={selectApp ? selectApp.ID : ''} onChange={this.changeApp}> |
| | | {applist.map(option => |
| | | <Select.Option key={option.ID} value={option.ID}>{option.remark}</Select.Option> |
| | | )} |
| | | </Select> |
| | | </div> |
| | | <div className="mk-form-item"> |
| | | <label>子应用:</label> |
| | | <Select value={selectSubApp ? selectSubApp.ID : ''} onChange={this.changeSubApp}> |
| | | {selectApp && selectApp.sublist.map(option => |
| | | <Select.Option key={option.ID} value={option.ID}>{`${option.typename}(${option.lang})`}</Select.Option> |
| | | )} |
| | | </Select> |
| | | </div> |
| | | </div> |
| | | <Row gutter={16}> |
| | | <Col span={5}> |
| | | <Card |
| | | className="role-list" |
| | | title={ |
| | | <span className="role-title"> |
| | | <Icon type="bank" /> |
| | | <span className="title">角色</span> |
| | | <Search placeholder="" value={primarykey} onChange={e => this.setState({primarykey: e.target.value})} onSearch={this.filterRole} /> |
| | | </span> |
| | | } |
| | | bordered={false} |
| | | > |
| | | <Menu selectedKeys={[selectRoleId]} mode="inline"> |
| | | {filterRoleList.map((role) => |
| | | <Menu.Item key={role.RoleID} onClick={() => this.changeRole(role)}>{role.RoleName}</Menu.Item> |
| | | )} |
| | | </Menu> |
| | | </Card> |
| | | </Col> |
| | | <Col span={19}> |
| | | <Tabs defaultActiveKey="all"> |
| | | <TabPane tab="权限" key="all"> |
| | | {selectSubApp && selectRoleId ? <Button className="submitBtn" type="primary" loading={submitloading} onClick={this.appRoleSubmit}>提交</Button> : null} |
| | | {selectSubApp ? <div> |
| | | {!loadingAppTree && appTrees && appTrees.length > 0 ? <Tree |
| | | checkable |
| | | selectable={false} |
| | | defaultExpandedKeys={appOpenKeys} |
| | | autoExpandParent={true} |
| | | onCheck={this.onAppCheck} |
| | | checkedKeys={appCheckedKeys} |
| | | > |
| | | {this.renderTreeNodes(appTrees)} |
| | | </Tree> : null} |
| | | {!loadingAppTree && (!appTrees || appTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingAppTree ? <Spin className="load-tree" /> : null} |
| | | </div> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={'请选择子应用'} />} |
| | | </TabPane> |
| | | <TabPane tab="已授权" key="selected"> |
| | | {selectSubApp ? <div> |
| | | {!loadingAppTree && selectAppTrees && selectAppTrees.length > 0 ? <DirectoryTree multiple defaultExpandedKeys={selectAppOpenKeys}> |
| | | {this.renderTreeNodes(selectAppTrees)} |
| | | </DirectoryTree> : null} |
| | | {!loadingAppTree && (!selectAppTrees || selectAppTrees.length === 0) ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> : null} |
| | | {loadingAppTree ? <Spin className="load-tree" /> : null} |
| | | </div> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={'请选择子应用'} />} |
| | | </TabPane> |
| | | </Tabs> |
| | | </Col> |
| | | </Row> |
| | | </TabPane> |
| | | </Tabs> |
| | | |
| | | </div> |
| | | ) |
| | | } |
| | |
| | | .role-title { |
| | | display: inline-block; |
| | | width: 100%; |
| | | color: #1890ff; |
| | | color: rgba(0, 0, 0, 0.65); |
| | | .anticon-bank { |
| | | margin-right: 5px; |
| | | } |
| | |
| | | left: calc(50vw - 22px); |
| | | top: calc(50vh - 70px); |
| | | z-index: 1; |
| | | } |
| | | .ant-tabs { |
| | | } |
| | | .ant-tabs-bar.ant-tabs-card-bar { |
| | | .ant-tabs-tab { |
| | | min-width: 120px; |
| | | text-align: center; |
| | | } |
| | | } |
| | | .ant-tabs.ant-tabs-line { |
| | | background: #fff; |
| | | min-height: calc(100vh - 125px); |
| | | box-shadow: 0px 0px 2px #eeeeee; |
| | |
| | | text-align: center; |
| | | color: #bcbcbc; |
| | | } |
| | | .submitBtn { |
| | | position: absolute; |
| | | right: 10px; |
| | | top: 15px; |
| | | } |
| | | } |
| | | } |
| | | .app-select { |
| | | position: absolute; |
| | | top: 0px; |
| | | right: 0px; |
| | | .mk-form-item { |
| | | display: inline-block; |
| | | width: 230px; |
| | | label { |
| | | width: 60px; |
| | | display: inline-block; |
| | | text-align: right; |
| | | padding-right: 5px; |
| | | white-space: nowrap; |
| | | } |
| | | .ant-select { |
| | | width: 150px; |
| | | } |
| | | } |
| | | } |
| | | } |