| | |
| | | import React, { useState } from 'react' |
| | | import { useDrop } from 'react-dnd' |
| | | import { is, fromJS } from 'immutable' |
| | | import update from 'immutability-helper' |
| | | import { message } from 'antd' |
| | | import { Empty, notification, Modal } from 'antd' |
| | | |
| | | import Utils from '@/utils/utils.js' |
| | | import Card from './card' |
| | | import './index.scss' |
| | | |
| | | const Container = ({config, handleList, handleMenu, deleteMenu, doubleClickCard }) => { |
| | | let target = null |
| | | const { confirm } = Modal |
| | | |
| | | const [cards, setCards] = useState(config.components) |
| | | const Container = ({menu, handleList }) => { |
| | | const [cards, setCards] = useState(menu.components) |
| | | const moveCard = (id, atIndex) => { |
| | | const { card, index } = findCard(id) |
| | | const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] }) |
| | | handleList({...config, components: _cards}) |
| | | console.log(_cards) |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | | } |
| | | |
| | | if (!is(fromJS(cards), fromJS(config.components))) { |
| | | setCards(config.components) |
| | | if (menu.components.length > cards.length) { |
| | | setCards(menu.components) |
| | | } |
| | | |
| | | const findCard = id => { |
| | |
| | | } |
| | | } |
| | | |
| | | // const doubleClickBtn = id => { |
| | | // const { card } = findCard(id) |
| | | // doubleClickCard(card) |
| | | // } |
| | | const updateConfig = (element) => { |
| | | const _cards = cards.map(item => item.uuid === element.uuid ? element : item) |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | | } |
| | | |
| | | // const editCard = id => { |
| | | // const { card } = findCard(id) |
| | | // handleMenu(card) |
| | | // } |
| | | const deleteCard = (id) => { |
| | | const { card } = findCard(id) |
| | | |
| | | // const delCard = id => { |
| | | // const { card } = findCard(id) |
| | | // deleteMenu(card) |
| | | // } |
| | | let hasComponent = false |
| | | if (card.type === 'tabs') { |
| | | card.subtabs.forEach(tab => { |
| | | if (tab.components.length > 0) { |
| | | hasComponent = true |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const hasDrop = (item) => { |
| | | target = item |
| | | confirm({ |
| | | title: `确定删除${card.name ? `《${card.name}》` : '组件'}吗?`, |
| | | content: hasComponent ? '当前组件中含有子组件!' : '', |
| | | onOk() { |
| | | const _cards = cards.filter(item => item.uuid !== card.uuid) |
| | | handleList({...menu, components: _cards}) |
| | | setCards(_cards) |
| | | }, |
| | | onCancel() {} |
| | | }) |
| | | } |
| | | |
| | | const [, drop] = useDrop({ |
| | | accept: 'mob', |
| | | accept: 'menu', |
| | | drop(item) { |
| | | if (item.hasOwnProperty('originalIndex')) { |
| | | if (item.hasOwnProperty('originalIndex') || item.added) { |
| | | delete item.added // 删除组件添加标记 |
| | | return |
| | | } |
| | | |
| | | if (cards.length > 0 && cards[0].type === 'login') { |
| | | message.warning('登录页不可添加其他元素!') |
| | | return |
| | | let style = null |
| | | |
| | | if (item.component === 'search') { // 搜索组件不可重复添加 |
| | | if (cards.filter(card => card.type === 'topbar' && card.wrap.type !== 'navbar').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '导航栏使用了搜索,不可添加搜索组件!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | if (cards.filter(card => card.type === 'search').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '搜索条件不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | } else if (item.component === 'navbar') { |
| | | if (cards.filter(card => card.type === 'navbar').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '菜单栏不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | if (!menu.style.paddingBottom) { |
| | | style = {...menu.style, paddingBottom: '50px'} |
| | | } |
| | | } else if (item.component === 'topbar') { |
| | | if (cards.filter(card => card.type === 'topbar').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '导航栏不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | if (!menu.style.paddingTop) { |
| | | style = {...menu.style, paddingTop: '50px'} |
| | | } |
| | | } else if (item.component === 'officialAccount') { |
| | | if (cards.filter(card => card.type === 'officialAccount').length > 0) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '关注组件不可重复添加!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | } |
| | | |
| | | let newcard = fromJS(item.param).toJS() |
| | | newcard.uuid = Utils.getuuid() |
| | | let name = '' |
| | | let names = { |
| | | bar: '柱状图', |
| | | line: '折线图', |
| | | tabs: '标签组', |
| | | pie: '饼图', |
| | | search: '搜索', |
| | | table: '表格', |
| | | group: '分组', |
| | | editor: '富文本', |
| | | code: '自定义', |
| | | carousel: '轮播', |
| | | dashboard: '仪表盘', |
| | | form: '表单', |
| | | card: '卡片', |
| | | navbar: '导航栏', |
| | | menubar: '菜单栏', |
| | | balcony: '浮动卡', |
| | | timeline: '时间轴', |
| | | officialAccount: '关注公众号', |
| | | sharecode: '分享码', |
| | | iframe: 'iframe', |
| | | login: '登录' |
| | | } |
| | | let i = 1 |
| | | |
| | | let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0 |
| | | if (target) { |
| | | targetId = target.uuid |
| | | while (!name && names[item.component]) { |
| | | let _name = names[item.component] + i |
| | | if (menu.components.filter(com => com.name === _name).length === 0) { |
| | | name = _name |
| | | } |
| | | i++ |
| | | } |
| | | |
| | | let newcard = { |
| | | uuid: Utils.getuuid(), |
| | | type: item.component, |
| | | subtype: item.subtype, |
| | | config: item.config, |
| | | width: item.width || 24, |
| | | name: name, |
| | | floor: 1, // 组件的层级 |
| | | 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}`) |
| | | let targetIndex = overIndex |
| | | let _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] }) |
| | | let Topbar = null |
| | | let Navbar = null |
| | | _cards = _cards.filter(item => { |
| | | if (item.type === 'topbar') { |
| | | Topbar = item |
| | | } else if (item.type === 'navbar') { |
| | | Navbar = item |
| | | } |
| | | |
| | | targetIndex++ |
| | | return item.type !== 'topbar' && item.type !== 'navbar' |
| | | }) |
| | | |
| | | const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] }) |
| | | if (Topbar) { |
| | | _cards.unshift(Topbar) |
| | | } |
| | | if (Navbar) { |
| | | _cards.push(Navbar) |
| | | } |
| | | |
| | | handleList({...config, components: _cards}) |
| | | target = null |
| | | if (style) { |
| | | handleList({...menu, style, components: _cards}) |
| | | } else { |
| | | handleList({...menu, components: _cards}) |
| | | } |
| | | setCards(_cards) |
| | | } |
| | | }) |
| | | |
| | | let style = JSON.stringify(menu.style || {}) |
| | | style = style.replace(/@mywebsite@\//ig, window.GLOB.baseurl) |
| | | style = JSON.parse(style) |
| | | |
| | | return ( |
| | | <div ref={drop} className="mob-shell-inner"> |
| | | {cards.map(card => ( |
| | | <Card |
| | | id={card.uuid} |
| | | key={card.uuid} |
| | | card={card} |
| | | moveCard={moveCard} |
| | | // editCard={editCard} |
| | | // delCard={delCard} |
| | | findCard={findCard} |
| | | hasDrop={hasDrop} |
| | | // doubleClickCard={doubleClickBtn} |
| | | /> |
| | | ))} |
| | | {/* {cards.length === 0 ? |
| | | <div className="common-drawarea-placeholder"> |
| | | {placeholder} |
| | | </div> : null |
| | | } */} |
| | | <div ref={drop} className="mob-shell-inner" id="menu-shell-inner"> |
| | | <div className="ant-row" style={style}> |
| | | {cards.map(card => ( |
| | | <Card |
| | | id={card.uuid} |
| | | key={card.uuid} |
| | | card={card} |
| | | moveCard={moveCard} |
| | | delCard={deleteCard} |
| | | findCard={findCard} |
| | | updateConfig={updateConfig} |
| | | /> |
| | | ))} |
| | | {cards.length === 0 ? |
| | | <Empty description="请添加组件" /> : null |
| | | } |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | export default Container |
| | | |