Compare commits

...

3 Commits

Author SHA1 Message Date
dayjoy
e47cf31c07 feat: 支持路由参数 2024-10-20 14:32:44 +08:00
dayjoy
82478e51b3 fix: 修改modal ref定义 2024-10-20 10:45:19 +08:00
dayjoy
42caa183d1 chore: 忽略开发配置文件 2024-10-20 10:45:00 +08:00
11 changed files with 126 additions and 15 deletions

2
template/.gitignore vendored
View File

@@ -1,4 +1,6 @@
src/meta.js
.idea
.vscode
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

View File

@@ -26,23 +26,26 @@
```ts
interface Meta {
displayName?: string; // 展示在菜单上的名字
displayName?: string; // 展示在菜单上的名字 可以用 {{language_id}} 包起来,用于国际化显示
icon?: string; // 展示在菜单上的图标
headMenu?: // 是否展示在头部菜单 或 所属头部菜单的名字
| boolean
| {
key: string;
label: string;
label: string; // 可以用 {{language_id}} 包起来,用于国际化显示
icon?: string;
order?: number; // 菜单序号,数字越小越靠前
};
sideMenu?: // 是否展示在侧边菜单 或 所属侧边菜单的名字
| boolean
| {
key: string;
label: string;
label: string; // 可以用 {{language_id}} 包起来,用于国际化显示
icon?: string;
order?: number; // 菜单序号,数字越小越靠前
};
order?: number; // 菜单排列序号,数字越小越靠前
order?: number; // 菜单序号,数字越小越靠前
route?: string; // 当前页面路由名字,支持 ':id' 等路由参数,不同则默认等于目录名
}
```

View File

@@ -10,6 +10,7 @@ function buildNestedStructure(filePaths) {
const parts = filePath.split('/').slice(2, -1); // 去掉 'src/pages' 'meta.json'
let current = root;
let parentFullRoute = '';
parts.forEach((part, index) => {
const find = current.find((item) => item._path === part);
@@ -25,9 +26,15 @@ function buildNestedStructure(filePaths) {
if (index === parts.length - 1) {
const content = fs.readFileSync(filePath, 'utf-8');
Object.assign(current, JSON.parse(content), {
const contentJSON = JSON.parse(content);
Object.assign(current, contentJSON, {
_fullpath: parts.join('/'),
_fullroute: parentFullRoute
? `${parentFullRoute}/${contentJSON.route || part}`
: contentJSON.route || part,
});
} else {
parentFullRoute = current._fullroute || parentFullRoute;
}
current = current._children;
});

View File

@@ -22,7 +22,7 @@ const parseMeta2Routes = (meta: Meta[]) => {
() => import(`@/pages/${item._fullpath}/${toPascalCase(item._path)}`),
);
const route: RouteObject = {
path: item._fullpath,
path: item._fullroute,
element: <Element />,
};
routes.push(route);

View File

@@ -1,8 +1,6 @@
import { ModalRef } from '@df/toco-ui';
declare global {
let tocoRefs: Record<string, any>;
let tocoModals: Record<string, ModalRef<any>>;
let tocoModals: Record<string, any>;
}
interface Meta {
@@ -25,6 +23,8 @@ interface Meta {
order?: number; // 菜单序号,数字越小越靠前
};
order?: number; // 菜单序号,数字越小越靠前
route?: string; // 当前页面路由名字,支持 ':id' 等路由参数,不同则默认等于目录名
_fullroute?: string; // 完整路由,最终路由
_path: string; // 目录名
_fullpath?: string; // 完整目录结构
_children: Meta[];

View File

@@ -1,6 +1,7 @@
import { useAppDispatch, useAppSelector } from '@/app/hooks';
import { User } from '@/pages/demo/demoAPI';
import { fetchUsers, selectDemo } from '@/pages/demo/demoSlice';
import withPage from '@/utils/withPage';
import { EditTableColumnsType, Table } from '@df/toco-ui';
import { useEffect } from 'react';
@@ -43,4 +44,4 @@ const Demo = () => {
);
};
export default Demo;
export default withPage(Demo);

View File

@@ -1,21 +1,19 @@
import { useAppSelector } from '@/app/hooks';
import withPage from '@/utils/withPage';
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import * as tocoServices from './testAPI';
const Test = (props) => {
const tocoStore = useAppSelector((state) => state);
const navigate = useNavigate();
useEffect(() => {
// 一些常用变量或方法
console.log('navigate', navigate);
console.log('props', props);
console.log('store', tocoStore);
console.log('services', tocoServices);
console.log('refs', tocoRefs);
console.log('modals', tocoModals);
}, [navigate, props, tocoStore]);
}, [props, tocoStore]);
return (
<div>
@@ -30,4 +28,4 @@ const Test = (props) => {
);
};
export default Test;
export default withPage(Test);

View File

@@ -0,0 +1,25 @@
import { useAppSelector } from '@/app/hooks';
import withPage from '@/utils/withPage';
import { useEffect } from 'react';
import * as tocoServices from './xxxAPI';
const Xxx = (props) => {
const tocoStore = useAppSelector((state) => state);
useEffect(() => {
// 一些常用变量或方法
console.log('props', props);
console.log('services', tocoServices);
console.log('refs', tocoRefs);
console.log('modals', tocoModals);
console.log('store', tocoStore);
}, [props, tocoStore]);
return (
<div>
<h1>xxx</h1>
</div>
);
};
export default withPage(Xxx);

View File

@@ -0,0 +1,8 @@
{
"displayName": "xxx",
"icon": "RobotOutlined",
"headMenu": false,
"sideMenu": false,
"order": 0,
"route": "xx/:oo"
}

View File

@@ -0,0 +1,26 @@
import axiosInstance from '@/app/request';
import { AxiosResponse } from 'axios';
export interface User {
name: {
first: string;
last: string;
};
phone: string;
gender: 'female' | 'male';
}
export const getUsers = async (): Promise<User[]> => {
const response: AxiosResponse<{
info: any;
results: User[];
}> = await axiosInstance.get(
`https://randomuser.me/api/?results=8&seed=toco`,
{
params: {
errorHandler: false,
},
},
);
return response.data?.results || [];
};

View File

@@ -0,0 +1,41 @@
import { useMemo } from 'react';
import {
useLocation,
useNavigate,
useParams,
useSearchParams,
} from 'react-router-dom';
const withPage = (BaseComponent: React.ComponentType) => {
const WithPageComponent = (props: any) => {
const navigate = useNavigate();
const params = useParams();
const location = useLocation();
const [searchParamsOri] = useSearchParams();
const searchParams = useMemo(() => {
const params = {};
for (const [key, value] of searchParamsOri.entries()) {
params[key] = value;
}
return params;
}, [searchParamsOri]);
return (
<>
<BaseComponent
{...props}
location={location}
params={params}
search={searchParams}
navigate={navigate}
/>
</>
);
};
WithPageComponent.displayName =
BaseComponent.displayName ?? 'WithPageComponent';
return WithPageComponent;
};
export default withPage;