@umijs/plugins 4.0.0-beta.8 → 4.0.0-canary-20240513.3

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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -1
  3. package/dist/access.d.ts +1 -1
  4. package/dist/access.js +194 -4
  5. package/dist/{sass.d.ts → analytics.d.ts} +1 -1
  6. package/dist/analytics.js +118 -0
  7. package/dist/antd.d.ts +1 -1
  8. package/dist/antd.js +345 -157
  9. package/dist/{icons.d.ts → confetti.d.ts} +1 -1
  10. package/dist/confetti.js +64 -0
  11. package/dist/constants.d.ts +1 -0
  12. package/dist/constants.js +30 -0
  13. package/dist/dva.d.ts +4 -1
  14. package/dist/dva.js +302 -8
  15. package/dist/initial-state.d.ts +1 -1
  16. package/dist/initial-state.js +147 -4
  17. package/dist/layout.d.ts +1 -1
  18. package/dist/layout.js +754 -4
  19. package/dist/locale.d.ts +2 -1
  20. package/dist/locale.js +257 -4
  21. package/dist/mf.d.ts +2 -0
  22. package/dist/mf.js +358 -0
  23. package/dist/model.d.ts +1 -1
  24. package/dist/model.js +109 -4
  25. package/dist/moment2dayjs.d.ts +3 -0
  26. package/dist/moment2dayjs.js +125 -0
  27. package/dist/qiankun/constants.d.ts +5 -0
  28. package/dist/qiankun/constants.js +41 -0
  29. package/dist/qiankun/master.d.ts +6 -0
  30. package/dist/qiankun/master.js +236 -0
  31. package/dist/qiankun/slave.d.ts +3 -0
  32. package/dist/qiankun/slave.js +345 -0
  33. package/dist/qiankun.d.ts +1 -1
  34. package/dist/qiankun.js +51 -4
  35. package/dist/react-query.d.ts +3 -0
  36. package/dist/react-query.js +193 -0
  37. package/dist/request.d.ts +1 -1
  38. package/dist/request.js +384 -4
  39. package/dist/styled-components.d.ts +3 -0
  40. package/dist/styled-components.js +150 -0
  41. package/dist/tailwindcss.d.ts +3 -0
  42. package/dist/tailwindcss.js +106 -0
  43. package/dist/unocss.d.ts +3 -0
  44. package/dist/unocss.js +71 -0
  45. package/dist/utils/astUtils.d.ts +3 -0
  46. package/dist/utils/astUtils.js +49 -0
  47. package/dist/utils/localeUtils.d.ts +33 -0
  48. package/dist/utils/localeUtils.js +139 -0
  49. package/dist/utils/mfUtils.d.ts +14 -0
  50. package/dist/utils/mfUtils.js +56 -0
  51. package/dist/utils/modelUtils.d.ts +40 -0
  52. package/dist/utils/modelUtils.js +286 -0
  53. package/dist/utils/resolveProjectDep.d.ts +5 -0
  54. package/dist/utils/resolveProjectDep.js +40 -0
  55. package/dist/utils/withTmpPath.d.ts +6 -0
  56. package/dist/utils/withTmpPath.js +39 -0
  57. package/dist/valtio.d.ts +3 -0
  58. package/dist/valtio.js +81 -0
  59. package/libs/dva.tsx +45 -0
  60. package/libs/model.tsx +180 -0
  61. package/libs/qiankun/master/AntdErrorBoundary.tsx +34 -0
  62. package/libs/qiankun/master/AntdLoader.tsx +15 -0
  63. package/libs/qiankun/master/ErrorBoundary.tsx +7 -0
  64. package/libs/qiankun/master/MicroApp.tsx +327 -0
  65. package/libs/qiankun/master/MicroAppWithMemoHistory.tsx +43 -0
  66. package/libs/qiankun/master/common.ts +172 -0
  67. package/libs/qiankun/master/constants.ts +19 -0
  68. package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +45 -0
  69. package/libs/qiankun/master/masterRuntimePlugin.tsx +161 -0
  70. package/libs/qiankun/master/routeUtils.ts +26 -0
  71. package/libs/qiankun/master/types.ts +54 -0
  72. package/libs/qiankun/slave/MicroAppLink.tsx +122 -0
  73. package/libs/qiankun/slave/connectMaster.tsx +14 -0
  74. package/libs/qiankun/slave/constants.ts +5 -0
  75. package/libs/qiankun/slave/lifecycles.ts +164 -0
  76. package/libs/qiankun/slave/qiankunModel.ts +18 -0
  77. package/libs/qiankun/slave/slaveRuntimePlugin.ts +36 -0
  78. package/package.json +54 -24
  79. package/templates/antd/runtime.ts.tpl +170 -0
  80. package/templates/antd/types.d.ts.tpl +17 -0
  81. package/templates/locale/SelectLang.tpl +502 -0
  82. package/templates/locale/locale.tpl +82 -0
  83. package/templates/locale/localeExports.tpl +307 -0
  84. package/templates/locale/runtime.tpl +34 -0
  85. package/templates/mf/runtime.ts.tpl +149 -0
  86. package/dist/access.d.ts.map +0 -1
  87. package/dist/antd.d.ts.map +0 -1
  88. package/dist/dva.d.ts.map +0 -1
  89. package/dist/icons.d.ts.map +0 -1
  90. package/dist/icons.js +0 -5
  91. package/dist/initial-state.d.ts.map +0 -1
  92. package/dist/layout.d.ts.map +0 -1
  93. package/dist/locale.d.ts.map +0 -1
  94. package/dist/model.d.ts.map +0 -1
  95. package/dist/qiankun.d.ts.map +0 -1
  96. package/dist/request.d.ts.map +0 -1
  97. package/dist/sass.d.ts.map +0 -1
  98. package/dist/sass.js +0 -5
package/dist/layout.js CHANGED
@@ -1,5 +1,755 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = (api) => {
4
- api;
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/layout.ts
30
+ var layout_exports = {};
31
+ __export(layout_exports, {
32
+ default: () => layout_default
33
+ });
34
+ module.exports = __toCommonJS(layout_exports);
35
+ var import_fs = require("fs");
36
+ var import_path = require("path");
37
+ var import_umi = require("umi");
38
+ var import_plugin_utils = require("umi/plugin-utils");
39
+ var import_resolveProjectDep = require("./utils/resolveProjectDep");
40
+ var import_withTmpPath = require("./utils/withTmpPath");
41
+ var antIconsPath = (0, import_plugin_utils.winPath)(
42
+ (0, import_path.dirname)(require.resolve("@ant-design/icons/package"))
43
+ );
44
+ var getAllIcons = () => {
45
+ const iconTypePath = (0, import_path.join)(antIconsPath, "./lib/icons/index.d.ts");
46
+ const iconTypeContent = (0, import_fs.readFileSync)(iconTypePath, "utf-8");
47
+ return [...iconTypeContent.matchAll(/default as (\w+)/g)].reduce(
48
+ (memo, cur) => {
49
+ memo[cur[1]] = true;
50
+ return memo;
51
+ },
52
+ {}
53
+ );
54
+ };
55
+ var ANT_PRO_COMPONENT = "@ant-design/pro-components";
56
+ var layout_default = (api) => {
57
+ let antdVersion = "4.0.0";
58
+ try {
59
+ const pkgPath2 = (0, import_resolveProjectDep.resolveProjectDep)({
60
+ pkg: api.pkg,
61
+ cwd: api.cwd,
62
+ dep: "antd"
63
+ }) || (0, import_path.dirname)(require.resolve("antd/package.json"));
64
+ antdVersion = require(`${pkgPath2}/package.json`).version;
65
+ } catch (e) {
66
+ }
67
+ const packageName = api.pkg.name || "plugin-layout";
68
+ const isAntd5 = antdVersion.startsWith("5");
69
+ const layoutFile = isAntd5 ? "Layout.css" : "Layout.less";
70
+ api.describe({
71
+ key: "layout",
72
+ config: {
73
+ schema({ zod }) {
74
+ return zod.record(zod.any());
75
+ },
76
+ onChange: api.ConfigChangeType.regenerateTmpFiles
77
+ },
78
+ enableBy: api.EnableBy.config
79
+ });
80
+ const depList = [
81
+ "@alipay/tech-ui",
82
+ ANT_PRO_COMPONENT,
83
+ "@ant-design/pro-layout"
84
+ ];
85
+ const pkgHasDep = depList.find((dep) => {
86
+ var _a, _b;
87
+ const { pkg } = api;
88
+ if (((_a = pkg.dependencies) == null ? void 0 : _a[dep]) || ((_b = pkg.devDependencies) == null ? void 0 : _b[dep])) {
89
+ return true;
90
+ }
91
+ return false;
92
+ });
93
+ const getPkgPath = () => {
94
+ if (pkgHasDep && (0, import_fs.existsSync)((0, import_path.join)(api.cwd, "node_modules", pkgHasDep, "package.json"))) {
95
+ return (0, import_path.join)(api.cwd, "node_modules", pkgHasDep);
96
+ }
97
+ const cwd = process.cwd();
98
+ if (pkgHasDep && api.cwd !== cwd && (0, import_fs.existsSync)((0, import_path.join)(cwd, "node_modules", pkgHasDep, "package.json"))) {
99
+ return (0, import_path.join)(cwd, "node_modules", pkgHasDep);
100
+ }
101
+ return (0, import_path.dirname)(require.resolve(`${ANT_PRO_COMPONENT}/package.json`));
102
+ };
103
+ const pkgPath = (0, import_plugin_utils.winPath)(getPkgPath());
104
+ const resolvedPkgPath = pkgPath || ANT_PRO_COMPONENT;
105
+ api.modifyAppData((memo) => {
106
+ const version = require(`${pkgPath}/package.json`).version;
107
+ memo.pluginLayout = {
108
+ pkgPath,
109
+ version
110
+ };
111
+ return memo;
112
+ });
113
+ api.modifyConfig((memo) => {
114
+ if (!pkgHasDep) {
115
+ const name = require(`${pkgPath}/package.json`).name;
116
+ memo.alias[name] = pkgPath;
117
+ }
118
+ return memo;
119
+ });
120
+ api.onGenerateFiles(() => {
121
+ var _a;
122
+ let realNpmClient = api.appData.npmClient;
123
+ if (api.appData.npmClient === import_plugin_utils.NpmClientEnum.tnpm && ((_a = api.pkg.tnpm) == null ? void 0 : _a.mode) && [import_plugin_utils.NpmClientEnum.npm, import_plugin_utils.NpmClientEnum.yarn].includes(api.pkg.tnpm.mode)) {
124
+ realNpmClient = api.pkg.tnpm.mode;
125
+ }
126
+ const isFlattedDepsDir = [import_plugin_utils.NpmClientEnum.npm, import_plugin_utils.NpmClientEnum.yarn].includes(
127
+ realNpmClient
128
+ );
129
+ const PKG_TYPE_REFERENCE = `
130
+ /// <reference types="${isFlattedDepsDir ? ANT_PRO_COMPONENT : resolvedPkgPath}" />
131
+ ${isFlattedDepsDir ? '/// <reference types="antd" />' : ""}
132
+ `.trimStart();
133
+ const hasInitialStatePlugin = api.config.initialState;
134
+ api.writeTmpFile({
135
+ path: "Layout.tsx",
136
+ content: `
137
+ ${PKG_TYPE_REFERENCE}
138
+ import {
139
+ Link, useLocation, useNavigate, Outlet, useAppData, matchRoutes,
140
+ type IRoute
141
+ } from '${api.appData.umi.importSource}';
142
+ import React, { useMemo } from 'react';
143
+ import {
144
+ ProLayout,
145
+ } from "${resolvedPkgPath}";
146
+ import './${layoutFile}';
147
+ import Logo from './Logo';
148
+ import Exception from './Exception';
149
+ import { getRightRenderContent } from './rightRender';
150
+ ${hasInitialStatePlugin ? `import { useModel } from '@@/plugin-model';` : "const useModel = null;"}
151
+ ${api.config.access ? `
152
+ import { useAccessMarkedRoutes } from '@@/plugin-access';
153
+ `.trim() : "const useAccessMarkedRoutes = (r) => r;"}
154
+ ${api.config.locale ? `
155
+ import { useIntl } from '@@/plugin-locale';
156
+ `.trim() : ""}
157
+
158
+ // 过滤出需要显示的路由, 这里的filterFn 指 不希望显示的层级
159
+ const filterRoutes = (routes: IRoute[], filterFn: (route: IRoute) => boolean) => {
160
+ if (routes.length === 0) {
161
+ return []
162
+ }
163
+
164
+ let newRoutes = []
165
+ for (const route of routes) {
166
+ const newRoute = {...route };
167
+ if (filterFn(route)) {
168
+ if (Array.isArray(newRoute.routes)) {
169
+ newRoutes.push(...filterRoutes(newRoute.routes, filterFn))
170
+ }
171
+ } else {
172
+ if (Array.isArray(newRoute.children)) {
173
+ newRoute.children = filterRoutes(newRoute.children, filterFn);
174
+ newRoute.routes = newRoute.children;
175
+ }
176
+ newRoutes.push(newRoute);
177
+ }
178
+ }
179
+
180
+ return newRoutes;
181
+ }
182
+
183
+ // 格式化路由 处理因 wrapper 导致的 菜单 path 不一致
184
+ const mapRoutes = (routes: IRoute[]) => {
185
+ if (routes.length === 0) {
186
+ return []
187
+ }
188
+ return routes.map(route => {
189
+ // 需要 copy 一份, 否则会污染原始数据
190
+ const newRoute = {...route}
191
+ if (route.originPath) {
192
+ newRoute.path = route.originPath
193
+ }
194
+
195
+ if (Array.isArray(route.routes)) {
196
+ newRoute.routes = mapRoutes(route.routes);
197
+ }
198
+
199
+ if (Array.isArray(route.children)) {
200
+ newRoute.children = mapRoutes(route.children);
201
+ }
202
+
203
+ return newRoute
204
+ })
205
+ }
206
+
207
+ export default (props: any) => {
208
+ const location = useLocation();
209
+ const navigate = useNavigate();
210
+ const { clientRoutes, pluginManager } = useAppData();
211
+ const initialInfo = (useModel && useModel('@@initialState')) || {
212
+ initialState: undefined,
213
+ loading: false,
214
+ setInitialState: null,
215
+ };
216
+ const { initialState, loading, setInitialState } = initialInfo;
217
+ const userConfig = ${JSON.stringify(api.config.layout, null, 2)};
218
+ ${api.config.locale ? `
219
+ const { formatMessage } = useIntl();
220
+ `.trim() : "const formatMessage = undefined;"}
221
+ const runtimeConfig = pluginManager.applyPlugins({
222
+ key: 'layout',
223
+ type: 'modify',
224
+ initialValue: {
225
+ ...initialInfo
226
+ },
227
+ });
228
+
229
+
230
+ // 现在的 layout 及 wrapper 实现是通过父路由的形式实现的, 会导致路由数据多了冗余层级, proLayout 消费时, 无法正确展示菜单, 这里对冗余数据进行过滤操作
231
+ const newRoutes = filterRoutes(clientRoutes.filter(route => route.id === 'ant-design-pro-layout'), (route) => {
232
+ return (!!route.isLayout && route.id !== 'ant-design-pro-layout') || !!route.isWrapper;
233
+ })
234
+ const [route] = useAccessMarkedRoutes(mapRoutes(newRoutes));
235
+
236
+ const matchedRoute = useMemo(() => matchRoutes(route.children, location.pathname)?.pop?.()?.route, [location.pathname]);
237
+
238
+ return (
239
+ <ProLayout
240
+ route={route}
241
+ location={location}
242
+ title={userConfig.title || '${packageName}'}
243
+ navTheme="dark"
244
+ siderWidth={256}
245
+ onMenuHeaderClick={(e) => {
246
+ e.stopPropagation();
247
+ e.preventDefault();
248
+ navigate('/');
249
+ }}
250
+ formatMessage={userConfig.formatMessage || formatMessage}
251
+ menu={{ locale: userConfig.locale }}
252
+ logo={Logo}
253
+ menuItemRender={(menuItemProps, defaultDom) => {
254
+ if (menuItemProps.isUrl || menuItemProps.children) {
255
+ return defaultDom;
256
+ }
257
+ if (menuItemProps.path && location.pathname !== menuItemProps.path) {
258
+ return (
259
+ // handle wildcard route path, for example /slave/* from qiankun
260
+ <Link to={menuItemProps.path.replace('/*', '')} target={menuItemProps.target}>
261
+ {defaultDom}
262
+ </Link>
263
+ );
264
+ }
265
+ return defaultDom;
266
+ }}
267
+ itemRender={(route, _, routes) => {
268
+ const { breadcrumbName, title, path } = route;
269
+ const label = title || breadcrumbName
270
+ const last = routes[routes.length - 1]
271
+ if (last) {
272
+ if (last.path === path || last.linkPath === path) {
273
+ return <span>{label}</span>;
274
+ }
275
+ }
276
+ return <Link to={path}>{label}</Link>;
277
+ }}
278
+ disableContentMargin
279
+ fixSiderbar
280
+ fixedHeader
281
+ {...runtimeConfig}
282
+ rightContentRender={
283
+ runtimeConfig.rightContentRender !== false &&
284
+ ((layoutProps) => {
285
+ const dom = getRightRenderContent({
286
+ runtimeConfig,
287
+ loading,
288
+ initialState,
289
+ setInitialState,
290
+ });
291
+ if (runtimeConfig.rightContentRender) {
292
+ return runtimeConfig.rightContentRender(layoutProps, dom, {
293
+ // BREAK CHANGE userConfig > runtimeConfig
294
+ userConfig,
295
+ runtimeConfig,
296
+ loading,
297
+ initialState,
298
+ setInitialState,
299
+ });
300
+ }
301
+ return dom;
302
+ })
303
+ }
304
+ >
305
+ <Exception
306
+ route={matchedRoute}
307
+ noFound={runtimeConfig?.noFound}
308
+ notFound={runtimeConfig?.notFound}
309
+ unAccessible={runtimeConfig?.unAccessible}
310
+ noAccessible={runtimeConfig?.noAccessible}
311
+ >
312
+ {runtimeConfig.childrenRender
313
+ ? runtimeConfig.childrenRender(<Outlet />, props)
314
+ : <Outlet />
315
+ }
316
+ </Exception>
317
+ </ProLayout>
318
+ );
319
+ }
320
+ `
321
+ });
322
+ api.writeTmpFile({
323
+ path: "index.ts",
324
+ content: `export type TempType = string`
325
+ });
326
+ api.writeTmpFile({
327
+ path: "types.d.ts",
328
+ content: `
329
+ ${PKG_TYPE_REFERENCE}
330
+ import type { ProLayoutProps, HeaderProps } from "${resolvedPkgPath}";
331
+ ${hasInitialStatePlugin ? `import type InitialStateType from '@@/plugin-initialState/@@initialState';
332
+ type InitDataType = ReturnType<typeof InitialStateType>;
333
+ ` : "type InitDataType = any;"}
334
+
335
+ import type { IConfigFromPlugins } from '@@/core/pluginConfig';
336
+
337
+ export type RunTimeLayoutConfig = (initData: InitDataType) => Omit<
338
+ ProLayoutProps,
339
+ 'rightContentRender'
340
+ > & {
341
+ childrenRender?: (dom: JSX.Element, props: ProLayoutProps) => React.ReactNode;
342
+ unAccessible?: JSX.Element;
343
+ noFound?: JSX.Element;
344
+ logout?: (initialState: InitDataType['initialState']) => Promise<void> | void;
345
+ rightContentRender?: ((
346
+ headerProps: HeaderProps,
347
+ dom: JSX.Element,
348
+ props: {
349
+ userConfig: IConfigFromPlugins['layout'];
350
+ runtimeConfig: RunTimeLayoutConfig;
351
+ loading: InitDataType['loading'];
352
+ initialState: InitDataType['initialState'];
353
+ setInitialState: InitDataType['setInitialState'];
354
+ },
355
+ ) => JSX.Element) | false;
356
+ rightRender?: (
357
+ initialState: InitDataType['initialState'],
358
+ setInitialState: InitDataType['setInitialState'],
359
+ runtimeConfig: RunTimeLayoutConfig,
360
+ ) => JSX.Element;
361
+ };
362
+ `.trimStart()
363
+ });
364
+ api.writeTmpFile({
365
+ path: import_umi.RUNTIME_TYPE_FILE_NAME,
366
+ content: `
367
+ import type { RunTimeLayoutConfig } from './types.d';
368
+ export interface IRuntimeConfig {
369
+ layout?: RunTimeLayoutConfig
370
+ }
371
+ `
372
+ });
373
+ const allIcons = getAllIcons();
374
+ const iconsMap = Object.keys(api.appData.routes).reduce((memo, id) => {
375
+ const { icon } = api.appData.routes[id];
376
+ if (icon) {
377
+ const upperIcon = import_plugin_utils.lodash.upperFirst(import_plugin_utils.lodash.camelCase(icon));
378
+ if (allIcons[upperIcon]) {
379
+ memo[upperIcon] = true;
380
+ }
381
+ if (allIcons[`${upperIcon}Outlined`]) {
382
+ memo[`${upperIcon}Outlined`] = true;
383
+ }
384
+ }
385
+ return memo;
386
+ }, {});
387
+ const icons = Object.keys(iconsMap);
388
+ api.writeTmpFile({
389
+ path: "icons.tsx",
390
+ content: `
391
+ ${icons.map((icon) => {
392
+ return `import ${icon} from '${antIconsPath}/es/icons/${icon}';`;
393
+ }).join("\n")}
394
+ export default { ${icons.join(", ")} };
395
+ `
396
+ });
397
+ api.writeTmpFile({
398
+ path: "runtime.tsx",
399
+ content: `
400
+ import React from 'react';
401
+ import icons from './icons';
402
+
403
+ function formatIcon(name: string) {
404
+ return name
405
+ .replace(name[0], name[0].toUpperCase())
406
+ .replace(/-(w)/g, function(all, letter) {
407
+ return letter.toUpperCase();
408
+ });
409
+ }
410
+
411
+ export function patchRoutes({ routes }) {
412
+ Object.keys(routes).forEach(key => {
413
+ const { icon } = routes[key];
414
+ if (icon && typeof icon === 'string') {
415
+ const upperIcon = formatIcon(icon);
416
+ if (icons[upperIcon] || icons[upperIcon + 'Outlined']) {
417
+ routes[key].icon = React.createElement(icons[upperIcon] || icons[upperIcon + 'Outlined']);
418
+ }
419
+ }
420
+ });
421
+ }
422
+ `
423
+ });
424
+ const rightRenderContent = `
425
+ import React from 'react';
426
+ import { Avatar, version, Dropdown, Menu, Spin } from 'antd';
427
+ import { LogoutOutlined } from '${antIconsPath}';
428
+ {{#Locale}}
429
+ import { SelectLang } from '@@/plugin-locale';
430
+ {{/Locale}}
431
+
432
+ export function getRightRenderContent (opts: {
433
+ runtimeConfig: any,
434
+ loading: boolean,
435
+ initialState: any,
436
+ setInitialState: any,
437
+ }) {
438
+ if (opts.runtimeConfig.rightRender) {
439
+ return opts.runtimeConfig.rightRender(
440
+ opts.initialState,
441
+ opts.setInitialState,
442
+ opts.runtimeConfig,
443
+ );
444
+ }
445
+
446
+ const showAvatar = opts.initialState?.avatar || opts.initialState?.name || opts.runtimeConfig.logout;
447
+ const disableAvatarImg = opts.initialState?.avatar === false;
448
+ const nameClassName = disableAvatarImg ? 'umi-plugin-layout-name umi-plugin-layout-hide-avatar-img' : 'umi-plugin-layout-name';
449
+ const avatar =
450
+ showAvatar ? (
451
+ <span className="umi-plugin-layout-action">
452
+ {!disableAvatarImg ?
453
+ (
454
+ <Avatar
455
+ size="small"
456
+ className="umi-plugin-layout-avatar"
457
+ src={
458
+ opts.initialState?.avatar ||
459
+ "https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png"
460
+ }
461
+ alt="avatar"
462
+ />
463
+ ) : null}
464
+ <span className={nameClassName}>{opts.initialState?.name}</span>
465
+ </span>
466
+ ) : null;
467
+
468
+
469
+ if (opts.loading) {
470
+ return (
471
+ <div className="umi-plugin-layout-right">
472
+ <Spin size="small" style={ { marginLeft: 8, marginRight: 8 } } />
473
+ </div>
474
+ );
475
+ }
476
+
477
+ // 如果没有打开Locale,并且头像为空就取消掉这个返回的内容
478
+ {{^Locale}}
479
+ if(!avatar) return null;
480
+ {{/Locale}}
481
+
482
+ const langMenu = {
483
+ className: "umi-plugin-layout-menu",
484
+ selectedKeys: [],
485
+ items: [
486
+ {
487
+ key: "logout",
488
+ label: (
489
+ <>
490
+ <LogoutOutlined />
491
+ 退出登录
492
+ </>
493
+ ),
494
+ onClick: () => {
495
+ opts?.runtimeConfig?.logout?.(opts.initialState);
496
+ },
497
+ },
498
+ ],
499
+ };
500
+ // antd@5 和 4.24 之后推荐使用 menu,性能更好
501
+ let dropdownProps;
502
+ if (version.startsWith("5.") || version.startsWith("4.24.")) {
503
+ dropdownProps = { menu: langMenu };
504
+ } else if (version.startsWith("3.")) {
505
+ dropdownProps = {
506
+ overlay: (
507
+ <Menu>
508
+ {langMenu.items.map((item) => (
509
+ <Menu.Item key={item.key} onClick={item.onClick}>
510
+ {item.label}
511
+ </Menu.Item>
512
+ ))}
513
+ </Menu>
514
+ ),
515
+ };
516
+ } else { // 需要 antd 4.20.0 以上版本
517
+ dropdownProps = { overlay: <Menu {...langMenu} /> };
518
+ }
519
+
520
+
521
+
522
+ return (
523
+ <div className="umi-plugin-layout-right anticon">
524
+ {opts.runtimeConfig.logout ? (
525
+ <Dropdown {...dropdownProps} overlayClassName="umi-plugin-layout-container">
526
+ {avatar}
527
+ </Dropdown>
528
+ ) : (
529
+ avatar
530
+ )}
531
+ {{#Locale}}
532
+ <SelectLang />
533
+ {{/Locale}}
534
+ </div>
535
+ );
536
+ }
537
+ `;
538
+ const Locale = api.isPluginEnable("locale");
539
+ api.writeTmpFile({
540
+ path: "rightRender.tsx",
541
+ content: import_plugin_utils.Mustache.render(rightRenderContent, {
542
+ Locale
543
+ })
544
+ });
545
+ api.writeTmpFile({
546
+ path: layoutFile,
547
+ content: `
548
+ ${// antd@5里面没有这个样式了
549
+ isAntd5 ? "" : "@import '~antd/es/style/themes/default.less';"}
550
+ @media screen and (max-width: 480px) {
551
+ /* 在小屏幕的时候可以有更好的体验 */
552
+ .umi-plugin-layout-container {
553
+ width: 100% !important;
554
+ }
555
+ .umi-plugin-layout-container > * {
556
+ border-radius: 0 !important;
557
+ }
558
+ }
559
+ .umi-plugin-layout-menu .anticon {
560
+ margin-right: 8px;
561
+ }
562
+ .umi-plugin-layout-menu .ant-dropdown-menu-item {
563
+ min-width: 160px;
564
+ }
565
+ .umi-plugin-layout-right {
566
+ display: flex !important;
567
+ float: right;
568
+ height: 100%;
569
+ margin-left: auto;
570
+ overflow: hidden;
571
+ }
572
+ .umi-plugin-layout-right .umi-plugin-layout-action {
573
+ display: flex;
574
+ align-items: center;
575
+ height: 100%;
576
+ padding: 0 12px;
577
+ cursor: pointer;
578
+ transition: all 0.3s;
579
+ }
580
+ .umi-plugin-layout-right .umi-plugin-layout-action > i {
581
+ color: rgba(255, 255, 255, 0.85);
582
+ vertical-align: middle;
583
+ }
584
+ .umi-plugin-layout-right .umi-plugin-layout-action:hover {
585
+ background: rgba(0, 0, 0, 0.025);
586
+ }
587
+ .umi-plugin-layout-right .umi-plugin-layout-action.opened {
588
+ background: rgba(0, 0, 0, 0.025);
589
+ }
590
+ .umi-plugin-layout-right .umi-plugin-layout-search {
591
+ padding: 0 12px;
592
+ }
593
+ .umi-plugin-layout-right .umi-plugin-layout-search:hover {
594
+ background: transparent;
595
+ }
596
+ .umi-plugin-layout-name {
597
+ margin-left: 8px;
598
+ }
599
+ .umi-plugin-layout-name.umi-plugin-layout-hide-avatar-img {
600
+ margin-left: 0;
601
+ }
602
+ `
603
+ });
604
+ api.writeTmpFile({
605
+ path: "Logo.tsx",
606
+ content: `
607
+ import React from 'react';
608
+
609
+ const LogoIcon: React.FC = () => {
610
+ return (
611
+ <svg
612
+ xmlns="http://www.w3.org/2000/svg"
613
+ width="32"
614
+ height="32"
615
+ viewBox="0 0 200 200"
616
+ >
617
+ <defs>
618
+ <linearGradient
619
+ id="linearGradient-1"
620
+ x1="62.102%"
621
+ x2="108.197%"
622
+ y1="0%"
623
+ y2="37.864%"
624
+ >
625
+ <stop offset="0%" stopColor="#4285EB"></stop>
626
+ <stop offset="100%" stopColor="#2EC7FF"></stop>
627
+ </linearGradient>
628
+ <linearGradient
629
+ id="linearGradient-2"
630
+ x1="69.644%"
631
+ x2="54.043%"
632
+ y1="0%"
633
+ y2="108.457%"
634
+ >
635
+ <stop offset="0%" stopColor="#29CDFF"></stop>
636
+ <stop offset="37.86%" stopColor="#148EFF"></stop>
637
+ <stop offset="100%" stopColor="#0A60FF"></stop>
638
+ </linearGradient>
639
+ <linearGradient
640
+ id="linearGradient-3"
641
+ x1="69.691%"
642
+ x2="16.723%"
643
+ y1="-12.974%"
644
+ y2="117.391%"
645
+ >
646
+ <stop offset="0%" stopColor="#FA816E"></stop>
647
+ <stop offset="41.473%" stopColor="#F74A5C"></stop>
648
+ <stop offset="100%" stopColor="#F51D2C"></stop>
649
+ </linearGradient>
650
+ <linearGradient
651
+ id="linearGradient-4"
652
+ x1="68.128%"
653
+ x2="30.44%"
654
+ y1="-35.691%"
655
+ y2="114.943%"
656
+ >
657
+ <stop offset="0%" stopColor="#FA8E7D"></stop>
658
+ <stop offset="51.264%" stopColor="#F74A5C"></stop>
659
+ <stop offset="100%" stopColor="#F51D2C"></stop>
660
+ </linearGradient>
661
+ </defs>
662
+ <g fill="none" fillRule="evenodd" stroke="none" strokeWidth="1">
663
+ <g transform="translate(-20 -20)">
664
+ <g transform="translate(20 20)">
665
+ <g>
666
+ <g fillRule="nonzero">
667
+ <g>
668
+ <path
669
+ fill="url(#linearGradient-1)"
670
+ d="M91.588 4.177L4.18 91.513a11.981 11.981 0 000 16.974l87.408 87.336a12.005 12.005 0 0016.989 0l36.648-36.618c4.209-4.205 4.209-11.023 0-15.228-4.208-4.205-11.031-4.205-15.24 0l-27.783 27.76c-1.17 1.169-2.945 1.169-4.114 0l-69.802-69.744c-1.17-1.169-1.17-2.942 0-4.11l69.802-69.745c1.17-1.169 2.944-1.169 4.114 0l27.783 27.76c4.209 4.205 11.032 4.205 15.24 0 4.209-4.205 4.209-11.022 0-15.227L108.581 4.056c-4.719-4.594-12.312-4.557-16.993.12z"
671
+ ></path>
672
+ <path
673
+ fill="url(#linearGradient-2)"
674
+ d="M91.588 4.177L4.18 91.513a11.981 11.981 0 000 16.974l87.408 87.336a12.005 12.005 0 0016.989 0l36.648-36.618c4.209-4.205 4.209-11.023 0-15.228-4.208-4.205-11.031-4.205-15.24 0l-27.783 27.76c-1.17 1.169-2.945 1.169-4.114 0l-69.802-69.744c-1.17-1.169-1.17-2.942 0-4.11l69.802-69.745c2.912-2.51 7.664-7.596 14.642-8.786 5.186-.883 10.855 1.062 17.009 5.837L108.58 4.056c-4.719-4.594-12.312-4.557-16.993.12z"
675
+ ></path>
676
+ </g>
677
+ <path
678
+ fill="url(#linearGradient-3)"
679
+ d="M153.686 135.855c4.208 4.205 11.031 4.205 15.24 0l27.034-27.012c4.7-4.696 4.7-12.28 0-16.974l-27.27-27.15c-4.218-4.2-11.043-4.195-15.254.013-4.209 4.205-4.209 11.022 0 15.227l18.418 18.403c1.17 1.169 1.17 2.943 0 4.111l-18.168 18.154c-4.209 4.205-4.209 11.023 0 15.228z"
680
+ ></path>
681
+ </g>
682
+ <ellipse
683
+ cx="100.519"
684
+ cy="100.437"
685
+ fill="url(#linearGradient-4)"
686
+ rx="23.6"
687
+ ry="23.581"
688
+ ></ellipse>
689
+ </g>
690
+ </g>
691
+ </g>
692
+ </g>
693
+ </svg>
694
+ );
695
+ };
696
+
697
+ export default LogoIcon;
698
+ `
699
+ });
700
+ api.writeTmpFile({
701
+ path: "Exception.tsx",
702
+ content: `
703
+ import React from 'react';
704
+ import { history, type IRoute } from '${api.appData.umi.importSource}';
705
+ import { Result, Button } from 'antd';
706
+
707
+ const Exception: React.FC<{
708
+ children: React.ReactNode;
709
+ route?: IRoute;
710
+ notFound?: React.ReactNode;
711
+ noAccessible?: React.ReactNode;
712
+ unAccessible?: React.ReactNode;
713
+ noFound?: React.ReactNode;
714
+ }> = (props) => (
715
+ // render custom 404
716
+ (!props.route && (props.noFound || props.notFound)) ||
717
+ // render custom 403
718
+ (props.route?.unaccessible && (props.unAccessible || props.noAccessible)) ||
719
+ // render default exception
720
+ ((!props.route || props.route?.unaccessible) && (
721
+ <Result
722
+ status={props.route ? '403' : '404'}
723
+ title={props.route ? '403' : '404'}
724
+ subTitle={props.route ? '抱歉,你无权访问该页面' : '抱歉,你访问的页面不存在'}
725
+ extra={
726
+ <Button type="primary" onClick={() => history.push('/')}>
727
+ 返回首页
728
+ </Button>
729
+ }
730
+ />
731
+ )) ||
732
+ // normal render
733
+ props.children
734
+ );
735
+
736
+ export default Exception;
737
+ `
738
+ });
739
+ });
740
+ api.addLayouts(() => {
741
+ return [
742
+ {
743
+ id: "ant-design-pro-layout",
744
+ file: (0, import_withTmpPath.withTmpPath)({ api, path: "Layout.tsx" }),
745
+ test: (route) => {
746
+ return route.layout !== false;
747
+ }
748
+ }
749
+ ];
750
+ });
751
+ api.addRuntimePluginKey(() => ["layout"]);
752
+ api.addRuntimePlugin(() => {
753
+ return [(0, import_withTmpPath.withTmpPath)({ api, path: "runtime.tsx" })];
754
+ });
5
755
  };