From a5d3342d93c1960833cab1b8c0ecc55e52428b3d Mon Sep 17 00:00:00 2001 From: wuxichen <17301714657@163.com> Date: Mon, 26 Jan 2026 17:59:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B7=AF=E7=94=B1=E7=99=BB=E5=BD=95=20?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=B7=AF=E7=94=B1=E9=87=8D=E5=AE=9A=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.tsx | 15 ++- src/pages/user/login/index.tsx | 166 +++++++++++++++++---------------- src/utils/menuUtils.tsx | 115 +---------------------- 3 files changed, 102 insertions(+), 194 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index f49ce02..74f7407 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -93,6 +93,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState, }) => { + const { wsCache } = useCache(); return { actionsRender: () => [ , @@ -101,6 +102,18 @@ export const layout: RunTimeLayoutConfig = ({ menu: { locale: false, // 关闭国际化- + // request: async () => { + // const currentUser = wsCache.get(CACHE_KEY.USER); + + // console.log("菜单请求被调用", initialState?.menus, currentUser); + // if (currentUser.menus) { + // const menuData = loopMenuItem(currentUser.menus); + // // console.log('转换后的菜单数据:', menuData); + // // const r = loopMenuItem(currentUser.menus); + // return menuData; + // } + // return []; + // }, }, avatarProps: { src: initialState?.currentUser?.user.avatar, @@ -238,7 +251,7 @@ export const request: RequestConfig = { // Umi 4 支持异步的 patchClientRoutes export async function patchClientRoutes({ routes }: any) { const { wsCache } = useCache(); - + console.log('patchClientRoutes', patchClientRoutes); // 先尝试从缓存获取 let menus = wsCache.get(CACHE_KEY.ROLE_ROUTERS); diff --git a/src/pages/user/login/index.tsx b/src/pages/user/login/index.tsx index 9c29923..ae2927e 100644 --- a/src/pages/user/login/index.tsx +++ b/src/pages/user/login/index.tsx @@ -1,4 +1,3 @@ -import { getTenantIdByName, login } from "@/services/login"; import { AlipayOutlined, LockOutlined, @@ -6,34 +5,36 @@ import { TaobaoOutlined, UserOutlined, WeiboOutlined, -} from "@ant-design/icons"; +} from '@ant-design/icons'; import { LoginFormPage, ProConfigProvider, ProFormCaptcha, ProFormCheckbox, ProFormText, -} from "@ant-design/pro-components"; -import { history, useModel, useNavigate } from "@umijs/max"; -import { Button, Divider, Space, Tabs, theme, message } from "antd"; -import type { CSSProperties } from "react"; -import { useState } from "react"; -import * as authUtil from "@/utils/auth"; -import { flushSync } from "react-dom"; -type LoginType = "phone" | "account"; +} from '@ant-design/pro-components'; +import { history, useModel, useNavigate } from '@umijs/max'; +import { Button, Divider, message, Space, Tabs, theme } from 'antd'; +import type { CSSProperties } from 'react'; +import { useState } from 'react'; +import { flushSync } from 'react-dom'; +import { getTenantIdByName, login } from '@/services/login'; +import * as authUtil from '@/utils/auth'; + +type LoginType = 'phone' | 'account'; const iconStyles: CSSProperties = { - color: "rgba(0, 0, 0, 0.2)", - fontSize: "18px", - verticalAlign: "middle", - cursor: "pointer", + color: 'rgba(0, 0, 0, 0.2)', + fontSize: '18px', + verticalAlign: 'middle', + cursor: 'pointer', }; const Page = () => { - const [loginType, setLoginType] = useState("account"); + const [loginType, setLoginType] = useState('account'); const { token } = theme.useToken(); const [messageApi, contextHolder] = message.useMessage(); - const { initialState, setInitialState } = useModel("@@initialState"); + const { initialState, setInitialState } = useModel('@@initialState'); const navigate = useNavigate(); // 获取租户 ID const getTenantId = async (name: string) => { @@ -57,7 +58,7 @@ const Page = () => { try { // 根据登录类型处理不同的参数 const params = { - tenantName: "芋道源码", + tenantName: '芋道源码', ...values, }; @@ -71,21 +72,22 @@ const Page = () => { // 调用登录接口 const data = await login(params); // 登录成功 - messageApi.success("登录成功!"); + messageApi.success('登录成功!'); // 跳转到首页 authUtil.setToken(data); await fetchUserInfo(); const urlParams = new URL(window.location.href).searchParams; - navigate(urlParams.get("redirect") || "/"); + // navigate(urlParams.get("redirect") || "/"); + window.location.href = urlParams.get('redirect') || '/'; } catch (error) { - messageApi.error("登录失败,请检查网络或稍后重试!"); + messageApi.error('登录失败,请检查网络或稍后重试!'); } }; return (
{contextHolder} @@ -95,8 +97,8 @@ const Page = () => { backgroundVideoUrl="https://gw.alipayobjects.com/v/huamei_gcee1x/afts/video/jXRBRK_VAwoAAAAAAAAAAAAAK4eUAQBr" // title="BY" containerStyle={{ - backgroundColor: "rgb(0 0 0 / 51%)", - backdropFilter: "blur(4px)", + backgroundColor: 'rgb(0 0 0 / 51%)', + backdropFilter: 'blur(4px)', }} onFinish={handleSubmit} subTitle="百业到家云控台" @@ -127,17 +129,17 @@ const Page = () => { actions={
@@ -147,48 +149,48 @@ const Page = () => {
- +
- +
- +
@@ -199,125 +201,125 @@ const Page = () => { activeKey={loginType} onChange={(activeKey) => setLoginType(activeKey as LoginType)} > - - + + - {loginType === "account" && ( + {loginType === 'account' && ( <> ), style: { - backgroundColor: "rgb(0 0 0 / 77%)", - color: "white", + backgroundColor: 'rgb(0 0 0 / 77%)', + color: 'white', }, }} - placeholder={"用户名: admin or user"} + placeholder={'用户名: admin or user'} rules={[ { required: true, - message: "请输入用户名!", + message: '请输入用户名!', }, ]} /> ), style: { - backgroundColor: "rgb(0 0 0 / 77%)", - color: "white", + backgroundColor: 'rgb(0 0 0 / 77%)', + color: 'white', }, }} - placeholder={"密码: ant.design"} + placeholder={'密码: ant.design'} rules={[ { required: true, - message: "请输入密码!", + message: '请输入密码!', }, ]} /> )} - {loginType === "phone" && ( + {loginType === 'phone' && ( <> ), style: { - backgroundColor: "rgb(0 0 0 / 77%)", - color: "white", + backgroundColor: 'rgb(0 0 0 / 77%)', + color: 'white', }, }} name="mobile" - placeholder={"手机号"} + placeholder={'手机号'} rules={[ { required: true, - message: "请输入手机号!", + message: '请输入手机号!', }, { pattern: /^1\d{10}$/, - message: "手机号格式错误!", + message: '手机号格式错误!', }, ]} /> ), }} captchaProps={{ - size: "large", + size: 'large', }} - placeholder={"请输入验证码"} + placeholder={'请输入验证码'} captchaTextRender={(timing, count) => { if (timing) { - return `${count} ${"获取验证码"}`; + return `${count} ${'获取验证码'}`; } - return "获取验证码"; + return '获取验证码'; }} name="captcha" rules={[ { required: true, - message: "请输入验证码!", + message: '请输入验证码!', }, ]} onGetCaptcha={async () => { - message.success("获取验证码成功!验证码为:1234"); + message.success('获取验证码成功!验证码为:1234'); }} /> @@ -332,7 +334,7 @@ const Page = () => { 忘记密码 diff --git a/src/utils/menuUtils.tsx b/src/utils/menuUtils.tsx index c578e2d..fe49b3e 100644 --- a/src/utils/menuUtils.tsx +++ b/src/utils/menuUtils.tsx @@ -2,7 +2,10 @@ import { Spin } from 'antd'; import React from 'react'; import type { MenuVO } from '@/services/system/menu'; -export const loopMenuItem = (menus: MenuVO[], pId: number | string): any[] => { +export const loopMenuItem = ( + menus: MenuVO[], + pId: number | string = '/', +): any[] => { return menus.map((item) => { let Component: React.ComponentType | null = null; if (item.component && item.component.trim().length > 0) { @@ -59,113 +62,3 @@ export const loopMenuItem = (menus: MenuVO[], pId: number | string): any[] => { return routeItem; }); }; - -// return menus.flatMap((item) => { -// let Component: React.ComponentType | null = null; -// if (item.component && item.component.length > 0) { -// // 防止配置了路由,但本地暂未添加对应的页面,产生的错误 -// Component = React.lazy(() => { -// const importComponent = () => import(`@/pages/${item.component}`); -// const import404 = () => import("@/pages/404"); -// return importComponent().catch(import404); -// }); -// } -// if (item.children && item.children.length > 0) { -// return [ -// { -// path: item.path, -// hideInMenu: false, -// parentId: pId, -// id: item.id, -// children: [...loopMenuItem(item.children, item.id)], // 添加缺失的 children 属性 -// }, -// ]; -// } else { -// return [ -// { -// path: item.path, -// name: item.name, -// // icon: item.icon, -// id: item.id, -// parentId: pId, -// hideInMenu: !item.visible, -// element: ( -// } -// > -// {Component && } -// -// ), -// }, -// ]; -// } -// }); -// return []; -// }; - -// function getFirstLeafPath(menus: any[], parentPath: string): string { -// const firstMenu = menus[0]; -// const currentPath = `${parentPath}/${firstMenu.path}`; -// if (firstMenu.children && firstMenu.children.length > 0) { -// if (!firstMenu.hideInMenu) { -// return getFirstLeafPath(firstMenu.children, currentPath); -// } else { -// return getFirstLeafPath(firstMenu.children, parentPath); -// } -// } else { -// return currentPath; -// } -// } -// src/utils/route.ts -import { lazy } from 'react'; - -export interface RouteItem { - id: number; - parentId: number; - name: string; - path: string; - component: string | null; - componentName: string; - icon: string; - visible: boolean; - keepAlive: boolean; - alwaysShow: boolean; - children: RouteItem[] | null; -} - -/** - * 转换后端路由数据为 Ant Design Pro 路由格式 - */ -export function transformRoutes(routes: MenuVO[]): any[] { - return routes - .filter((route) => route.visible) // 只显示可见路由 - .map((route) => { - const routeConfig: any = { - path: route.path, - name: route.name, - icon: route.icon || undefined, - }; - - // 处理组件 - if (route.component) { - routeConfig.component = lazy( - () => - import(`@/pages/${route.component}`).catch( - () => import('@/pages/404'), - ), // 组件不存在时显示404 - ); - } - - // 处理子路由 - if (route.children && route.children.length > 0) { - routeConfig.routes = transformRoutes(route.children); - } - - // 隐藏菜单但保留路由 - if (!route.visible) { - routeConfig.hideInMenu = true; - } - - return routeConfig; - }); -}