Skip to content

Commit f94900a

Browse files
committed
fix:调整路由,支持react-router 6.4 的loader功能
1 parent 3ecd11f commit f94900a

File tree

11 files changed

+542
-352
lines changed

11 files changed

+542
-352
lines changed

examples/base/src/layouts/BasicLayout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { RoutersProps } from '@uiw-admin/router-control'
66
// import { history } from '@uiw-admin/router-control'
77
import { Badge, Icon } from 'uiw'
88
import useSWR from 'swr'
9-
import LayoutTabs from '@uiw-admin/layout-tabs'
9+
// import LayoutTabs from '@uiw-admin/layout-tabs'
10+
import { Outlet } from 'react-router-dom'
1011
import AuthPage from '@uiw-admin/authorized'
1112
interface BasicLayoutProps {
1213
routes: RoutersProps[]
@@ -88,8 +89,8 @@ function BasicLayoutScreen(props: BasicLayoutProps = { routes: [] }) {
8889
console.log('logo点击事件', event)
8990
}}
9091
isDefaultContentStyle={false}>
91-
{/* <Outlet /> */}
92-
<LayoutTabs routes={props.routes || []} />
92+
<Outlet />
93+
{/* <LayoutTabs routes={props.routes || []} /> */}
9394
</BasicLayout>
9495
</AuthPage>
9596
)

examples/base/src/pages/TableList/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import { useState } from 'react'
22
import { ProTable, useTable } from '@uiw-admin/components'
33
import { useCity } from '../../servers'
4+
import { useLoaderData } from 'react-router-dom'
5+
6+
Demo.loader = () => {
7+
return {
8+
a: 1,
9+
}
10+
}
411

512
export default function Demo() {
13+
const data = useLoaderData()
14+
console.log('data', data)
15+
616
const table = useTable('/api/getData', {
717
// 格式化接口返回的数据,必须返回{total 总数, data: 列表数据}的格式
818
formatData: (data) => {

packages/plugins/src/rematch/index.ts

Lines changed: 25 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
import fs from 'fs';
55
import path from 'path';
66
import webpack from 'webpack';
7-
import { IsModel } from './../utils';
7+
import { RematchFiles, getFilenameInfo } from './../utils';
88
import createRematchTemps, { createModelsTempStr } from './temp';
99
import { ModelType } from './../utils/interface';
1010
import chokidar from 'chokidar';
11+
import { getModelInfo } from './utils';
1112

1213
export type { ModelType };
1314
class RematchWebpackPlugin {
@@ -31,47 +32,9 @@ class RematchWebpackPlugin {
3132
this.restCreate();
3233
}
3334
// 递归文件
34-
getPathDeep = (filePath: string, isModel = false) => {
35-
const files = fs.readdirSync(filePath);
36-
if (files) {
37-
files.forEach((filename: string) => {
38-
let mode = isModel;
39-
const filedir = path.join(filePath, filename);
40-
const isNoEmty = fs.existsSync(filedir);
41-
if (!isNoEmty) {
42-
return;
43-
}
44-
const stats = fs.statSync(filedir);
45-
if (stats) {
46-
const isFile = stats.isFile(); //是文件
47-
const isDir = stats.isDirectory(); //是文件夹
48-
if (isFile && isModel && /\.(ts||js)$/.test(filename)) {
49-
const data = fs.readFileSync(filedir, { encoding: 'utf-8' });
50-
const { isModels, modelNames, isCreateModel } = IsModel(data);
51-
const pathUrls = `${filedir}`.replace(/\\/g, '/');
52-
const location = pathUrls.replace(/\/models.*$/, '');
53-
const srcPath = pathUrls.replace(new RegExp(this.src), '.');
54-
if (isModels) {
55-
this.oldModel.push({
56-
path: pathUrls,
57-
filename: filename.replace(/\.(ts|js)$/, ''),
58-
modelName: modelNames,
59-
isCreateModel,
60-
location,
61-
name: modelNames || filename,
62-
srcPath,
63-
});
64-
}
65-
}
66-
if (filename === 'models') {
67-
mode = true;
68-
}
69-
if (isDir) {
70-
this.getPathDeep(filedir, mode); //递归,如果是文件夹,就继续遍历该文件夹下面的文件
71-
}
72-
}
73-
});
74-
}
35+
getPathDeep = (filePath: string) => {
36+
const rematchFiles = new RematchFiles(filePath);
37+
this.oldModel = rematchFiles.modelList;
7538
};
7639

7740
// 重新生成
@@ -131,22 +94,9 @@ class RematchWebpackPlugin {
13194
if (stats.isDirectory()) {
13295
return;
13396
}
134-
// 1. 判断是否已经存在
135-
// 如果已经存在着直接更新
136-
let isMode = false;
137-
let modelName: undefined;
138-
let isCreateModel = false;
139-
// 先判断路径是否存在models 和ts|js 结尾
140-
if (/\.(ts|js)$/.test(newPath) && /models/.test(newPath)) {
141-
const {
142-
isModels,
143-
modelNames,
144-
isCreateModel: isCreate,
145-
} = IsModel(fs.readFileSync(newPath, { encoding: 'utf-8' }));
146-
modelName = modelNames;
147-
isMode = isModels;
148-
isCreateModel = isCreate;
149-
}
97+
// 获取文件信息
98+
const { isMode, modelName, isCreateModel } = getModelInfo(newPath);
99+
150100
const newFile = this.oldModel.find((item) => item.path === newPath);
151101
if (newFile) {
152102
// 进行判断是否还是 model
@@ -167,26 +117,24 @@ class RematchWebpackPlugin {
167117
return { ...item };
168118
});
169119
}
170-
this.restCreate();
171-
} else {
120+
} else if (isMode) {
172121
// 判断是不是 model 是则更新
173-
if (isMode) {
174-
const pathUrls = `${newPath}`.replace(/\\/g, '/');
175-
const arr = pathUrls.split(/\\|\//);
176-
let filename = arr[arr.length - 1].replace(/\.(ts|js)$/, '');
177-
const location = pathUrls.replace(/\/models.*$/, '');
178-
const srcPath = pathUrls.replace(new RegExp(this.src), '.');
179-
this.oldModel.push({
180-
path: pathUrls,
181-
filename,
182-
modelName,
183-
isCreateModel,
184-
location,
185-
name: modelName || filename,
186-
srcPath,
187-
});
188-
this.restCreate();
189-
}
122+
const { srcPath, location, pathUrls, fileName } = getFilenameInfo(
123+
newPath,
124+
this.src,
125+
);
126+
this.oldModel.push({
127+
path: pathUrls,
128+
filename: fileName,
129+
modelName,
130+
isCreateModel,
131+
location,
132+
name: modelName || fileName,
133+
srcPath,
134+
});
135+
}
136+
if (isMode || newFile) {
137+
this.restCreate();
190138
}
191139
};
192140
// 校验文件
@@ -217,16 +165,6 @@ class RematchWebpackPlugin {
217165
this.checkField(path.resolve(process.cwd(), 'src', pathName));
218166
}
219167
});
220-
// const watcher = fs.watch(path.resolve(process.cwd(), 'src'), {
221-
// recursive: true,
222-
// });
223-
// watcher.on('change', (type, filename) => {
224-
// if (typeof filename === 'string') {
225-
// this.field = filename as string;
226-
// this.newPath = path.resolve(process.cwd(), 'src', this.field);
227-
// this.checkField();
228-
// }
229-
// });
230168
}
231169
});
232170
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import fs from 'fs';
2+
import { IsModel } from '../utils';
3+
/**获取model文件信息*/
4+
export const getModelInfo = (newPath: string) => {
5+
// 1. 判断是否已经存在
6+
// 如果已经存在着直接更新
7+
/**是否是model*/
8+
let isMode = false;
9+
/**model 名称*/
10+
let modelName: undefined;
11+
/** model 是否使用 createModel 导出 */
12+
let isCreateModel = false;
13+
// 先判断路径是否存在models 和ts|js 结尾
14+
if (/\.(ts|js)$/.test(newPath) && /models/.test(newPath)) {
15+
const {
16+
isModels,
17+
modelNames,
18+
isCreateModel: isCreate,
19+
} = IsModel(fs.readFileSync(newPath, { encoding: 'utf-8' }));
20+
modelName = modelNames;
21+
isMode = isModels;
22+
isCreateModel = isCreate;
23+
}
24+
return {
25+
/**是否是model*/
26+
modelName,
27+
/**model 名称*/
28+
isMode,
29+
/** model 是否使用 createModel 导出 */
30+
isCreateModel,
31+
};
32+
};

packages/plugins/src/routes/index.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
import fs from 'fs';
55
import path from 'path';
66
import webpack from 'webpack';
7-
import createTemp, { getJsonToString } from './temp';
7+
import createTemp from './temp';
88
import chokidar from 'chokidar';
9-
import { getJSONData, stringToJson, getRouteMapModels } from './../utils';
10-
import { RoutersProps } from './../utils/interface';
9+
import {
10+
getJSONData,
11+
stringToJson,
12+
getRouteMapModels,
13+
babelPluginComponents,
14+
} from '../utils';
15+
import { RoutersProps } from '../utils/interface';
1116

1217
type ISTYPE = 'json' | 'ts' | 'js' | false;
1318

@@ -67,8 +72,14 @@ class RoutesWebpackPlugin {
6772
if (!fs.existsSync(this.uiw)) {
6873
fs.mkdirSync(this.uiw);
6974
}
75+
const content = ['js', 'ts'].includes(isType as string)
76+
? this.jsonCode
77+
: strs;
78+
const babelIcons = babelPluginComponents(content);
7079
let routeTemp = createTemp(
71-
['js', 'ts'].includes(isType as string) ? this.jsonCode : strs,
80+
babelIcons.code,
81+
babelIcons.iconsList,
82+
babelIcons.importLazy,
7283
isType,
7384
);
7485
fs.writeFileSync(
@@ -86,12 +97,12 @@ class RoutesWebpackPlugin {
8697
checkPreAndNext = (isType: ISTYPE) => {
8798
if (this.preString !== this.nextString) {
8899
// 读取文件数据
89-
const routerTemp = JSON.stringify(this.routes, getJsonToString, 2)
90-
.replace(/\"component\": (\"(.+?)\")/g, (global, m1, m2) => {
91-
return `"component": ${m2.replace(/\^/g, '"')}`;
92-
})
93-
.replace(/\\r\\n/g, '\r\n')
94-
.replace(/\\n/g, '\r\n');
100+
const routerTemp = JSON.stringify(this.routes, null, 2);
101+
// .replace(/\"component\": (\"(.+?)\")/g, (global, m1, m2) => {
102+
// return `"component": ${m2.replace(/\^/g, '"')}`;
103+
// })
104+
// .replace(/\\r\\n/g, '\r\n')
105+
// .replace(/\\n/g, '\r\n');
95106
this.createTemps(routerTemp, isType);
96107
}
97108
};
Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,48 @@
11
// 模板
2-
export default (routeStr: string, isType: 'ts' | 'js' | 'json' | boolean) => {
3-
// from "react"
2+
const getReactLazy = (importLazy: Record<string, string>) => {
3+
let lazyString = '';
4+
Object.entries(importLazy).map(([key, paths]) => {
5+
lazyString = lazyString + `import ${key} from "${paths}"\n`;
6+
});
7+
return lazyString;
8+
};
9+
10+
export default (
11+
routeStr: string,
12+
iconsList: string[],
13+
importLazy: Record<string, string>,
14+
isType: 'ts' | 'js' | 'json' | boolean,
15+
) => {
416
let reactTemp = `import React from "react"`;
17+
const iconStr = createIcons(iconsList);
518
if (['js', 'ts'].includes(isType as string)) {
619
// 1. 判断是否 已经存在 from "react"
720
const isReact = !/\/\/(.+|)import React.+ from "react"/.test(routeStr);
821
return `
922
// @ts-nocheck
1023
${(!isReact && reactTemp) || ''}
1124
import {Exceptions404,Exceptions403,Exceptions500 } from "@uiw-admin/exceptions"
25+
${getReactLazy(importLazy)}
26+
${iconStr}
1227
${routeStr};
1328
`;
1429
}
1530
return `
1631
// @ts-nocheck
1732
import React from "react";
33+
${iconStr}
1834
import {Exceptions404,Exceptions403,Exceptions500 } from "@uiw-admin/exceptions"
35+
${getReactLazy(importLazy)}
1936
export default ${routeStr};
2037
`;
2138
};
2239

23-
export const getJsonToString = (key: string, value: string) => {
24-
if (key === 'component' && ['403', '404', '500'].includes(value)) {
25-
return `<Exceptions${value} />`;
26-
} else if (key === 'component') {
27-
return `React.lazy(() => import('${value}'))`;
28-
}
29-
return value;
40+
// 创建 icon 图标
41+
export const createIcons = (iconsList: string[]) => {
42+
let iconStr = '';
43+
iconsList.forEach((key) => {
44+
const [icon] = key.split('_');
45+
iconStr += `import { ${icon} as ${key} } from "@uiw/icons/lib/${icon}";\n`;
46+
});
47+
return iconStr;
3048
};

0 commit comments

Comments
 (0)