@umijs/plugins 4.0.0-rc.2 → 4.0.0-rc.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access.js +78 -16
- package/dist/antd.js +45 -12
- package/dist/dva.js +27 -2
- package/dist/initial-state.js +3 -3
- package/dist/layout.js +99 -28
- package/dist/locale.js +46 -50
- package/dist/model.js +21 -36
- package/dist/moment2dayjs.js +4 -4
- package/dist/qiankun/master.js +33 -12
- package/dist/qiankun/slave.js +67 -44
- package/dist/qiankun.js +1 -0
- package/dist/request.js +134 -127
- package/dist/tailwindcss.js +31 -29
- package/dist/unocss.js +15 -33
- package/dist/utils/astUtils.js +5 -1
- package/dist/utils/localeUtils.js +15 -24
- package/dist/utils/modelUtils.d.ts +5 -1
- package/dist/utils/modelUtils.js +93 -7
- package/dist/utils/withTmpPath.js +2 -2
- package/libs/locale/localeExports.tpl +6 -6
- package/libs/qiankun/master/MicroApp.tsx +7 -0
- package/libs/qiankun/master/common.ts +15 -10
- package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +5 -16
- package/libs/qiankun/master/masterRuntimePlugin.tsx +6 -5
- package/libs/qiankun/slave/connectMaster.tsx +0 -1
- package/libs/qiankun/slave/lifecycles.ts +14 -8
- package/libs/qiankun/slave/qiankunModel.ts +0 -1
- package/libs/qiankun/slave/slaveRuntimePlugin.ts +9 -15
- package/package.json +15 -13
package/dist/access.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
4
|
};
|
|
11
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
7
|
const path_1 = require("path");
|
|
13
8
|
const withTmpPath_1 = require("./utils/withTmpPath");
|
|
14
9
|
exports.default = (api) => {
|
|
15
|
-
// TODO: route access
|
|
16
10
|
api.describe({
|
|
17
11
|
config: {
|
|
18
12
|
schema(joi) {
|
|
@@ -21,19 +15,29 @@ exports.default = (api) => {
|
|
|
21
15
|
},
|
|
22
16
|
enableBy: api.EnableBy.config,
|
|
23
17
|
});
|
|
24
|
-
api.onGenerateFiles(() =>
|
|
18
|
+
api.onGenerateFiles(async () => {
|
|
19
|
+
// allow enable access without access file
|
|
20
|
+
const hasAccessFile = ['js', 'jsx', 'ts', 'tsx'].some((ext) => fs_1.default.existsSync((0, path_1.join)(api.paths.absSrcPath, `access.${ext}`)));
|
|
25
21
|
// runtime.tsx
|
|
26
22
|
api.writeTmpFile({
|
|
27
23
|
path: 'runtime.tsx',
|
|
28
24
|
content: `
|
|
29
|
-
import React from 'react'
|
|
30
|
-
|
|
25
|
+
import React from 'react';${hasAccessFile
|
|
26
|
+
? `
|
|
27
|
+
import accessFactory from '@/access'
|
|
31
28
|
import { useModel } from '@@/plugin-model';
|
|
29
|
+
`
|
|
30
|
+
: ''}
|
|
32
31
|
import { AccessContext } from './context';
|
|
33
32
|
|
|
34
|
-
function Provider(props) {
|
|
33
|
+
function Provider(props) {${hasAccessFile
|
|
34
|
+
? `
|
|
35
35
|
const { initialState } = useModel('@@initialState');
|
|
36
36
|
const access = React.useMemo(() => accessFactory(initialState), [initialState]);
|
|
37
|
+
`
|
|
38
|
+
: `
|
|
39
|
+
const access = {};
|
|
40
|
+
`}
|
|
37
41
|
return (
|
|
38
42
|
<AccessContext.Provider value={access}>
|
|
39
43
|
{ props.children }
|
|
@@ -46,16 +50,74 @@ export function accessProvider(container) {
|
|
|
46
50
|
}
|
|
47
51
|
`,
|
|
48
52
|
});
|
|
49
|
-
// index.
|
|
53
|
+
// index.tsx
|
|
50
54
|
api.writeTmpFile({
|
|
51
|
-
path: 'index.
|
|
55
|
+
path: 'index.tsx',
|
|
52
56
|
content: `
|
|
53
57
|
import React from 'react';
|
|
54
58
|
import { AccessContext } from './context';
|
|
59
|
+
import type { IRoute } from 'umi';
|
|
55
60
|
|
|
56
61
|
export const useAccess = () => {
|
|
57
62
|
return React.useContext(AccessContext);
|
|
58
63
|
};
|
|
64
|
+
|
|
65
|
+
export interface AccessProps {
|
|
66
|
+
accessible: boolean;
|
|
67
|
+
fallback?: React.ReactNode;
|
|
68
|
+
}
|
|
69
|
+
export const Access: React.FC<AccessProps> = (props) => {
|
|
70
|
+
if (process.env.NODE_ENV === 'development' && typeof props.accessible !== 'boolean') {
|
|
71
|
+
throw new Error('[access] the \`accessible\` property on <Access /> should be a boolean');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return <>{ props.accessible ? props.children : props.fallback }</>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const useAccessMarkedRoutes = (routes: IRoute[]) => {
|
|
78
|
+
const access = useAccess();
|
|
79
|
+
const markdedRoutes: IRoute[] = React.useMemo(() => {
|
|
80
|
+
const process = (route, parentAccessCode) => {
|
|
81
|
+
const accessCode = route.access || parentAccessCode;
|
|
82
|
+
|
|
83
|
+
// set default status
|
|
84
|
+
route.unaccessible = ${api.config.access.strictMode ? 'true' : 'false'};
|
|
85
|
+
|
|
86
|
+
// check access code
|
|
87
|
+
if (typeof accessCode === 'string') {
|
|
88
|
+
const detector = access[route.access];
|
|
89
|
+
|
|
90
|
+
if (typeof detector === 'function') {
|
|
91
|
+
route.unaccessible = !detector(route);
|
|
92
|
+
} else if (typeof detector === 'boolean') {
|
|
93
|
+
route.unaccessible = !detector;
|
|
94
|
+
} else if (typeof detector === 'undefined') {
|
|
95
|
+
route.unaccessible = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// check children access code
|
|
100
|
+
if (route.routes) {
|
|
101
|
+
const isNoAccessibleChild = !route.routes.reduce((hasAccessibleChild, child) => {
|
|
102
|
+
process(child, accessCode);
|
|
103
|
+
|
|
104
|
+
return hasAccessibleChild || !child.unaccessible;
|
|
105
|
+
}, false);
|
|
106
|
+
|
|
107
|
+
// make sure parent route is unaccessible if all children are unaccessible
|
|
108
|
+
if (isNoAccessibleChild) {
|
|
109
|
+
route.unaccessible = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return route;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return routes.map(route => process(route));
|
|
117
|
+
}, [routes.length]);
|
|
118
|
+
|
|
119
|
+
return markdedRoutes;
|
|
120
|
+
}
|
|
59
121
|
`,
|
|
60
122
|
});
|
|
61
123
|
// context.ts
|
|
@@ -66,7 +128,7 @@ import React from 'react';
|
|
|
66
128
|
export const AccessContext = React.createContext<any>(null);
|
|
67
129
|
`,
|
|
68
130
|
});
|
|
69
|
-
})
|
|
131
|
+
});
|
|
70
132
|
api.addRuntimePlugin(() => {
|
|
71
133
|
return [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })];
|
|
72
134
|
});
|
package/dist/antd.js
CHANGED
|
@@ -5,11 +5,16 @@ const plugin_utils_1 = require("umi/plugin-utils");
|
|
|
5
5
|
const resolveProjectDep_1 = require("./utils/resolveProjectDep");
|
|
6
6
|
const withTmpPath_1 = require("./utils/withTmpPath");
|
|
7
7
|
exports.default = (api) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
let pkgPath;
|
|
9
|
+
try {
|
|
10
|
+
pkgPath =
|
|
11
|
+
(0, resolveProjectDep_1.resolveProjectDep)({
|
|
12
|
+
pkg: api.pkg,
|
|
13
|
+
cwd: api.cwd,
|
|
14
|
+
dep: 'antd',
|
|
15
|
+
}) || (0, path_1.dirname)(require.resolve('antd/package.json'));
|
|
16
|
+
}
|
|
17
|
+
catch (e) { }
|
|
13
18
|
api.describe({
|
|
14
19
|
config: {
|
|
15
20
|
schema(Joi) {
|
|
@@ -25,9 +30,20 @@ exports.default = (api) => {
|
|
|
25
30
|
});
|
|
26
31
|
},
|
|
27
32
|
},
|
|
28
|
-
enableBy
|
|
33
|
+
enableBy({ userConfig }) {
|
|
34
|
+
// 由于本插件有 api.modifyConfig 的调用,以及 Umi 框架的限制
|
|
35
|
+
// 在其他插件中通过 api.modifyDefaultConfig 设置 antd 并不能让 api.modifyConfig 生效
|
|
36
|
+
// 所以这里通过环境变量来判断是否启用
|
|
37
|
+
return process.env.UMI_PLUGIN_ANTD_ENABLE || userConfig.antd;
|
|
38
|
+
},
|
|
29
39
|
});
|
|
40
|
+
function checkPkgPath() {
|
|
41
|
+
if (!pkgPath) {
|
|
42
|
+
throw new Error(`Can't find antd package. Please install antd first.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
30
45
|
api.modifyAppData((memo) => {
|
|
46
|
+
checkPkgPath();
|
|
31
47
|
const version = require(`${pkgPath}/package.json`).version;
|
|
32
48
|
memo.antd = {
|
|
33
49
|
pkgPath,
|
|
@@ -36,17 +52,32 @@ exports.default = (api) => {
|
|
|
36
52
|
return memo;
|
|
37
53
|
});
|
|
38
54
|
api.modifyConfig((memo) => {
|
|
55
|
+
checkPkgPath();
|
|
56
|
+
const antd = memo.antd || {};
|
|
57
|
+
// defaultConfig 的取值在 config 之后,所以改用环境变量传默认值
|
|
58
|
+
if (process.env.UMI_PLUGIN_ANTD_ENABLE) {
|
|
59
|
+
const { defaultConfig } = JSON.parse(process.env.UMI_PLUGIN_ANTD_ENABLE);
|
|
60
|
+
Object.assign(antd, defaultConfig);
|
|
61
|
+
}
|
|
39
62
|
// antd import
|
|
40
63
|
memo.alias.antd = pkgPath;
|
|
41
64
|
// moment > dayjs
|
|
42
|
-
if (
|
|
65
|
+
if (antd.dayjs) {
|
|
43
66
|
memo.alias.moment = (0, path_1.dirname)(require.resolve('dayjs/package.json'));
|
|
44
67
|
}
|
|
45
68
|
// dark mode & compact mode
|
|
46
|
-
if (
|
|
69
|
+
if (antd.dark || antd.compact) {
|
|
47
70
|
const { getThemeVariables } = require('antd/dist/theme');
|
|
48
|
-
memo.theme =
|
|
71
|
+
memo.theme = {
|
|
72
|
+
...getThemeVariables(antd),
|
|
73
|
+
...memo.theme,
|
|
74
|
+
};
|
|
49
75
|
}
|
|
76
|
+
// antd theme
|
|
77
|
+
memo.theme = {
|
|
78
|
+
'root-entry-name': 'default',
|
|
79
|
+
...memo.theme,
|
|
80
|
+
};
|
|
50
81
|
return memo;
|
|
51
82
|
});
|
|
52
83
|
// babel-plugin-import
|
|
@@ -61,17 +92,19 @@ exports.default = (api) => {
|
|
|
61
92
|
libraryDirectory: 'es',
|
|
62
93
|
style: style === 'less' ? true : 'css',
|
|
63
94
|
},
|
|
95
|
+
'antd',
|
|
64
96
|
],
|
|
65
97
|
]
|
|
66
98
|
: [];
|
|
67
99
|
});
|
|
68
100
|
// antd config provider
|
|
69
101
|
api.onGenerateFiles(() => {
|
|
70
|
-
if (!api.config.antd.
|
|
102
|
+
if (!api.config.antd.configProvider)
|
|
71
103
|
return;
|
|
72
104
|
api.writeTmpFile({
|
|
73
105
|
path: `runtime.tsx`,
|
|
74
106
|
content: plugin_utils_1.Mustache.render(`
|
|
107
|
+
import React from 'react';
|
|
75
108
|
import { ConfigProvider, Modal, message, notification } from 'antd';
|
|
76
109
|
|
|
77
110
|
export function rootContainer(container) {
|
|
@@ -90,12 +123,12 @@ export function rootContainer(container) {
|
|
|
90
123
|
return <ConfigProvider {...finalConfig}>{container}</ConfigProvider>;
|
|
91
124
|
}
|
|
92
125
|
`.trim(), {
|
|
93
|
-
config: JSON.stringify(api.config.antd.
|
|
126
|
+
config: JSON.stringify(api.config.antd.configProvider),
|
|
94
127
|
}),
|
|
95
128
|
});
|
|
96
129
|
});
|
|
97
130
|
api.addRuntimePlugin(() => {
|
|
98
|
-
return api.config.antd.
|
|
131
|
+
return api.config.antd.configProvider
|
|
99
132
|
? [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })]
|
|
100
133
|
: [];
|
|
101
134
|
});
|
package/dist/dva.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -21,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
21
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
26
|
exports.getAllModels = exports.getModelUtil = void 0;
|
|
23
27
|
const t = __importStar(require("@umijs/bundler-utils/compiled/babel/types"));
|
|
28
|
+
const utils_1 = require("@umijs/utils");
|
|
24
29
|
const path_1 = require("path");
|
|
25
30
|
const plugin_utils_1 = require("umi/plugin-utils");
|
|
26
31
|
const modelUtils_1 = require("./utils/modelUtils");
|
|
@@ -32,6 +37,7 @@ exports.default = (api) => {
|
|
|
32
37
|
schema(Joi) {
|
|
33
38
|
return Joi.object({
|
|
34
39
|
extraModels: Joi.array().items(Joi.string()),
|
|
40
|
+
immer: Joi.object(),
|
|
35
41
|
});
|
|
36
42
|
},
|
|
37
43
|
},
|
|
@@ -51,6 +57,7 @@ exports.default = (api) => {
|
|
|
51
57
|
return memo;
|
|
52
58
|
});
|
|
53
59
|
api.onGenerateFiles((args) => {
|
|
60
|
+
var _a, _b, _c, _d, _e, _f;
|
|
54
61
|
const models = args.isFirstTime
|
|
55
62
|
? api.appData.pluginDva.models
|
|
56
63
|
: getAllModels(api);
|
|
@@ -66,16 +73,29 @@ exports.default = (api) => {
|
|
|
66
73
|
// It's faked dva
|
|
67
74
|
// aliased to @umijs/plugins/templates/dva
|
|
68
75
|
import { create, Provider } from 'dva';
|
|
76
|
+
import createLoading from '${(0, utils_1.winPath)(require.resolve('dva-loading'))}';
|
|
77
|
+
${((_a = api.config.dva) === null || _a === void 0 ? void 0 : _a.immer)
|
|
78
|
+
? `
|
|
79
|
+
import dvaImmer, { enableES5, enableAllPlugins } from '${(0, utils_1.winPath)(require.resolve('dva-immer'))}';
|
|
80
|
+
`
|
|
81
|
+
: ''}
|
|
69
82
|
import React, { useRef } from 'react';
|
|
70
|
-
import { history } from 'umi';
|
|
83
|
+
import { history, ApplyPluginsType, useAppData } from 'umi';
|
|
71
84
|
import { models } from './models';
|
|
72
85
|
|
|
73
86
|
export function RootContainer(props: any) {
|
|
87
|
+
const { pluginManager } = useAppData();
|
|
74
88
|
const app = useRef<any>();
|
|
89
|
+
const runtimeDva = pluginManager.applyPlugins({
|
|
90
|
+
key: 'dva',
|
|
91
|
+
type: ApplyPluginsType.modify,
|
|
92
|
+
initialValue: {},
|
|
93
|
+
});
|
|
75
94
|
if (!app.current) {
|
|
76
95
|
app.current = create(
|
|
77
96
|
{
|
|
78
97
|
history,
|
|
98
|
+
...(runtimeDva.config || {}),
|
|
79
99
|
},
|
|
80
100
|
{
|
|
81
101
|
initialReducer: {},
|
|
@@ -87,6 +107,10 @@ export function RootContainer(props: any) {
|
|
|
87
107
|
},
|
|
88
108
|
},
|
|
89
109
|
);
|
|
110
|
+
app.current.use(createLoading());
|
|
111
|
+
${((_b = api.config.dva) === null || _b === void 0 ? void 0 : _b.immer) ? `app.current.use(dvaImmer());` : ''}
|
|
112
|
+
${((_d = (_c = api.config.dva) === null || _c === void 0 ? void 0 : _c.immer) === null || _d === void 0 ? void 0 : _d.enableES5) ? `enableES5();` : ''}
|
|
113
|
+
${((_f = (_e = api.config.dva) === null || _e === void 0 ? void 0 : _e.immer) === null || _f === void 0 ? void 0 : _f.enableAllPlugins) ? `enableAllPlugins();` : ''}
|
|
90
114
|
for (const id of Object.keys(models)) {
|
|
91
115
|
app.current.model(models[id].model);
|
|
92
116
|
}
|
|
@@ -122,6 +146,7 @@ export { connect, useDispatch, useStore, useSelector } from 'dva';`,
|
|
|
122
146
|
api.addRuntimePlugin(() => {
|
|
123
147
|
return [(0, withTmpPath_1.withTmpPath)({ api, path: 'runtime.tsx' })];
|
|
124
148
|
});
|
|
149
|
+
api.addRuntimePluginKey(() => ['dva']);
|
|
125
150
|
// dva list model
|
|
126
151
|
api.registerCommand({
|
|
127
152
|
name: 'dva',
|
package/dist/initial-state.js
CHANGED
|
@@ -30,8 +30,8 @@ exports.default = (api) => {
|
|
|
30
30
|
import React from 'react';
|
|
31
31
|
import { useModel } from '@@/plugin-model';
|
|
32
32
|
${loading
|
|
33
|
-
? `import Loading from ${loading}`
|
|
34
|
-
: `function Loading() { return <div
|
|
33
|
+
? `import Loading from '${loading}'`
|
|
34
|
+
: `function Loading() { return <div />; }`}
|
|
35
35
|
export default function InitialStateProvider(props: any) {
|
|
36
36
|
const appLoaded = React.useRef(false);
|
|
37
37
|
const { loading = false } = useModel("@@initialState") || {};
|
|
@@ -107,7 +107,7 @@ export default () => ({ loading: false, refresh: () => {} })
|
|
|
107
107
|
content: `
|
|
108
108
|
import React from 'react';
|
|
109
109
|
import Provider from './Provider';
|
|
110
|
-
export function
|
|
110
|
+
export function dataflowProvider(container) {
|
|
111
111
|
return <Provider>{ container }</Provider>;
|
|
112
112
|
}
|
|
113
113
|
`,
|
package/dist/layout.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -18,15 +22,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
21
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
-
};
|
|
24
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
26
|
const allIcons = __importStar(require("@ant-design/icons"));
|
|
26
|
-
const
|
|
27
|
+
const fs_1 = require("fs");
|
|
27
28
|
const path_1 = require("path");
|
|
28
29
|
const plugin_utils_1 = require("umi/plugin-utils");
|
|
29
|
-
const resolveProjectDep_1 = require("./utils/resolveProjectDep");
|
|
30
30
|
const withTmpPath_1 = require("./utils/withTmpPath");
|
|
31
31
|
exports.default = (api) => {
|
|
32
32
|
api.describe({
|
|
@@ -39,11 +39,28 @@ exports.default = (api) => {
|
|
|
39
39
|
},
|
|
40
40
|
enableBy: api.EnableBy.config,
|
|
41
41
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
/**
|
|
43
|
+
* 优先去找 '@alipay/tech-ui',保证稳定性
|
|
44
|
+
*/
|
|
45
|
+
const depList = ['@alipay/tech-ui', '@ant-design/pro-layout'];
|
|
46
|
+
const pkgHasDep = depList.find((dep) => {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const { pkg } = api;
|
|
49
|
+
if (((_a = pkg.dependencies) === null || _a === void 0 ? void 0 : _a[dep]) || ((_b = pkg.devDependencies) === null || _b === void 0 ? void 0 : _b[dep])) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
});
|
|
54
|
+
const getPkgPath = () => {
|
|
55
|
+
// 如果 layout 和 techui至少有一个在,找到他们的地址
|
|
56
|
+
if (pkgHasDep &&
|
|
57
|
+
(0, fs_1.existsSync)((0, path_1.join)(api.cwd, 'node_modules', pkgHasDep, 'package.json'))) {
|
|
58
|
+
return (0, path_1.join)(api.cwd, 'node_modules', pkgHasDep);
|
|
59
|
+
}
|
|
60
|
+
// 如果项目中没有去找插件以来的
|
|
61
|
+
return (0, path_1.dirname)(require.resolve('@ant-design/pro-layout/package.json'));
|
|
62
|
+
};
|
|
63
|
+
const pkgPath = getPkgPath();
|
|
47
64
|
api.modifyAppData((memo) => {
|
|
48
65
|
const version = require(`${pkgPath}/package.json`).version;
|
|
49
66
|
memo.pluginLayout = {
|
|
@@ -53,8 +70,11 @@ exports.default = (api) => {
|
|
|
53
70
|
return memo;
|
|
54
71
|
});
|
|
55
72
|
api.modifyConfig((memo) => {
|
|
56
|
-
//
|
|
57
|
-
|
|
73
|
+
// 只在没有自行依赖 @ant-design/pro-layout 或 @alipay/tech-ui 时
|
|
74
|
+
// 才使用插件中提供的 @ant-design/pro-layout
|
|
75
|
+
if (!pkgHasDep) {
|
|
76
|
+
memo.alias['@ant-design/pro-layout'] = pkgPath;
|
|
77
|
+
}
|
|
58
78
|
return memo;
|
|
59
79
|
});
|
|
60
80
|
api.onGenerateFiles(() => {
|
|
@@ -63,17 +83,23 @@ exports.default = (api) => {
|
|
|
63
83
|
api.writeTmpFile({
|
|
64
84
|
path: 'Layout.tsx',
|
|
65
85
|
content: `
|
|
66
|
-
import { Link, useLocation, useNavigate, Outlet, useAppData,
|
|
67
|
-
import
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
import { Link, useLocation, useNavigate, Outlet, useAppData, useRouteData, matchRoutes } from 'umi';
|
|
87
|
+
import { useMemo } from 'react';
|
|
88
|
+
import {
|
|
89
|
+
ProLayout,
|
|
90
|
+
} from "${pkgHasDep || '@ant-design/pro-layout'}";
|
|
70
91
|
import './Layout.less';
|
|
71
92
|
import Logo from './Logo';
|
|
93
|
+
import Exception from './Exception';
|
|
72
94
|
import { getRightRenderContent } from './rightRender';
|
|
73
95
|
${hasInitialStatePlugin
|
|
74
96
|
? `import { useModel } from '@@/plugin-model';`
|
|
75
97
|
: 'const useModel = null;'}
|
|
76
|
-
|
|
98
|
+
${api.config.access
|
|
99
|
+
? `
|
|
100
|
+
import { useAccessMarkedRoutes } from '@@/plugin-access';
|
|
101
|
+
`.trim()
|
|
102
|
+
: 'const useAccessMarkedRoutes = (r) => r;'}
|
|
77
103
|
${api.config.locale
|
|
78
104
|
? `
|
|
79
105
|
import { useIntl } from '@@/plugin-locale';
|
|
@@ -81,7 +107,7 @@ import { useIntl } from '@@/plugin-locale';
|
|
|
81
107
|
: ''}
|
|
82
108
|
|
|
83
109
|
|
|
84
|
-
export default () => {
|
|
110
|
+
export default (props: any) => {
|
|
85
111
|
const location = useLocation();
|
|
86
112
|
const navigate = useNavigate();
|
|
87
113
|
const { clientRoutes, pluginManager } = useAppData();
|
|
@@ -104,9 +130,8 @@ const { formatMessage } = useIntl();
|
|
|
104
130
|
...initialInfo
|
|
105
131
|
},
|
|
106
132
|
});
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
})[0];
|
|
133
|
+
const matchedRoute = useMemo(() => matchRoutes(clientRoutes, location.pathname).pop()?.route, [location.pathname]);
|
|
134
|
+
const [route] = useAccessMarkedRoutes(clientRoutes.filter(({ id }) => id === 'ant-design-pro-layout'));
|
|
110
135
|
return (
|
|
111
136
|
<ProLayout
|
|
112
137
|
route={route}
|
|
@@ -128,7 +153,8 @@ const { formatMessage } = useIntl();
|
|
|
128
153
|
}
|
|
129
154
|
if (menuItemProps.path && location.pathname !== menuItemProps.path) {
|
|
130
155
|
return (
|
|
131
|
-
|
|
156
|
+
// handle wildcard route path, for example /slave/* from qiankun
|
|
157
|
+
<Link to={menuItemProps.path.replace('/*', '')} target={menuItemProps.target}>
|
|
132
158
|
{defaultDom}
|
|
133
159
|
</Link>
|
|
134
160
|
);
|
|
@@ -162,7 +188,16 @@ const { formatMessage } = useIntl();
|
|
|
162
188
|
})
|
|
163
189
|
}
|
|
164
190
|
>
|
|
165
|
-
<
|
|
191
|
+
<Exception
|
|
192
|
+
route={matchedRoute}
|
|
193
|
+
notFound={runtimeConfig.notFound}
|
|
194
|
+
noAccessible={runtimeConfig.noAccessible}
|
|
195
|
+
>
|
|
196
|
+
{runtimeConfig.childrenRender
|
|
197
|
+
? runtimeConfig.childrenRender(<Outlet />, props)
|
|
198
|
+
: <Outlet />
|
|
199
|
+
}
|
|
200
|
+
</Exception>
|
|
166
201
|
</ProLayout>
|
|
167
202
|
);
|
|
168
203
|
}
|
|
@@ -172,9 +207,6 @@ const { formatMessage } = useIntl();
|
|
|
172
207
|
const { icon } = api.appData.routes[id];
|
|
173
208
|
if (icon) {
|
|
174
209
|
const upperIcon = plugin_utils_1.lodash.upperFirst(plugin_utils_1.lodash.camelCase(icon));
|
|
175
|
-
(0, assert_1.default)(
|
|
176
|
-
// @ts-ignore
|
|
177
|
-
allIcons[upperIcon] || allIcons[`${upperIcon}Outlined`], `Icon ${upperIcon} is not found`);
|
|
178
210
|
// @ts-ignore
|
|
179
211
|
if (allIcons[upperIcon]) {
|
|
180
212
|
memo[upperIcon] = true;
|
|
@@ -219,7 +251,9 @@ export function patchRoutes({ routes }) {
|
|
|
219
251
|
const { icon } = routes[key];
|
|
220
252
|
if (icon && typeof icon === 'string') {
|
|
221
253
|
const upperIcon = formatIcon(icon);
|
|
222
|
-
|
|
254
|
+
if (icons[upperIcon] || icons[upperIcon + 'Outlined']) {
|
|
255
|
+
routes[key].icon = React.createElement(icons[upperIcon] || icons[upperIcon + 'Outlined']);
|
|
256
|
+
}
|
|
223
257
|
}
|
|
224
258
|
});
|
|
225
259
|
}
|
|
@@ -464,6 +498,43 @@ const LogoIcon: React.FC = () => {
|
|
|
464
498
|
export default LogoIcon;
|
|
465
499
|
`,
|
|
466
500
|
});
|
|
501
|
+
api.writeTmpFile({
|
|
502
|
+
path: 'Exception.tsx',
|
|
503
|
+
content: `
|
|
504
|
+
import React from 'react';
|
|
505
|
+
import { history, type IRoute } from 'umi';
|
|
506
|
+
import { Result, Button } from 'antd';
|
|
507
|
+
|
|
508
|
+
const Exception: React.FC<{
|
|
509
|
+
children: React.ReactNode;
|
|
510
|
+
route?: IRoute;
|
|
511
|
+
notFound?: React.ReactNode;
|
|
512
|
+
noAccessible?: React.ReactNode;
|
|
513
|
+
}> = (props) => (
|
|
514
|
+
// render custom 404
|
|
515
|
+
(!props.route && props.notFound) ||
|
|
516
|
+
// render custom 403
|
|
517
|
+
(props.route.unaccessible && props.noAccessible) ||
|
|
518
|
+
// render default exception
|
|
519
|
+
((!props.route || props.route.unaccessible) && (
|
|
520
|
+
<Result
|
|
521
|
+
status={props.route ? '403' : '404'}
|
|
522
|
+
title={props.route ? '403' : '404'}
|
|
523
|
+
subTitle={props.route ? '抱歉,你无权访问该页面' : '抱歉,你访问的页面不存在'}
|
|
524
|
+
extra={
|
|
525
|
+
<Button type="primary" onClick={() => history.push('/')}>
|
|
526
|
+
返回首页
|
|
527
|
+
</Button>
|
|
528
|
+
}
|
|
529
|
+
/>
|
|
530
|
+
)) ||
|
|
531
|
+
// normal render
|
|
532
|
+
props.children
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
export default Exception;
|
|
536
|
+
`,
|
|
537
|
+
});
|
|
467
538
|
});
|
|
468
539
|
api.addLayouts(() => {
|
|
469
540
|
return [
|