@allahjs/umi-plugin-layout-lite 0.1.0
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/README.md +46 -0
- package/dist/Layout.d.ts +5 -0
- package/dist/Layout.js +127 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +19 -0
- package/dist/runtime.d.ts +3 -0
- package/dist/runtime.js +44 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @allahjs/umi-plugin-layout-lite
|
|
2
|
+
|
|
3
|
+
轻量版 Umi Layout 插件,替代官方 layout 插件并保留常用能力:
|
|
4
|
+
|
|
5
|
+
- 自动注入全局布局(基于 `ProLayout`)
|
|
6
|
+
- 支持 `export const layout = (...) => ({ ... })` 运行时配置
|
|
7
|
+
- 支持 `rightRender` / `rightContentRender`
|
|
8
|
+
- 兼容 `@ant-design/pro-components` 3.x:内部自动把 `rightContentRender` 适配为 `actionsRender`
|
|
9
|
+
- 支持路由 `icon` 字符串自动映射
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i @allahjs/umi-plugin-layout-lite
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 使用
|
|
18
|
+
|
|
19
|
+
在 `config/config.ts` 中:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { defineConfig } from '@umijs/max'
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
layout: false,
|
|
26
|
+
plugins: [require.resolve('@allahjs/umi-plugin-layout-lite')],
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
在 `src/app.tsx` 中:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
export const layout = ({ initialState }: any) => ({
|
|
34
|
+
title: '管理系统',
|
|
35
|
+
rightContentRender: (_layoutProps: any, _dom: any, _meta: any) => {
|
|
36
|
+
return <div>自定义右上角</div>
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 发布
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
cd packages/umi-plugin-layout-lite
|
|
45
|
+
npm publish --access public
|
|
46
|
+
```
|
package/dist/Layout.d.ts
ADDED
package/dist/Layout.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var max = require('@umijs/max');
|
|
6
|
+
var proComponents = require('@ant-design/pro-components');
|
|
7
|
+
var antd = require('antd');
|
|
8
|
+
|
|
9
|
+
const Exception = props => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
return ((!props.route && (props.noFound || props.notFound)) ||
|
|
12
|
+
(((_a = props.route) === null || _a === void 0 ? void 0 : _a.unaccessible) &&
|
|
13
|
+
(props.unAccessible || props.noAccessible)) ||
|
|
14
|
+
((!props.route || ((_b = props.route) === null || _b === void 0 ? void 0 : _b.unaccessible)) && (jsxRuntime.jsx(antd.Result, { status: props.route ? '403' : '404', title: props.route ? '403' : '404', subTitle: props.route ? '抱歉,你无权访问该页面' : '抱歉,你访问的页面不存在', extra: jsxRuntime.jsx(antd.Button, { type: "primary", onClick: () => max.history.push('/'), children: "\u8FD4\u56DE\u9996\u9875" }) }))) ||
|
|
15
|
+
props.children);
|
|
16
|
+
};
|
|
17
|
+
function getRightRenderContent(opts) {
|
|
18
|
+
if (opts.runtimeConfig.rightRender) {
|
|
19
|
+
return opts.runtimeConfig.rightRender(opts.initialState, opts.setInitialState, opts.runtimeConfig);
|
|
20
|
+
}
|
|
21
|
+
if (opts.loading) {
|
|
22
|
+
return jsxRuntime.jsx(antd.Spin, { size: "small", style: { marginLeft: 8, marginRight: 8 } });
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const filterRoutes = (routes, filterFn) => {
|
|
27
|
+
if (routes.length === 0)
|
|
28
|
+
return [];
|
|
29
|
+
const nextRoutes = [];
|
|
30
|
+
for (const route of routes) {
|
|
31
|
+
const nextRoute = { ...route };
|
|
32
|
+
if (filterFn(route)) {
|
|
33
|
+
if (Array.isArray(nextRoute.routes)) {
|
|
34
|
+
nextRoutes.push(...filterRoutes(nextRoute.routes, filterFn));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (Array.isArray(nextRoute.children)) {
|
|
39
|
+
nextRoute.children = filterRoutes(nextRoute.children, filterFn);
|
|
40
|
+
nextRoute.routes = nextRoute.children;
|
|
41
|
+
}
|
|
42
|
+
nextRoutes.push(nextRoute);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return nextRoutes;
|
|
46
|
+
};
|
|
47
|
+
const mapRoutes = (routes) => {
|
|
48
|
+
if (routes.length === 0)
|
|
49
|
+
return [];
|
|
50
|
+
return routes.map(route => {
|
|
51
|
+
const nextRoute = { ...route };
|
|
52
|
+
if (route.originPath) {
|
|
53
|
+
nextRoute.path = route.originPath;
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(route.routes)) {
|
|
56
|
+
nextRoute.routes = mapRoutes(route.routes);
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(route.children)) {
|
|
59
|
+
nextRoute.children = mapRoutes(route.children);
|
|
60
|
+
}
|
|
61
|
+
return nextRoute;
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
function LayoutLite(props) {
|
|
65
|
+
const location = max.useLocation();
|
|
66
|
+
const navigate = max.useNavigate();
|
|
67
|
+
const { clientRoutes, pluginManager } = max.useAppData();
|
|
68
|
+
const initialInfo = max.useModel('@@initialState') || {
|
|
69
|
+
initialState: undefined,
|
|
70
|
+
loading: false,
|
|
71
|
+
setInitialState: null,
|
|
72
|
+
};
|
|
73
|
+
const { initialState, loading, setInitialState } = initialInfo;
|
|
74
|
+
const runtimeConfig = pluginManager.applyPlugins({
|
|
75
|
+
key: 'layout',
|
|
76
|
+
type: 'modify',
|
|
77
|
+
initialValue: {
|
|
78
|
+
...initialInfo,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
const userConfig = {};
|
|
82
|
+
const newRoutes = filterRoutes(clientRoutes.filter((route) => route.id === 'layout-lite'), route => (route.isLayout && route.id !== 'layout-lite') || !!route.isWrapper);
|
|
83
|
+
const route = mapRoutes(newRoutes)[0];
|
|
84
|
+
const matchedRoute = React.useMemo(() => { var _a, _b, _c; return (_c = (_b = (_a = max.matchRoutes((route === null || route === void 0 ? void 0 : route.children) || [], location.pathname)) === null || _a === void 0 ? void 0 : _a.pop) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.route; }, [route, location.pathname]);
|
|
85
|
+
const renderRightActions = (layoutProps) => {
|
|
86
|
+
const dom = getRightRenderContent({
|
|
87
|
+
runtimeConfig,
|
|
88
|
+
loading,
|
|
89
|
+
initialState,
|
|
90
|
+
setInitialState,
|
|
91
|
+
});
|
|
92
|
+
if (runtimeConfig.rightContentRender) {
|
|
93
|
+
return runtimeConfig.rightContentRender(layoutProps, dom, {
|
|
94
|
+
userConfig,
|
|
95
|
+
runtimeConfig,
|
|
96
|
+
loading,
|
|
97
|
+
initialState,
|
|
98
|
+
setInitialState,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return dom;
|
|
102
|
+
};
|
|
103
|
+
return (jsxRuntime.jsx(proComponents.ProLayout, { route: route, location: location, title: runtimeConfig.title || 'layout-lite', menu: { locale: runtimeConfig.locale }, onMenuHeaderClick: event => {
|
|
104
|
+
event.stopPropagation();
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
navigate('/');
|
|
107
|
+
}, menuItemRender: (menuItemProps, defaultDom) => {
|
|
108
|
+
if (menuItemProps.isUrl || menuItemProps.children) {
|
|
109
|
+
return defaultDom;
|
|
110
|
+
}
|
|
111
|
+
if (menuItemProps.path && location.pathname !== menuItemProps.path) {
|
|
112
|
+
return (jsxRuntime.jsx(max.Link, { to: menuItemProps.path.replace('/*', ''), target: menuItemProps.target, children: defaultDom }));
|
|
113
|
+
}
|
|
114
|
+
return defaultDom;
|
|
115
|
+
}, itemRender: (currentRoute, _, routes) => {
|
|
116
|
+
const label = currentRoute.title || currentRoute.breadcrumbName;
|
|
117
|
+
const lastRoute = routes[routes.length - 1];
|
|
118
|
+
if (lastRoute && (lastRoute.path === currentRoute.path || lastRoute.linkPath === currentRoute.path)) {
|
|
119
|
+
return jsxRuntime.jsx("span", { children: label });
|
|
120
|
+
}
|
|
121
|
+
return jsxRuntime.jsx(max.Link, { to: currentRoute.path || '/', children: label });
|
|
122
|
+
}, actionsRender: renderRightActions, ...runtimeConfig, children: jsxRuntime.jsx(Exception, { route: matchedRoute, noFound: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.noFound, notFound: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.notFound, unAccessible: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.unAccessible, noAccessible: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.noAccessible, children: runtimeConfig.childrenRender
|
|
123
|
+
? runtimeConfig.childrenRender(jsxRuntime.jsx(max.Outlet, {}), props)
|
|
124
|
+
: jsxRuntime.jsx(max.Outlet, {}) }) }));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = LayoutLite;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = (api) => {
|
|
4
|
+
api.addLayouts(() => {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
id: 'layout-lite',
|
|
8
|
+
file: require.resolve('./Layout'),
|
|
9
|
+
test: (route) => route.layout !== false,
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
});
|
|
13
|
+
api.addRuntimePluginKey(() => ['layout']);
|
|
14
|
+
api.addRuntimePlugin(() => {
|
|
15
|
+
return [require.resolve('./runtime')];
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = index;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var Icons = require('@ant-design/icons');
|
|
5
|
+
|
|
6
|
+
function _interopNamespaceDefault(e) {
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var Icons__namespace = /*#__PURE__*/_interopNamespaceDefault(Icons);
|
|
24
|
+
|
|
25
|
+
function formatIcon(name) {
|
|
26
|
+
return name
|
|
27
|
+
.replace(name[0], name[0].toUpperCase())
|
|
28
|
+
.replace(/-(\w)/g, (_all, letter) => letter.toUpperCase());
|
|
29
|
+
}
|
|
30
|
+
function patchRoutes({ routes }) {
|
|
31
|
+
Object.keys(routes).forEach(key => {
|
|
32
|
+
var _a;
|
|
33
|
+
const icon = (_a = routes[key]) === null || _a === void 0 ? void 0 : _a.icon;
|
|
34
|
+
if (!icon || typeof icon !== 'string')
|
|
35
|
+
return;
|
|
36
|
+
const iconName = formatIcon(icon);
|
|
37
|
+
const IconComponent = Icons__namespace[iconName] || Icons__namespace[`${iconName}Outlined`];
|
|
38
|
+
if (IconComponent) {
|
|
39
|
+
routes[key].icon = React.createElement(IconComponent);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.patchRoutes = patchRoutes;
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@allahjs/umi-plugin-layout-lite",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight Umi layout plugin with ProLayout and rightContentRender compatibility.",
|
|
5
|
+
"repository": "https://github.com/allah-prime/umi-plugin-layout-lite",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "rimraf dist && rollup -c",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"umi",
|
|
25
|
+
"umijs",
|
|
26
|
+
"plugin",
|
|
27
|
+
"layout",
|
|
28
|
+
"prolayout",
|
|
29
|
+
"antd"
|
|
30
|
+
],
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@ant-design/icons": ">=6",
|
|
33
|
+
"@ant-design/pro-components": ">=3.0.0-0",
|
|
34
|
+
"@umijs/max": ">=4",
|
|
35
|
+
"antd": ">=6",
|
|
36
|
+
"react": ">=18",
|
|
37
|
+
"react-dom": ">=18",
|
|
38
|
+
"umi": ">=4"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@rollup/plugin-commonjs": "^28.0.9",
|
|
42
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
43
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
44
|
+
"@types/node": "^24.3.0",
|
|
45
|
+
"@types/react": "^19.2.0",
|
|
46
|
+
"rimraf": "^6.0.1",
|
|
47
|
+
"rollup": "^4.50.1",
|
|
48
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
49
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
50
|
+
"tslib": "^2.8.1",
|
|
51
|
+
"typescript": "^5.9.0"
|
|
52
|
+
},
|
|
53
|
+
"license": "MIT"
|
|
54
|
+
}
|