feat(web): 新增系统管理功能

- 添加系统管理相关的 API 接口和功能模块
- 实现组织机构管理、用户管理、角色管理等系统管理功能
- 新增系统管理相关的页面和组件
- 更新侧边栏菜单,增加系统管理选项
- 添加多语言支持
main
Tuzki 5 months ago
parent de7e203502
commit 9f8cec8233
  1. 14
      web/client/api/index.ts
  2. 132
      web/client/api/request.ts
  3. 89
      web/client/api/system/index.ts
  4. 14
      web/components/layout/side-bar.tsx
  5. 8
      web/hooks/use-chat.ts
  6. 9
      web/locales/en/common.ts
  7. 9
      web/locales/zh/common.ts
  8. 103
      web/new-components/layout/SystemConstruct.tsx
  9. 1
      web/package.json
  10. 11
      web/pages/system/index.tsx
  11. 0
      web/pages/system/menu/菜单管理.md
  12. 15
      web/pages/system/organization/index.module.scss
  13. 369
      web/pages/system/organization/index.tsx
  14. 0
      web/pages/system/organization/组织机构管理.md
  15. 0
      web/pages/system/role/角色管理.md
  16. 0
      web/pages/system/user/index.module.css
  17. 0
      web/pages/system/user/index.tsx
  18. 0
      web/pages/system/user/用户管理.md
  19. 24
      web/tsconfig.json
  20. 31
      web/types/prompt.ts
  21. 7
      web/types/system.ts
  22. 129
      web/yarn.lock

@ -3,6 +3,7 @@ import { HEADER_USER_ID_KEY } from '@/utils/constants/index';
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { STORAGE_USERINFO_KEY } from '@/utils/constants/index';
// 定义 API 响应数据的类型
export type ResponseType<T = any> = {
data: T;
err_code: string | null;
@ -10,16 +11,21 @@ export type ResponseType<T = any> = {
success: boolean;
};
// 定义 Axios 响应的类型,包含自定义的 ResponseType
export type ApiResponse<T = any, D = any> = AxiosResponse<ResponseType<T>, D>;
// 定义成功的 API 请求结果元组类型
export type SuccessTuple<T = any, D = any> = [null, T, ResponseType<T>, ApiResponse<T, D>];
// 定义失败的 API 请求结果元组类型
export type FailedTuple<T = any, D = any> = [Error | AxiosError<T, D>, null, null, null];
// 创建一个 Axios 实例,配置基础 URL
const ins = axios.create({
baseURL: process.env.API_BASE_URL ?? '',
});
// 长时间执行的 API 请求路径列表
const LONG_TIME_API: string[] = [
'/db/add',
'/db/test/connect',
@ -39,6 +45,7 @@ const LONG_TIME_API: string[] = [
'/personal/agent/upload',
];
let authToken = '';
// 请求拦截器,设置请求头和超时时间
ins.interceptors.request.use(request => {
if (typeof window !== 'undefined') {
const tokenStr = localStorage.getItem(STORAGE_USERINFO_KEY) || '{}';
@ -53,6 +60,7 @@ ins.interceptors.request.use(request => {
return request;
});
// 发送 GET 请求的函数
export const GET = <Params = any, Response = any, D = any>(
url: string,
params?: Params,
@ -61,10 +69,12 @@ export const GET = <Params = any, Response = any, D = any>(
return ins.get<Params, ApiResponse<Response>>(url, { params, ...config });
};
// 发送 POST 请求的函数
export const POST = <Data = any, Response = any, D = any>(url: string, data?: Data, config?: AxiosRequestConfig<D>) => {
return ins.post<Data, ApiResponse<Response>>(url, data, config);
};
// 发送 PATCH 请求的函数
export const PATCH = <Data = any, Response = any, D = any>(
url: string,
data?: Data,
@ -73,10 +83,12 @@ export const PATCH = <Data = any, Response = any, D = any>(
return ins.patch<Data, ApiResponse<Response>>(url, data, config);
};
// 发送 PUT 请求的函数
export const PUT = <Data = any, Response = any, D = any>(url: string, data?: Data, config?: AxiosRequestConfig<D>) => {
return ins.put<Data, ApiResponse<Response>>(url, data, config);
};
// 发送 DELETE 请求的函数
export const DELETE = <Params = any, Response = any, D = any>(
url: string,
params?: Params,
@ -85,6 +97,7 @@ export const DELETE = <Params = any, Response = any, D = any>(
return ins.delete<Params, ApiResponse<Response>>(url, { params, ...config });
};
// 导出其他模块的 API 函数
export * from './app';
export * from './chat';
export * from './evaluate';
@ -94,3 +107,4 @@ export * from './prompt';
export * from './request';
export * from './tools';
export * from './user';
export * from './system';

@ -53,6 +53,7 @@ import { AxiosRequestConfig } from 'axios';
import { DELETE, GET, POST, PUT } from '.';
import { STORAGE_USERINFO_KEY } from '@/utils/constants/index';
// 获取存储在 localStorage 中的 token 信息
const getToken = () => {
if (typeof window !== 'undefined') {
const tokenStr = localStorage.getItem(STORAGE_USERINFO_KEY) || '{}';
@ -60,10 +61,13 @@ const getToken = () => {
}
return { token: '' };
};
/** App */
// 获取对话场景列表
export const postScenes = () => {
return POST<null, Array<SceneResponse>>('/api/v1/chat/dialogue/scenes');
};
// 创建新的对话
export const newDialogue = (data: NewDialogueParam) => {
return POST<NewDialogueParam, IChatDialogueSchema>(
`/api/v1/chat/dialogue/new?chat_mode=${data.chat_mode}&model_name=${data.model}`,
@ -71,6 +75,7 @@ export const newDialogue = (data: NewDialogueParam) => {
);
};
// 构建带有查询参数的 URL
const buildUrl = (baseUrl: string, params: any) => {
const queryString = Object.keys(params)
.filter(key => params[key] !== undefined) //
@ -80,49 +85,72 @@ const buildUrl = (baseUrl: string, params: any) => {
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
};
// 添加用户
export const addUser = (data: UserParam) => {
return POST<UserParam, UserParamResponse>('/api/v1/user/add', data);
};
/** Database Page */
// 获取数据库列表
export const getDbList = () => {
return GET<null, DbListResponse>('/api/v2/serve/datasources');
};
// 获取支持的数据库类型
export const getDbSupportType = () => {
return GET<null, DbSupportTypeResponse>('/api/v2/serve/datasource-types');
};
// 删除指定 ID 的数据库
export const postDbDelete = (id: string) => {
return DELETE(`/api/v2/serve/datasources/${id}`);
};
// 编辑数据库信息
export const postDbEdit = (data: PostDbParams) => {
return PUT<PostDbParams, null>('/api/v2/serve/datasources', data);
};
// 添加新的数据库
export const postDbAdd = (data: PostDbParams) => {
return POST<PostDbParams, null>('/api/v2/serve/datasources', data);
};
// 测试数据库连接
export const postDbTestConnect = (data: PostDbParams) => {
return POST<PostDbParams, null>('/api/v2/serve/datasources/test-connection', data);
};
// 刷新数据库连接
export const postDbRefresh = (data: PostDbRefreshParams) => {
return POST<PostDbRefreshParams, boolean>(`/api/v2/serve/datasources/${data.id}/refresh`);
};
/** Chat Page */
// 获取对话列表
export const getDialogueList = () => {
return GET<null, DialogueListResponse>('/api/v1/chat/dialogue/list');
};
// 获取可用的模型列表
export const getUsableModels = () => {
return GET<null, Array<string>>('/api/v1/model/types');
};
// 获取聊天模式参数列表
export const postChatModeParamsList = (chatMode: string) => {
return POST<null, IDB[]>(`/api/v1/chat/mode/params/list?chat_mode=${chatMode}`);
};
// 获取聊天模式参数信息列表
export const postChatModeParamsInfoList = (chatMode: string) => {
return POST<null, Record<string, string>>(`/api/v1/chat/mode/params/info?chat_mode=${chatMode}`);
};
// 获取聊天历史记录
export const getChatHistory = (convId: string) => {
return GET<null, ChatHistoryResponse>(`/api/v1/chat/dialogue/messages/history?con_uid=${convId}`);
};
// 上传文件并加载聊天模式参数
export const postChatModeParamsFileLoad = ({
convUid,
chatMode,
@ -165,28 +193,37 @@ export const postChatModeParamsFileLoad = ({
});
};
// 清除聊天历史记录
export const clearChatHistory = (conUid: string) => {
return POST<null, Record<string, string>>(`/api/v1/chat/dialogue/clear?con_uid=${conUid}`);
};
/** Menu */
// 删除指定对话
export const delDialogue = (conv_uid: string) => {
return POST(`/api/v1/chat/dialogue/delete?con_uid=${conv_uid}`);
};
/** Editor */
// 获取编辑器 SQL 轮次信息
export const getEditorSqlRounds = (id: string) => {
return GET<null, GetEditorSQLRoundRequest>(`/api/v1/editor/sql/rounds?con_uid=${id}`);
};
// 运行编辑器 SQL
export const postEditorSqlRun = (data: PostEditorSQLRunParams) => {
return POST<PostEditorSQLRunParams>(`/api/v1/editor/sql/run`, data);
};
// 运行编辑器图表
export const postEditorChartRun = (data: PostEditorChartRunParams) => {
return POST<PostEditorChartRunParams, PostEditorChartRunResponse>(`/api/v1/editor/chart/run`, data);
};
// 提交 SQL 编辑器内容
export const postSqlEditorSubmit = (data: PostSQLEditorSubmitParams) => {
return POST<PostSQLEditorSubmitParams>(`/api/v1/sql/editor/submit`, data);
};
// 获取编辑器 SQL 内容
export const getEditorSql = (id: string, round: string | number) => {
return POST<GetEditorySqlParams, string | Array<any>>('/api/v1/editor/sql', {
con_uid: id,
@ -194,139 +231,176 @@ export const getEditorSql = (id: string, round: string | number) => {
});
};
/** knowledge */
// 获取知识库参数
export const getArguments = (knowledgeName: string) => {
return POST<any, IArguments>(`/knowledge/${knowledgeName}/arguments`, {});
};
// 保存知识库参数
export const saveArguments = (knowledgeName: string, data: ArgumentsParams) => {
return POST<ArgumentsParams, IArguments>(`/knowledge/${knowledgeName}/argument/save`, data);
};
// 获取知识库列表
export const getSpaceList = (data?: any) => {
return POST<any, Array<ISpace>>('/knowledge/space/list', data);
};
// 获取文档列表
export const getDocumentList = (spaceName: string, data: Record<string, number | Array<number>>) => {
return POST<Record<string, number | Array<number>>, IDocumentResponse>(`/knowledge/${spaceName}/document/list`, data);
};
// 获取图谱可视化结果
export const getGraphVis = (spaceName: string, data: { limit: number }) => {
return POST<Record<string, number>, GraphVisResult>(`/knowledge/${spaceName}/graphvis`, data);
};
// 添加文档
export const addDocument = (knowledgeName: string, data: DocumentParams) => {
return POST<DocumentParams, number>(`/knowledge/${knowledgeName}/document/add`, data);
};
// 添加知识库
export const addSpace = (data: AddKnowledgeParams) => {
return POST<AddKnowledgeParams, number>(`/knowledge/space/add`, data);
};
// 获取文档分块策略列表
export const getChunkStrategies = () => {
return GET<null, Array<IChunkStrategyResponse>>('/knowledge/document/chunkstrategies');
};
// 同步文档
export const syncDocument = (spaceName: string, data: Record<string, Array<number>>) => {
return POST<Record<string, Array<number>>, string | null>(`/knowledge/${spaceName}/document/sync`, data);
};
// 批量同步文档
export const syncBatchDocument = (spaceName: string, data: Array<ISyncBatchParameter>) => {
return POST<Array<ISyncBatchParameter>, ISyncBatchResponse>(`/knowledge/${spaceName}/document/sync_batch`, data);
};
// 上传文档
export const uploadDocument = (knowLedgeName: string, data: FormData) => {
return POST<FormData, number>(`/knowledge/${knowLedgeName}/document/upload`, data);
};
// 获取文档分块列表
export const getChunkList = (spaceName: string, data: ChunkListParams) => {
return POST<ChunkListParams, IChunkList>(`/knowledge/${spaceName}/chunk/list`, data);
};
// 删除文档
export const delDocument = (spaceName: string, data: Record<string, number>) => {
return POST<Record<string, number>, null>(`/knowledge/${spaceName}/document/delete`, data);
};
// 删除知识库
export const delSpace = (data: Record<string, string>) => {
return POST<Record<string, string>, null>(`/knowledge/space/delete`, data);
};
/** models */
// 获取模型列表
export const getModelList = () => {
return GET<null, Array<IModelData>>('/api/v2/serve/model/models');
};
// Create and deploy a new model
// 创建并部署新的模型
export const createModel = (data: StartModelParams) => {
return POST<StartModelParams, boolean>('/api/v2/serve/model/models', data);
};
// Stop the running model
// 停止正在运行的模型
export const stopModel = (data: BaseModelParams) => {
return POST<BaseModelParams, boolean>('/api/v2/serve/model/models/stop', data);
};
// Start the stopped model
// 启动已停止的模型
export const startModel = (data: BaseModelParams) => {
return POST<BaseModelParams, boolean>('/api/v2/serve/model/models/start', data);
};
// 获取支持的模型列表
export const getSupportModels = () => {
return GET<null, Array<SupportModel>>('/api/v2/serve/model/model-types');
};
/** Agent */
// 查询代理
export const postAgentQuery = (data: PostAgentQueryParams) => {
return POST<PostAgentQueryParams, PostAgentPluginResponse>('/api/v1/agent/query', data);
};
// 查询 DBGPTs
export const postDbgptsQuery = (data: PostAgentQueryParams) => {
return POST<PostAgentQueryParams, PostAgentPluginResponse>(
`/api/v1/serve/dbgpts/hub/query_page?page=${data?.page_index}&page_size=${data?.page_size}`,
data,
);
};
// 更新代理
export const postAgentHubUpdate = (data?: PostAgentHubUpdateParams) => {
return POST<PostAgentHubUpdateParams>(
'/api/v1/agent/hub/update',
data ?? { channel: '', url: '', branch: '', authorization: '' },
);
};
// 更新 DBGPTs
export const postDbgptsHubUpdate = (data?: PostAgentHubUpdateParams) => {
return POST<PostAgentHubUpdateParams>(
'/api/v1/serve/dbgpts/hub/source/refresh',
data ?? { channel: '', url: '', branch: '', authorization: '' },
);
};
// 获取我的代理
export const postAgentMy = (user?: string) => {
return POST<undefined, PostAgentMyPluginResponse>('/api/v1/agent/my', undefined, { params: { user } });
};
// 获取我的 DBGPTs
export const postDbgptsMy = (data?: PostDbgptMyQueryParams) => {
return POST<PostDbgptMyQueryParams, PostAgentMyPluginResponse>(
`/api/v1/serve/dbgpts/my/query_page?page=${data?.page_index}&page_size=${data?.page_size}`,
data,
);
};
// 安装代理
export const postAgentInstall = (pluginName: string, user?: string) => {
return POST('/api/v1/agent/install', undefined, {
params: { plugin_name: pluginName, user },
timeout: 60000,
});
};
// 安装 DBGPTs
export const postDbgptsInstall = (data: object, user?: string) => {
return POST('/api/v1/serve/dbgpts/hub/install', data, {
params: { user },
timeout: 60000,
});
};
// 卸载代理
export const postAgentUninstall = (pluginName: string, user?: string) => {
return POST('/api/v1/agent/uninstall', undefined, {
params: { plugin_name: pluginName, user },
timeout: 60000,
});
};
// 卸载 DBGPTs
export const postDbgptsUninstall = (data: { name: string; type: string }, user?: string) => {
return POST('/api/v1/serve/dbgpts/my/uninstall', undefined, {
params: { ...data, user },
timeout: 60000,
});
};
// 上传代理
export const postAgentUpload = (user = '', data: FormData, config?: Omit<AxiosRequestConfig, 'headers'>) => {
return POST<FormData>('/api/v1/personal/agent/upload', data, {
params: { user },
@ -337,20 +411,26 @@ export const postAgentUpload = (user = '', data: FormData, config?: Omit<AxiosRe
...config,
});
};
// 获取 DBGPTs 列表
export const getDbgptsList = () => {
return GET<undefined, GetDBGPTsListResponse>('/api/v1/dbgpts/list');
};
/** chat feedback **/
// 获取聊天反馈选择
export const getChatFeedBackSelect = () => {
return GET<null, FeedBack>(`/api/v1/feedback/select`, undefined);
};
// 获取聊天反馈项
export const getChatFeedBackItme = (conv_uid: string, conv_index: number) => {
return GET<null, Record<string, string>>(
`/api/v1/feedback/find?conv_uid=${conv_uid}&conv_index=${conv_index}`,
undefined,
);
};
// 提交聊天反馈表单
export const postChatFeedBackForm = ({
data,
config,
@ -367,66 +447,78 @@ export const postChatFeedBackForm = ({
});
};
/** prompt */
/** app */
// 收集应用
export const collectApp = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/v1/app/collect', data);
};
// 取消收集应用
export const unCollectApp = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/v1/app/uncollect', data);
};
// 获取资源类型列表
export const getResourceType = () => {
return GET<null, string[]>('/api/v1/resource-type/list');
};
// 发布应用
export const publishApp = (app_code: string) => {
return POST<Record<string, any>, []>('/api/v1/app/publish', { app_code });
};
// 取消发布应用
export const unPublishApp = (app_code: string) => {
return POST<Record<string, any>, []>('/api/v1/app/unpublish', { app_code });
};
// 添加 OMC DB
export const addOmcDB = (params: Record<string, string>) => {
return POST<Record<string, any>, []>('/api/v1/chat/db/add', params);
// return POST<Record<string, any>, []>('/api/v2/serve/datasources', params);
};
// 获取应用信息
export const getAppInfo = (data: GetAppInfoParams) => {
return GET<GetAppInfoParams, IApp>('/api/v1/app/info', data);
};
// 获取支持的数据库列表
export const getSupportDBList = (db_name = '') => {
return GET<null, Record<string, any>>(`/api/v1/permission/db/list?db_name=${db_name}`);
};
// 推荐应用
export const recommendApps = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/v1/app/hot/list', data);
};
// 流搜索
export const flowSearch = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/v1/serve/awel/flows', data);
};
// 模型搜索
export const modelSearch = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/controller/models', data);
};
// 获取知识库管理员列表
export const getKnowledgeAdmins = (spaceId: string) => {
return GET<string, Record<string, any>>(`/knowledge/users/list?space_id=${spaceId}`);
};
// 更新知识库管理员信息
export const updateKnowledgeAdmins = (data: Record<string, string>) => {
return POST<Record<string, any>, any[]>(`/knowledge/users/update`, data);
};
/** AWEL Flow */
/** app */
// 删除应用
export const delApp = (data: Record<string, string>) => {
return POST<Record<string, string>, []>('/api/v1/app/remove', data);
};
// 获取空间配置
export const getSpaceConfig = () => {
return GET<string, SpaceConfig>(`/knowledge/space/config`);
};
};

@ -0,0 +1,89 @@
import {
orgizationParams,
} from '@/types/system';
import { DELETE, GET, POST,PUT } from '../index';
//组织机构管理
//1.查询全部组织机构
export const getAllOrg = (prpos: orgizationParams) => {
return GET<orgizationParams, any>(`/api/dept/list`,prpos);
};
//2.新增部门信息
export const addAllOrg = (prpos:any) => {
return POST<any,[]>('/api/dept/create', prpos);
};
//2.修改部门信息
// 导出一个函数addAllOrg,接收一个参数prpos
export const updateAllOrg = (prpos:any) => {
// 调用POST函数,发送一个POST请求,请求地址为'/api/dept/create',参数为prpos,返回一个Promise对象
return PUT<any,[]>('/api/dept/update', prpos);
};
//3.查询部门详情
export const getDetailAllOrg = (id: number) => {
return GET<any, any>(`/api/dept/`+id);
};
//4.删除部门
export const deleteAllOrg = (id: number) => {
return DELETE<any, any>(`/api/dept/`+id);
};
// export const promptTemplateLoad = (props: PromptTemplateLoadProps) => {
// return POST<PromptTemplateLoadProps, PromptTemplateLoadResponse>(
// `/prompt/template/load?prompt_type=${props.prompt_type}&target=${props.target}`,
// props,
// );
// };
// export const promptResponseVerify = (props: PromptResponseVerifyProps) => {
// return POST<PromptResponseVerifyProps, Record<string, string>>('/prompt/response/verify', props);
// };
// /**
// * 创建prompt
// */
// export const addPrompt = (data: OperatePromptParams) => {
// return POST<OperatePromptParams, []>('/prompt/add', data);
// };
// /**
// * 编辑prompt
// */
// export const updatePrompt = (data: OperatePromptParams) => {
// return POST<OperatePromptParams, []>('/prompt/update', data);
// };
// /**
// * 删除prompt
// */
// export const deletePrompt = (data: OperatePromptParams) => {
// return POST<OperatePromptParams, null>('/prompt/delete', data);
// };
// /**
// * prompt列表
// */
// export const getPromptList = (data: Record<string, any>) => {
// return POST<Record<string, any>, PromptListResponse>(
// `/prompt/query_page?page=${data.page}&page_size=${data.page_size}`,
// data,
// );
// };
// /**
// * LLM测试
// */
// export const llmTest = (data: DebugParams) => {
// return POST<DebugParams, Record<string, any>>('/prompt/template/debug', data);
// };
// /**
// * llm输出验证
// */
// export const llmOutVerify = (data: LlmOutVerifyParams) => {
// return POST<LlmOutVerifyParams, Record<string, any>>('/prompt/response/verify', data);
// };

@ -292,6 +292,20 @@ function SideBar() {
/>
),
path: '/construct/app',
},{
key: 'system_management',
name: t('system_management'),
isActive: pathname.startsWith('/system'),
icon: (
<Image
key='image_construct'
src={pathname.startsWith('/system') ? '/pictures/app_active.png' : '/pictures/app.png'}
alt='construct_image'
width={40}
height={40}
/>
),
path: '/system/organization',
},
];
// if (hasAdmin) {

@ -5,6 +5,7 @@ import { HEADER_USER_ID_KEY } from '@/utils/constants/index';
import { EventStreamContentType, fetchEventSource } from '@microsoft/fetch-event-source';
import { message } from 'antd';
import { useCallback, useContext, useState } from 'react';
import { STORAGE_USERINFO_KEY } from '@/utils/constants/index';
type Props = {
queryAgentURL?: string;
@ -21,7 +22,11 @@ type ChatParams = {
onDone?: () => void;
onError?: (content: string, error?: Error) => void;
};
let authToken = '';
if (typeof window !== 'undefined') {
const tokenStr = localStorage.getItem(STORAGE_USERINFO_KEY) || '{}';
authToken = JSON.parse(tokenStr)?.token || '';
}
const useChat = ({ queryAgentURL = '/api/v1/chat/completions', app_code }: Props) => {
const [ctrl, setCtrl] = useState<AbortController>({} as AbortController);
const { scene } = useContext(ChatContext);
@ -50,6 +55,7 @@ const useChat = ({ queryAgentURL = '/api/v1/chat/completions', app_code }: Props
headers: {
'Content-Type': 'application/json',
[HEADER_USER_ID_KEY]: getUserId() ?? '',
'authorization': `Bearer ${authToken}`,
},
body: JSON.stringify(params),
signal: ctrl ? ctrl.signal : null,

@ -358,4 +358,13 @@ export const CommonEn = {
resources: 'Resources',
app: 'App',
please_select_resource_type: 'Please select resource type',
user_information_management:'userInformationManagement',//用户管理
institutional_framework: 'institutionalFramework', //机构框架
role_management: 'roleManagement', //角色管理
menu_management: 'menuManagement', //菜单管理
system_management: 'systemManagement', //系统管理
department_name:'departmentName',
principal:'Principal',
sort:'Sort',
create_time:'Create Time',
} as const;

@ -363,4 +363,13 @@ export const CommonZh: Resources['translation'] = {
resources: '资源',
app: '应用',
please_select_resource_type: '请选择资源类型',
user_information_management: '用户管理',
institutional_framework: '机构管理',
role_management: '角色管理',
menu_management: '菜单管理',
system_management: '系统管理',
department_name:'部门名称',
principal:'负责人',
sort:'排序',
create_time:'创建时间',
} as const;

@ -0,0 +1,103 @@
import { createFromIconfontCN } from '@ant-design/icons';
import {
MenuFoldOutlined,
UsergroupDeleteOutlined,
UserOutlined
} from '@ant-design/icons';
import { ConfigProvider, Tabs } from 'antd';
import { t } from 'i18next';
import { useRouter } from 'next/router';
import React from 'react';
import './style.css';
const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4926951_si989wen79f.js',
});
function SystemConstructLayout({ children }: { children: React.ReactNode }) {
const items = [
//菜单
{
key: 'menu',
name: t('menu_management'),
path: '/menu',
icon: <MenuFoldOutlined />
},
//角色
{
key: 'role',
name: t('role_management'),
icon: <UsergroupDeleteOutlined />,
path: '/role',
},
//机构
{
key: 'organization',
name: t('institutional_framework'),
path: '/organization',
icon: <IconFont type="icon-company" />,
},
//用户
{
key: 'user',
name: t('user_information_management'),
icon: <UserOutlined />,
path: '/user',
},
];
const router = useRouter();
const activeKey = router.pathname.split('/')[2];
// const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; // unused
return (
<div className='flex flex-col h-full w-full dark:bg-gradient-dark bg-gradient-light bg-cover bg-center'>
<ConfigProvider
theme={{
components: {
Button: {
// defaultBorderColor: 'white',
},
Segmented: {
itemSelectedBg: '#2867f5',
itemSelectedColor: 'white',
},
},
}}
>
<Tabs
// tabBarStyle={{
// background: '#edf8fb',
// border: 'none',
// height: '3.5rem',
// padding: '0 1.5rem',
// color: !isDarkMode ? 'white' : 'black',
// }}
activeKey={activeKey}
items={items.map(items => {
return {
key: items.key,
label: items.name,
children: children,
icon: items.icon,
};
})}
onTabClick={key => {
router.push(`/system/${key}`);
}}
// tabBarExtraContent={
// <Button
// className='border-none text-white bg-button-gradient h-full flex items-center'
// icon={<PlusOutlined className='text-base' />}
// // onClick={handleCreate}
// >
// {t('create_app')}
// </Button>
// }
/>
</ConfigProvider>
</div>
);
}
export default SystemConstructLayout;

@ -80,6 +80,7 @@
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
"sass": "^1.89.0",
"sequelize": "^6.33.0",
"sql-formatter": "^12.2.4",
"tailwindcss": "3.3.2",

@ -0,0 +1,11 @@
import SystemConstructConstruct from '@/new-components/layout/SystemConstruct';
function index() {
return (
<SystemConstructConstruct>
<div>index</div>
</SystemConstructConstruct>
);
}
export default index;

@ -0,0 +1,15 @@
.color-red {
color: red
}
.text-center {
text-align: center
}
.p-10 {
padding: 10px
}
.construc-container table{
display: table;;
}

@ -0,0 +1,369 @@
import { Space, Switch, Input, Table, Form, Button, Select, Popconfirm, App, Modal, InputNumber, TreeSelect } from 'antd';
import { apiInterceptors, getAllOrg, addAllOrg, getDetailAllOrg, updateAllOrg, deleteAllOrg } from '@/client/api';
import useUser from '@/hooks/use-user';
import SystemConstructConstruct from '@/new-components/layout/SystemConstruct';
import styles from './index.module.scss';
import type { ColumnsType } from 'antd/es/table';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { IPrompt, orginzationResponse } from '@/types/prompt';
import { useRequest } from 'ahooks';
import { TFunction } from 'i18next';
const { Option } = Select;
type LayoutType = Parameters<typeof Form>[0]['layout'];
const Prompt = () => {
const [editId, setEditId] = useState<number | null>(null);
const [modalType, setModalType] = useState<'add' | 'edit'>('add');
const [addForm] = Form.useForm();
const { message } = App.useApp();
const [addLoading, setAddLoading] = useState(false);
const { t } = useTranslation();
const [formLayout] = useState<LayoutType>('inline');
const [promptList, setPromptList] = useState<orginzationResponse>();
const DeleteBtn: React.FC<{ record: IPrompt; }> = ({ record }) => {
const userInfo = useUser();
const { t } = useTranslation();
const { message } = App.useApp();
// 删除prompt
const { run: deletePromptRun, loading: deleteLoading } = useRequest(
async record => {
await deleteAllOrg(record?.id);
},
{
manual: true,
onSuccess: async (res: any) => {
if (res?.success == true) {
message.success('删除成功');
await getPrompts();
}else{
message.error('删除失败,请联系管理员');
}
},
onError: (err: any) => {
message.error(err?.message);
},
},
);
// if (userInfo?.id !== record?.id) {
// return null;
// }
return (
<Popconfirm title='确认删除吗?' onConfirm={async () => await deletePromptRun(record)}>
<Button loading={deleteLoading}>{t('Delete')}</Button>
</Popconfirm>
);
};
const getColumns = (t: TFunction, handleEdit: (prompt: IPrompt) => void): ColumnsType<IPrompt> => [
{
title: t('department_name'),
dataIndex: 'name',
key: 'name',
width: '25%',
ellipsis: true,
showSorterTooltip: true,
},
{
title: t('principal'),
dataIndex: 'leader_user_id',
key: 'leader_user_id',
// width: '10%',
},
{
title: t('sort'),
dataIndex: 'sort',
// width: '10%',
key: 'sort',
}, {
title: t('Status'),
dataIndex: 'status',
// width: '10%',
key: 'status',
}, {
title: t('create_time'),
dataIndex: 'create_time',
width: '20%',
key: 'create_time',
}, {
title: t('Operation'),
dataIndex: 'operate',
key: 'operate',
// width: '25%',
render: (_, record) => (
<Space align='center'>
<Button
onClick={() => {
handleEdit(record);
}}
type='primary'
>
{t('Edit')}
</Button>
<DeleteBtn record={record} />
</Space>
),
},
];
const handleEditBtn = async (prompt: IPrompt) => {
setModalType('edit');
setEditId(prompt.id);
try {
const [_, data] = await apiInterceptors(getDetailAllOrg(prompt.id));
if (data) {
addForm.setFieldsValue({
...data,
parent_id: data.parent_id || undefined,
status: data.status === 1
});
setModalVisible(true);
}
} catch (err) {
message.error('获取详情失败');
}
};
const buildTree = (data: IPrompt[]): IPrompt[] => {
const map = new Map<number, IPrompt>();
const tree: IPrompt[] = [];
// 创建哈希映射时不自动添加children字段
data.forEach(item => {
map.set(item.id, { ...item });
});
data.forEach(item => {
const node = map.get(item.id)!;
if (item.parent_id !== 0) {
const parent = map.get(item.parent_id);
if (parent) {
// 只在需要时初始化children数组
parent.children = parent.children || [];
parent.children.push(node);
} else {
tree.push(node);
}
} else {
tree.push(node);
}
});
// 后处理:移除空children
const removeEmptyChildren = (nodes: IPrompt[]): IPrompt[] => {
return nodes.map(node => ({
...node,
children: node.children?.length ? removeEmptyChildren(node.children) : undefined
}));
};
return removeEmptyChildren(tree);
};
const {
run: getPrompts, loading: loadingOrgs
} = useRequest(
async (params?: { name?: string; status?: string }) => { // 改为对象参数
const [_, data] = await apiInterceptors(
getAllOrg(params) // 直接传递参数对象
);
return data;
},
{
manual: true,
onSuccess: data => {
const treeData = buildTree(data.dept_list);
setPromptList({ ...data, dept_list: treeData });
},
},
);
const handleSearch = async () => {
try {
const values = await addForm.validateFields();
await getPrompts({
name: values.name || undefined,
status: values.status || undefined
});
} catch (err) {
console.error('表单验证失败:', err);
}
};
const handleReset = async () => {
addForm.resetFields(); // 清空表单
await getPrompts(); // 重新获取全部数据
};
const [modalVisible, setModalVisible] = useState(false);
const [deptTree, setDeptTree] = useState<any[]>([]);
// 转换部门列表为树形结构
const convertToTree = (data: IPrompt[], parentId = 0, excludeId?: number): any[] => {
return data
.filter(item => !excludeId || item.id !== excludeId) // 仅在编辑时过滤
.filter(item => item.parent_id === parentId)
.map(item => ({
title: item.name,
value: item.id,
children: convertToTree(data, item.id, excludeId),
}));
};
useEffect(() => {
if (promptList?.dept_list) {
// 仅在编辑模式排除当前编辑ID
const excludeId = modalType === 'edit' ? editId : undefined;
setDeptTree(convertToTree(promptList.dept_list, 0, excludeId));
}
}, [promptList, modalType, editId]);
const buttonItemLayout =
formLayout === 'inline'
? {
wrapperCol: { span: 14, offset: 6 },
}
: null;
useEffect(() => {
getPrompts();
}, []);
return (
<SystemConstructConstruct>
<div className={`px-6 py-2 ${styles['construc-container']} md:p-6 h-[90vh] overflow-y-auto`}>
<Form className={`${styles['p-10']} ${styles['color-red ']}`}
onFinish={handleSearch}
layout={'inline'}
form={addForm}
initialValues={{ layout: formLayout }}
>
<Form.Item label="部门名称" name="name">
<Input placeholder="请输入部门名称" />
</Form.Item>
<Form.Item label="部门状态" name="status">
<Select style={{ width: 100 }} placeholder="请选择部门状态">
<Option value="0"></Option>
<Option value="1"></Option>
</Select>
</Form.Item>
<Form.Item {...buttonItemLayout}>
<Button htmlType="submit" type="primary"></Button>
</Form.Item>
<Form.Item {...buttonItemLayout}>
<Button onClick={handleReset} type="primary"></Button>
</Form.Item>
<Form.Item {...buttonItemLayout}>
<Button type="primary" onClick={() => {
setModalType('add');
setModalVisible(true);
addForm.resetFields();
}}></Button>
</Form.Item>
</Form>
<Modal
title={modalType === 'add' ? '新增部门' : '编辑部门'}
open={modalVisible}
onCancel={() => {
setModalVisible(false);
addForm.resetFields();
}}
footer={null}
>
<Form
form={addForm}
labelCol={{ span: 6 }}
wrapperCol={{ span: 16 }}
onFinish={async (values) => {
setAddLoading(true);
try {
let apiCall;
if (modalType === 'edit' && editId) {
apiCall = updateAllOrg({ ...values, status: values.status ? 1 : 0, id: editId });
} else {
apiCall = addAllOrg({
...values,
status: values.status ? 1 : 0,
});
}
const [_, data] = await apiInterceptors(apiCall);
if (data) {
message.success(modalType === 'edit' ? '编辑成功' : '新增成功');
setModalVisible(false);
addForm.resetFields();
await getPrompts();
setEditId(null);
}
} catch (err) {
console.error('操作失败:', err);
} finally {
setAddLoading(false);
}
}}
>
<Form.Item label="部门名称" name="name" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item label="上级部门" name="parent_id">
<TreeSelect
treeData={deptTree}
placeholder="请选择上级部门"
treeDefaultExpandAll
/>
</Form.Item>
<Form.Item label="排序" name="sort" rules={[{ required: true }]}>
<InputNumber min={0} style={{ width: '100%' }} />
</Form.Item>
<Form.Item label="负责人ID" name="leader_user_id" rules={[{ required: true }]}>
<InputNumber min={1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item label="联系电话" name="phone">
<Input />
</Form.Item>
<Form.Item label="邮箱" name="email">
<Input />
</Form.Item>
<Form.Item label="状态" name="status" valuePropName="checked">
<Switch checkedChildren="开启" unCheckedChildren="关闭" />
</Form.Item>
<Form.Item wrapperCol={{ offset: 8, span: 16 }}>
<Space>
<Button onClick={() => setModalVisible(false)}></Button>
<Button type="primary" htmlType="submit" loading={addLoading}></Button>
</Space>
</Form.Item>
</Form>
</Modal>
<Table
columns={getColumns(t, handleEditBtn)}
dataSource={promptList?.dept_list || []}
rowKey={record => record.id}
loading={loadingOrgs}
childrenColumnName="children"
defaultExpandAllRows={true}
// pagination={{
// pageSize: 10,
// total: promptList?.total_count,
// onChange: async (page, page_size) => {
// await getPrompts(page, page_size);
// },
// }}
/>
</div>
</SystemConstructConstruct>
);
};
export default Prompt;

@ -2,7 +2,11 @@
"compilerOptions": {
//
"target": "es6", // ECMAScript
"lib": ["dom", "dom.iterable", "esnext"], //
"lib": [
"dom",
"dom.iterable",
"esnext"
], //
"allowJs": true, // JavaScript
"skipLibCheck": true, //
"strict": false, //
@ -21,9 +25,19 @@
}
],
"paths": {
"@/*": ["./*"] //
}
"@/*": [
"./*"
] //
},
"strictNullChecks": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], //
"exclude": ["node_modules"] //
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
], //
"exclude": [
"node_modules"
] //
}

@ -11,16 +11,29 @@ export interface UpdatePromptParams extends IPrompt {
}
export interface IPrompt {
chat_scene: string;
content: string;
gmt_created: string;
gmt_modified: string;
chat_scene?: string;
content?: string;
gmt_created?: string;
gmt_modified?: string;
id: number;
prompt_name: string;
prompt_type: string;
sub_chat_scene: string;
prompt_name?: string;
prompt_type?: string;
sub_chat_scene?: string;
user_name?: string;
user_id?: string;
name?: string;
sort?:number
leader_user_id?: number;
phone?:string,
email?:string,
status?:number,
creator?:string,
create_time?:string
updater?:string,
update_time?:string
parent_id?:number
children?: IPrompt[];
key?: React.ReactNode;
}
export interface PromptTemplateProps {
@ -86,3 +99,7 @@ export interface PromptListResponse {
total_count: number;
total_pages: number;
}
export interface orginzationResponse {
dept_list: any[];
}

@ -0,0 +1,7 @@
export interface orgizationParams {
params?:{
name?: string;
status?: number;};
name?: string;
status?: number;
}

@ -1592,6 +1592,95 @@
resolved "https://registry.npmmirror.com/@panva/hkdf/-/hkdf-1.2.0.tgz"
integrity sha512-97ZQvZJ4gJhi24Io6zI+W7B67I82q1I8i3BSzQ4OyZj1z4OW87/ruF26lrMES58inTKLy2KgVIDcx8PU4AaANQ==
"@parcel/watcher-android-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1"
integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
"@parcel/watcher-darwin-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67"
integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
"@parcel/watcher-darwin-x64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8"
integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
"@parcel/watcher-freebsd-x64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b"
integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
"@parcel/watcher-linux-arm-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1"
integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
"@parcel/watcher-linux-arm-musl@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e"
integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
"@parcel/watcher-linux-arm64-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30"
integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
"@parcel/watcher-linux-arm64-musl@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2"
integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
"@parcel/watcher-linux-x64-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e"
integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
"@parcel/watcher-linux-x64-musl@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee"
integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
"@parcel/watcher-win32-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243"
integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
"@parcel/watcher-win32-ia32@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6"
integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
"@parcel/watcher-win32-x64@2.5.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947"
integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==
"@parcel/watcher@^2.4.1":
version "2.5.1"
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200"
integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==
dependencies:
detect-libc "^1.0.3"
is-glob "^4.0.3"
micromatch "^4.0.5"
node-addon-api "^7.0.0"
optionalDependencies:
"@parcel/watcher-android-arm64" "2.5.1"
"@parcel/watcher-darwin-arm64" "2.5.1"
"@parcel/watcher-darwin-x64" "2.5.1"
"@parcel/watcher-freebsd-x64" "2.5.1"
"@parcel/watcher-linux-arm-glibc" "2.5.1"
"@parcel/watcher-linux-arm-musl" "2.5.1"
"@parcel/watcher-linux-arm64-glibc" "2.5.1"
"@parcel/watcher-linux-arm64-musl" "2.5.1"
"@parcel/watcher-linux-x64-glibc" "2.5.1"
"@parcel/watcher-linux-x64-musl" "2.5.1"
"@parcel/watcher-win32-arm64" "2.5.1"
"@parcel/watcher-win32-ia32" "2.5.1"
"@parcel/watcher-win32-x64" "2.5.1"
"@peculiar/asn1-schema@^2.3.8":
version "2.3.13"
resolved "https://registry.npmmirror.com/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz"
@ -4337,6 +4426,13 @@ chokidar@^3.5.3:
optionalDependencies:
fsevents "~2.3.2"
chokidar@^4.0.0:
version "4.0.3"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30"
integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==
dependencies:
readdirp "^4.0.1"
chroma-js@^2.1.2:
version "2.4.2"
resolved "https://registry.npmmirror.com/chroma-js/-/chroma-js-2.4.2.tgz"
@ -5009,6 +5105,11 @@ detect-indent@^7.0.1:
resolved "https://registry.npmmirror.com/detect-indent/-/detect-indent-7.0.1.tgz"
integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==
detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
detect-newline@^4.0.0:
version "4.0.1"
resolved "https://registry.npmmirror.com/detect-newline/-/detect-newline-4.0.1.tgz"
@ -6380,6 +6481,11 @@ ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1:
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
immutable@^5.0.2:
version "5.1.2"
resolved "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz#e8169476414505e5a4fa650107b65e1227d16d4b"
integrity sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==
import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz"
@ -7990,6 +8096,11 @@ next@13.4.7:
"@next/swc-win32-ia32-msvc" "13.4.7"
"@next/swc-win32-x64-msvc" "13.4.7"
node-addon-api@^7.0.0:
version "7.1.1"
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
node-fetch@^2.6.9:
version "2.7.0"
resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz"
@ -9101,6 +9212,11 @@ readable-stream@^2.2.2:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readdirp@^4.0.1:
version "4.1.2"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d"
integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz"
@ -9396,6 +9512,17 @@ safe-regex-test@^1.0.3:
resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sass@^1.89.0:
version "1.89.0"
resolved "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz#6df72360c5c3ec2a9833c49adafe57b28206752d"
integrity sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==
dependencies:
chokidar "^4.0.0"
immutable "^5.0.2"
source-map-js ">=0.6.2 <2.0.0"
optionalDependencies:
"@parcel/watcher" "^2.4.1"
scheduler@^0.23.2:
version "0.23.2"
resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz"
@ -9622,7 +9749,7 @@ sort-package-json@2.10.1:
semver "^7.6.0"
sort-object-keys "^1.1.3"
source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1:
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==

Loading…
Cancel
Save