umi 架子怎么搭

409 阅读1分钟

umi 一般的架子

routes.ts

export default [
    {
      path: '/',
      // 推荐自己写 layouts 作为根路由
      component: '@/layouts',
      // 子路由
      routes: [
        {
          path: '/level1',
          name: '一级',
          // 面包屑
          breadcrumbKey: 'level1',
          routes: [
            {
              path: '/level1/2',
              name: '二级',
              breadcrumbKey: '2',
              component: '@/pages/...',
            }
          ],
        },
      ],
    },
];

面包屑组件

// process.env.BASE 有些项目会有额外的url,或者项目是作为应用的微应用,也会增加一些url
export default (props) => {
    const getPath = () => location.pathname.substr(process.env.BASE?.length || 0);
    // route 数组
    const pathSplits = getPath().substr(1).split('/');
  
    const mapRoutes = (ary: any[]) => {
      const map = new Map();
  
      const traverse = (route: any) => {
        // breadcrumbKey 在这使用
        const { breadcrumbKey = '', routes = [] } = route;
        if (!breadcrumbKey)
          throw 'every route should have a breadcrumbKey to map view';
  
        map.set(breadcrumbKey, route);
  
        if (routes.length) routes.forEach((i: any) => traverse(i));
      };
  
      ary.forEach((i) => traverse(i));
  
      return map;
    };
  
    const map = React.useMemo(() => mapRoutes(props.routes), []);
  
    const breadcrumbClick = (path, flag) => {
      if (flag || !path) return;
      history.push(path);
    };
  
    return (
      <Breadcrumb>
        {pathSplits.map((i, index) => {
          const r = map.get(i) || {};
          // 第一个 和 最后一个样式做特殊处理,也不能点击;
          const s = index === 0;
          const e = index === pathSplits.length - 1;
          return (
            <Breadcrumb.Item
              key={i}
              onClick={() => breadcrumbClick(r.path, s || e)}
            >
              <span
                className={
                  s
                    ? styles.breadItemStart
                    : e
                    ? styles.breadItemEnd
                    : styles.breadItem
                }
              >
                {r.name || i}
              </span>
            </Breadcrumb.Item>
          );
        })}
      </Breadcrumb>
    );
};

layouts

<ProLayout
    route={{ routes: renderRoutes }}
    subMenuItemRender={(_: any, node: React.ReactNode) => node}
    menuItemRender={(itemInfo, node) => <Link to={itemInfo.path}>{node}</Link>}
    menuProps={{
        selectedKeys: [path],
        openKeys: subs,
        onOpenChange: handleOpenChange,
    }}
    headerContentRender={headerContentRender}
    title={title}
    logo={logo}
    fixSiderbar={fixSiderbar}
    fixedHeader={fixedHeader}
>
        {children}
</ProLayout>

项目配置

import routes from './routes';

export default defineConfig({
    routes,
    qiankun: {
      slave: {},
    },
    define: {
        'process.env.ENV': 'dev',
        BASE_REQUEST: '/api',
        'process.env.BASE': '',
    },
    publicPath: '/metadata-web/',
    antd: {},
    nodeModulesTransform: {
      type: 'none',
    },
    fastRefresh: {},
    links: [{ rel: 'icon', href }],
    proxy: {
        '/api': {
          target: 'http://localhost:8080',
          changeOrigin: true,
          pathRewrite: {
            '^/api': '',
          },
        },
    },
})

request

const request = extend({});

// 请求拦截
request.interceptors.request.use((url, options) => {
  const headers = options.headers;

  return {
    // 代理
    url: `${BASE_REQUEST}${url}`,
    options: {
      ...options,
      headers: {
        ...headers,
        // token校验
        token:
          localStorage.getItem('token') ||
          'dc41d433-f01f-4cc4-af16-340c6d74700a',
      },
    },
  };
});

request.interceptors.response.use(async (response, option) => {
  // 响应头
  const contentType = response.headers.get('Content-type');

  // 特殊响应头处理
  if (contentType === 'application/octet-stream') {
    const blob = await response.blob();
    return {
      data: blob,
      code: 200,
    };
  }

  // 请求失败(接口错误)
  if (response.status !== 200) {
    message.error('error');

    return {
      code: -1,
    };
  }

  const res = await response.clone().json();
  // 响应码错误
  if (res.code !== 200) message.error(res.message || '请求错误');

  return res;
});