| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Tabs, Icon, Popover, Modal } from 'antd' |
| | | import { Tabs, Popover, Modal } from 'antd' |
| | | import { PlusOutlined, CloseOutlined, EditOutlined, DeleteOutlined, FontColorsOutlined, ToolOutlined } from '@ant-design/icons' |
| | | |
| | | import MKEmitter from '@/utils/events.js' |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import asyncIconComponent from '@/utils/asyncIconComponent' |
| | | import MkIcon from '@/components/mk-icon' |
| | | 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 { getTabForm, getTabsSetForm } from './options' |
| | | import zhCN from '@/locales/zh-CN/model.js' |
| | | import enUS from '@/locales/en-US/model.js' |
| | | import './index.scss' |
| | | |
| | | const NormalForm = asyncIconComponent(() => import('@/components/normalform')) |
| | |
| | | } |
| | | |
| | | state = { |
| | | dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS, |
| | | appType: sessionStorage.getItem('appType'), |
| | | tabs: null, |
| | | editab: null, |
| | | defaultActiveKey: '' |
| | |
| | | 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: [] } |
| | | { uuid: Utils.getuuid(), label: 'Tab 1', icon: '', components: [] }, |
| | | { uuid: Utils.getuuid(), label: 'Tab 2', icon: '', components: [] }, |
| | | { uuid: Utils.getuuid(), label: 'Tab 3', icon: '', components: [] } |
| | | ] |
| | | } |
| | | this.setState({ |
| | |
| | | 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更新,清除快捷键设置 |
| | | */ |
| | |
| | | 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) |
| | | MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], tabs.style, this.getStyle) |
| | | } |
| | | |
| | | getStyle = (comIds, style) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (comIds.length !== 1 || comIds[0] !== tabs.uuid) return |
| | | |
| | | let _card = {...tabs, style} |
| | | getStyle = (style) => { |
| | | let _card = {...this.state.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) |
| | | } |
| | | getSubIds = (components, ids) => { |
| | | components.forEach(item => { |
| | | if (item.type === 'tabs') { |
| | | item.subtabs.forEach(tab => { |
| | | this.getSubIds(tab.components, ids) |
| | | }) |
| | | } else if (item.type === 'group') { |
| | | this.getSubIds(item.components, ids) |
| | | } else { |
| | | ids.push(item.uuid) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | updateComponent = (component) => { |
| | |
| | | |
| | | if (!is(fromJS(tabs.setting), fromJS(component.setting)) || !is(fromJS(tabs.style), fromJS(component.style))) { |
| | | // 注册事件-标签变化,通知标签内元素 |
| | | MKEmitter.emit('tabsChange', tabs.uuid) |
| | | let ids = [] |
| | | tabs.subtabs.forEach(tab => { |
| | | this.getSubIds(tab.components, ids) |
| | | }) |
| | | MKEmitter.emit('tabsChange', ids.join(',')) |
| | | } |
| | | |
| | | component.width = component.setting.width |
| | |
| | | |
| | | delTab = (tab) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | const _this = this |
| | | const that = 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) |
| | | that.setState({tabs}) |
| | | that.props.updateConfig(tabs) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | |
| | | this.props.updateConfig(tabs) |
| | | } |
| | | |
| | | insert = (item, tab) => { |
| | | insert = (item, tabId) => { |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | |
| | | tabs.subtabs.forEach(stab => { |
| | | if (stab.uuid === tab.uuid) { |
| | | if (stab.uuid === tabId) { |
| | | stab.components.push(item) |
| | | } |
| | | }) |
| | |
| | | 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) |
| | | } |
| | | } |
| | | |
| | | getTabForms = (tab) => { |
| | | const { tabs } = this.state |
| | | |
| | | if (!tab) { |
| | | tab = { |
| | | uuid: '', |
| | | parentId: tabs.uuid, |
| | | floor: tabs.floor, |
| | | label: '', |
| | | icon: '', |
| | | components: [] |
| | |
| | | editab: tab |
| | | }) |
| | | |
| | | return getTabForm(tab, tabs.setting) |
| | | return getTabForm(tab) |
| | | } |
| | | |
| | | updateTab = (res) => { |
| | |
| | | |
| | | editab.label = res.label |
| | | editab.icon = res.icon |
| | | editab.hasSearch = res.hasSearch || '' |
| | | editab.hide = res.hide || 'false' |
| | | editab.backgroundColor = res.backgroundColor |
| | | // editab.controlVal = res.controlVal || '' |
| | | // editab.selectVal = res.selectVal || '' |
| | | editab.blacklist = res.blacklist |
| | | |
| | | if (/^\s+$/.test(editab.label) && editab.icon) { |
| | | editab.taType = 'only-icon' |
| | | } else { |
| | | delete editab.taType |
| | | } |
| | | |
| | | if (editab.uuid) { |
| | | tabs.subtabs = tabs.subtabs.map(t => { |
| | |
| | | getTabsForms = () => { |
| | | const { tabs } = this.state |
| | | |
| | | return getTabsSetForm(tabs.setting) |
| | | return getTabsSetForm(tabs.setting, tabs.uuid, tabs.subtabs) |
| | | } |
| | | |
| | | updateTabs = (res) => { |
| | | this.updateComponent({...this.state.tabs, setting: res}) |
| | | let tabs = fromJS(this.state.tabs).toJS() |
| | | |
| | | if (res.controlVals) { |
| | | let values = {} |
| | | res.controlVals.forEach(item => { |
| | | values[item.uuid] = item.value |
| | | }) |
| | | tabs.subtabs.forEach(tab => { |
| | | tab.controlVal = values[tab.uuid] |
| | | }) |
| | | |
| | | delete res.controlVals |
| | | } |
| | | if (res.selectVals) { |
| | | let values = {} |
| | | res.selectVals.forEach(item => { |
| | | values[item.uuid] = item.value |
| | | }) |
| | | tabs.subtabs.forEach(tab => { |
| | | tab.selectVal = values[tab.uuid] |
| | | }) |
| | | |
| | | delete res.selectVals |
| | | } |
| | | |
| | | res.tabStyle = res.tabStyle || 'line' |
| | | res.cusClass = '' |
| | | |
| | | if (!['line', 'card'].includes(res.tabStyle)) { |
| | | res.cusClass = res.tabStyle |
| | | res.tabStyle = 'line' |
| | | } |
| | | |
| | | tabs.setting = res |
| | | |
| | | this.updateComponent(tabs) |
| | | } |
| | | |
| | | onChange = (key) => { |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { tabs, appType, defaultActiveKey } = this.state |
| | | const { tabs, defaultActiveKey } = 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 defaultActiveKey={defaultActiveKey} tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch} onChange={this.onChange}> |
| | | <div className="menu-tabs-edit-box" style={_style} id={tabs.uuid}> |
| | | <DraggableTabs defaultActiveKey={defaultActiveKey} tabBarStyle={{background: tabs.setting.backgroundColor || 'transparent'}} tabPosition={tabs.setting.position} type={tabs.setting.tabStyle} tabsMove={this.moveSwitch} onChange={this.onChange}> |
| | | {tabs.subtabs.map(tab => ( |
| | | <TabPane tab={ |
| | | <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ |
| | | <div className="mk-popover-control"> |
| | | <NormalForm title="标签编辑" width={600} update={this.updateTab} getForms={() => this.getTabForms(tab)}> |
| | | <Icon type="edit" style={{color: '#1890ff'}} title="编辑"/> |
| | | <NormalForm title="标签编辑" width={800} update={this.updateTab} getForms={() => this.getTabForms(tab)}> |
| | | <EditOutlined style={{color: '#1890ff'}} title="编辑"/> |
| | | </NormalForm> |
| | | <PasteController type="tab" Tab={tab} insert={this.insert} /> |
| | | <Icon className="close" title="delete" type="close" onClick={() => this.delTab(tab)} /> |
| | | <PasteController type="tabs" tab={tab} insert={(item) => this.insert(item, tab.uuid)} /> |
| | | <CloseOutlined className="close" onClick={() => this.delTab(tab)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span> |
| | | <span style={{textDecoration: tab.hide === 'true' ? 'line-through' : 'none'}}>{tab.icon ? <MkIcon 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} |
| | | } key={tab.uuid} style={{backgroundColor: tab.backgroundColor || 'transparent'}}> |
| | | <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"> |
| | | <NormalForm title="添加标签" width={600} update={this.updateTab} getForms={() => this.getTabForms()}> |
| | | <Icon type="plus" className="plus" title="添加标签"/> |
| | | <NormalForm title="添加标签" width={800} update={this.updateTab} getForms={() => this.getTabForms()}> |
| | | <PlusOutlined className="plus" title="添加标签"/> |
| | | </NormalForm> |
| | | <NormalForm title="标签页设置" width={700} update={this.updateTabs} getForms={this.getTabsForms}> |
| | | <Icon type="edit" style={{color: '#1890ff'}} title="编辑"/> |
| | | <NormalForm title="标签页设置" width={800} update={this.updateTabs} getForms={this.getTabsForms}> |
| | | <EditOutlined style={{color: '#1890ff'}} title="编辑"/> |
| | | </NormalForm> |
| | | <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)} /> |
| | | <FontColorsOutlined className="style" title="调整样式" onClick={this.changeStyle}/> |
| | | <DeleteOutlined className="close" onClick={() => this.props.deletecomponent(tabs.uuid)} /> |
| | | </div> |
| | | } trigger="hover"> |
| | | <Icon type="tool" /> |
| | | <ToolOutlined /> |
| | | </Popover> |
| | | </div> |
| | | ) |