feat: 消息中心-站内信管理
This commit is contained in:
90
src/app.tsx
90
src/app.tsx
@@ -1,38 +1,38 @@
|
||||
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
|
||||
import { SettingDrawer } from '@ant-design/pro-components';
|
||||
import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max';
|
||||
import { history, Link, Navigate } from '@umijs/max';
|
||||
import { Modal, Spin } from 'antd';
|
||||
import React, {
|
||||
Children,
|
||||
Component,
|
||||
createContext,
|
||||
JSX,
|
||||
Suspense,
|
||||
} from "react";
|
||||
import { Modal, Spin } from "antd";
|
||||
import type { Settings as LayoutSettings } from "@ant-design/pro-components";
|
||||
import { SettingDrawer } from "@ant-design/pro-components";
|
||||
import type { RequestConfig, RunTimeLayoutConfig } from "@umijs/max";
|
||||
import { history, Link, Navigate } from "@umijs/max";
|
||||
} from 'react';
|
||||
import {
|
||||
AvatarDropdown,
|
||||
AvatarName,
|
||||
Footer,
|
||||
Question,
|
||||
SelectLang,
|
||||
} from "@/components";
|
||||
import { getInfo } from "@/services/login";
|
||||
import type { UserVO, TokenType, UserInfoVO } from "@/services/login/types";
|
||||
import defaultSettings from "../config/defaultSettings";
|
||||
import { errorConfig } from "./requestErrorConfig";
|
||||
import "@ant-design/v5-patch-for-react-19";
|
||||
import { getAccessToken, getRefreshToken, getTenantId } from "@/utils/auth";
|
||||
import { CACHE_KEY, useCache } from "./hooks/web/useCache";
|
||||
import { MenuVO } from "./services/system/menu";
|
||||
|
||||
} from '@/components';
|
||||
import { getInfo } from '@/services/login';
|
||||
import type { TokenType, UserInfoVO, UserVO } from '@/services/login/types';
|
||||
import defaultSettings from '../config/defaultSettings';
|
||||
import { errorConfig } from './requestErrorConfig';
|
||||
import '@ant-design/v5-patch-for-react-19';
|
||||
import { getAccessToken, getRefreshToken, getTenantId } from '@/utils/auth';
|
||||
import {
|
||||
transformBackendMenuToFlatRoutes,
|
||||
transformMenuToRoutes,
|
||||
} from "@/utils/menuUtils";
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
} from '@/utils/menuUtils';
|
||||
import { CACHE_KEY, useCache } from './hooks/web/useCache';
|
||||
import { MenuVO } from './services/system/menu';
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
const isDevOrTest = isDev || process.env.CI;
|
||||
const loginPath = "/user/login";
|
||||
const loginPath = '/user/login';
|
||||
|
||||
// 全局存储菜单数据和路由映射
|
||||
|
||||
@@ -51,7 +51,7 @@ export async function getInitialState(): Promise<{
|
||||
try {
|
||||
const token = getAccessToken();
|
||||
if (!token) {
|
||||
throw new Error("No token found");
|
||||
throw new Error('No token found');
|
||||
}
|
||||
const data = await getInfo();
|
||||
wsCache.set(CACHE_KEY.USER, data);
|
||||
@@ -69,8 +69,8 @@ export async function getInitialState(): Promise<{
|
||||
const { location } = history;
|
||||
|
||||
if (
|
||||
![loginPath, "/user/register", "/user/register-result"].includes(
|
||||
location.pathname
|
||||
![loginPath, '/user/register', '/user/register-result'].includes(
|
||||
location.pathname,
|
||||
)
|
||||
) {
|
||||
const currentUser = wsCache.get(CACHE_KEY.USER);
|
||||
@@ -125,22 +125,22 @@ export const layout: RunTimeLayoutConfig = ({
|
||||
},
|
||||
bgLayoutImgList: [
|
||||
{
|
||||
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr",
|
||||
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr',
|
||||
left: 85,
|
||||
bottom: 100,
|
||||
height: "303px",
|
||||
height: '303px',
|
||||
},
|
||||
{
|
||||
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr",
|
||||
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr',
|
||||
bottom: -68,
|
||||
right: -45,
|
||||
height: "303px",
|
||||
height: '303px',
|
||||
},
|
||||
{
|
||||
src: "https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr",
|
||||
src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: "331px",
|
||||
width: '331px',
|
||||
},
|
||||
],
|
||||
menuHeaderRender: undefined,
|
||||
@@ -178,14 +178,14 @@ export const layout: RunTimeLayoutConfig = ({
|
||||
* @doc https://umijs.org/docs/max/request#配置
|
||||
*/
|
||||
export const request: RequestConfig = {
|
||||
baseURL: isDev ? "" : "https://proapi.azurewebsites.net",
|
||||
baseURL: isDev ? '' : 'https://proapi.azurewebsites.net',
|
||||
...errorConfig,
|
||||
// 添加请求拦截器
|
||||
requestInterceptors: [
|
||||
(url, options) => {
|
||||
// 为所有请求添加 API 前缀
|
||||
if (url && !url.startsWith(process.env.API_PREFIX || "/admin-api")) {
|
||||
url = (process.env.API_PREFIX || "/admin-api") + url;
|
||||
if (url && !url.startsWith(process.env.API_PREFIX || '/admin-api')) {
|
||||
url = (process.env.API_PREFIX || '/admin-api') + url;
|
||||
}
|
||||
// 获取存储在本地的 token 和 tenantId
|
||||
const token = getAccessToken();
|
||||
@@ -193,12 +193,12 @@ export const request: RequestConfig = {
|
||||
// 设置统一的请求头
|
||||
const headers: Record<string, string> = {
|
||||
...options.headers,
|
||||
Accept: "*",
|
||||
"tenant-id": tenantId,
|
||||
Accept: '*',
|
||||
'tenant-id': tenantId,
|
||||
};
|
||||
// 如果有token,则添加Authorization头
|
||||
if (token) {
|
||||
headers["Authorization"] = `Bearer ${getAccessToken()}`;
|
||||
headers['Authorization'] = `Bearer ${getAccessToken()}`;
|
||||
}
|
||||
return { url, options: { ...options, headers } };
|
||||
},
|
||||
@@ -210,7 +210,7 @@ export const request: RequestConfig = {
|
||||
const appendParams = (key: string, value: any) => {
|
||||
if (Array.isArray(value)) {
|
||||
// 特殊处理 createTime 数组,转换为 createTime[0] 和 createTime[1] 格式
|
||||
if (key === "createTime") {
|
||||
if (key === 'createTime') {
|
||||
value.forEach((val, index) => {
|
||||
searchParams.append(`${key}[${index}]`, val);
|
||||
});
|
||||
@@ -237,23 +237,23 @@ export function patchClientRoutes({ routes }: { routes: any }) {
|
||||
const { wsCache } = useCache();
|
||||
console.log(2222);
|
||||
const globalMenus = wsCache.get(CACHE_KEY.ROLE_ROUTERS);
|
||||
const routerIndex = routes.findIndex((item: any) => item.path === "/");
|
||||
const routerIndex = routes.findIndex((item: any) => item.path === '/');
|
||||
const parentId = routes[routerIndex].id;
|
||||
|
||||
if (globalMenus) {
|
||||
routes[routerIndex]["routes"].push(...loopMenuItem(globalMenus, parentId));
|
||||
routes[routerIndex]['routes'].push(...loopMenuItem(globalMenus, parentId));
|
||||
}
|
||||
}
|
||||
|
||||
const loopMenuItem = (menus: any[], pId: number | string): any[] => {
|
||||
return menus.flatMap((item) => {
|
||||
let Component: React.ComponentType<any> | null = null;
|
||||
console.log(findFirstLeafRoute(item), "item");
|
||||
console.log(findFirstLeafRoute(item), 'item');
|
||||
if (item.component && item.component.length > 0) {
|
||||
// 防止配置了路由,但本地暂未添加对应的页面,产生的错误
|
||||
Component = React.lazy(() => {
|
||||
const importComponent = () => import(`@/pages/${item.component}`);
|
||||
const import404 = () => import("@/pages/404");
|
||||
const import404 = () => import('@/pages/404');
|
||||
return importComponent().catch(import404);
|
||||
});
|
||||
}
|
||||
@@ -262,7 +262,7 @@ const loopMenuItem = (menus: any[], pId: number | string): any[] => {
|
||||
{
|
||||
path: item.path,
|
||||
name: item.name,
|
||||
icon: item.icon,
|
||||
// icon: item.icon,
|
||||
id: item.id,
|
||||
parentId: pId,
|
||||
|
||||
@@ -281,13 +281,13 @@ const loopMenuItem = (menus: any[], pId: number | string): any[] => {
|
||||
{
|
||||
path: item.path,
|
||||
name: item.name,
|
||||
icon: item.icon,
|
||||
// icon: item.icon,
|
||||
id: item.menuID,
|
||||
parentId: pId,
|
||||
redirect: "/system/tenant/list",
|
||||
redirect: '/system/tenant/list',
|
||||
element: (
|
||||
<React.Suspense
|
||||
fallback={<Spin style={{ width: "100%", height: "100%" }} />}
|
||||
fallback={<Spin style={{ width: '100%', height: '100%' }} />}
|
||||
>
|
||||
{Component && <Component />}
|
||||
</React.Suspense>
|
||||
@@ -299,7 +299,7 @@ const loopMenuItem = (menus: any[], pId: number | string): any[] => {
|
||||
});
|
||||
};
|
||||
|
||||
const findFirstLeafRoute = (menuItem: any, parent = "/"): string | null => {
|
||||
const findFirstLeafRoute = (menuItem: any, parent = '/'): string | null => {
|
||||
// 如果没有子菜单,返回当前路径
|
||||
|
||||
if (!menuItem.children || menuItem.children.length === 0) {
|
||||
@@ -308,7 +308,7 @@ const findFirstLeafRoute = (menuItem: any, parent = "/"): string | null => {
|
||||
|
||||
// 递归查找第一个叶子节点
|
||||
for (const child of menuItem.children) {
|
||||
const leafRoute = findFirstLeafRoute(child, menuItem.path + "/");
|
||||
const leafRoute = findFirstLeafRoute(child, menuItem.path + '/');
|
||||
if (leafRoute) {
|
||||
return leafRoute;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user