Преглед на файлове

refactor: upgrade to umi4 and refactor related code

lanjianrong преди 3 години
родител
ревизия
ae167cab11
променени са 74 файла, в които са добавени 492 реда и са изтрити 1553 реда
  1. 13 5
      .eslintrc.js
  2. 6 10
      .prettierrc.js
  3. 4 3
      .stylelintrc.js
  4. 0 5
      README.md
  5. 0 17
      config/config.dev.ts
  6. 62 53
      config/config.ts
  7. 0 1
      config/defaultSettings.ts
  8. 0 175
      mock/listTableList.ts
  9. 0 107
      mock/notices.ts
  10. 0 5
      mock/route.ts
  11. 0 203
      mock/user.ts
  12. 35 71
      package.json
  13. 0 5
      public/pro_icon.svg
  14. 64 107
      src/app.tsx
  15. 1 1
      src/components/Footer/index.tsx
  16. 63 65
      src/components/NoticeIcon/index.tsx
  17. 6 10
      src/components/RightContent/AvatarDropdown.tsx
  18. 1 1
      src/components/RightContent/index.tsx
  19. 0 61
      src/e2e/baseLayout.e2e.js
  20. 0 0
      src/favicon.ico
  21. 1 2
      src/global.tsx
  22. 2 4
      src/hooks/core/useWebSocketFn.ts
  23. 0 22
      src/manifest.json
  24. 1 1
      src/pages/404.tsx
  25. 8 17
      src/pages/Institutions/Company/Detail/components/Organization.tsx
  26. 1 1
      src/pages/Institutions/Company/Detail/components/OrganizationModal.tsx
  27. 1 1
      src/pages/Institutions/Company/Detail/components/Role.tsx
  28. 6 7
      src/pages/Institutions/Company/Detail/components/Staff.tsx
  29. 1 1
      src/pages/Institutions/Company/Detail/index.tsx
  30. 2 2
      src/pages/Institutions/Company/List/components/CompanyDrawer.tsx
  31. 2 4
      src/pages/Institutions/Company/List/index.tsx
  32. 2 2
      src/pages/Institutions/Staff/components/StaffDetail.tsx
  33. 1 1
      src/pages/Institutions/Staff/index.tsx
  34. 1 1
      src/pages/Institutions/model.ts
  35. 2 5
      src/pages/Permission/Role/components/ConnectModal/index.tsx
  36. 9 25
      src/pages/Permission/Role/components/PermTabs/index.tsx
  37. 4 15
      src/pages/Permission/Role/components/RoleLeftMenu/index.tsx
  38. 7 9
      src/pages/Permission/Role/index.tsx
  39. 3 7
      src/pages/Project/Created/index.tsx
  40. 1 1
      src/pages/Project/Management/Detail/components/AuditPerm.tsx
  41. 3 8
      src/pages/Project/Management/Detail/components/ProjectInfo.tsx
  42. 2 4
      src/pages/Project/Management/Detail/components/RolePerm.tsx
  43. 1 1
      src/pages/Project/Management/Detail/index.tsx
  44. 2 2
      src/pages/Project/Management/List/components/ProjectModal.tsx
  45. 7 16
      src/pages/Project/Management/List/components/TreeNodeSelect.tsx
  46. 3 5
      src/pages/Project/Management/List/index.tsx
  47. 1 1
      src/pages/Project/Verification/Detail/Flow/components/Drawer/ParticipantCard.tsx
  48. 3 9
      src/pages/Project/Verification/Detail/Flow/components/Drawer/index.tsx
  49. 1 1
      src/pages/Project/Verification/Detail/Flow/index.tsx
  50. 3 10
      src/pages/Project/Verification/index.tsx
  51. 1 1
      src/pages/Project/model.ts
  52. 1 1
      src/pages/Schema/Base/components/Designable/index.tsx
  53. 1 1
      src/pages/Schema/Base/components/Designable/widgets/ActionsWidget.tsx
  54. 3 5
      src/pages/Schema/Base/detail.tsx
  55. 3 3
      src/pages/Schema/Base/index.tsx
  56. 1 1
      src/pages/Schema/Base/model.ts
  57. 3 9
      src/pages/Schema/Budget/index.tsx
  58. 8 18
      src/pages/Schema/Option/Components/LeftMenu.tsx
  59. 5 13
      src/pages/Schema/Option/index.tsx
  60. 3 9
      src/pages/System/AdminUpdate/index.tsx
  61. 1 1
      src/pages/System/Setting/index.tsx
  62. 0 235
      src/pages/document.ejs
  63. 30 64
      src/pages/user/Login/index.tsx
  64. 0 65
      src/service-worker.js
  65. 5 15
      src/services/api/institution.ts
  66. 1 1
      src/services/api/login.ts
  67. 2 6
      src/services/api/project.ts
  68. 1 1
      src/services/api/schema.ts
  69. 1 1
      src/services/api/store.ts
  70. 1 1
      src/services/api/system.ts
  71. 3 10
      src/services/api/user.ts
  72. 1 1
      src/services/permission.ts
  73. 4 1
      src/utils/consts.ts
  74. 77 0
      unocss.config.ts

+ 13 - 5
.eslintrc.js

@@ -1,10 +1,7 @@
-// eslint-disable-next-line no-undef
 module.exports = {
-  // eslint-disable-next-line no-undef
-  extends: [require.resolve('@umijs/fabric/dist/eslint')],
+  extends: require.resolve('@umijs/max/eslint'),
   globals: {
-    ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
-    page: true
+    REACT_APP_ENV: true
   },
   rules: {
     semi: ['error', 'never'],
@@ -25,6 +22,17 @@ module.exports = {
       }
     ],
     'react-hooks/exhaustive-deps': 0,
+    'no-unused-expressions': [
+      'error',
+      {
+        allowShortCircuit: true
+      }
+    ],
     '@typescript-eslint/no-unused-expressions': 0
+  },
+  settings: {
+    react: {
+      version: 'detect'
+    }
   }
 }

+ 6 - 10
.prettierrc.js

@@ -1,7 +1,4 @@
-const fabric = require('@umijs/fabric');
-
 module.exports = {
-  ...fabric.prettier,
   semi: false,
   // quoteProps: 'consistent',
   htmlWhitespaceSensitivity: 'ignore',
@@ -9,8 +6,7 @@ module.exports = {
   trailingComma: 'none',
   bracketSpacing: true,
   arrowParens: 'avoid',
-
-  printWidth: 100,
+  printWidth: 110,
   tabWidth: 2,
   singleQuote: true,
   quoteProps: 'as-needed',
@@ -26,8 +22,8 @@ module.exports = {
     {
       files: '*.md',
       options: {
-        tabWidth: 2,
-      },
-    },
-  ],
-};
+        tabWidth: 2
+      }
+    }
+  ]
+}

+ 4 - 3
.stylelintrc.js

@@ -1,6 +1,5 @@
 module.exports = {
-  extends: [require.resolve('@umijs/fabric/dist/stylelint')],
-  customSyntax: 'postcss-less',
+  extends: require.resolve('@umijs/max/stylelint'),
   rules: {
     indentation: 2,
     'block-no-empty': null,
@@ -10,7 +9,9 @@ module.exports = {
     'rule-empty-line-before': null,
     'unit-no-unknown': null,
     'selector-max-compound-selectors': 5,
+    'color-hex-length': 'long',
     'at-rule-no-unknown': null,
-    'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global'] }]
+    'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global'] }],
+    'no-descending-specificity': null
   }
 }

+ 0 - 5
README.md

@@ -1,5 +0,0 @@
-## 启动项目
-
-`npm run dev`
-
-## 端口: localhost:8090

+ 0 - 17
config/config.dev.ts

@@ -1,17 +0,0 @@
-// https://umijs.org/config/
-import { defineConfig } from 'umi'
-export default defineConfig({
-  plugins: [
-    // https://github.com/zthxxx/react-dev-inspector
-    'react-dev-inspector/plugins/umi/react-inspector'
-  ],
-  // https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
-  inspectorConfig: {
-    exclude: [],
-    babelPlugins: [],
-    babelOptions: {}
-  }
-  // devServer: {
-  //   port: 8080
-  // }
-})

+ 62 - 53
config/config.ts

@@ -1,69 +1,78 @@
 // https://umijs.org/config/
-import { defineConfig } from 'umi'
-import { join } from 'path'
+
+const prodGzipList = ['js', 'css', 'html']
+
+import { defineConfig } from '@umijs/max'
 import defaultSettings from './defaultSettings'
 import proxy from './proxy'
 import routes from './routes'
-import WindiCSSPlugin from 'windicss-webpack-plugin'
 const { REACT_APP_ENV } = process.env
-
 export default defineConfig({
+  plugins: [require.resolve('@umijs/plugins/dist/unocss')],
+  npmClient: 'pnpm',
   hash: true,
-  antd: {},
-  dva: {
-    hmr: true
+  antd: { import: true },
+  model: {},
+  moment2dayjs: {},
+  request: {},
+  initialState: {},
+  access: {},
+  dva: {},
+  mfsu: {},
+  srcTranspiler: 'esbuild',
+  fastRefresh: true,
+  unocss: {
+    watch: ['src/pages/**/*.{jsx,tsx,less}', 'src/components/**/*.{jsx,tsx,less}'] // 添加其他包含 unocss 的 classname 的文件目录
   },
-  layout: {
-    // https://umijs.org/zh-CN/plugins/plugin-layout
-    locale: true,
-    siderWidth: 208,
-    ...defaultSettings
-  },
-  // https://umijs.org/zh-CN/plugins/plugin-locale
+  // Fast Refresh 热更新
+  theme: {},
+  layout: {},
   locale: {
-    // default zh-CN
     default: 'zh-CN',
-    antd: true,
-    // default true, when it is true, will use `navigator.language` overwrite default
-    baseNavigator: true
-  },
-  dynamicImport: {
-    loading: '@ant-design/pro-layout/es/PageLoading'
+    antd: false,
+    baseNavigator: false
   },
-  targets: {
-    ie: 11
-  },
-  // request: { dataField: 'data' },
-  // umi routes: https://umijs.org/docs/routing
+  define: { REACT_APP_ENV: REACT_APP_ENV || false },
+  targets: { ie: 11 },
   routes,
-  // Theme for antd: https://ant.design/docs/react/customize-theme-cn
-  theme: {
-    'primary-color': defaultSettings.primaryColor
-  },
-  // esbuild is father build tools
-  // https://umijs.org/plugins/plugin-esbuild
-  esbuild: {},
   title: false,
-  ignoreMomentLocale: true,
   proxy: proxy[REACT_APP_ENV || 'dev'],
-  manifest: {
-    basePath: '/'
-  },
-  chainWebpack(config) {
-    config.plugin('windicss').use(WindiCSSPlugin)
-  },
+  manifest: { basePath: '/' },
   extraBabelPlugins: [
-    ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'antd'],
-    [
-      'babel-plugin-import',
-      { libraryName: '@formily/antd', libraryDirectory: 'esm', style: true },
-      '@formily/antd'
-    ]
-  ],
-  // Fast Refresh 热更新
-  fastRefresh: {},
-  nodeModulesTransform: { type: 'none' },
-  // mfsu: {},
-  // webpack5: {},
-  exportStatic: {}
+    '@babel/plugin-proposal-nullish-coalescing-operator',
+    '@babel/plugin-proposal-optional-chaining',
+    ['import', { libraryName: '@formily/antd', libraryDirectory: 'esm', style: true }, '@formily/antd']
+  ]
+  // chainWebpack(config, { env }) {
+  //   if (env === 'production') {
+  //     config.merge({
+  //       optimization: {
+  //         minimize: true,
+  //         splitChunks: {
+  //           chunks: 'all',
+  //           minSize: 30000,
+  //           minChunks: 2,
+  //           automaticNameDelimiter: '.',
+  //           cacheGroups: {
+  //             vendor: {
+  //               name: 'vendors',
+  //               test: ({ resource }) => /^.(?=react).$/.test(resource),
+  //               chunks: 'all',
+  //               priority: 20
+  //             }
+  //           }
+  //         }
+  //       }
+  //     })
+  //     config.plugin('compression-webpack-plugin').use(
+  //       new CompressionWebpackPlugin({
+  //         // filename: 文件名称,这里我们不设置,让它保持和未压缩的文件同一个名称
+  //         algorithm: 'gzip', // 指定生成gzip格式
+  //         test: new RegExp('\\.(' + prodGzipList.join('|') + ')$'), // 匹配哪些格式文件需要压缩
+  //         threshold: 10000, //对超过10k的数据进行压缩
+  //         minRatio: 0.6 // 压缩比例,值为0 ~ 1
+  //       })
+  //     )
+  //   }
+  // }
 })

+ 0 - 1
config/defaultSettings.ts

@@ -14,7 +14,6 @@ const Settings: LayoutSettings & {
   colorWeak: false,
   title: '指标库后台',
   pwa: false,
-  // logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
   logo: '/logo.png',
   iconfontUrl: '//at.alicdn.com/t/font_2906856_2hmrdvasx37.js'
 }

+ 0 - 175
mock/listTableList.ts

@@ -1,175 +0,0 @@
-// eslint-disable-next-line import/no-extraneous-dependencies
-import { Request, Response } from 'express';
-import moment from 'moment';
-import { parse } from 'url';
-
-// mock tableListDataSource
-const genList = (current: number, pageSize: number) => {
-  const tableListDataSource: API.RuleListItem[] = [];
-
-  for (let i = 0; i < pageSize; i += 1) {
-    const index = (current - 1) * 10 + i;
-    tableListDataSource.push({
-      key: index,
-      disabled: i % 6 === 0,
-      href: 'https://ant.design',
-      avatar: [
-        'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
-        'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
-      ][i % 2],
-      name: `TradeCode ${index}`,
-      owner: '曲丽丽',
-      desc: '这是一段描述',
-      callNo: Math.floor(Math.random() * 1000),
-      status: Math.floor(Math.random() * 10) % 4,
-      updatedAt: moment().format('YYYY-MM-DD'),
-      createdAt: moment().format('YYYY-MM-DD'),
-      progress: Math.ceil(Math.random() * 100),
-    });
-  }
-  tableListDataSource.reverse();
-  return tableListDataSource;
-};
-
-let tableListDataSource = genList(1, 100);
-
-function getRule(req: Request, res: Response, u: string) {
-  let realUrl = u;
-  if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
-    realUrl = req.url;
-  }
-  const { current = 1, pageSize = 10 } = req.query;
-  const params = parse(realUrl, true).query as unknown as API.PageParams &
-    API.RuleListItem & {
-      sorter: any;
-      filter: any;
-    };
-
-  let dataSource = [...tableListDataSource].slice(
-    ((current as number) - 1) * (pageSize as number),
-    (current as number) * (pageSize as number),
-  );
-  if (params.sorter) {
-    const sorter = JSON.parse(params.sorter);
-    dataSource = dataSource.sort((prev, next) => {
-      let sortNumber = 0;
-      Object.keys(sorter).forEach((key) => {
-        if (sorter[key] === 'descend') {
-          if (prev[key] - next[key] > 0) {
-            sortNumber += -1;
-          } else {
-            sortNumber += 1;
-          }
-          return;
-        }
-        if (prev[key] - next[key] > 0) {
-          sortNumber += 1;
-        } else {
-          sortNumber += -1;
-        }
-      });
-      return sortNumber;
-    });
-  }
-  if (params.filter) {
-    const filter = JSON.parse(params.filter as any) as {
-      [key: string]: string[];
-    };
-    if (Object.keys(filter).length > 0) {
-      dataSource = dataSource.filter((item) => {
-        return Object.keys(filter).some((key) => {
-          if (!filter[key]) {
-            return true;
-          }
-          if (filter[key].includes(`${item[key]}`)) {
-            return true;
-          }
-          return false;
-        });
-      });
-    }
-  }
-
-  if (params.name) {
-    dataSource = dataSource.filter((data) => data?.name?.includes(params.name || ''));
-  }
-  const result = {
-    data: dataSource,
-    total: tableListDataSource.length,
-    success: true,
-    pageSize,
-    current: parseInt(`${params.current}`, 10) || 1,
-  };
-
-  return res.json(result);
-}
-
-function postRule(req: Request, res: Response, u: string, b: Request) {
-  let realUrl = u;
-  if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
-    realUrl = req.url;
-  }
-
-  const body = (b && b.body) || req.body;
-  const { method, name, desc, key } = body;
-
-  switch (method) {
-    /* eslint no-case-declarations:0 */
-    case 'delete':
-      tableListDataSource = tableListDataSource.filter((item) => key.indexOf(item.key) === -1);
-      break;
-    case 'post':
-      (() => {
-        const i = Math.ceil(Math.random() * 10000);
-        const newRule: API.RuleListItem = {
-          key: tableListDataSource.length,
-          href: 'https://ant.design',
-          avatar: [
-            'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
-            'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
-          ][i % 2],
-          name,
-          owner: '曲丽丽',
-          desc,
-          callNo: Math.floor(Math.random() * 1000),
-          status: Math.floor(Math.random() * 10) % 2,
-          updatedAt: moment().format('YYYY-MM-DD'),
-          createdAt: moment().format('YYYY-MM-DD'),
-          progress: Math.ceil(Math.random() * 100),
-        };
-        tableListDataSource.unshift(newRule);
-        return res.json(newRule);
-      })();
-      return;
-
-    case 'update':
-      (() => {
-        let newRule = {};
-        tableListDataSource = tableListDataSource.map((item) => {
-          if (item.key === key) {
-            newRule = { ...item, desc, name };
-            return { ...item, desc, name };
-          }
-          return item;
-        });
-        return res.json(newRule);
-      })();
-      return;
-    default:
-      break;
-  }
-
-  const result = {
-    list: tableListDataSource,
-    pagination: {
-      total: tableListDataSource.length,
-    },
-  };
-
-  res.json(result);
-}
-
-export default {
-  'GET /api/rule': getRule,
-  'POST /api/rule': postRule,
-};

+ 0 - 107
mock/notices.ts

@@ -1,107 +0,0 @@
-import { Request, Response } from 'express';
-
-const getNotices = (req: Request, res: Response) => {
-  res.json({
-    data: [
-      {
-        id: '000000001',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
-        title: '你收到了 14 份新周报',
-        datetime: '2017-08-09',
-        type: 'notification',
-      },
-      {
-        id: '000000002',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png',
-        title: '你推荐的 曲妮妮 已通过第三轮面试',
-        datetime: '2017-08-08',
-        type: 'notification',
-      },
-      {
-        id: '000000003',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png',
-        title: '这种模板可以区分多种通知类型',
-        datetime: '2017-08-07',
-        read: true,
-        type: 'notification',
-      },
-      {
-        id: '000000004',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
-        title: '左侧图标用于区分不同的类型',
-        datetime: '2017-08-07',
-        type: 'notification',
-      },
-      {
-        id: '000000005',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
-        title: '内容不要超过两行字,超出时自动截断',
-        datetime: '2017-08-07',
-        type: 'notification',
-      },
-      {
-        id: '000000006',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
-        title: '曲丽丽 评论了你',
-        description: '描述信息描述信息描述信息',
-        datetime: '2017-08-07',
-        type: 'message',
-        clickClose: true,
-      },
-      {
-        id: '000000007',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
-        title: '朱偏右 回复了你',
-        description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
-        datetime: '2017-08-07',
-        type: 'message',
-        clickClose: true,
-      },
-      {
-        id: '000000008',
-        avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
-        title: '标题',
-        description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
-        datetime: '2017-08-07',
-        type: 'message',
-        clickClose: true,
-      },
-      {
-        id: '000000009',
-        title: '任务名称',
-        description: '任务需要在 2017-01-12 20:00 前启动',
-        extra: '未开始',
-        status: 'todo',
-        type: 'event',
-      },
-      {
-        id: '000000010',
-        title: '第三方紧急代码变更',
-        description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
-        extra: '马上到期',
-        status: 'urgent',
-        type: 'event',
-      },
-      {
-        id: '000000011',
-        title: '信息安全考试',
-        description: '指派竹尔于 2017-01-09 前完成更新并发布',
-        extra: '已耗时 8 天',
-        status: 'doing',
-        type: 'event',
-      },
-      {
-        id: '000000012',
-        title: 'ABCD 版本发布',
-        description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
-        extra: '进行中',
-        status: 'processing',
-        type: 'event',
-      },
-    ],
-  });
-};
-
-export default {
-  'GET /api/notices': getNotices,
-};

+ 0 - 5
mock/route.ts

@@ -1,5 +0,0 @@
-export default {
-  '/api/auth_routes': {
-    '/form/advanced-form': { authority: ['admin', 'user'] },
-  },
-};

+ 0 - 203
mock/user.ts

@@ -1,203 +0,0 @@
-import { Request, Response } from 'express'
-
-const waitTime = (time: number = 100) => {
-  return new Promise(resolve => {
-    setTimeout(() => {
-      resolve(true)
-    }, time)
-  })
-}
-
-async function getFakeCaptcha(req: Request, res: Response) {
-  await waitTime(2000)
-  return res.json('captcha-xxx')
-}
-
-const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env
-
-/**
- * 当前用户的权限,如果为空代表没登录
- * current user access, if is '', user need login
- * 如果是 pro 的预览,默认是有权限的
- */
-let access = ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site' ? 'admin' : ''
-
-const getAccess = () => {
-  return access
-}
-
-// 代码中会兼容本地 service mock 以及部署站点的静态数据
-export default {
-  // 支持值为 Object 和 Array
-  'GET /api/currentUser': (req: Request, res: Response) => {
-    if (!getAccess()) {
-      res.status(401).send({
-        data: {
-          isLogin: false
-        },
-        errorCode: '401',
-        errorMessage: '请先登录!',
-        success: true
-      })
-      return
-    }
-    res.send({
-      success: true,
-      data: {
-        name: 'Serati Ma',
-        avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
-        userid: '00000001',
-        email: 'antdesign@alipay.com',
-        signature: '海纳百川,有容乃大',
-        title: '交互专家',
-        group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED',
-        tags: [
-          {
-            key: '0',
-            label: '很有想法的'
-          },
-          {
-            key: '1',
-            label: '专注设计'
-          },
-          {
-            key: '2',
-            label: '辣~'
-          },
-          {
-            key: '3',
-            label: '大长腿'
-          },
-          {
-            key: '4',
-            label: '川妹子'
-          },
-          {
-            key: '5',
-            label: '海纳百川'
-          }
-        ],
-        notifyCount: 12,
-        unreadCount: 11,
-        country: 'China',
-        access: getAccess(),
-        geographic: {
-          province: {
-            label: '浙江省',
-            key: '330000'
-          },
-          city: {
-            label: '杭州市',
-            key: '330100'
-          }
-        },
-        address: '西湖区工专路 77 号',
-        phone: '0752-268888888'
-      }
-    })
-  },
-  // GET POST 可省略
-  'GET /api/users': [
-    {
-      key: '1',
-      name: 'John Brown',
-      age: 32,
-      address: 'New York No. 1 Lake Park'
-    },
-    {
-      key: '2',
-      name: 'Jim Green',
-      age: 42,
-      address: 'London No. 1 Lake Park'
-    },
-    {
-      key: '3',
-      name: 'Joe Black',
-      age: 32,
-      address: 'Sidney No. 1 Lake Park'
-    }
-  ],
-  'POST /api/login/account': async (req: Request, res: Response) => {
-    const { password, username, type } = req.body
-    await waitTime(2000)
-    if (password === '123456' && username === 'admin') {
-      res.send({
-        status: 'ok',
-        type,
-        currentAuthority: 'admin'
-      })
-      access = 'admin'
-      return
-    }
-    if (password === '123456' && username === 'user') {
-      res.send({
-        status: 'ok',
-        type,
-        currentAuthority: 'user'
-      })
-      access = 'user'
-      return
-    }
-    if (type === 'mobile') {
-      res.send({
-        status: 'ok',
-        type,
-        currentAuthority: 'admin'
-      })
-      access = 'admin'
-      return
-    }
-
-    res.send({
-      status: 'error',
-      type,
-      currentAuthority: 'guest'
-    })
-    access = 'guest'
-  },
-  'POST /api/login/outLogin': (req: Request, res: Response) => {
-    access = ''
-    res.send({ data: {}, success: true })
-  },
-  'POST /api/register': (req: Request, res: Response) => {
-    res.send({ status: 'ok', currentAuthority: 'user', success: true })
-  },
-  'GET /api/500': (req: Request, res: Response) => {
-    res.status(500).send({
-      timestamp: 1513932555104,
-      status: 500,
-      error: 'error',
-      message: 'error',
-      path: '/base/category/list'
-    })
-  },
-  'GET /api/404': (req: Request, res: Response) => {
-    res.status(404).send({
-      timestamp: 1513932643431,
-      status: 404,
-      error: 'Not Found',
-      message: 'No message available',
-      path: '/base/category/list/2121212'
-    })
-  },
-  'GET /api/403': (req: Request, res: Response) => {
-    res.status(403).send({
-      timestamp: 1513932555104,
-      status: 403,
-      error: 'Forbidden',
-      message: 'Forbidden',
-      path: '/base/category/list'
-    })
-  },
-  'GET /api/401': (req: Request, res: Response) => {
-    res.status(401).send({
-      timestamp: 1513932555104,
-      status: 401,
-      error: 'Unauthorized',
-      message: 'Unauthorized',
-      path: '/base/category/list'
-    })
-  },
-
-  'GET  /api/login/captcha': getFakeCaptcha
-}

+ 35 - 71
package.json

@@ -1,43 +1,24 @@
 {
-  "name": "ant-design-pro",
-  "version": "5.0.0",
+  "name": "financial_audit_console",
+  "version": "1.0.0",
   "private": true,
-  "description": "An out-of-box UI solution for enterprise applications",
+  "description": "",
   "scripts": {
-    "analyze": "cross-env ANALYZE=1 umi build",
-    "build": "umi build",
+    "analyze": "cross-env ANALYZE=1 max build",
+    "build": "max build",
     "deploy:qa": "cross-env REACT_APP_ENV=dev auto-deploy build -t qa",
+    "deploy:prod": "cross-env REACT_APP_ENV=prod auto-deploy build -t prod",
     "dev": "npm run start:dev",
-    "gh-pages": "gh-pages -d dist",
-    "i18n-remove": "pro i18n-remove --locale=zh-CN --write",
-    "postinstall": "umi g tmp",
-    "lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier && npm run tsc",
-    "lint-staged": "lint-staged",
-    "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
-    "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style",
-    "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src",
-    "lint:prettier": "prettier -c --write \"src/**/*\" --end-of-line auto",
-    "lint:style": "stylelint --fix \"src/**/*.less\" --custom-syntax postcss-less",
+    "postinstall": "max setup",
     "precommit": "lint-staged",
-    "prettier": "prettier -c --write \"src/**/*\"",
-    "start": "cross-env UMI_ENV=dev umi dev",
-    "start:dev": "cross-env PORT=8090 REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev",
-    "start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev",
-    "start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev",
-    "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev umi dev",
-    "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev umi dev",
-    "pretest": "node ./tests/beforeTest",
-    "test": "umi test",
-    "test:all": "node ./tests/run-tests.js",
-    "test:component": "umi test ./src/components",
-    "serve": "umi-serve",
-    "tsc": "tsc --noEmit"
+    "start": "max dev",
+    "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none max dev",
+    "start:org": "cross-env REACT_APP_ENV=org MOCK=none max dev",
+    "prepare": "husky install"
   },
   "lint-staged": {
-    "**/*.less": "stylelint --syntax less",
-    "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js",
-    "**/*.{js,jsx,tsx,ts,less,md,json}": [
-      "prettier --write"
+    "**/*.{js,jsx,tsx,ts,less}": [
+      "max lint"
     ]
   },
   "browserslist": [
@@ -48,7 +29,7 @@
   "dependencies": {
     "@ant-design/icons": "^4.5.0",
     "@ant-design/pro-form": "1.67.1",
-    "@ant-design/pro-layout": "6.19.3",
+    "@ant-design/pro-layout": "6.38.8",
     "@ant-design/pro-table": "2.74.1",
     "@designable/core": "^1.0.0-beta.43",
     "@designable/formily-setters": "^1.0.0-beta.43",
@@ -62,60 +43,43 @@
     "@formily/reactive": "^2.1.4",
     "@formily/reactive-react": "^2.1.4",
     "@formily/shared": "^2.1.4",
-    "@umijs/route-utils": "^1.0.36",
+    "@umijs/max": "4.0.0",
+    "@umijs/plugins": "4.0.0",
     "ahooks": "^3.0.0",
     "antd": "4.20.7",
     "array-move": "^4.0.0",
     "classnames": "^2.2.6",
     "dayjs": "^1.10.7",
     "lodash": "^4.17.11",
-    "moment": "^2.29.3",
     "omit.js": "^2.0.2",
     "rc-menu": "^9.0.13",
     "rc-util": "^5.14.0",
-    "react": "^17.0.0",
+    "react": "18.1.0",
+    "react-dom": "18.1.0",
     "react-copy-to-clipboard": "^5.1.0",
-    "react-dom": "^17.0.0",
     "react-flow-renderer": "^9.6.11",
-    "react-sortable-hoc": "^2.0.0",
-    "umi": "^3.5.0"
+    "react-sortable-hoc": "^2.0.0"
   },
   "devDependencies": {
-    "@types/express": "^4.17.0",
-    "@types/history": "^4.7.2",
-    "@types/jest": "^26.0.0",
+    "@babel/plugin-proposal-class-properties": "^7.16.7",
+    "@babel/plugin-proposal-decorators": "^7.17.2",
+    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.17.12",
+    "@babel/plugin-proposal-optional-chaining": "^7.13.12",
     "@types/lodash": "^4.14.144",
-    "@types/react": "^17.0.0",
-    "@types/react-dom": "^17.0.0",
-    "@types/react-helmet": "^6.1.0",
-    "@umijs/fabric": "^2.11.1",
-    "@umijs/plugin-antd-dayjs": "^0.3.0",
-    "@umijs/plugin-esbuild": "^1.4.1",
-    "@umijs/preset-ant-design-pro": "^1.2.0",
-    "@umijs/preset-react": "^1.8.17",
-    "@umijs/yorkie": "^2.0.3",
-    "babel-plugin-import": "^1.13.3",
-    "browserslist": "^4.18.1",
-    "carlo": "^0.9.46",
-    "cross-env": "^7.0.3",
-    "cross-port-killer": "^1.1.1",
-    "detect-installer": "^1.0.1",
-    "eslint-plugin-javascript": "^1.3.4",
-    "eslint-plugin-jsx": "^0.1.0",
-    "eslint-plugin-typescript": "^0.14.0",
-    "express": "^4.17.1",
-    "gh-pages": "^3.0.0",
+    "@types/react": "^18.0.0",
+    "@types/react-dom": "^18.0.0",
+    "@unocss/cli": "^0.38.2",
+    "unocss": "^0.38.2",
+    "babel-plugin-import": "^1.13.5",
+    "cross-env": "^7.0.0",
+    "eslint": "^8.17.0",
+    "husky": "^8.0.0",
     "lint-staged": "^10.0.0",
-    "prettier": "^2.3.2",
-    "puppeteer-core": "^8.0.0",
-    "react-dev-inspector": "^1.1.1",
-    "stylelint": "13.0.0",
-    "typescript": "^4.2.2",
-    "umi-serve": "^1.9.10",
-    "windicss": "^3.2.0",
-    "windicss-webpack-plugin": "^1.5.5"
+    "prettier": "^2.6.1",
+    "stylelint": "^14.9.0",
+    "typescript": "^4.7.3"
   },
   "engines": {
-    "node": ">=10.0.0"
+    "node": ">=14.0.0"
   }
 }

Файловите разлики са ограничени, защото са твърде много
+ 0 - 5
public/pro_icon.svg


+ 64 - 107
src/app.tsx

@@ -1,22 +1,12 @@
-import type { Settings as LayoutSettings } from '@ant-design/pro-layout'
 import { notification } from 'antd'
-import { PageLoading } from '@ant-design/pro-layout'
-import type { RequestConfig, RunTimeLayoutConfig } from 'umi'
-import { Link, history } from 'umi'
-import type { RequestOptionsInit, ResponseError } from 'umi-request'
+import { createSearchParams, history } from '@umijs/max'
 import RightContent from '@/components/RightContent'
-// import { currentUser as queryCurrentUser } from './services/ant-design-pro/api'
 import consts from './utils/consts'
 import { queryCurrentUser } from './services/api/login'
+import defaultSettings from '../config/defaultSettings'
+import type { Settings as LayoutSettings } from '@ant-design/pro-layout'
+import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max'
 
-/** 获取用户信息比较慢的时候会展示一个 loading */
-export const initialStateConfig = {
-  loading: <PageLoading />
-}
-
-/**
- * @see  https://umijs.org/zh-CN/plugins/plugin-initial-state
- * */
 export async function getInitialState(): Promise<{
   settings?: Partial<LayoutSettings>
   currentUser?: API.CurrentUser
@@ -37,135 +27,102 @@ export async function getInitialState(): Promise<{
     return {
       fetchUserInfo,
       ...currentUser,
-      settings: {}
+      settings: { ...defaultSettings }
     }
   }
   return {
     fetchUserInfo,
-    settings: {}
+    settings: { ...defaultSettings }
   }
 }
 
-const codeMaps = {
-  // 200: '成功返回请求的数据。',
-  201: '新建或修改数据成功。',
-  202: '一个请求已经进入后台排队(异步任务)。',
-  204: '删除数据成功。',
-  400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
-  401: '用户没有权限(令牌、用户名、密码错误)。',
-  403: '用户得到授权,但是访问是被禁止的。',
-  404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
-  406: '请求的格式不可得。',
-  410: '请求的资源被永久删除,且不会再得到的。',
-  422: '当创建一个对象时,发生一个验证错误。',
-  500: '服务器发生错误,请检查服务器。',
-  502: '网关错误。',
-  503: '服务不可用,服务器暂时过载或维护。',
-  504: '网关超时。'
-}
-
-const authHeaderInterceptor = (url: string, options: RequestOptionsInit) => {
+const authHeaderInterceptor = options => {
   const token = window.localStorage.getItem('TOKEN_ID')
   // 如果是登录页面,不执行
-  if (!token && history.location.pathname !== consts.loginPath) {
-    return history.replace(consts.loginPath)
-  }
-  // const authHeader = { Authorization: `Bearer ${JSON.parse(token)}` }
-  const authHeader = { Authorization: `Bearer ${token}` }
-  return {
-    url: `${url}`,
-    options: { ...options, interceptors: true, headers: authHeader }
+  if (token) {
+    // 在白名单里的请求放过
+    if (consts.TOKEN_WHITE_LIST.includes(options.url)) {
+      return options
+    }
+    options.headers[consts.TOKEN_HEADER] = `bearer ${token}`
   }
+  return options
 }
 
-// 处理非200的 http 状态码
-const responseInterceptor = response => {
-  codeMaps[response.status] &&
-    notification.error({ message: response.status, description: codeMaps[response.status] })
-  return response
-}
-export const request: RequestConfig = {
-  errorHandler: (err: ResponseError) => {
-    if (err.name === 'BizError') {
-      const response = err.data
-      if (response.code === consts.RET_CODE.SUCCESS) {
-        return response
-      }
-      if (
-        consts.TOKEN_INVALID_CODE.includes(response.code) &&
-        window.location.pathname !== consts.loginPath
-      ) {
-        notification.error({
-          message: '用户信息过期',
-          description: '请重新登录'
-        })
-        history.replace({
-          pathname: consts.loginPath,
-          search: stringify({
-            redirect: window.location.pathname
-          })
-        })
-      }
+const errorHandler = err => {
+  if (err.name === 'BizError') {
+    const response = err.info
+    if (consts.TOKEN_INVALID_CODE.includes(response.code) && window.location.pathname !== consts.loginPath) {
       notification.error({
-        message: '请求失败',
-        description: response.msg
+        message: '用户信息过期',
+        description: '请重新登录'
       })
-      // 阻断代码向下执行
-      return Promise.reject(response)
+      history.replace({
+        pathname: consts.loginPath,
+        search: createSearchParams({
+          redirect: window.location.pathname
+        }).toString()
+      })
+      return
     }
-    // 那么对于其他的错误, 需要实践中一个个找出来
-    if (err.name === 'RequestError') {
-      switch (err.type) {
-        case 'Timeout': {
-          message.error('系统超时,请联系开发人员')
-        }
+    notification.error({
+      message: '请求失败',
+      description: response.msg
+    })
+    return
+  }
+  // 那么对于其他的错误, 需要实践中一个个找出来
+  if (err.name === 'RequestError') {
+    switch (err.type) {
+      case 'Timeout': {
+        message.error('系统超时,请联系开发人员')
       }
     }
+    return
+  }
+}
 
-    return Promise.reject(err)
-  },
-  prefix: '/api',
+const responseInterceptor = response => {
+  const { code = -1 } = response?.data || {}
+  if (code !== consts.RET_CODE.SUCCESS) {
+    return Promise.reject(response?.data)
+  }
+  return Promise.resolve(response)
+}
+export const request: RequestConfig = {
   errorConfig: {
-    adaptor: resData => {
-      return {
-        success: resData.code === consts.RET_CODE.SUCCESS,
-        data: resData.data,
-        errorCode: resData.code,
-        errorMessage: resData.msg
+    errorThrower: res => {
+      const { data, code, msg } = res
+      if (code !== consts.RET_CODE.SUCCESS) {
+        const error: any = new Error(errorMessage)
+        error.name = 'BizError'
+        error.info = { code, msg, data }
+        throw error // 抛出自制的错误
       }
-    }
+    },
+    errorHandler
   },
+  baseURL: consts.PREFIX_URL,
   responseInterceptors: [responseInterceptor],
   requestInterceptors: [authHeaderInterceptor]
 }
 
-// ProLayout 支持的api https://procomponents.ant.design/components/layout
 export const layout: RunTimeLayoutConfig = ({ initialState }) => {
   return {
     rightContentRender: () => <RightContent />,
     disableContentMargin: false,
-    // waterMarkProps: {
-    //   content: initialState?.currentUser?.name
-    // },
     onPageChange: () => {
-      if (!initialState?.currentUser?.ID && location.pathname !== consts.loginPath) {
+      if (!initialState?.currentUser?.ID && window.location.pathname !== consts.loginPath) {
+        console.log('111')
+
         history.replace({
           pathname: consts.loginPath,
-          search: stringify({
+          search: createSearchParams({
             redirect: history.location.pathname
-          })
+          }).toString()
         })
       }
     },
-    menuHeaderRender: undefined,
-    itemRender: (route, _, routes) => {
-      if (routes.indexOf(route) === routes.length - 1) {
-        return <span>{route.breadcrumbName}</span>
-      }
-      return <Link to={route.path}>{route.breadcrumbName}</Link>
-    },
-    // 自定义 403 页面
-    // unAccessible: <div>unAccessible</div>,
     ...initialState?.settings
   }
 }

+ 1 - 1
src/components/Footer/index.tsx

@@ -1,4 +1,4 @@
-import { useIntl } from 'umi'
+import { useIntl } from '@umijs/max'
 import { GithubOutlined } from '@ant-design/icons'
 import { DefaultFooter } from '@ant-design/pro-layout'
 

+ 63 - 65
src/components/NoticeIcon/index.tsx

@@ -1,33 +1,33 @@
-import { useEffect, useState } from 'react';
-import { Tag, message } from 'antd';
-import { groupBy } from 'lodash';
-import moment from 'moment';
-import { useModel, useRequest } from 'umi';
-import { getNotices } from '@/services/ant-design-pro/api';
+import { useEffect, useState } from 'react'
+import { Tag, message } from 'antd'
+import { groupBy } from 'lodash'
+import moment from 'moment'
+import { useModel, useRequest } from '@umijs/max'
+import { getNotices } from '@/services/ant-design-pro/api'
 
-import NoticeIcon from './NoticeIcon';
-import styles from './index.less';
+import NoticeIcon from './NoticeIcon'
+import styles from './index.less'
 
 export type GlobalHeaderRightProps = {
-  fetchingNotices?: boolean;
-  onNoticeVisibleChange?: (visible: boolean) => void;
-  onNoticeClear?: (tabName?: string) => void;
-};
+  fetchingNotices?: boolean
+  onNoticeVisibleChange?: (visible: boolean) => void
+  onNoticeClear?: (tabName?: string) => void
+}
 
 const getNoticeData = (notices: API.NoticeIconItem[]): Record<string, API.NoticeIconItem[]> => {
   if (!notices || notices.length === 0 || !Array.isArray(notices)) {
-    return {};
+    return {}
   }
 
-  const newNotices = notices.map((notice) => {
-    const newNotice = { ...notice };
+  const newNotices = notices.map(notice => {
+    const newNotice = { ...notice }
 
     if (newNotice.datetime) {
-      newNotice.datetime = moment(notice.datetime as string).fromNow();
+      newNotice.datetime = moment(notice.datetime as string).fromNow()
     }
 
     if (newNotice.id) {
-      newNotice.key = newNotice.id;
+      newNotice.key = newNotice.id
     }
 
     if (newNotice.extra && newNotice.status) {
@@ -35,93 +35,91 @@ const getNoticeData = (notices: API.NoticeIconItem[]): Record<string, API.Notice
         todo: '',
         processing: 'blue',
         urgent: 'red',
-        doing: 'gold',
-      }[newNotice.status];
+        doing: 'gold'
+      }[newNotice.status]
       newNotice.extra = (
         <Tag
           color={color}
           style={{
-            marginRight: 0,
-          }}
-        >
+            marginRight: 0
+          }}>
           {newNotice.extra}
         </Tag>
-      ) as any;
+      ) as any
     }
 
-    return newNotice;
-  });
-  return groupBy(newNotices, 'type');
-};
+    return newNotice
+  })
+  return groupBy(newNotices, 'type')
+}
 
 const getUnreadData = (noticeData: Record<string, API.NoticeIconItem[]>) => {
-  const unreadMsg: Record<string, number> = {};
-  Object.keys(noticeData).forEach((key) => {
-    const value = noticeData[key];
+  const unreadMsg: Record<string, number> = {}
+  Object.keys(noticeData).forEach(key => {
+    const value = noticeData[key]
 
     if (!unreadMsg[key]) {
-      unreadMsg[key] = 0;
+      unreadMsg[key] = 0
     }
 
     if (Array.isArray(value)) {
-      unreadMsg[key] = value.filter((item) => !item.read).length;
+      unreadMsg[key] = value.filter(item => !item.read).length
     }
-  });
-  return unreadMsg;
-};
+  })
+  return unreadMsg
+}
 
 const NoticeIconView = () => {
-  const { initialState } = useModel('@@initialState');
-  const { currentUser } = initialState || {};
-  const [notices, setNotices] = useState<API.NoticeIconItem[]>([]);
-  const { data } = useRequest(getNotices);
+  const { initialState } = useModel('@@initialState')
+  const { currentUser } = initialState || {}
+  const [notices, setNotices] = useState<API.NoticeIconItem[]>([])
+  const { data } = useRequest(getNotices)
 
   useEffect(() => {
-    setNotices(data || []);
-  }, [data]);
+    setNotices(data || [])
+  }, [data])
 
-  const noticeData = getNoticeData(notices);
-  const unreadMsg = getUnreadData(noticeData || {});
+  const noticeData = getNoticeData(notices)
+  const unreadMsg = getUnreadData(noticeData || {})
 
   const changeReadState = (id: string) => {
     setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
+      notices.map(item => {
+        const notice = { ...item }
         if (notice.id === id) {
-          notice.read = true;
+          notice.read = true
         }
-        return notice;
-      }),
-    );
-  };
+        return notice
+      })
+    )
+  }
 
   const clearReadState = (title: string, key: string) => {
     setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
+      notices.map(item => {
+        const notice = { ...item }
         if (notice.type === key) {
-          notice.read = true;
+          notice.read = true
         }
-        return notice;
-      }),
-    );
-    message.success(`${'清空了'} ${title}`);
-  };
+        return notice
+      })
+    )
+    message.success(`${'清空了'} ${title}`)
+  }
 
   return (
     <NoticeIcon
       className={styles.action}
       count={currentUser && currentUser.unreadCount}
-      onItemClick={(item) => {
-        changeReadState(item.id!);
+      onItemClick={item => {
+        changeReadState(item.id!)
       }}
       onClear={(title: string, key: string) => clearReadState(title, key)}
       loading={false}
       clearText="清空"
       viewMoreText="查看更多"
       onViewMore={() => message.info('Click on view more')}
-      clearClose
-    >
+      clearClose>
       <NoticeIcon.Tab
         tabKey="notification"
         count={unreadMsg.notification}
@@ -147,7 +145,7 @@ const NoticeIconView = () => {
         showViewMore
       />
     </NoticeIcon>
-  );
-};
+  )
+}
 
-export default NoticeIconView;
+export default NoticeIconView

+ 6 - 10
src/components/RightContent/AvatarDropdown.tsx

@@ -1,13 +1,12 @@
 import React, { useCallback } from 'react'
 import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'
-import { Avatar, Menu, Spin } from 'antd'
-import { history, useModel } from 'umi'
+import { Menu, Spin } from 'antd'
+import { createSearchParams, history, useModel } from '@umijs/max'
 import { stringify } from 'querystring'
 import HeaderDropdown from '../HeaderDropdown'
 import styles from './index.less'
 // import { outLogin } from '@/services/ant-design-pro/api';
 import { outLogin } from '@/services/api/login'
-import type { MenuInfo } from 'rc-menu/lib/interface'
 
 export type GlobalHeaderRightProps = {
   menu?: boolean
@@ -18,15 +17,12 @@ export type GlobalHeaderRightProps = {
  */
 const loginOut = async () => {
   await outLogin()
-  const { query = {}, pathname } = history.location
-  const { redirect } = query
-  // Note: There may be security issues, please note
-  if (window.location.pathname !== '/user/login' && !redirect) {
+  if (window.location.pathname !== '/user/login') {
     history.replace({
       pathname: '/user/login',
-      search: stringify({
-        redirect: pathname
-      })
+      search: createSearchParams({
+        redirect: window.location.pathname
+      }).toString()
     })
   }
 }

+ 1 - 1
src/components/RightContent/index.tsx

@@ -1,7 +1,7 @@
 import { Space } from 'antd'
 // import { QuestionCircleOutlined } from '@ant-design/icons'
 import React from 'react'
-import { useModel, SelectLang } from 'umi'
+import { useModel, SelectLang } from '@umijs/max'
 import Avatar from './AvatarDropdown'
 // import HeaderSearch from '../HeaderSearch'
 import styles from './index.less'

+ 0 - 61
src/e2e/baseLayout.e2e.js

@@ -1,61 +0,0 @@
-const { uniq } = require('lodash');
-const RouterConfig = require('../../config/config').default.routes;
-
-const BASE_URL = `http://localhost:${process.env.PORT || 8001}`;
-
-function formatter(routes, parentPath = '') {
-  const fixedParentPath = parentPath.replace(/\/{1,}/g, '/');
-  let result = [];
-  routes.forEach((item) => {
-    if (item.path && !item.path.startsWith('/')) {
-      result.push(`${fixedParentPath}/${item.path}`.replace(/\/{1,}/g, '/'));
-    }
-    if (item.path && item.path.startsWith('/')) {
-      result.push(`${item.path}`.replace(/\/{1,}/g, '/'));
-    }
-    if (item.routes) {
-      result = result.concat(
-        formatter(item.routes, item.path ? `${fixedParentPath}/${item.path}` : parentPath),
-      );
-    }
-  });
-  return uniq(result.filter((item) => !!item));
-}
-
-beforeEach(async () => {
-  await page.goto(`${BASE_URL}`);
-  await page.evaluate(() => {
-    localStorage.setItem('antd-pro-authority', '["admin"]');
-  });
-});
-
-describe('Ant Design Pro E2E test', () => {
-  const testPage = (path) => async () => {
-    await page.goto(`${BASE_URL}${path}`);
-    await page.waitForSelector('footer', {
-      timeout: 2000,
-    });
-    const haveFooter = await page.evaluate(
-      () => document.getElementsByTagName('footer').length > 0,
-    );
-    expect(haveFooter).toBeTruthy();
-  };
-
-  const routers = formatter(RouterConfig);
-  routers.forEach((route) => {
-    it(`test pages ${route}`, testPage(route));
-  });
-
-  it('topmenu should have footer', async () => {
-    const params = '?navTheme=light&layout=topmenu';
-    await page.goto(`${BASE_URL}${params}`);
-    await page.waitForSelector('footer', {
-      timeout: 2000,
-    });
-
-    const haveFooter = await page.evaluate(
-      () => document.getElementsByTagName('footer').length > 0,
-    );
-    expect(haveFooter).toBeTruthy();
-  });
-});

public/faviconTwo.ico → src/favicon.ico


+ 1 - 2
src/global.tsx

@@ -1,7 +1,6 @@
 import { Button, message, notification } from 'antd'
-import { useIntl } from 'umi'
+import { useIntl } from '@umijs/max'
 import defaultSettings from '../config/defaultSettings'
-import 'windi.css'
 const { pwa } = defaultSettings
 const isHttps = document.location.protocol === 'https:'
 

+ 2 - 4
src/hooks/core/useWebSocketFn.ts

@@ -1,7 +1,7 @@
 /* eslint-disable react-hooks/rules-of-hooks */
 import { useWebSocket } from 'ahooks'
 import { useEffect, useState } from 'react'
-import { useModel } from 'umi'
+import { useModel } from '@umijs/max'
 
 export enum cmdType {
   Single = 10,
@@ -49,9 +49,7 @@ export default function useWebSocketFn() {
   }, [])
 
   function sendMsg(cmd: cmdType, options: any) {
-    webSocketIns?.send(
-      JSON.stringify({ cmd, userid: `${currentUser.staffId}_${copyCount}`, ...options })
-    )
+    webSocketIns?.send(JSON.stringify({ cmd, userid: `${currentUser.staffId}_${copyCount}`, ...options }))
   }
   return { webSocketIns, sendMsg }
 }

+ 0 - 22
src/manifest.json

@@ -1,22 +0,0 @@
-{
-  "name": "Ant Design Pro",
-  "short_name": "Ant Design Pro",
-  "display": "standalone",
-  "start_url": "./?utm_source=homescreen",
-  "theme_color": "#002140",
-  "background_color": "#001529",
-  "icons": [
-    {
-      "src": "icons/icon-192x192.png",
-      "sizes": "192x192"
-    },
-    {
-      "src": "icons/icon-128x128.png",
-      "sizes": "128x128"
-    },
-    {
-      "src": "icons/icon-512x512.png",
-      "sizes": "512x512"
-    }
-  ]
-}

+ 1 - 1
src/pages/404.tsx

@@ -1,6 +1,6 @@
 import { Button, Result } from 'antd'
 import React from 'react'
-import { history } from 'umi'
+import { history } from '@umijs/max'
 
 const NoFoundPage: React.FC = () => (
   <Result

+ 8 - 17
src/pages/Institutions/Company/Detail/components/Organization.tsx

@@ -2,7 +2,7 @@ import { Button, message, Tooltip } from 'antd'
 import type { ActionType } from '@ant-design/pro-table'
 import ProTable from '@ant-design/pro-table'
 import React, { useState, useRef } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import {
   ArrowDownOutlined,
   ArrowUpOutlined,
@@ -11,10 +11,7 @@ import {
   PlusSquareOutlined,
   SwapOutlined
 } from '@ant-design/icons'
-import {
-  queryOrganizationalStructureList,
-  moveSortOrganizationalStructure
-} from '@/services/api/institution'
+import { queryOrganizationalStructureList, moveSortOrganizationalStructure } from '@/services/api/institution'
 import OrganizationModal from './OrganizationModal'
 // import { ModalType } from '@/utils/enum'
 
@@ -101,8 +98,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
           {record.isStart === false ? (
             <div
               className="px-2 text-primary cursor-pointer hover:text-hex-967bbd"
-              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'up' })}
-            >
+              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'up' })}>
               <Tooltip placement="top" title="上移">
                 <ArrowUpOutlined />
               </Tooltip>
@@ -111,8 +107,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
           {record.isEnd === false ? (
             <div
               className="px-2 text-primary cursor-pointer hover:text-hex-967bbd"
-              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'down' })}
-            >
+              onClick={() => tryMoveOrganization({ ID: record.ID, operation: 'down' })}>
               <Tooltip placement="top" title="下移">
                 <ArrowDownOutlined />
               </Tooltip>
@@ -128,8 +123,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
                   defaultFormData: record,
                   currentModalType: ModalTypeEnum.MOVE
                 })
-              }}
-            >
+              }}>
               <Tooltip placement="top" title="移动">
                 <SwapOutlined />
               </Tooltip>
@@ -149,8 +143,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
                 },
                 currentModalType: ModalTypeEnum.ADDITEM
               })
-            }}
-          >
+            }}>
             <Tooltip placement="top" title="添加子项">
               <PlusSquareOutlined />
             </Tooltip>
@@ -164,8 +157,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
                 defaultFormData: record,
                 currentModalType: ModalTypeEnum.UPDATE
               })
-            }}
-          >
+            }}>
             <Tooltip placement="top" title="重命名">
               <EditOutlined />
             </Tooltip>
@@ -237,8 +229,7 @@ const Organization: React.FC<OrganizationProps> = ({ dataID, structureType = 1 }
                     parentID: state.parentID
                   }
                 })
-              }
-            >
+              }>
               添加组织
             </Button>
           ]

+ 1 - 1
src/pages/Institutions/Company/Detail/components/OrganizationModal.tsx

@@ -1,4 +1,4 @@
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import React, { useRef, useEffect, useState } from 'react'
 import { Modal, message, TreeSelect, Form } from 'antd'
 import type { FormInstance } from 'antd'

+ 1 - 1
src/pages/Institutions/Company/Detail/components/Role.tsx

@@ -7,7 +7,7 @@ import type { ProFormInstance } from '@ant-design/pro-form'
 import ProForm, { ProFormSelect } from '@ant-design/pro-form'
 import consts from '@/utils/consts'
 import { queryAccountList, saveInstitutionSetting } from '@/services/api/institution'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 
 interface RoleProps {
   dataID: string

+ 6 - 7
src/pages/Institutions/Company/Detail/components/Staff.tsx

@@ -3,7 +3,7 @@ import type { ProColumnType } from '@ant-design/pro-table'
 import React, { useState, useEffect, useRef, useMemo } from 'react'
 import { Button, Tooltip } from 'antd'
 import consts from '@/utils/consts'
-import { connect } from 'umi'
+import { connect } from '@umijs/max'
 import dayjs from 'dayjs'
 import { queryAccountList } from '@/services/api/institution'
 import StaffDetail from '@/pages/Institutions/Staff/components/StaffDetail'
@@ -208,12 +208,11 @@ const Staff: React.FC<ListProps> = ({
         columns={generateColumns(columns, schema)}
         search={false}
         request={async (params, filter, sorter) => {
-          const { code = -1, data: { items = [], total = 0, iCount = 0 } = {} } =
-            await queryAccountList({
-              ...params,
-              ...filter,
-              ...sorter
-            })
+          const { code = -1, data: { items = [], total = 0, iCount = 0 } = {} } = await queryAccountList({
+            ...params,
+            ...filter,
+            ...sorter
+          })
 
           setState({ ...state, total: iCount })
           return {

+ 1 - 1
src/pages/Institutions/Company/Detail/index.tsx

@@ -5,7 +5,7 @@ import Role from './components/Role'
 import { PageContainer } from '@ant-design/pro-layout'
 import type { RouteComponentProps } from 'react-router'
 import type { InstitutionDetailProps } from '../List'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { queryInstitution } from '@/services/api/institution'
 
 export enum TabEnum {

+ 2 - 2
src/pages/Institutions/Company/List/components/CompanyDrawer.tsx

@@ -1,10 +1,10 @@
-import { connect, useRequest } from 'umi'
+import { connect, useRequest } from '@umijs/max'
 import { useEffect } from 'react'
 import { message } from 'antd'
 import { addInstitution, updateInstitution } from '@/services/api/institution'
 import { ModalType } from '@/utils/enum'
 import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
 import { createForm } from '@formily/core'
 import {

+ 2 - 4
src/pages/Institutions/Company/List/index.tsx

@@ -3,7 +3,7 @@ import ProTable from '@ant-design/pro-table'
 import consts from '@/utils/consts'
 import { Button } from 'antd'
 import { useMemo, useRef, useState } from 'react'
-import { history } from 'umi'
+import { history } from '@umijs/max'
 import { queryInstitutionList } from '@/services/api/institution'
 import type { ProColumnType, ActionType } from '@ant-design/pro-table'
 import { PageContainer } from '@ant-design/pro-layout'
@@ -144,9 +144,7 @@ const CompanyList = () => {
             <Button
               key="add"
               type="primary"
-              onClick={() =>
-                setState({ ...state, visible: true, currentModalType: ModalType.ADD })
-              }>
+              onClick={() => setState({ ...state, visible: true, currentModalType: ModalType.ADD })}>
               新建企事业单位
             </Button>
           ]

+ 2 - 2
src/pages/Institutions/Staff/components/StaffDetail.tsx

@@ -1,9 +1,9 @@
 import React, { useEffect, useMemo, useRef } from 'react'
 import { message, Button } from 'antd'
-import { connect, useRequest } from 'umi'
+import { connect, useRequest } from '@umijs/max'
 import { addAccount, updateAccount } from '@/services/api/institution'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 import type { InstitutionsModelState } from '../../model'
 import { ModalType } from '@/utils/enum'
 import type { ProFormInstance } from '@ant-design/pro-form'

+ 1 - 1
src/pages/Institutions/Staff/index.tsx

@@ -3,7 +3,7 @@ import type { ProColumnType, ActionType } from '@ant-design/pro-table'
 import { PageContainer } from '@ant-design/pro-layout'
 import consts from '@/utils/consts'
 import { useMemo, useRef, useState } from 'react'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 import { queryAccountList } from '@/services/api/institution'
 import dayjs from 'dayjs'
 import StaffDetail from './components/StaffDetail'

+ 1 - 1
src/pages/Institutions/model.ts

@@ -2,7 +2,7 @@
 // import consts from '@/utils/consts'
 import { getAccountTypeList, queryOrganizationalStructureList } from '@/services/api/institution'
 import consts from '@/utils/consts'
-import type { Effect, Reducer } from 'umi'
+import type { Effect, Reducer } from '@umijs/max'
 
 export interface InstitutionsModelState {
   list: API.InstitutionListItem[]

+ 2 - 5
src/pages/Permission/Role/components/ConnectModal/index.tsx

@@ -5,7 +5,7 @@ import ProForm, { ModalForm } from '@ant-design/pro-form'
 import { Button, message } from 'antd'
 import { useRef } from 'react'
 import type { ProFormInstance } from '@ant-design/pro-form'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 
 const ConnectModal = ({ dataId, onReload }) => {
   const formRef = useRef<ProFormInstance>(null)
@@ -36,10 +36,7 @@ const ConnectModal = ({ dataId, onReload }) => {
         message.success('添加成功')
         return true
       }}>
-      <ProForm.Item
-        label="选择用户"
-        name="accountIDs"
-        rules={[{ required: true, message: '请选择创建人' }]}>
+      <ProForm.Item label="选择用户" name="accountIDs" rules={[{ required: true, message: '请选择创建人' }]}>
         <TreeNodeSelect exclusionRoleID={dataId} />
       </ProForm.Item>
     </ModalForm>

+ 9 - 25
src/pages/Permission/Role/components/PermTabs/index.tsx

@@ -1,7 +1,7 @@
 import { Card, Tabs, Checkbox, Affix, Button, message, Spin } from 'antd'
 import React, { useState } from 'react'
 import { queryRoleDetailByID, setRolePermission } from '@/services/permission'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { RoleType } from '../RoleLeftMenu'
 import './index.less'
 const { TabPane } = Tabs
@@ -70,9 +70,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                 <div>
                   {/* <h4>我的项目</h4> */}
                   <div className="my-2">
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'todo')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'todo')} disabled>
                       已办待办
                     </Checkbox>
                   </div>
@@ -128,9 +126,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                     <Checkbox
                       disabled={roleType === RoleType.SYSTEM}
                       checked={state.frontPermission.includes('viewParticipatingProject')}
-                      onChange={e =>
-                        handleFrontOnchange(e.target.checked, 'viewParticipatingProject')
-                      }>
+                      onChange={e => handleFrontOnchange(e.target.checked, 'viewParticipatingProject')}>
                       查看项目
                     </Checkbox>
                     <Checkbox
@@ -142,9 +138,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                     <Checkbox
                       disabled={roleType === RoleType.SYSTEM}
                       checked={state.frontPermission.includes('exportParticipatingProject')}
-                      onChange={e =>
-                        handleFrontOnchange(e.target.checked, 'exportParticipatingProject')
-                      }>
+                      onChange={e => handleFrontOnchange(e.target.checked, 'exportParticipatingProject')}>
                       导出
                     </Checkbox>
                   </div>
@@ -169,9 +163,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                 <div>
                   <h4 className="pt-3">指标库</h4>
                   <div className="my-2">
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'section')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'section')} disabled>
                       区间对数
                     </Checkbox>
                   </div>
@@ -183,9 +175,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                 <div>
                   <h4>基本设置</h4>
                   <div className="my-2">
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'edit')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'edit')} disabled>
                       编辑
                     </Checkbox>
                   </div>
@@ -193,9 +183,7 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                 <div>
                   <h4 className="pt-3">企事业信息</h4>
                   <div className="my-2">
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'access2')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'access2')} disabled>
                       查看
                     </Checkbox>
                   </div>
@@ -203,14 +191,10 @@ const PermTabs: React.FC<PermTabsProps> = ({ currentPermData: { ID, roleType } }
                 <div>
                   <h4 className="pt-3">安全设置</h4>
                   <div className="my-2">
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'phone')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'phone')} disabled>
                       手机绑定
                     </Checkbox>
-                    <Checkbox
-                      onChange={e => handleFrontOnchange(e.target.checked, 'password')}
-                      disabled>
+                    <Checkbox onChange={e => handleFrontOnchange(e.target.checked, 'password')} disabled>
                       密码修改
                     </Checkbox>
                   </div>

+ 4 - 15
src/pages/Permission/Role/components/RoleLeftMenu/index.tsx

@@ -1,17 +1,12 @@
 import { addRoleMenu, delRoleMenuByRoleID, updateRoleMenu } from '@/services/permission'
 import { isNullOrUnDef } from '@/utils/is'
-import {
-  DeleteOutlined,
-  FormOutlined,
-  PlusOutlined,
-  QuestionCircleOutlined
-} from '@ant-design/icons'
+import { DeleteOutlined, FormOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'
 import { ModalForm, ProFormText } from '@ant-design/pro-form'
 import type { ProFormInstance } from '@ant-design/pro-form'
 import type { TreeDataNode } from 'antd'
 import { Button, Input, Tree, message, Popconfirm } from 'antd'
 import { useRef, useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 const { DirectoryTree } = Tree
 import './index.less'
 
@@ -127,9 +122,7 @@ const RoleLeftMenu: React.FC<RoleLeftMenuProps> = ({
 
   if (!menuRoles?.length || isNullOrUnDef(defaultActiveRole)) return null
   return (
-    <div
-      className="min-w-54 rounded-3xl"
-      style={{ height: 'calc(100vh - 122px)', background: '#ffffff' }}>
+    <div className="min-w-54 rounded-3xl" style={{ height: 'calc(100vh - 122px)', background: '#ffffff' }}>
       <div className="menu-title flex items-center justify-around">
         <span className="py-4 text-base text-opacity-85">角色列表</span>
         <ModalForm
@@ -149,11 +142,7 @@ const RoleLeftMenu: React.FC<RoleLeftMenuProps> = ({
             message.success('添加成功')
             return true
           }}>
-          <ProFormText
-            name="name"
-            label="角色名称"
-            rules={[{ required: true, message: '请输入角色名' }]}
-          />
+          <ProFormText name="name" label="角色名称" rules={[{ required: true, message: '请输入角色名' }]} />
         </ModalForm>
       </div>
       <div

+ 7 - 9
src/pages/Permission/Role/index.tsx

@@ -3,7 +3,7 @@ import { DeleteOutlined } from '@ant-design/icons'
 import { PageContainer } from '@ant-design/pro-layout'
 import { message, Popconfirm, Spin, Table, Tabs } from 'antd'
 import { useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import ConnectModal from './components/ConnectModal'
 import RoleLeftMenu, { RoleType } from './components/RoleLeftMenu'
 import PermTabs from './components/PermTabs'
@@ -119,14 +119,12 @@ const Role = () => {
         <div className="w-6/7 ml-8 bg-white p-4 rounded-20px relative">
           <Tabs
             tabBarExtraContent={{
-              right: state.activeTab === '1' &&
-                state.currentRoleID &&
-                state.roleType !== RoleType.SYSTEM && (
-                  <ConnectModal
-                    dataId={state.currentRoleID}
-                    onReload={() => tryGetRoleStaffList(state.currentRoleID)}
-                  />
-                )
+              right: state.activeTab === '1' && state.currentRoleID && state.roleType !== RoleType.SYSTEM && (
+                <ConnectModal
+                  dataId={state.currentRoleID}
+                  onReload={() => tryGetRoleStaffList(state.currentRoleID)}
+                />
+              )
             }}
             defaultActiveKey="1"
             onChange={key => setState({ ...state, activeTab: key })}>

+ 3 - 7
src/pages/Project/Created/index.tsx

@@ -10,7 +10,7 @@ import { queryAccountList } from '@/services/api/institution'
 import consts from '@/utils/consts'
 import { Button, Form, message, Table } from 'antd'
 import { saveCreator } from '@/services/api/user'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { getProjectList } from '@/services/api/project'
 import TreeNodeSelect from '../Management/List/components/TreeNodeSelect'
 import type { ColumnsStateType } from '@ant-design/pro-table/lib/typing'
@@ -141,9 +141,7 @@ const Created = () => {
               key="add_created_btn"
               type="primary"
               icon={<PlusOutlined />}
-              onClick={() =>
-                setState({ ...state, modalVisible: true, modalType: CreatedModalType.ADD })
-              }>
+              onClick={() => setState({ ...state, modalVisible: true, modalType: CreatedModalType.ADD })}>
               添加创建人
             </Button>
           ]
@@ -204,9 +202,7 @@ const Created = () => {
           </>
         ) : (
           <>
-            <p className="text-red-500">
-              当前创建人已经管理以下项目,移除后,这些项目对应创建人也将被移除。
-            </p>
+            <p className="text-red-500">当前创建人已经管理以下项目,移除后,这些项目对应创建人也将被移除。</p>
             <div className="mt-7">
               <Table
                 rowKey="ID"

+ 1 - 1
src/pages/Project/Management/Detail/components/AuditPerm.tsx

@@ -1,7 +1,7 @@
 import ProForm, { ProFormSelect } from '@ant-design/pro-form'
 import type { ProFormInstance } from '@ant-design/pro-form'
 import React, { useEffect, useRef, useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { getApprovalList, queryApprovalDetail, setApproval } from '@/services/api/project'
 import { Card, message } from 'antd'
 import consts from '@/utils/consts'

+ 3 - 8
src/pages/Project/Management/Detail/components/ProjectInfo.tsx

@@ -16,8 +16,8 @@ import {
   Cascader
 } from '@formily/antd'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
-import type { ConnectProps } from 'umi'
-import { connect } from 'umi'
+import type { ConnectProps } from '@umijs/max'
+import { connect } from '@umijs/max'
 import { useEffect } from 'react'
 import { Card } from 'antd'
 
@@ -27,12 +27,7 @@ type ProjectInfoProps = ConnectProps & {
   defaultFormData: API.ProjectListItem
 }
 
-const ProjectInfo: React.FC<ProjectInfoProps> = ({
-  dispatch,
-  pTypeList,
-  projectSchema,
-  defaultFormData
-}) => {
+const ProjectInfo: React.FC<ProjectInfoProps> = ({ dispatch, pTypeList, projectSchema, defaultFormData }) => {
   useEffect(() => {
     if (!pTypeList.length) {
       dispatch({

+ 2 - 4
src/pages/Project/Management/Detail/components/RolePerm.tsx

@@ -1,7 +1,7 @@
 import ProForm from '@ant-design/pro-form'
 import type { ProFormInstance } from '@ant-design/pro-form'
 import React, { useEffect, useRef } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { setProjectPersonor } from '@/services/api/project'
 import { Card, Form, message } from 'antd'
 import TreeNodeSelect from '../../List/components/TreeNodeSelect'
@@ -31,9 +31,7 @@ export default function RolePerm(props: RolePermProps) {
   return (
     <Card>
       <div className="max-w-320px">
-        <ProForm
-          formRef={ref}
-          onFinish={formData => trySetProjectPersonor({ ...formData, ID: dataID })}>
+        <ProForm formRef={ref} onFinish={formData => trySetProjectPersonor({ ...formData, ID: dataID })}>
           <Form.Item
             tooltip="创建项目、管理编辑者、上传项目数据、编制项目、添加批注"
             label="创建人"

+ 1 - 1
src/pages/Project/Management/Detail/index.tsx

@@ -1,7 +1,7 @@
 import { getProject } from '@/services/api/project'
 import { PageContainer } from '@ant-design/pro-layout'
 import React, { useEffect, useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import ProjectInfo from './components/ProjectInfo'
 import type { RouteComponentProps } from 'umi/node_modules/@types/react-router'
 import RolePerm from './components/RolePerm'

+ 2 - 2
src/pages/Project/Management/List/components/ProjectModal.tsx

@@ -1,4 +1,4 @@
-import { connect, useRequest } from 'umi'
+import { connect, useRequest } from '@umijs/max'
 import { message } from 'antd'
 import { addProject, updateProject } from '@/services/api/project'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
@@ -23,7 +23,7 @@ import {
 import { createSchemaField } from '@formily/react'
 
 import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 
 export enum ModalType {
   ADD,

+ 7 - 16
src/pages/Project/Management/List/components/TreeNodeSelect.tsx

@@ -1,25 +1,16 @@
 import React, { useState } from 'react'
 import { TreeSelect } from 'antd'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { queryAcountListByInstitutionID } from '@/services/api/institution'
 
-const TreeNodeSelect = ({
-  params,
-  onChange,
-  placeholder = '请选择',
-  exclusionRoleID,
-  ...otherProps
-}) => {
+const TreeNodeSelect = ({ params, onChange, placeholder = '请选择', exclusionRoleID, ...otherProps }) => {
   const [list, setList] = useState([])
-  useRequest(
-    () => queryAcountListByInstitutionID({ ...params, pageSize: 125000, exclusionRoleID }),
-    {
-      refreshDeps: [exclusionRoleID],
-      onSuccess: result => {
-        setList(result)
-      }
+  useRequest(() => queryAcountListByInstitutionID({ ...params, pageSize: 125000, exclusionRoleID }), {
+    refreshDeps: [exclusionRoleID],
+    onSuccess: result => {
+      setList(result)
     }
-  )
+  })
 
   const onNodeChange = (value, labelList) => {
     onChange?.(value, { value, label: labelList[0] })

+ 3 - 5
src/pages/Project/Management/List/index.tsx

@@ -3,7 +3,7 @@ import ProTable from '@ant-design/pro-table'
 import { Button, Tag, Modal } from 'antd'
 import consts from '@/utils/consts'
 import { useRef, useState, useEffect, useMemo } from 'react'
-import { connect, history, useRequest } from 'umi'
+import { connect, history, useRequest } from '@umijs/max'
 import { DeleteOutlined } from '@ant-design/icons'
 import ProjectModal, { ModalType } from './components/ProjectModal'
 import dayjs from 'dayjs'
@@ -11,7 +11,7 @@ import { PageContainer } from '@ant-design/pro-layout'
 import { BaseMenuEnum } from '@/pages/Schema/Base'
 import AnimateContent from '@/components/AnimateContent'
 import type { ProColumnType, ActionType } from '@ant-design/pro-table'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 import type { SchemaBaseModelState } from '@/pages/Schema/Base/model'
 import type { ColumnsStateType } from '@ant-design/pro-table/lib/typing'
 
@@ -101,9 +101,7 @@ const List: React.FC<ListProps> = ({ schema, dispatch, pTypeList }) => {
       width: 326,
       onHeaderCell: () => ({ style: { textAlign: 'center' } }),
       renderText: (_, record) =>
-        record?.created?.ID
-          ? `${record?.created?.name}(${record?.created?.institution?.name})`
-          : null
+        record?.created?.ID ? `${record?.created?.name}(${record?.created?.institution?.name})` : null
     },
     {
       dataIndex: 'reportAccount',

+ 1 - 1
src/pages/Project/Verification/Detail/Flow/components/Drawer/ParticipantCard.tsx

@@ -3,7 +3,7 @@ import { ApprovalWay, approvalWayConfigurationsEnum, ParticipantMode } from '../
 import { ConfigureType } from '../../enum'
 import { queryAccountList } from '@/services/api/institution'
 import { Col, Collapse, Row, Select, Switch } from 'antd'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { eId, FlowContext } from '../../context'
 import { isEdge, isNode } from 'react-flow-renderer'
 

+ 3 - 9
src/pages/Project/Verification/Detail/Flow/components/Drawer/index.tsx

@@ -14,7 +14,7 @@ import { queryInstitutionList } from '@/services/api/institution'
 import { buildUUID } from '@/utils/uuid'
 import styles from './index.less'
 import ParticipantCard from './ParticipantCard'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { saveApprovalParticipant } from '@/services/api/project'
 import consts from '@/utils/consts'
 import classNames from 'classnames'
@@ -183,9 +183,7 @@ const FlowDrawer = () => {
           key={participant.uid}>
           <div className="flex flex-row justify-between">
             <div className="text-base font-medium">参与者</div>
-            <div
-              className="text-primary cursor-pointer"
-              onClick={() => delCardItem(participant.uid)}>
+            <div className="text-primary cursor-pointer" onClick={() => delCardItem(participant.uid)}>
               删除
             </div>
           </div>
@@ -247,11 +245,7 @@ const FlowDrawer = () => {
       <Tabs>
         <Tabs.TabPane tab="设置审批人" key="1">
           <div>
-            <Radio.Group
-              options={plainOptions}
-              onChange={approvalWayChange}
-              value={state.approvalWay}
-            />
+            <Radio.Group options={plainOptions} onChange={approvalWayChange} value={state.approvalWay} />
             {/* {state.approvalWay === ApprovalWay.JOINTLYSIGN ? (
               <div className="mt-20px">
                 <Select

+ 1 - 1
src/pages/Project/Verification/Detail/Flow/index.tsx

@@ -3,7 +3,7 @@ import { ReactFlowProvider } from 'react-flow-renderer'
 import { FlowContextProvider } from './context'
 import FlowGroph from './components/Graph'
 import FlowDrawer from './components/Drawer'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { queryApprovalDetail } from '@/services/api/project'
 import './index.less'
 import { LoadingBar } from './components/Toolbar'

+ 3 - 10
src/pages/Project/Verification/index.tsx

@@ -4,7 +4,7 @@ import { PageContainer } from '@ant-design/pro-layout'
 import ProTable from '@ant-design/pro-table'
 import { Button, message, Modal } from 'antd'
 import { useRef, useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { addApproval, delApproval, getApprovalList, saveApproval } from '@/services/api/project'
 import type { ActionType, ProColumnType } from '@ant-design/pro-table'
 
@@ -212,10 +212,7 @@ const FlowList = () => {
         title={state.current.name}
         visible={state.visible}
         onVisibleChange={visible => setState({ ...state, visible })}>
-        <ApprovalDetail
-          {...state.current}
-          onVisibleChange={visible => setState({ ...state, visible })}
-        />
+        <ApprovalDetail {...state.current} onVisibleChange={visible => setState({ ...state, visible })} />
       </AnimateContent>
       <ModalForm
         visible={state.modalVisible}
@@ -247,11 +244,7 @@ const FlowList = () => {
             return false
           }
         }}>
-        <ProFormText
-          name="name"
-          label="名称"
-          rules={[{ required: true, message: '请输入流程名称' }]}
-        />
+        <ProFormText name="name" label="名称" rules={[{ required: true, message: '请输入流程名称' }]} />
       </ModalForm>
     </PageContainer>
   )

+ 1 - 1
src/pages/Project/model.ts

@@ -1,6 +1,6 @@
 import { getProjectTypeList } from '@/services/api/project'
 import consts from '@/utils/consts'
-import type { Effect, Reducer } from 'umi'
+import type { Effect, Reducer } from '@umijs/max'
 
 export interface ProjectModelState {
   projectTypeList: API.ProjectTypeList

+ 1 - 1
src/pages/Schema/Base/components/Designable/index.tsx

@@ -36,7 +36,7 @@ import {
   FormGrid,
   FormLayout
 } from './antd'
-import { connect, useLocation } from 'umi'
+import { connect, useLocation } from '@umijs/max'
 
 GlobalRegistry.registerDesignerLocales({
   'zh-CN': {

+ 1 - 1
src/pages/Schema/Base/components/Designable/widgets/ActionsWidget.tsx

@@ -4,7 +4,7 @@ import { useDesigner, TextWidget } from '@designable/react'
 import { GlobalRegistry } from '@designable/core'
 import { observer } from '@formily/react'
 import { loadInitialSchema } from '../service'
-import { useDispatch, useHistory, useLocation, useRequest } from 'umi'
+import { useDispatch, useHistory, useLocation, useRequest } from '@umijs/max'
 import { transformToSchema } from '@designable/formily-transformer'
 import { updateSchema } from '@/services/api/schema'
 

+ 3 - 5
src/pages/Schema/Base/detail.tsx

@@ -1,7 +1,7 @@
 import React, { useEffect } from 'react'
 import { PageContainer } from '@ant-design/pro-layout'
-import { connect } from 'umi'
-import type { ConnectProps } from 'umi'
+import { connect } from '@umijs/max'
+import type { ConnectProps } from '@umijs/max'
 import type { RouteComponentProps } from 'react-router'
 import type { SchemaBaseModelState } from './model'
 import { menuOptions } from '.'
@@ -27,9 +27,7 @@ const Detail: React.FC<DetailProps> = ({ dispatch, base, location }) => {
   return (
     <PageContainer title={false}>
       <div className="h-full w-full bg-white px-4 pb-4 rounded-20px">
-        <Designable
-          title={menuOptions.find(item => item.value === columnType)?.label + '数据模型'}
-        />
+        <Designable title={menuOptions.find(item => item.value === columnType)?.label + '数据模型'} />
       </div>
     </PageContainer>
   )

+ 3 - 3
src/pages/Schema/Base/index.tsx

@@ -2,8 +2,8 @@
 import { PageContainer } from '@ant-design/pro-layout'
 import LeftMenu from './components/LeftMenu'
 import { useState, useEffect } from 'react'
-import { history, connect, Link } from 'umi'
-import type { ProjectModelState, SchemaBaseModelState } from 'umi'
+import { history, connect, Link } from '@umijs/max'
+import type { ProjectModelState, SchemaBaseModelState } from '@umijs/max'
 import { createForm } from '@formily/core'
 import { createSchemaField } from '@formily/react'
 import {
@@ -24,7 +24,7 @@ import {
 } from '@formily/antd'
 import 'antd/dist/antd.less'
 import { projectSchema, institutionSchema, staffSchema } from '@/utils/schema'
-import type { ConnectProps } from 'umi'
+import type { ConnectProps } from '@umijs/max'
 import { Button } from 'antd'
 
 export enum BaseMenuEnum {

+ 1 - 1
src/pages/Schema/Base/model.ts

@@ -1,6 +1,6 @@
 import { getSchemaByColmunType } from '@/services/api/schema'
 import consts from '@/utils/consts'
-import type { Effect, Reducer } from 'umi'
+import type { Effect, Reducer } from '@umijs/max'
 
 export interface SchemaBaseModelState {
   base: Record<

+ 3 - 9
src/pages/Schema/Budget/index.tsx

@@ -1,7 +1,7 @@
 import { queryTemplateList } from '@/services/api/schema'
 import { PageContainer } from '@ant-design/pro-layout'
 import React, { useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import LeftMenu from './Components/LeftMenu'
 
 type iState = {
@@ -28,14 +28,8 @@ const Budget = () => {
   return (
     <PageContainer title={false}>
       <div className="h-full w-full flex flex-row">
-        <LeftMenu
-          onSelect={onSelect}
-          options={state.menuData}
-          initFn={() => tryFetchTemplateList()}
-        />
-        <div className="w-6/7 ml-8 bg-white p-4  rounded-20px shadow-hex-3e2c5a relative">
-          表单详情
-        </div>
+        <LeftMenu onSelect={onSelect} options={state.menuData} initFn={() => tryFetchTemplateList()} />
+        <div className="w-6/7 ml-8 bg-white p-4  rounded-20px shadow-hex-3e2c5a relative">表单详情</div>
       </div>
     </PageContainer>
   )

+ 8 - 18
src/pages/Schema/Option/Components/LeftMenu.tsx

@@ -1,11 +1,6 @@
-import {
-  DeleteOutlined,
-  FormOutlined,
-  PlusOutlined,
-  QuestionCircleOutlined
-} from '@ant-design/icons'
+import { DeleteOutlined, FormOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'
 import { ModalForm, ProFormText } from '@ant-design/pro-form'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import type { ProFormInstance } from '@ant-design/pro-form'
 import { Button, Input, message, Popconfirm, Tree } from 'antd'
 import type { DirectoryTreeProps } from 'antd/lib/tree'
@@ -38,15 +33,12 @@ const LeftMenu: React.FC<LeftMenuProps> = ({ onSelect, options, showDelIcon, ini
       }
     }
   )
-  const { run: tryAddDataSource } = useRequest(
-    (params: API.CreateRoleParams) => addDataSource(params),
-    {
-      manual: true,
-      onSuccess: () => {
-        initFn()
-      }
+  const { run: tryAddDataSource } = useRequest((params: API.CreateRoleParams) => addDataSource(params), {
+    manual: true,
+    onSuccess: () => {
+      initFn()
     }
-  )
+  })
   const { run: tryDelRole } = useRequest((ID: string) => delDataSourceID({ ID }), {
     manual: true,
     onSuccess: () => {
@@ -150,9 +142,7 @@ const LeftMenu: React.FC<LeftMenuProps> = ({ onSelect, options, showDelIcon, ini
         className="p-4 bg-white rounded-b-20px"
         style={{ height: 'calc(100% - 1rem*2 - 20px)' }}>
         <DirectoryTree
-          treeData={renderTreeNode(
-            options.map(item => ({ title: item.name, key: item.ID, ...item }))
-          )}
+          treeData={renderTreeNode(options.map(item => ({ title: item.name, key: item.ID, ...item })))}
           height={virtualHeigh - 32}
           onSelect={handleOnSelect}
           showIcon={false}

+ 5 - 13
src/pages/Schema/Option/index.tsx

@@ -5,7 +5,7 @@ import { arrayMoveImmutable } from 'array-move'
 import type { ColumnsType } from 'antd/lib/table'
 import type { SortableContainerProps, SortEnd } from 'react-sortable-hoc'
 import { useEffect, useRef, useState } from 'react'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import type { ProFormInstance } from '@ant-design/pro-form'
 import { addDataSourceItem, queryDataSource, updateDataSourceItem } from '@/services/api/schema'
 import { CopyOutlined, MenuOutlined, PlusOutlined } from '@ant-design/icons'
@@ -26,9 +26,7 @@ enum OptionModalType {
 
 const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />)
 
-const SortableItem = SortableElement((props: React.HTMLAttributes<HTMLTableRowElement>) => (
-  <tr {...props} />
-))
+const SortableItem = SortableElement((props: React.HTMLAttributes<HTMLTableRowElement>) => <tr {...props} />)
 const SortableBody = SortableContainer((props: React.HTMLAttributes<HTMLTableSectionElement>) => (
   <tbody {...props} />
 ))
@@ -109,10 +107,7 @@ const Option = () => {
       render: text => (
         <div className="flex items-center">
           <span
-            className={classNames(
-              'w-3 h-3 rounded-1/2 inline-flex',
-              text ? 'bg-green-500' : 'bg-red-500'
-            )}
+            className={classNames('w-3 h-3 rounded-1/2 inline-flex', text ? 'bg-green-500' : 'bg-red-500')}
           />
           <span className="ml-1">{text ? '已启用' : '已停用'}</span>
         </div>
@@ -178,8 +173,7 @@ const Option = () => {
     if (state.activeID) {
       setState({
         ...state,
-        menuDataTitle:
-          state.menuData.find(i => i.ID === state.activeID)?.name + `:` + menuTitleCopyUrl,
+        menuDataTitle: state.menuData.find(i => i.ID === state.activeID)?.name + `:` + menuTitleCopyUrl,
         menuTitleUrl: menuTitleCopyUrl
       })
     }
@@ -220,9 +214,7 @@ const Option = () => {
             toolbar={{
               title: state.activeID ? state.menuDataTitle : null,
               subTitle: state.activeID ? (
-                <CopyToClipboard
-                  onCopy={() => message.success('复制成功')}
-                  text={state.menuTitleUrl}>
+                <CopyToClipboard onCopy={() => message.success('复制成功')} text={state.menuTitleUrl}>
                   <Tooltip placement="right" title="复制" className="ml-5px">
                     <CopyOutlined />
                   </Tooltip>

+ 3 - 9
src/pages/System/AdminUpdate/index.tsx

@@ -3,7 +3,7 @@ import consts from '@/utils/consts'
 import { PageContainer } from '@ant-design/pro-layout'
 import { Card, Form, Input, Button, message } from 'antd'
 import React from 'react'
-import { history, useRequest } from 'umi'
+import { history, useRequest } from '@umijs/max'
 
 const AdminUpdate = () => {
   const [form] = Form.useForm()
@@ -33,16 +33,10 @@ const AdminUpdate = () => {
           <Form.Item label="帐号" name="username">
             <Input disabled />
           </Form.Item>
-          <Form.Item
-            label="旧密码"
-            name="password"
-            rules={[{ required: true, message: '请输入密码' }]}>
+          <Form.Item label="旧密码" name="password" rules={[{ required: true, message: '请输入密码' }]}>
             <Input.Password placeholder="请输入" />
           </Form.Item>
-          <Form.Item
-            label="新密码"
-            name="newPassword"
-            rules={[{ required: true, message: '请输入密码' }]}>
+          <Form.Item label="新密码" name="newPassword" rules={[{ required: true, message: '请输入密码' }]}>
             <Input.Password placeholder="请输入" />
           </Form.Item>
           <Form.Item

+ 1 - 1
src/pages/System/Setting/index.tsx

@@ -1,5 +1,5 @@
 import { getSetting } from '@/services/api/system'
-import { useRequest } from 'umi'
+import { useRequest } from '@umijs/max'
 import { PageContainer } from '@ant-design/pro-layout'
 import { Card, Form, Input, Button, Upload } from 'antd'
 import { UploadOutlined } from '@ant-design/icons'

+ 0 - 235
src/pages/document.ejs

@@ -1,235 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-    <meta
-      name="keywords"
-      content="antd,umi,umijs,ant design,Scaffolding, layout, Ant Design, project, Pro, admin, console, homepage, out-of-the-box, middle and back office, solution, component library"
-    />
-    <meta
-      name="description"
-      content="
-    An out-of-box UI solution for enterprise applications as a React boilerplate."
-    />
-    <meta
-      name="description"
-      content="
-      Out-of-the-box mid-stage front-end/design solution."
-    />
-    <meta
-      name="viewport"
-      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
-    />
-    <title>指标库后台</title>
-    <link rel="icon" href="<%= context.config.publicPath +'faviconTwo.ico'%>" type="image/x-icon" />
-  </head>
-  <body>
-    <noscript>
-      <div class="noscript-container">
-        Hi there! Please
-        <div class="noscript-enableJS">
-          <a href="https://www.enablejavascript.io/en" target="_blank" rel="noopener noreferrer">
-            <b>enable Javascript</b>
-          </a>
-        </div>
-        in your browser to use Ant Design, Out-of-the-box mid-stage front/design solution!
-      </div>
-    </noscript>
-    <div id="root">
-      <style>
-        html,
-        body,
-        #root {
-          height: 100%;
-          margin: 0;
-          padding: 0;
-        }
-        #root {
-          background-repeat: no-repeat;
-          background-size: 100% auto;
-        }
-        .noscript-container {
-          display: flex;
-          align-content: center;
-          justify-content: center;
-          margin-top: 90px;
-          font-size: 20px;
-          font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode',
-            Geneva, Verdana, sans-serif;
-        }
-        .noscript-enableJS {
-          padding-right: 3px;
-          padding-left: 3px;
-        }
-        .page-loading-warp {
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          padding: 98px;
-        }
-        .ant-spin {
-          position: absolute;
-          display: none;
-          -webkit-box-sizing: border-box;
-          box-sizing: border-box;
-          margin: 0;
-          padding: 0;
-          color: rgba(0, 0, 0, 0.65);
-          color: #1890ff;
-          font-size: 14px;
-          font-variant: tabular-nums;
-          line-height: 1.5;
-          text-align: center;
-          list-style: none;
-          opacity: 0;
-          -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-          transition: -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
-            -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
-          -webkit-font-feature-settings: 'tnum';
-          font-feature-settings: 'tnum';
-        }
-
-        .ant-spin-spinning {
-          position: static;
-          display: inline-block;
-          opacity: 1;
-        }
-
-        .ant-spin-dot {
-          position: relative;
-          display: inline-block;
-          width: 20px;
-          height: 20px;
-          font-size: 20px;
-        }
-
-        .ant-spin-dot-item {
-          position: absolute;
-          display: block;
-          width: 9px;
-          height: 9px;
-          background-color: #1890ff;
-          border-radius: 100%;
-          -webkit-transform: scale(0.75);
-          -ms-transform: scale(0.75);
-          transform: scale(0.75);
-          -webkit-transform-origin: 50% 50%;
-          -ms-transform-origin: 50% 50%;
-          transform-origin: 50% 50%;
-          opacity: 0.3;
-          -webkit-animation: antspinmove 1s infinite linear alternate;
-          animation: antSpinMove 1s infinite linear alternate;
-        }
-
-        .ant-spin-dot-item:nth-child(1) {
-          top: 0;
-          left: 0;
-        }
-
-        .ant-spin-dot-item:nth-child(2) {
-          top: 0;
-          right: 0;
-          -webkit-animation-delay: 0.4s;
-          animation-delay: 0.4s;
-        }
-
-        .ant-spin-dot-item:nth-child(3) {
-          right: 0;
-          bottom: 0;
-          -webkit-animation-delay: 0.8s;
-          animation-delay: 0.8s;
-        }
-
-        .ant-spin-dot-item:nth-child(4) {
-          bottom: 0;
-          left: 0;
-          -webkit-animation-delay: 1.2s;
-          animation-delay: 1.2s;
-        }
-
-        .ant-spin-dot-spin {
-          -webkit-transform: rotate(45deg);
-          -ms-transform: rotate(45deg);
-          transform: rotate(45deg);
-          -webkit-animation: antrotate 1.2s infinite linear;
-          animation: antRotate 1.2s infinite linear;
-        }
-
-        .ant-spin-lg .ant-spin-dot {
-          width: 32px;
-          height: 32px;
-          font-size: 32px;
-        }
-
-        .ant-spin-lg .ant-spin-dot i {
-          width: 14px;
-          height: 14px;
-        }
-
-        @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
-          .ant-spin-blur {
-            background: #fff;
-            opacity: 0.5;
-          }
-        }
-
-        @-webkit-keyframes antSpinMove {
-          to {
-            opacity: 1;
-          }
-        }
-
-        @keyframes antSpinMove {
-          to {
-            opacity: 1;
-          }
-        }
-
-        @-webkit-keyframes antRotate {
-          to {
-            -webkit-transform: rotate(405deg);
-            transform: rotate(405deg);
-          }
-        }
-
-        @keyframes antRotate {
-          to {
-            -webkit-transform: rotate(405deg);
-            transform: rotate(405deg);
-          }
-        }
-      </style>
-      <div
-        style="
-          display: flex;
-          flex-direction: column;
-          align-items: center;
-          justify-content: center;
-          height: 100%;
-          min-height: 420px;
-        "
-      >
-        <img src="<%= context.config.publicPath +'logo_icon.svg'%>" alt="logo" width="256" />
-        <div class="page-loading-warp">
-          <div class="ant-spin ant-spin-lg ant-spin-spinning">
-            <span class="ant-spin-dot ant-spin-dot-spin"
-              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
-              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
-            ></span>
-          </div>
-        </div>
-        <div style="display: flex; align-items: center; justify-content: center">
-          <img
-            src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
-            width="32"
-            style="margin-right: 8px"
-          />
-          Ant Design
-        </div>
-      </div>
-    </div>
-  </body>
-</html>

+ 30 - 64
src/pages/user/Login/index.tsx

@@ -1,8 +1,16 @@
 import { LockOutlined, UserOutlined } from '@ant-design/icons'
-import { Alert, message } from 'antd'
-import React, { useState } from 'react'
+import { Alert, message, notification } from 'antd'
+import React, { useState, useTransition } from 'react'
 import ProForm, { ProFormCheckbox, ProFormText } from '@ant-design/pro-form'
-import { useIntl, history, FormattedMessage, SelectLang, useModel, useRequest } from 'umi'
+import {
+  useIntl,
+  history,
+  FormattedMessage,
+  SelectLang,
+  useModel,
+  useRequest,
+  createSearchParams
+} from '@umijs/max'
 import { login } from '@/services/api/login'
 import { queryCurrentUser } from '@/services/api/login'
 import consts from '@/utils/consts'
@@ -21,21 +29,22 @@ const LoginMessage: React.FC<{
   />
 )
 
-/** 此方法会跳转到 redirect 参数所在的位置 */
-const goto = () => {
-  if (!history) return
-  setTimeout(() => {
-    const { query } = history.location
-    const { redirect } = query as { redirect: string }
-    history.push(redirect || '/')
-  }, 10)
-}
-
 const Login: React.FC = () => {
-  // const { setAuthToken } = useModel('user')
   const [userLoginState, setUserLoginState] = useState<API.LoginResult>({})
   const [type] = useState<string>('account')
+  const [, startTransition] = useTransition()
   const { initialState, setInitialState } = useModel('@@initialState')
+  const intl = useIntl()
+
+  /** 此方法会跳转到 redirect 参数所在的位置 */
+  const goto = userInfo => {
+    console.log(userInfo)
+
+    if (!history || !userInfo) return
+    const searchParams = createSearchParams(window.location.search)
+    const redirect = searchParams.get('redirect')
+    history.replace(redirect || '/')
+  }
 
   const { run: tryGetUserInfo, loading } = useRequest(queryCurrentUser, {
     manual: true,
@@ -44,29 +53,18 @@ const Login: React.FC = () => {
         ...initialState,
         currentUser: result.currentUser
       })
-      goto()
+      startTransition(() => {
+        goto(result.currentUser)
+      })
     }
   })
 
-  const intl = useIntl()
-
-  // const fetchUserInfo = async () => {
-  //   const userInfo = await initialState?.fetchUserInfo?.()
-  //   if (userInfo) {
-  //     await setInitialState(s => ({
-  //       ...s,
-  //       currentUser: userInfo
-  //     }))
-  //   }
-  // }
-
   const { run: tryLogin } = useRequest((values: API.LoginParams) => login(values), {
     manual: true,
     onSuccess: async result => {
       window.localStorage.setItem('TOKEN_ID', result)
       message.success('登录成功')
       await tryGetUserInfo()
-      // await fetchUserInfo()
     },
     onError: () => {
       setUserLoginState({ ...userLoginState, code: -1 })
@@ -79,33 +77,6 @@ const Login: React.FC = () => {
     } catch (error) {
       message.error('登录失败,请重试')
     }
-    // try {
-    //   // 登录
-    //   const msg = await login({ ...values, type })
-    //   if (msg.status === 'ok') {
-    //     const defaultLoginSuccessMessage = intl.formatMessage({
-    //       id: 'pages.login.success',
-    //       defaultMessage: '登录成功!'
-    //     })
-    //     message.success(defaultLoginSuccessMessage)
-    //     await fetchUserInfo()
-    //     /** 此方法会跳转到 redirect 参数所在的位置 */
-    //     if (!history) return
-    //     const { query } = history.location
-    //     const { redirect } = query as { redirect: string }
-    //     history.push(redirect || '/')
-    //     return
-    //   }
-    //   console.log(msg)
-    //   // 如果失败去设置用户错误信息
-    //   setUserLoginState(msg)
-    // } catch (error) {
-    //   const defaultLoginFailureMessage = intl.formatMessage({
-    //     id: 'pages.login.failure',
-    //     defaultMessage: '登录失败,请重试!'
-    //   })
-    //   message.error(defaultLoginFailureMessage)
-    // }
   }
   const { code } = userLoginState
 
@@ -123,9 +94,7 @@ const Login: React.FC = () => {
                 <span className={styles.title}>珠海市政府投资项目经济技术指标库</span>
               </div>
             </div>
-            <div className={styles.desc}>
-              {intl.formatMessage({ id: 'pages.layouts.userLayout.title' })}
-            </div>
+            <div className={styles.desc}>{intl.formatMessage({ id: 'pages.layouts.userLayout.title' })}</div>
           </div>
           <div className={styles.main}>
             <ProForm
@@ -149,8 +118,7 @@ const Login: React.FC = () => {
                   }
                 }
               }}
-              onFinish={values => handleSubmit(values as API.LoginParams)}
-            >
+              onFinish={values => handleSubmit(values as API.LoginParams)}>
               {/* <Tabs activeKey={type} onChange={setType}>
                 <Tabs.TabPane
                   key="account"
@@ -215,16 +183,14 @@ const Login: React.FC = () => {
               <div
                 style={{
                   marginBottom: 24
-                }}
-              >
+                }}>
                 <ProFormCheckbox noStyle name="autoLogin">
                   <FormattedMessage id="pages.login.rememberMe" defaultMessage="自动登录" />
                 </ProFormCheckbox>
                 <a
                   style={{
                     float: 'right'
-                  }}
-                >
+                  }}>
                   <FormattedMessage id="pages.login.forgotPassword" defaultMessage="忘记密码" />
                 </a>
               </div>

+ 0 - 65
src/service-worker.js

@@ -1,65 +0,0 @@
-/* eslint-disable no-restricted-globals */
-/* eslint-disable no-underscore-dangle */
-/* globals workbox */
-workbox.core.setCacheNameDetails({
-  prefix: 'antd-pro',
-  suffix: 'v5',
-});
-// Control all opened tabs ASAP
-workbox.clientsClaim();
-
-/**
- * Use precaching list generated by workbox in build process.
- * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.precaching
- */
-workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
-
-/**
- * Register a navigation route.
- * https://developers.google.com/web/tools/workbox/modules/workbox-routing#how_to_register_a_navigation_route
- */
-workbox.routing.registerNavigationRoute('/index.html');
-
-/**
- * Use runtime cache:
- * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.routing#.registerRoute
- *
- * Workbox provides all common caching strategies including CacheFirst, NetworkFirst etc.
- * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.strategies
- */
-
-/** Handle API requests */
-workbox.routing.registerRoute(/\/api\//, workbox.strategies.networkFirst());
-
-/** Handle third party requests */
-workbox.routing.registerRoute(
-  /^https:\/\/gw\.alipayobjects\.com\//,
-  workbox.strategies.networkFirst(),
-);
-workbox.routing.registerRoute(
-  /^https:\/\/cdnjs\.cloudflare\.com\//,
-  workbox.strategies.networkFirst(),
-);
-workbox.routing.registerRoute(/\/color.less/, workbox.strategies.networkFirst());
-
-/** Response to client after skipping waiting with MessageChannel */
-addEventListener('message', (event) => {
-  const replyPort = event.ports[0];
-  const message = event.data;
-  if (replyPort && message && message.type === 'skip-waiting') {
-    event.waitUntil(
-      self.skipWaiting().then(
-        () => {
-          replyPort.postMessage({
-            error: null,
-          });
-        },
-        (error) => {
-          replyPort.postMessage({
-            error,
-          });
-        },
-      ),
-    );
-  }
-});

+ 5 - 15
src/services/api/institution.ts

@@ -1,4 +1,4 @@
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 企事业单位列表 */
 export async function queryInstitutionList(params: API.InstitutionListParams) {
@@ -78,9 +78,7 @@ export async function getAccountTypeList() {
 }
 
 /** 组织架构列表 */
-export async function queryOrganizationalStructureList(
-  params: API.OrganizationalStructureListParams
-) {
+export async function queryOrganizationalStructureList(params: API.OrganizationalStructureListParams) {
   // console.log(params)
 
   return request('/OrganizationalStructure/list', {
@@ -98,9 +96,7 @@ export async function addOrganizationalStructure(params: API.OrganizationalStruc
 }
 
 /** 编辑组织结构 */
-export async function updateOrganizationalStructure(
-  params: API.OrganizationalStructureUpdateParams
-) {
+export async function updateOrganizationalStructure(params: API.OrganizationalStructureUpdateParams) {
   return request('/OrganizationalStructure/update', {
     method: 'POST',
     data: params
@@ -108,9 +104,7 @@ export async function updateOrganizationalStructure(
 }
 
 /** 上下移动组织架构 */
-export async function moveSortOrganizationalStructure(
-  params: API.OrganizationalStructureMoveSortParams
-) {
+export async function moveSortOrganizationalStructure(params: API.OrganizationalStructureMoveSortParams) {
   return request('/OrganizationalStructure/moveSort', {
     method: 'POST',
     data: params
@@ -134,11 +128,7 @@ export async function delOrganizationalStructure(params: API.OrganizationalStruc
 }
 
 /** 企事业单位设置 */
-export async function saveInstitutionSetting(params: {
-  ID: string
-  accountID: string
-  memberTotal: string
-}) {
+export async function saveInstitutionSetting(params: { ID: string; accountID: string; memberTotal: string }) {
   return request('/institution/setting', {
     method: 'POST',
     data: params

+ 1 - 1
src/services/api/login.ts

@@ -1,4 +1,4 @@
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 获取当前的用户 GET /backstage/currentUser */
 export async function queryCurrentUser() {

+ 2 - 6
src/services/api/project.ts

@@ -1,5 +1,5 @@
 import type { SectorType } from '@/pages/Project/Verification/Detail/Flow/components/Edge'
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 获取项目列表 POST /api/project/list */
 export async function getProjectList(params: API.ProjectListParams) {
@@ -97,11 +97,7 @@ export async function saveApproval(params: { ID: string; name: string }) {
 }
 
 /** 设置项目人员 */
-export async function setProjectPersonor(params: {
-  ID: string
-  createdID: string
-  reportAccount: string
-}) {
+export async function setProjectPersonor(params: { ID: string; createdID: string; reportAccount: string }) {
   return request('/project/set/personnel', {
     method: 'POST',
     data: params

+ 1 - 1
src/services/api/schema.ts

@@ -1,4 +1,4 @@
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 获取对应类型的的schema */
 export async function getSchemaByColmunType(params: API.SchemaParams) {

+ 1 - 1
src/services/api/store.ts

@@ -1,6 +1,6 @@
 // @ts-ignore
 /* eslint-disable */
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
 export async function getInventory(options?: { [key: string]: any }) {

+ 1 - 1
src/services/api/system.ts

@@ -1,4 +1,4 @@
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 更改管理员密码 */
 export async function updateSetting(params: API.UpdateSettingParams) {

+ 3 - 10
src/services/api/user.ts

@@ -1,6 +1,6 @@
 // @ts-ignore
 /* eslint-disable */
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** Create user This can only be done by the logged in user. POST /user */
 export async function createUser(body: API.User, options?: { [key: string]: any }) {
@@ -12,10 +12,7 @@ export async function createUser(body: API.User, options?: { [key: string]: any
 }
 
 /** Creates list of users with given input array POST /user/createWithArray */
-export async function createUsersWithArrayInput(
-  body: API.User[],
-  options?: { [key: string]: any }
-) {
+export async function createUsersWithArrayInput(body: API.User[], options?: { [key: string]: any }) {
   return request<any>('/user/createWithArray', {
     method: 'POST',
     data: body,
@@ -122,11 +119,7 @@ export async function saveCreator(params: { ID: string; isCreated?: 1 | 0 }) {
 }
 
 // 更换账号密码
-export async function changeAccountPsw(params: {
-  ID: string
-  newPassword: string
-  confirmPassword: string
-}) {
+export async function changeAccountPsw(params: { ID: string; newPassword: string; confirmPassword: string }) {
   return request('/account/change/password', {
     method: 'POST',
     data: params

+ 1 - 1
src/services/permission.ts

@@ -1,4 +1,4 @@
-import { request } from 'umi'
+import { request } from '@umijs/max'
 
 /** 获取单菜单下的角色列表 */
 export async function fetchRoleList(params: API.RoleListParams) {

+ 4 - 1
src/utils/consts.ts

@@ -3,6 +3,9 @@ export default {
     SUCCESS: 0,
     ERROR: -1
   },
+  PREFIX_URL: '/api',
   TOKEN_INVALID_CODE: [2],
-  loginPath: '/user/login'
+  loginPath: '/user/login',
+  TOKEN_WHITE_LIST: ['/api/login'], // 不需要设置token的白名单
+  TOKEN_HEADER: 'Authorization' // token的键值
 }

+ 77 - 0
unocss.config.ts

@@ -0,0 +1,77 @@
+import { defineConfig, presetWind } from 'unocss'
+import proSettings from './config/defaultSettings'
+export function createConfig({ dev = true } = {}) {
+  return defineConfig({
+    envMode: dev ? 'dev' : 'build',
+    presets: [presetWind()],
+    theme: {
+      colors: {
+        primary: proSettings.primaryColor
+      },
+      screens: {
+        sm: '576px',
+        md: '768px',
+        lg: '992px',
+        xl: '1200px',
+        '2xl': '1600px'
+      },
+      boxShadow: {
+        card: '0 0 13px 0 rgba(74, 53, 107, 0.08)'
+      }
+    }
+    // transformers: [transformerDirectives()]
+    // rules: [createEnterPlugin()]
+    // variants: [createEnterPlugin()]
+  })
+}
+
+export default createConfig()
+/**
+ * Used for animation when the element is displayed
+ * @param maxOutput The larger the maxOutput output, the larger the generated css volume
+ */
+function createEnterPlugin(maxOutput = 10) {
+  const createCss = (index: number, d = 'x') => {
+    const upd = d.toUpperCase()
+    return {
+      [`*> .enter-${d}:nth-child(${index})`]: {
+        transform: `translate${upd}(50px)`
+      },
+      [`*> .-enter-${d}:nth-child(${index})`]: {
+        transform: `translate${upd}(-50px)`
+      },
+      [`* > .enter-${d}:nth-child(${index}),* > .-enter-${d}:nth-child(${index})`]: {
+        'z-index': `${10 - index}`,
+        opacity: '0',
+        animation: `enter-${d}-animation 0.4s ease-in-out 0.3s`,
+        'animation-fill-mode': 'forwards',
+        'animation-delay': `${(index * 1) / 10}s`
+      }
+    }
+  }
+  const handler = () => {
+    const addRawCss = {}
+    for (let index = 1; index < maxOutput; index++) {
+      Object.assign(m, {
+        ...createCss(index, 'x'),
+        ...createCss(index, 'y')
+      })
+    }
+    return {
+      ...addRawCss,
+      [`@keyframes enter-x-animation`]: {
+        to: {
+          opacity: '1',
+          transform: 'translateX(0)'
+        }
+      },
+      [`@keyframes enter-y-animation`]: {
+        to: {
+          opacity: '1',
+          transform: 'translateY(0)'
+        }
+      }
+    }
+  }
+  return [/^enter-(x|y)/, () => handler()]
+}