yunsii/ant-design-pro-plus

if (!isPathInMenus(location.pathname, originalMenuData)) 有些菜单会返回null,tab就被覆盖了, 要怎么避免呢?

gclsoft opened this issue · 11 comments

 const location = useLocation();
  // if (mode && menuLoading) {
  //  return <PageLoading />;
  // }
  if (mode && routes) {
    const originalMenuData = memoizedOneLocaleRoutes(routes);
    // 有些菜单会返回 null, tab 就被覆盖了, 要怎么避免呢?
    if (!isPathInMenus(location.pathname, originalMenuData)) {
      console.error("mode=",mode)
      // return children!;
    }

    return (
      <RouteTabs
        mode={mode}
        fixed={fixedRouteTabs}
        originalMenuData={originalMenuData}
        animated={false}
      >
        {children as UmiChildren}

        {/*<footer>{footerRender()}</footer>*/}
      </RouteTabs>
    );
  }
  return children;
}

if (!isPathInMenus(location.pathname, originalMenuData)) 有些菜单会返回 null, tab 就被覆盖了, 要怎么避免呢?

我看了看判断逻辑只是比较了一级路由而已。你这个返回 null 的路由不在 BasicLayout 下?或者你把路由定义和返回 null 的路由贴出来看看,不然不好判断。

[
    {
        "createUser": "1123598821738675201",
        "createDept": "1269081986007015426",
        "createTime": "2020-08-03 09:21:44",
        "updateUser": "1123598821738675201",
        "updateTime": "2020-12-02 10:14:23",
        "status": 1,
        "isDeleted": 0,
        "name": "渠道工作站",
        "alias": "/customer/archiving",
        "path": "/customer/archiving",
        "type": 1,
        "action": 3,
        "level": 2,
        "systems": 1,
        "remark": "",
        "isOpen": 0,
        "hasChildren": false,
        "parentName": "",
        "typeName": "",
        "actionName": "",
        "canUp": true,
        "canDown": true,
        "routes": [
            {
                "createUser": "1123598821738675201",
                "createDept": "1269081986007015426",
                "createTime": "2020-08-03 09:25:00",
                "updateUser": "1123598821738675201",
                "updateTime": "2020-09-30 09:15:28",
                "status": 1,
                "isDeleted": 0,
                "name": "渠道工作站",
                "alias": "archiving",
                "path": "/customer/archiving/company",
                "type": 1,
                "action": 3,
                "level": 2,
                "systems": 1,
                "remark": "",
                "isOpen": 0,
                "hasChildren": false,
                "parentName": "",
                "typeName": "",
                "actionName": "",
                "canUp": true,
                "canDown": false
            },
            {
                "createUser": "1123598821738675201",
                "createDept": "1269081986007015426",
                "createTime": "2020-08-26 11:09:12",
                "updateUser": "1123598821738675201",
                "updateTime": "2020-08-28 15:57:27",
                "status": 1,
                "isDeleted": 0,
                "name": "个人报表",
                "alias": "/base/report-form",
                "path": "/base/report-form",
                "type": 1,
                "action": 3,
                "level": 2,
                "systems": 1,
                "remark": "",
                "isOpen": 0,
                "hasChildren": false,
                "parentName": "",
                "typeName": "",
                "actionName": "",
                "canUp": true,
                "canDown": true
            }
        ]
    },

一级的路由是/customer/archiving, 二级的菜单path是/customer/archiving/company就正常,是/base/report-form就不正常, 如上面的json路由一样, 第二个就不正常, 会不显示tab

正常来说 /base/report-form 应该也得 /customer/archiving 前缀的,不然不用标签页功能的话,应该都加载不出这个页面。

      {
        path: '/base',
        routes: [
          { path: '/base/report-form', component: './Base/ReportForm/index' }, // 现场咨询个人报表,预约报表 回访报表 业绩报表
          { path: '/base/append-info', component: './Base/AppendInfo/Append' },
          { path: '/base/default-value', component: './Base/DefaultValue/DefaultValue' },

我把这个/base/report-form移到下面的/base路由下,也是一样加载不出这个页面

现在只支持将 BasicLayout 下标签化展示,你这个都不在一个路由下了吧。要不把完整的路由定义过滤掉冗余字段贴出来看看呢。

image
虽然router.config.js改了,但是菜单配置的必须是要在这里,所以刚才移动了router.config.js等于是没改,菜单比较灵活,有时代码写完都要自由移动, 那是不是只能统一由一级路由,第二级名字写长点, 这样来解决?

自由度过高了,菜单应该是相对固定的状态。而且按照路由匹配规则也不能把 /base/report-form 放到 /customer/archiving 下。我的意见是一级路由可排序,各子路由只能内部排序。要作为标签页的话,得在 BasicLayout 下才行

那确实有移动菜单的需求, 可能会从第二大级菜单移动到第一大级菜单里,这边要怎么做,才能让每个菜单,都能正常打开新标签?

我没理解错的话,都放到 BasicLayout 下应该是可以的。可能画个图或者举个栗子更好一些 😂

我是放在BasicLayout文件里的:

import React, { Suspense } from 'react';
import { Layout } from 'antd';
import DocumentTitle from 'react-document-title';
import { connect } from 'dva';
import { ContainerQuery } from 'react-container-query';
import classNames from 'classnames';
import Media from 'react-media';
import logo from '../assets/img/logo.png';
import Footer from './Footer';
import Header from './Header';
import Context from './MenuContext';
import SiderMenu from '@/components/SiderMenu';
import getPageTitle from '@/utils/getPageTitle';
import styles from './BasicLayout.less';
import RouteTabsLayout from './RouteTabsLayout';
import Websocket from 'react-websocket';
import { getOrgid, getUserId } from '@/utils/authority';
import Func from '@/utils/Func';
//import InfoAreaEdit from '@/pages/Customer/Archiving/edit';
import router from 'umi/router';

const { Content } = Layout;
//import webSocket from 'socket.io-client';

/***
 * 设置响应式组件配置
 * e.g. 当浏览器宽度为574,container会配置一个'screen-xs'的class,方便响应
 */
const query = {
  'screen-xs': {
    maxWidth: 575,
  },
  'screen-sm': {
    minWidth: 576,
    maxWidth: 767,
  },
  'screen-md': {
    minWidth: 768,
    maxWidth: 991,
  },
  'screen-lg': {
    minWidth: 992,
    maxWidth: 1199,
  },
  'screen-xl': {
    minWidth: 1200,
    maxWidth: 1599,
  },
  'screen-xxl': {
    minWidth: 1600,
  },
};

class BasicLayout extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
    };
  }

  componentDidMount() {
    const {
      dispatch,

      route: { routes, path, authority },
    } = this.props;

    // 全局基础请求,进入即请求
    dispatch({
      type: 'user/fetchCurrent',
    });
    dispatch({
      type: 'setting/getSetting',
    });
    dispatch({
      type: 'menu/fetchMenuData',
      payload: { routes, path, authority },
    });
    dispatch({
      type: 'global/fetchNoticesStat',
    });
    //this.connectWebSocket();
  }

  connectWebSocket = () => {
    var options = {};
    options.forceNew = true;

    let ws = require('socket.io-client')('http://192.168.16.10:2120', options,
    );
    //连接后登录
    ws.on('connect', message => {
      console.log('###login:' + 6038);
      ws.emit('login', '6038');//seatNo);//6038
    });

    ws.on('new_msg', msg => {
      console.log('###new_msg:' + msg);
      this.OnCallIn('6038', msg);
    });
  };

  //来电 s1座席信息  s2是来电客户电话号码
  OnCallIn(s1, s2) {
    var fnumber = '6038';
    var cuid = 'XUcxXx3I8ZzgUwsBAAqiihO33n8=';
    //console.log("")
    //if(s1==fnumber){
    this.fPopUpCallDlg(s1, s2, fnumber, cuid);
    //  }
  }

  //打开来电弹屏
  fPopUpCallDlg(s1, s2, s3, s4) {
    //去0
    var inComeTel = '';
    var cusTel = '';
    if (s2.indexOf('|') != -1) {
      cusTel = s2.split('|')[0];
      inComeTel = s2.split('|')[1];
    } else {
      cusTel = s2;
    }
    if (cusTel.length > 11) {
      cusTel = cusTel.substring(cusTel.length - 11, cusTel.length);
    }


    console.log('$$$$cusTel=' + cusTel + ',inComeTel=' + inComeTel);
    this.openBuildChannelPage(cusTel);
  }

  openBuildChannelPage(cusTel, inComeTel) {
    //const { host } = window.location; // `http://127.0.0.1/blade-bi/report/show#`;
    const orgId = getOrgid();

    // let baseURL = host.startsWith('http') ? host : `http://${host}`;
    let orgType = 'company';
    if (Func.isEmpty(orgId)) {
      orgType = 'area';
    }
    router.push(`/customer/archiving/${orgType}/${cusTel}`);
    // const iframeSrc = `${baseURL}/#;
    // window.open(iframeSrc, '_blank');
  }

  // 上下文配置,同步参数
  getContext() {
    const { location, breadcrumbNameMap } = this.props;
    return {
      location,
      breadcrumbNameMap,
    };
  }

  // 设置左侧栏的宽度,折叠/非折叠的宽度
  getLayoutStyle = () => {
    const { fixSiderbar, isMobile, collapsed, layout } = this.props;
    if (fixSiderbar && layout !== 'topmenu' && !isMobile) {
      return {
        // paddingLeft: collapsed ? '80px' : '256px',
        paddingLeft: collapsed ? '0px' : '256px',
      };
    }
    return null;
  };

  // 触发折叠左侧栏宽度
  handleMenuCollapse = collapsed => {
    const { dispatch } = this.props;
    dispatch({
      type: 'global/changeLayoutCollapsed',
      payload: collapsed,
    });
  };

  setVisible(data) {
    this.setState({ visible: data });
  }

  // 处理收到的websocket信息
  handleData(data) {
    const {
      dispatch,
      route: { routes, path, authority },
    } = this.props;

    let result;
    try {
      result = JSON.parse(data);
    } catch (e) {
      console.log(e);
    }

    dispatch({
      type: 'global/addNotice',
      payload: result,
    });
  }

  // 判断是否允许显示右侧的网站风格设置
  renderSettingDrawer = () => {
    return null;
  };

  render() {
    const {
      navTheme,
      layout: PropsLayout,
      children,
      location: { pathname },
      isMobile,
      menuData,
      breadcrumbNameMap,
      fixedHeader,
    } = this.props;

    const { visible } = this.state;

    const isTop = PropsLayout === 'topmenu';
    const contentStyle = !fixedHeader ? { paddingTop: 0 } : {};
    const layout = (
      <Layout>
        {isTop && !isMobile ? null : (
          <SiderMenu
            logo={logo}
            theme={navTheme}
            onCollapse={this.handleMenuCollapse}
            menuData={menuData}
            isMobile={isMobile}
            {...this.props}
          />
        )}
        <Layout
          className={styles.layoutMain}
          style={{
            ...this.getLayoutStyle(),
            minHeight: '100vh',
          }}
        >
          <Header
            menuData={menuData}
            handleMenuCollapse={this.handleMenuCollapse}
            logo={logo}
            isMobile={isMobile}
            {...this.props}
          />
          <Content className={classNames(styles.content, isTop ? '' : styles.siderContent)} style={contentStyle}>
            {/*<TabPages {...this.props} homePageKey='/dashboard/workplace'  />*/}
            {/*<TabPages {...this.props} maxTab="5" preventReload remberRefresh animated homePage="/dashboard/analysis" />*/}

            {/* @TODO 判断是否有访问对应路由的权限,如果没有无法进入 */}
            {/*<Authorized authority={authorized!.authority} noMatch={noMatch}>*/}
            <RouteTabsLayout
              mode='route'
              fixedRouteTabs='false'
              menuLoading='false'
              routes={menuData}
            >
              {children}
            </RouteTabsLayout>

            {/*<Modal visible={!visible} onCancel={() => this.setVisible(false)} destroyOnClose getContainer={() => document.body}>*/}
            {/*   <InfoAreaEdit orgType={'1'} tel={'18823233232'}></InfoAreaEdit>*/}
            {/*</Modal>*/}


            {/*</Authorized>*/}
          </Content>
          <Footer/>
        </Layout>
      </Layout>
    );
    return (
      <React.Fragment>
        <DocumentTitle title={getPageTitle(pathname, breadcrumbNameMap)}>
          <ContainerQuery query={query}>
            {params => (
              <Context.Provider value={this.getContext()}>
                <div className={classNames(params)}>{layout}</div>
                {
                  getUserId() &&
                  <Websocket
                    url={WEBSOCKET_URL + '/msgHandler/ID:' + getUserId()}
                    onMessage={this.handleData.bind(this)}
                  />
                }
              </Context.Provider>
            )}
          </ContainerQuery>
        </DocumentTitle>
        <Suspense fallback={null}>{this.renderSettingDrawer()}</Suspense>
      </React.Fragment>
    );
  }
}

export default connect(({ global, setting, menu: menuModel }) => ({
  collapsed: global.collapsed,
  layout: setting.layout,
  menuData: menuModel.menuData,
  breadcrumbNameMap: menuModel.breadcrumbNameMap,
  ...setting,
}))(props => (
  <Media query="(max-width: 599px)">
    {/* 通过Media组件,判断是否为手机界面,顺带传入到layout中 */}
    {isMobile => <BasicLayout {...props} isMobile={isMobile}/>}
  </Media>
));

RouteTabsLayout是放在这个文件里的

我的意思你刚说的你期望的路由要怎么调整也能展示标签页?根据路由配置举例更好一些。