fix: menu item highlight
This commit is contained in:
		
							parent
							
								
									b7be09efd7
								
							
						
					
					
						commit
						9560276fa1
					
				@ -45,6 +45,7 @@ import {
 | 
				
			|||||||
} from './SiteTitle';
 | 
					} from './SiteTitle';
 | 
				
			||||||
import { AuthProvider } from './Auth';
 | 
					import { AuthProvider } from './Auth';
 | 
				
			||||||
import { Helmet } from 'react-helmet';
 | 
					import { Helmet } from 'react-helmet';
 | 
				
			||||||
 | 
					import { MenuSelectedKeysContext } from '../../schemas/menu';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function DesignableToggle() {
 | 
					function DesignableToggle() {
 | 
				
			||||||
  const { designable, setDesignable } = useDesignableSwitchContext();
 | 
					  const { designable, setDesignable } = useDesignableSwitchContext();
 | 
				
			||||||
@ -77,17 +78,58 @@ function LayoutWithMenu(props: LayoutWithMenuProps) {
 | 
				
			|||||||
  const { title } = useSystemSettings();
 | 
					  const { title } = useSystemSettings();
 | 
				
			||||||
  const [activeKey, setActiveKey] = useState(match.params.name);
 | 
					  const [activeKey, setActiveKey] = useState(match.params.name);
 | 
				
			||||||
  const { setPageTitle } = usePageTitleContext();
 | 
					  const { setPageTitle } = usePageTitleContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [selectedKeys, setSelectedKeys] = useState(defaultSelectedKeys);
 | 
				
			||||||
  const onSelect = (info) => {
 | 
					  const onSelect = (info) => {
 | 
				
			||||||
    if (!info.schema) {
 | 
					    if (!info.schema) {
 | 
				
			||||||
      setActiveKey(null);
 | 
					      setActiveKey(null);
 | 
				
			||||||
    } else if (info.schema['x-component'] === 'Menu.SubMenu') {
 | 
					    } else if (info.schema['x-component'] === 'Menu.SubMenu') {
 | 
				
			||||||
 | 
					      const findMenuItem = (schema: Schema) => {
 | 
				
			||||||
 | 
					        const first = Object.values(schema.properties || {}).shift();
 | 
				
			||||||
 | 
					        if (!first) {
 | 
				
			||||||
 | 
					          return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (['Menu.Link', 'Menu.URL'].includes(first['x-component'])) {
 | 
				
			||||||
 | 
					          return first;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return findMenuItem(first);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      console.log('info.schema', findMenuItem(info.schema));
 | 
				
			||||||
      // 实际应该取第一个子元素
 | 
					      // 实际应该取第一个子元素
 | 
				
			||||||
      setActiveKey(null);
 | 
					      const node = findMenuItem(info.schema);
 | 
				
			||||||
 | 
					      setActiveKey(node?.key);
 | 
				
			||||||
 | 
					      if (node?.key) {
 | 
				
			||||||
 | 
					        history.push(`/admin/${node?.key}`);
 | 
				
			||||||
 | 
					        const keys = [node?.name];
 | 
				
			||||||
 | 
					        let parent = node?.parent;
 | 
				
			||||||
 | 
					        while (parent) {
 | 
				
			||||||
 | 
					          if (parent['x-component'] === 'Menu') {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          keys.unshift(parent.name);
 | 
				
			||||||
 | 
					          parent = parent.parent;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setSelectedKeys(keys);
 | 
				
			||||||
 | 
					        if (node.title) {
 | 
				
			||||||
 | 
					          setPageTitle(node.title);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      setActiveKey(info.schema.key);
 | 
					      setActiveKey(info.schema.key);
 | 
				
			||||||
      history.push(`/admin/${info.schema.key}`);
 | 
					      history.push(`/admin/${info.schema.key}`);
 | 
				
			||||||
      if (info.schema.title) {
 | 
					      if (info.schema.title) {
 | 
				
			||||||
        setPageTitle(info.schema.title);
 | 
					        setPageTitle(info.schema.title);
 | 
				
			||||||
 | 
					        const keys = [info.schema?.name];
 | 
				
			||||||
 | 
					        let parent = info.schema?.parent;
 | 
				
			||||||
 | 
					        while (parent) {
 | 
				
			||||||
 | 
					          if (parent['x-component'] === 'Menu') {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          keys.unshift(parent.name);
 | 
				
			||||||
 | 
					          parent = parent.parent;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setSelectedKeys(keys);
 | 
				
			||||||
 | 
					        // setSelectedKeys([info.schema.name]);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@ -97,20 +139,26 @@ function LayoutWithMenu(props: LayoutWithMenuProps) {
 | 
				
			|||||||
  const onMenuItemRemove = () => {
 | 
					  const onMenuItemRemove = () => {
 | 
				
			||||||
    history.push(`/admin`);
 | 
					    history.push(`/admin`);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  console.log({ activeKey });
 | 
					  console.log({ activeKey, selectedKeys });
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Layout>
 | 
					    <Layout>
 | 
				
			||||||
      <Layout.Header className={'site-header'} style={{ display: 'flex' }}>
 | 
					      <Layout.Header className={'site-header'} style={{ display: 'flex' }}>
 | 
				
			||||||
        <SiteTitle />
 | 
					        <SiteTitle />
 | 
				
			||||||
 | 
					        <MenuSelectedKeysContext.Provider value={selectedKeys}>
 | 
				
			||||||
          <SchemaRenderer
 | 
					          <SchemaRenderer
 | 
				
			||||||
            schema={schema}
 | 
					            schema={schema}
 | 
				
			||||||
            scope={{
 | 
					            scope={{
 | 
				
			||||||
              sideMenuRef,
 | 
					              sideMenuRef,
 | 
				
			||||||
              onSelect,
 | 
					              onSelect,
 | 
				
			||||||
              onMenuItemRemove,
 | 
					              onMenuItemRemove,
 | 
				
			||||||
            selectedKeys: defaultSelectedKeys.filter(Boolean),
 | 
					              getSelectedKeys: () => {
 | 
				
			||||||
 | 
					                console.log('getSelectedKeys', schema);
 | 
				
			||||||
 | 
					                return selectedKeys.filter(Boolean);
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              selectedKeys: selectedKeys.filter(Boolean),
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
 | 
					        </MenuSelectedKeysContext.Provider>
 | 
				
			||||||
        <DesignableToggle />
 | 
					        <DesignableToggle />
 | 
				
			||||||
        <Database />
 | 
					        <Database />
 | 
				
			||||||
        <Permissions />
 | 
					        <Permissions />
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,14 @@ export const linkTo: FieldOptions = {
 | 
				
			|||||||
      'x-decorator': 'FormItem',
 | 
					      'x-decorator': 'FormItem',
 | 
				
			||||||
      'x-component': 'Select',
 | 
					      'x-component': 'Select',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    // 'uiSchema.x-component-props.fieldNames.label': {
 | 
				
			||||||
 | 
					    //   type: 'string',
 | 
				
			||||||
 | 
					    //   title: '要显示的标题字段',
 | 
				
			||||||
 | 
					    //   required: true,
 | 
				
			||||||
 | 
					    //   'x-reactions': ['{{useAsyncDataSource(loadCollectionFields)}}'],
 | 
				
			||||||
 | 
					    //   'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					    //   'x-component': 'Select',
 | 
				
			||||||
 | 
					    // },
 | 
				
			||||||
    'uiSchema.x-component-props.multiple': {
 | 
					    'uiSchema.x-component-props.multiple': {
 | 
				
			||||||
      type: 'boolean',
 | 
					      type: 'boolean',
 | 
				
			||||||
      'x-content': '允许关联多条记录',
 | 
					      'x-content': '允许关联多条记录',
 | 
				
			||||||
 | 
				
			|||||||
@ -82,6 +82,10 @@ export const MenuContext = createContext<MenuContextProps>(null);
 | 
				
			|||||||
const SideMenu = (props: any) => {
 | 
					const SideMenu = (props: any) => {
 | 
				
			||||||
  const { selectedKey, defaultSelectedKeys, onSelect, path } = props;
 | 
					  const { selectedKey, defaultSelectedKeys, onSelect, path } = props;
 | 
				
			||||||
  const { schema } = useDesignable();
 | 
					  const { schema } = useDesignable();
 | 
				
			||||||
 | 
					  const [selectedKeys, setSelectedKeys] = useState(defaultSelectedKeys);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    setSelectedKeys(defaultSelectedKeys);
 | 
				
			||||||
 | 
					  }, [defaultSelectedKeys]);
 | 
				
			||||||
  if (!selectedKey) {
 | 
					  if (!selectedKey) {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -89,10 +93,17 @@ const SideMenu = (props: any) => {
 | 
				
			|||||||
  if (!child || child['x-component'] !== 'Menu.SubMenu') {
 | 
					  if (!child || child['x-component'] !== 'Menu.SubMenu') {
 | 
				
			||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <MenuModeContext.Provider value={'inline'}>
 | 
					    <MenuModeContext.Provider value={'inline'}>
 | 
				
			||||||
      <AntdMenu mode={'inline'} onSelect={onSelect}>
 | 
					      <AntdMenu
 | 
				
			||||||
 | 
					        mode={'inline'}
 | 
				
			||||||
 | 
					        onSelect={onSelect}
 | 
				
			||||||
 | 
					        onOpenChange={(openKeys) => {
 | 
				
			||||||
 | 
					          setSelectedKeys(openKeys);
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					        openKeys={selectedKeys}
 | 
				
			||||||
 | 
					        selectedKeys={selectedKeys}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
        <RecursionField schema={child} onlyRenderProperties />
 | 
					        <RecursionField schema={child} onlyRenderProperties />
 | 
				
			||||||
        <Menu.AddNew key={uid()} path={[...path, selectedKey]}>
 | 
					        <Menu.AddNew key={uid()} path={[...path, selectedKey]}>
 | 
				
			||||||
          <Button
 | 
					          <Button
 | 
				
			||||||
@ -109,15 +120,19 @@ const SideMenu = (props: any) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const MenuSelectedKeysContext = createContext<any>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Menu: any = observer((props: any) => {
 | 
					export const Menu: any = observer((props: any) => {
 | 
				
			||||||
  const {
 | 
					  const {
 | 
				
			||||||
    mode,
 | 
					    mode,
 | 
				
			||||||
    onSelect,
 | 
					    onSelect,
 | 
				
			||||||
    sideMenuRef,
 | 
					    sideMenuRef,
 | 
				
			||||||
    defaultSelectedKeys = [],
 | 
					    defaultSelectedKeys: keys,
 | 
				
			||||||
 | 
					    getSelectedKeys,
 | 
				
			||||||
    onRemove,
 | 
					    onRemove,
 | 
				
			||||||
    ...others
 | 
					    ...others
 | 
				
			||||||
  } = props;
 | 
					  } = props;
 | 
				
			||||||
 | 
					  const defaultSelectedKeys = useContext(MenuSelectedKeysContext);
 | 
				
			||||||
  const { root, schema, insertAfter, remove } = useDesignable();
 | 
					  const { root, schema, insertAfter, remove } = useDesignable();
 | 
				
			||||||
  const moveToAfter = (path1, path2) => {
 | 
					  const moveToAfter = (path1, path2) => {
 | 
				
			||||||
    if (!path1 || !path2) {
 | 
					    if (!path1 || !path2) {
 | 
				
			||||||
@ -163,7 +178,7 @@ export const Menu: any = observer((props: any) => {
 | 
				
			|||||||
  }, [selectedKey]);
 | 
					  }, [selectedKey]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [dragOverlayContent, setDragOverlayContent] = useState('');
 | 
					  const [dragOverlayContent, setDragOverlayContent] = useState('');
 | 
				
			||||||
  console.log('onRemove', onRemove);
 | 
					  // console.log('defaultSelectedKeys', defaultSelectedKeys, getSelectedKeys);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <MenuContext.Provider value={{ schema, onRemove }}>
 | 
					    <MenuContext.Provider value={{ schema, onRemove }}>
 | 
				
			||||||
      <DndContext
 | 
					      <DndContext
 | 
				
			||||||
@ -193,6 +208,7 @@ export const Menu: any = observer((props: any) => {
 | 
				
			|||||||
        )}
 | 
					        )}
 | 
				
			||||||
        <MenuModeContext.Provider value={mode}>
 | 
					        <MenuModeContext.Provider value={mode}>
 | 
				
			||||||
          <AntdMenu
 | 
					          <AntdMenu
 | 
				
			||||||
 | 
					            defaultOpenKeys={defaultSelectedKeys}
 | 
				
			||||||
            defaultSelectedKeys={defaultSelectedKeys}
 | 
					            defaultSelectedKeys={defaultSelectedKeys}
 | 
				
			||||||
            {...others}
 | 
					            {...others}
 | 
				
			||||||
            mode={mode === 'mix' ? 'horizontal' : mode}
 | 
					            mode={mode === 'mix' ? 'horizontal' : mode}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user