import React, { Children, createContext, useContext, useEffect, useRef, useState, } from 'react'; import { connect, observer, mapProps, mapReadPretty, useField, useFieldSchema, RecursionField, Schema, SchemaOptionsContext, FormProvider, useForm, } from '@formily/react'; import { Menu as AntdMenu, MenuProps, MenuItemProps, SubMenuProps, DividerProps, Dropdown, Modal, Button, } from 'antd'; import get from 'lodash/get'; import { uid } from '@formily/shared'; import { MenuOutlined, GroupOutlined, PlusOutlined, LinkOutlined, AppstoreAddOutlined, EditOutlined, DeleteOutlined, ArrowRightOutlined, SettingOutlined, ArrowUpOutlined, ArrowDownOutlined, } from '@ant-design/icons'; import './style.less'; import { Icon } from '../icon-picker'; import { useHistory } from 'react-router-dom'; import cls from 'classnames'; import ReactDOM from 'react-dom'; import { useMount } from 'ahooks'; import { useDesignable, SchemaRenderer } from '..'; import { Router } from "react-router"; import { useLifecycle } from 'beautiful-react-hooks'; import { useDefaultAction } from '../action'; export type MenuType = React.FC & { Item?: React.FC; SubMenu?: React.FC; Divider?: React.FC; DesignableBar?: React.FC; AddNew?: React.FC; Link?: React.FC; Url?: React.FC; }; export const MenuContainerContext = createContext({ sideMenuRef: null, }); export const MenuContext = createContext({ mode: null, designableBar: null, }); function Blank() { return null; } function useDesignableBar() { const { designableBar } = useContext(MenuContext); const options = useContext(SchemaOptionsContext); const DesignableBar = designableBar ? get(options.components, designableBar) : null; return { DesignableBar: DesignableBar || Blank, }; } export const Menu: MenuType = observer((props) => { const { onSelect, mode, defaultSelectedKeys, ...others } = props; const { sideMenuRef } = useContext(MenuContainerContext); const schema = useFieldSchema(); const { schema: designableSchema, refresh } = useDesignable(); const designableBar = schema['x-designable-bar']; const history = useHistory(); const renderSideMenu = (selectedKey) => { if (!selectedKey) { return; } if ((mode as any) !== 'mix') { return; } if (!sideMenuRef || !sideMenuRef.current) { return; } const properties = schema.properties[selectedKey].properties; console.log({ selectedKey, properties }); sideMenuRef.current.style.display = properties ? 'block' : 'none'; const newProps = {}; Object.keys(properties || {}).forEach((name) => { newProps[name] = properties[name].toJSON(); }); ReactDOM.render( properties ? ( { const selected = designableSchema.properties[selectedKey]; const diff = subSchema.properties[`${schema.name}.${selectedKey}`]; Object.keys(selected.properties).forEach((name) => { selected.properties[name].parent.removeProperty(name); }); Object.keys(diff.properties).forEach((name) => { if (name.endsWith('-add-new')) { return; } console.log('diff', name) const current = diff.properties[name]; selected.addProperty(current.name, current.toJSON()); }); console.log({selected }) refresh(); }} schema={{ type: 'void', name: `${schema.name}.${selectedKey}`, 'x-component': 'Menu', 'x-designable-bar': designableBar, 'x-component-props': { mode: 'inline', onSelect, }, properties: { ...newProps, [`${uid()}-add-new`]: { type: 'void', 'x-component': 'Menu.AddNew', }, }, }} /> ) : null, sideMenuRef.current, ); }; useMount(() => { const defaultSelectedKey = defaultSelectedKeys ? defaultSelectedKeys[0] : null; renderSideMenu(defaultSelectedKey); }); return ( { console.log('info.key', info.key); renderSideMenu(info.key); onSelect && onSelect(info); }} mode={(mode as any) === 'mix' ? 'horizontal' : mode} /> ); }); const AddNewAction = () => { const { insertBefore } = useDesignable(); return ( { insertBefore({ type: 'void', title: uid(), "x-component": 'Menu.Item', }) }} style={{ minWidth: 150 }}> 新建菜单 新建分组 添加链接 } > ); }; Menu.AddNew = observer((props) => { const { designableBar } = useContext(MenuContext); return designableBar ? ( } > ) : null; }); Menu.Url = observer((props) => { const field = useField(); const schema = useFieldSchema(); const { DesignableBar } = useDesignableBar(); return ( { window.open(props.url); }} icon={props.icon ? : undefined} > {field.title} ); }); Menu.Link = observer((props) => { const history = useHistory(); const field = useField(); const schema = useFieldSchema(); const { DesignableBar } = useDesignableBar(); return ( { history.push(schema.name as string); }} icon={props.icon ? : undefined} > {field.title} ); }); Menu.Item = observer((props: any) => { const { useAction = useDefaultAction, ...others } = props; const { run } = useAction(); const field = useField(); const schema = useFieldSchema(); const { DesignableBar } = useDesignableBar(); return ( { await run(); }} schema={schema} // @ts-ignore eventKey={schema.name} key={schema.name} icon={props.icon ? : undefined} > {field.title} ); }); Menu.SubMenu = observer((props) => { const { DesignableBar } = useDesignableBar(); const schema = useFieldSchema(); const { mode } = useContext(MenuContext); return mode === 'mix' ? ( ) : ( {schema.title} } eventKey={schema.name} key={schema.name} icon={ props.icon ? ( ) : undefined } /> ); }); Menu.Divider = observer(AntdMenu.Divider); function useDesigner() { const field = useField(); } Menu.DesignableBar = (props) => { const field = useField(); const fieldSchema = useFieldSchema(); const [visible, setVisible] = useState(false); const { schema, remove, refresh } = useDesignable(); return (
{ e.stopPropagation(); e.preventDefault(); }} className={'designable-bar-actions'} > { // setVisible(visible); // }} trigger={['click']} overlay={ { const title = uid(); field.title = title; field.componentProps['icon'] = 'DeleteOutlined'; schema['x-component-props'] = schema['x-component-props'] || {}; schema['x-component-props']['icon'] = 'DeleteOutlined'; schema.title = title; fieldSchema.title = title; fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; fieldSchema['x-component-props']['icon'] = 'DeleteOutlined'; refresh(); }} > 修改标题 { Modal.confirm({ title: '删除菜单', content: '确认删除此菜单项吗?', onOk: () => { remove(); }, }); }} > 删除菜单 } >
); }; export default Menu;