feat: 路由调整
This commit is contained in:
parent
c522de39ae
commit
098f90d746
|
@ -21,7 +21,8 @@
|
||||||
"@tavi/i18n": "^1.5.0",
|
"@tavi/i18n": "^1.5.0",
|
||||||
"@tavi/util": "1.0.0",
|
"@tavi/util": "1.0.0",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
"three": "0.156.1"
|
"three": "0.156.1",
|
||||||
|
"path-to-regexp": "6.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.21.8",
|
"@babel/core": "^7.21.8",
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import { Outlet } from "react-router";
|
import { Outlet, useLocation } from "react-router";
|
||||||
|
|
||||||
interface LayoutProps {
|
interface LayoutProps {
|
||||||
children?: JSX.Element;
|
children?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Layout = (props: LayoutProps) => {
|
export const Layout = (props: LayoutProps) => {
|
||||||
|
const location = useLocation();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<header>12222</header>
|
<header> {location.pathname}</header>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,3 +25,5 @@ export const theme: ThemeConfig = {
|
||||||
* @enum "zh-CN" | 'en' | 'en-US' | 'zh'
|
* @enum "zh-CN" | 'en' | 'en-US' | 'zh'
|
||||||
*/
|
*/
|
||||||
export const defaultLang = "zh-CN";
|
export const defaultLang = "zh-CN";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { FormFields, LoginForm } from "./LoginForm";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import { useDomain } from "@/hook/useDomain";
|
import { useDomain } from "@/hook/useDomain";
|
||||||
import { useTranslation } from "@tavi/i18n";
|
import { useTranslation } from "@tavi/i18n";
|
||||||
import { Observer, observer } from "mobx-react-lite";
|
|
||||||
import { UserService } from "@@/domain/User/UserService";
|
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
|
|
||||||
|
@ -13,14 +11,6 @@ interface LoginProps {
|
||||||
children?: JSX.Element;
|
children?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const TestComponent: React.FC<{ domainService: UserService }> = observer(
|
|
||||||
// ({ domainService }) => (
|
|
||||||
// <div style={{ color: "#fff" }}>
|
|
||||||
// <p>name: {domainService.user.isLoggedIn ? "登录" : "未登录"}</p>
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
|
|
||||||
export const Login = (props: LoginProps) => {
|
export const Login = (props: LoginProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -55,7 +45,6 @@ export const Login = (props: LoginProps) => {
|
||||||
<Logo isClicked={false} />
|
<Logo isClicked={false} />
|
||||||
<LanguageSelect />
|
<LanguageSelect />
|
||||||
</header>
|
</header>
|
||||||
{/* <TestComponent domainService={userDomainService} /> */}
|
|
||||||
<LoginForm
|
<LoginForm
|
||||||
styles={{ width: "100%" }}
|
styles={{ width: "100%" }}
|
||||||
onFormChange={(v) => userDomainService.updateLoginForm(v)}
|
onFormChange={(v) => userDomainService.updateLoginForm(v)}
|
||||||
|
|
|
@ -1,47 +1,29 @@
|
||||||
import { AuthFailedReplacePath } from "@/constant";
|
import { AuthFailedReplacePath } from "@/constant";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useEffect } from "react";
|
import { pathToRegexp } from "path-to-regexp";
|
||||||
import { useDomain } from "@/hook/useDomain";
|
import { useDomain } from "@/hook/useDomain";
|
||||||
import { message } from "antd";
|
|
||||||
|
|
||||||
interface GuardProps {
|
interface RouteGuardProps {
|
||||||
element: JSX.Element;
|
children?: React.ReactNode;
|
||||||
auth?: boolean;
|
ignorePaths: string[];
|
||||||
title?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export const RouteGuard = (props: RouteGuardProps) => {
|
||||||
* 守卫
|
const { children, ignorePaths } = props;
|
||||||
*/
|
const { userDomainService } = useDomain();
|
||||||
export const Guard = (props: GuardProps) => {
|
const { user } = userDomainService;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { userDomainService } = useDomain();
|
|
||||||
const [messageApi, contextHolder] = message.useMessage();
|
|
||||||
const { isLoggedIn } = userDomainService.user;
|
|
||||||
|
|
||||||
useEffect(() => {
|
const ignore = ignorePaths.some((p) =>
|
||||||
if (props.auth && !isLoggedIn) {
|
pathToRegexp(p).test(location.pathname)
|
||||||
userDomainService.userAuth().then((result: any) => {
|
);
|
||||||
const { success, msg } = result;
|
|
||||||
if (!success) {
|
if (!ignore && !user.isLoggedIn) {
|
||||||
messageApi.error(msg);
|
userDomainService.userAuth().then(({ success }) => {
|
||||||
navigate(AuthFailedReplacePath);
|
if (!success) navigate(AuthFailedReplacePath);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return () => {};
|
|
||||||
}, [navigate]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
return children;
|
||||||
if (props?.title) document.title = props?.title;
|
|
||||||
return () => {};
|
|
||||||
}, [location.pathname]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{contextHolder}
|
|
||||||
{props.element}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,44 @@
|
||||||
import { routesConfig } from "./router.config";
|
import { baseRoutes } from "./router.config";
|
||||||
import { useRoutes } from "react-router";
|
import { Route, RouteObject, Routes, useLocation } from "react-router-dom";
|
||||||
|
import { RouteGuard } from "./AuthGuard";
|
||||||
|
import { pathToRegexp } from "path-to-regexp";
|
||||||
|
import { defaultTitle } from "@/constant";
|
||||||
|
|
||||||
export const RouterElements = () => useRoutes(routesConfig);
|
// export const RouterElements = () => useRoutes(routesConfig);
|
||||||
|
|
||||||
|
export type ExpandRouteProps = {
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RouterElements = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
console.log(location.pathname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* document.title
|
||||||
|
*/
|
||||||
|
const currentRoute = [...baseRoutes].find((r) =>
|
||||||
|
pathToRegexp(location.pathname).test(r.path!)
|
||||||
|
);
|
||||||
|
document.title = currentRoute?.title ?? defaultTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归children
|
||||||
|
*/
|
||||||
|
const generateRoutes = (routes: (RouteObject & ExpandRouteProps)[]) =>
|
||||||
|
routes.map((r) => (
|
||||||
|
<Route key={r.path} path={r.path} element={r.element}>
|
||||||
|
{r.children && generateRoutes(r.children)}
|
||||||
|
</Route>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RouteGuard ignorePaths={[]}>
|
||||||
|
<Routes>
|
||||||
|
{generateRoutes(baseRoutes)}
|
||||||
|
<Route key="notfound" path="*" element={<span>404</span>} />
|
||||||
|
</Routes>
|
||||||
|
</RouteGuard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -5,17 +5,22 @@ import { RootViewer } from "../modules/Root/Viewer/Root";
|
||||||
import { PeripheralViewer } from "../modules/Peripheral";
|
import { PeripheralViewer } from "../modules/Peripheral";
|
||||||
import { Dashboard } from "@/modules/Dashboard";
|
import { Dashboard } from "@/modules/Dashboard";
|
||||||
import { ReportFullVersion } from "@/modules/Report/Full";
|
import { ReportFullVersion } from "@/modules/Report/Full";
|
||||||
import { Guard } from "./AuthGuard";
|
|
||||||
import { Layout } from "@/components/Layout";
|
import { Layout } from "@/components/Layout";
|
||||||
|
import { ExpandRouteProps } from ".";
|
||||||
|
|
||||||
export const routesConfig: RouteObject[] = [
|
/**
|
||||||
|
* 基础路由
|
||||||
|
*/
|
||||||
|
export const baseRoutes: (RouteObject & ExpandRouteProps)[] = [
|
||||||
{
|
{
|
||||||
path: "login",
|
path: "/login",
|
||||||
element: <Guard element={<Login />} title="CVPILOT Viewer" />,
|
element: <Login />,
|
||||||
|
title: "登录 - CVPILOT Viewer",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
element: <Guard element={<Layout />} auth />,
|
element: <Layout />,
|
||||||
|
title: "CVPILOT Viewer",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
@ -23,28 +28,24 @@ export const routesConfig: RouteObject[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "dash",
|
path: "dash",
|
||||||
element: <Guard element={<Dashboard />} title="仪表盘" />,
|
element: <Dashboard />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "list",
|
path: "list",
|
||||||
element: <Guard element={<PatientList />} title="患者列表" />,
|
element: <PatientList />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "root/viewer",
|
path: "root/viewer",
|
||||||
element: <Guard element={<RootViewer />} title="根部分析" />,
|
element: <RootViewer />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "root/report/full",
|
path: "root/report/full",
|
||||||
element: <Guard element={<ReportFullVersion />} title="完整报告" />,
|
element: <ReportFullVersion />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "peripheral/viewer",
|
path: "peripheral/viewer",
|
||||||
element: <Guard element={<PeripheralViewer />} title="外周分析" />,
|
element: <PeripheralViewer />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "*",
|
|
||||||
element: <span>404</span>,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -5,8 +5,7 @@ import { User } from "./entities/User";
|
||||||
|
|
||||||
export class RbacRepository {
|
export class RbacRepository {
|
||||||
async saveRole(role: Role) {
|
async saveRole(role: Role) {
|
||||||
const { code } = await Apis.saveRole(role);
|
return await Apis.saveRole(role);
|
||||||
return code === "ok";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateRole(role: Role) {
|
async updateRole(role: Role) {
|
||||||
|
@ -43,8 +42,8 @@ export class RbacRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveUser(user: User) {
|
async saveUser(user: User) {
|
||||||
const { code } = await Apis.saveUser(user);
|
const { code, data, msg } = await Apis.saveUser(user);
|
||||||
return code === "ok";
|
return { code, data, msg };
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUser(user: Omit<User, "roles"> & { roles: number[] }) {
|
async updateUser(user: Omit<User, "roles"> & { roles: number[] }) {
|
||||||
|
|
|
@ -37,11 +37,14 @@ export class RbacService {
|
||||||
* 添加角色
|
* 添加角色
|
||||||
*/
|
*/
|
||||||
async addRole(role: Role) {
|
async addRole(role: Role) {
|
||||||
|
const { code, msg } = await this.rbacRepository.saveRole(role);
|
||||||
|
if (code === 0) {
|
||||||
this.roleList = [
|
this.roleList = [
|
||||||
...this.roleList,
|
...this.roleList,
|
||||||
{ ...role, isEnabled: true, permissions: [] },
|
{ ...role, isEnabled: true, permissions: [] },
|
||||||
];
|
];
|
||||||
return await this.rbacRepository.saveRole(role);
|
}
|
||||||
|
return { code, msg };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,8 +118,14 @@ export class RbacService {
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
createTime: new Date().toLocaleString(),
|
createTime: new Date().toLocaleString(),
|
||||||
};
|
};
|
||||||
this.userList = [...this.userList, user];
|
const { code, data, msg } = await this.rbacRepository.saveUser({
|
||||||
return await this.rbacRepository.saveUser({ ...user, password });
|
...user,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
if (code === 0) {
|
||||||
|
this.userList = [...this.userList, data as User];
|
||||||
|
}
|
||||||
|
return { data, msg, code };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,8 +26,9 @@ export const Role = (props: RoleProps) => {
|
||||||
|
|
||||||
const onModalConfirm = async (fields: fieldsType) => {
|
const onModalConfirm = async (fields: fieldsType) => {
|
||||||
setModalVisible(false);
|
setModalVisible(false);
|
||||||
const ok = await rbacDomainService.addRole({ ...fields });
|
const { code, msg } = await rbacDomainService.addRole({ ...fields });
|
||||||
messageApi.info(ok ? "ok" : "failed");
|
code === 0 ? messageApi.success(msg) : messageApi.error(msg);
|
||||||
|
rbacDomainService.findAllRoleWithPermissions();
|
||||||
};
|
};
|
||||||
|
|
||||||
const RoleListComponent: React.FC<{ domainService: RbacService }> = observer(
|
const RoleListComponent: React.FC<{ domainService: RbacService }> = observer(
|
||||||
|
|
|
@ -25,13 +25,18 @@ export const CreateUserForm = (props: CreateUserFormProps) => {
|
||||||
|
|
||||||
const onConfirmCreateUser = async (fields: CreateUserFormFields) => {
|
const onConfirmCreateUser = async (fields: CreateUserFormFields) => {
|
||||||
const { roleIds, username, password, phoneNumber } = fields;
|
const { roleIds, username, password, phoneNumber } = fields;
|
||||||
const success = await rbacDomainService.saveUser({
|
const { code, data, msg } = await rbacDomainService.saveUser({
|
||||||
roleIds,
|
roleIds,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
});
|
});
|
||||||
if (success) messageApi.success(`用户: ${username} 创建成功`);
|
if (code === 0) {
|
||||||
|
messageApi.success(msg);
|
||||||
|
rbacDomainService.findAllRoleWithPermissions();
|
||||||
|
} else {
|
||||||
|
messageApi.error(msg);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -36,7 +36,7 @@ export const RouterElements = observer(() => {
|
||||||
const currentRoute = [...currentRoutes, ...baseRoutes].find((r) =>
|
const currentRoute = [...currentRoutes, ...baseRoutes].find((r) =>
|
||||||
pathToRegexp(r.path!).test(location.pathname)
|
pathToRegexp(r.path!).test(location.pathname)
|
||||||
);
|
);
|
||||||
if (currentRoute) document.title = currentRoute.title || defaultDocumentTitle;
|
document.title = currentRoute?.title ?? defaultDocumentTitle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归children
|
* 递归children
|
||||||
|
|
|
@ -53,10 +53,10 @@ export class RbacService {
|
||||||
|
|
||||||
async createRole(payload: Role) {
|
async createRole(payload: Role) {
|
||||||
const { name, alias, description } = payload;
|
const { name, alias, description } = payload;
|
||||||
const exsit = await this.roleRepository.findOne({ where: { name } });
|
const exist = await this.roleRepository.findOne({ where: { name } });
|
||||||
if (exsit) return { message: '用户已存在' };
|
if (exist) return { message: '角色已存在', success: false };
|
||||||
const result = await this.roleRepository.save({ name, alias, description });
|
const result = await this.roleRepository.save({ name, alias, description });
|
||||||
return result;
|
return { success: true, result, message: '角色创建成功' };
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAllRole() {
|
async findAllRole() {
|
||||||
|
|
|
@ -43,14 +43,15 @@ export class UserService {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// 如果username存在
|
// 如果username存在
|
||||||
if (user) return false;
|
if (user) return { success: false, msg: '用户名已存在' };
|
||||||
const cipher = await this.bcryptService.hashPassword(password);
|
const cipher = await this.bcryptService.hashPassword(password);
|
||||||
return await this.userRepository.save({
|
const userCreated = await this.userRepository.save({
|
||||||
username,
|
username,
|
||||||
password: cipher,
|
password: cipher,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
roles,
|
roles,
|
||||||
});
|
});
|
||||||
|
return { success: true, msg: '用户创建成功', data: userCreated };
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(fields: User) {
|
async update(fields: User) {
|
||||||
|
|
|
@ -24,11 +24,12 @@ export class AdminController {
|
||||||
|
|
||||||
@Post('role/create')
|
@Post('role/create')
|
||||||
async createRole(@Body() createRoleDto: CreateRoleDto) {
|
async createRole(@Body() createRoleDto: CreateRoleDto) {
|
||||||
const pattern = { cmd: 'cert.create.role' };
|
const { success, result, message } = await firstValueFrom(
|
||||||
const result = await firstValueFrom(
|
this.client.send({ cmd: 'cert.create.role' }, createRoleDto),
|
||||||
this.client.send(pattern, createRoleDto),
|
|
||||||
);
|
);
|
||||||
return { code: 'ok', data: result };
|
return success
|
||||||
|
? { code: 0, data: result, msg: message }
|
||||||
|
: { code: 1, msg: message };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('role/remove')
|
@Post('role/remove')
|
||||||
|
@ -87,17 +88,17 @@ export class AdminController {
|
||||||
|
|
||||||
@Post('user/create')
|
@Post('user/create')
|
||||||
async createUser(@Body() createUserDto: CreateUserDto) {
|
async createUser(@Body() createUserDto: CreateUserDto) {
|
||||||
const pattern = { cmd: 'cert.user.create' };
|
const { success, msg, data } = await firstValueFrom(
|
||||||
const payload = createUserDto;
|
this.client.send({ cmd: 'cert.user.create' }, createUserDto),
|
||||||
const result = await firstValueFrom(this.client.send(pattern, payload));
|
);
|
||||||
return { code: 'ok', data: result };
|
return success ? { code: 0, data, msg } : { code: 1, msg };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('user/find/all')
|
@Get('user/find/all')
|
||||||
async userSelect() {
|
async userSelect() {
|
||||||
const pattern = { cmd: 'cert.find.all.user' };
|
const result = await firstValueFrom(
|
||||||
const payload = [];
|
this.client.send({ cmd: 'cert.find.all.user' }, []),
|
||||||
const result = await firstValueFrom(this.client.send(pattern, payload));
|
);
|
||||||
return { code: 'ok', data: result };
|
return { code: 'ok', data: result };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,9 @@ importers:
|
||||||
mobx-react-lite:
|
mobx-react-lite:
|
||||||
specifier: 3.4.3
|
specifier: 3.4.3
|
||||||
version: 3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0)
|
version: 3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
path-to-regexp:
|
||||||
|
specifier: 6.2.1
|
||||||
|
version: 6.2.1
|
||||||
react:
|
react:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user