feat: 内容管理

This commit is contained in:
2025-10-29 17:10:53 +08:00
parent 476ee7a754
commit 4c628fee22
67 changed files with 8210 additions and 4494 deletions

View File

@@ -1,28 +1,28 @@
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 } from "@umijs/max";
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 } from '@umijs/max';
import {
AvatarDropdown,
AvatarName,
Footer,
Question,
SelectLang,
} from "@/components";
import { getInfo } from "@/services/login";
import type { UserInfoVO } from "@/services/login/types";
import defaultSettings from "../config/defaultSettings";
import { errorConfig } from "./requestErrorConfig";
import "@ant-design/v5-patch-for-react-19";
import { useDictStore } from "@/hooks/stores/dict";
import { getAccessToken, getTenantId } from "@/utils/auth";
import { CACHE_KEY, useCache } from "./hooks/web/useCache";
import type { MenuVO } from "./services/system/menu";
import { loopMenuItem } from "./utils/menuUtils";
} from '@/components';
import { getInfo } from '@/services/login';
import type { UserInfoVO } from '@/services/login/types';
import defaultSettings from '../config/defaultSettings';
import { errorConfig } from './requestErrorConfig';
import '@ant-design/v5-patch-for-react-19';
import { useDictStore } from '@/hooks/stores/dict';
import { getAccessToken, getTenantId } from '@/utils/auth';
import { CACHE_KEY, useCache } from './hooks/web/useCache';
import type { MenuVO } from './services/system/menu';
import { loopMenuItem } from './utils/menuUtils';
const isDev = process.env.NODE_ENV === "development";
const isDev = process.env.NODE_ENV === 'development';
const isDevOrTest = isDev || process.env.CI;
const loginPath = "/user/login";
const loginPath = '/user/login';
// 标记是否已添加动态路由
/**
@@ -42,7 +42,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);
@@ -64,8 +64,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);
@@ -122,24 +122,29 @@ 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',
},
],
// 面包屑配置
breadcrumb: {
enable: true,
useRoutes: true,
},
menuHeaderRender: undefined,
// 自定义 403 页面
unAccessible: <div>unAccessible</div>,
@@ -175,57 +180,30 @@ 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();
const tenantId = getTenantId(); // 默认租户ID为1
const contentType: string = options.headers?.["Content-Type"] as string;
// 设置统一的请求头
const headers: Record<string, string> = {
...options.headers,
Accept: "*",
"tenant-id": tenantId,
Accept: '*',
'tenant-id': tenantId,
};
// 如果有token则添加Authorization头
if (token) {
headers.Authorization = `Bearer ${getAccessToken()}`;
headers["Content-Type"] = contentType || "application/json";
}
return { url, options: { ...options, headers } };
},
// requestInterceptors: [
// (url, options) => {
// // 为所有请求添加 API 前缀
// if (url && !url.startsWith(process.env.API_PREFIX || "/admin-api")) {
// url = (process.env.API_PREFIX || "/admin-api") + url;
// }
// // 获取存储在本地的 token 和 tenantId
// const token = getAccessToken();
// const tenantId = getTenantId(); // 默认租户ID为1
// console.log("request", options);
// // 设置统一的请求头
// const contentType: string = options.headers?.["Content-Type"] as string;
// const headers: Record<string, string> = {
// ...options.headers,
// Accept: "*",
// "Content-Type": contentType || "application/json",
// "tenant-id": tenantId,
// };
// // 如果有token则添加Authorization头
// if (token) {
// headers.Authorization = `Bearer ${getAccessToken()}`;
// }
// console.log("headers", headers);
// return { url, options: { ...options, ...headers } };
// },
],
// 添加参数序列化配置
@@ -234,7 +212,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);
});
@@ -272,7 +250,7 @@ export async function patchClientRoutes({ routes }: any) {
wsCache.set(CACHE_KEY.ROLE_ROUTERS, data.menus);
menus = data.menus;
} catch (error) {
console.error("获取菜单失败:", error);
console.error('获取菜单失败:', error);
return;
}
}
@@ -280,7 +258,7 @@ export async function patchClientRoutes({ routes }: any) {
if (!menus || menus.length === 0) {
return;
}
const routerIndex = routes.findIndex((item: any) => item.path === "/");
const routerIndex = routes.findIndex((item: any) => item.path === '/');
const parentId = routes[routerIndex].id;
if (menus) {