From a7f5e37aacb9a955bbfcc301b6d95c40d85db735 Mon Sep 17 00:00:00 2001 From: sunqh <253801736@qq.com> Date: Tue, 20 Jan 2026 16:52:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E5=8F=B0=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/configs/adminDepConfig.ts | 12 + src/configs/adminGrpConfig.ts | 12 + src/configs/routes.ts | 6 +- src/pages/Index/index.tsx | 123 +++++++-- src/pages/Login/index.tsx | 2 +- .../Grp/components/AdminGrpEditModal.tsx | 245 ++++++++++++++++++ .../Staff/Grp/components/AdminGrpSelect.tsx | 55 ++++ src/pages/Staff/Grp/index.tsx | 242 +++++++++++++++++ .../Staff/List/components/AdminEditModal.tsx | 47 +++- src/pages/Staff/List/index.tsx | 72 +++-- .../dep/components/AdminDepEditModal.tsx | 116 +++++++++ .../Staff/dep/components/AdminDepSelect.tsx | 55 ++++ src/pages/Staff/dep/index.tsx | 242 ++++++++++++++++- src/pages/Staff/group/index.tsx | 17 -- src/services/AdminDepartmentServices.ts | 4 + src/services/AdminGroupServices.ts | 6 + src/services/AdminServices.ts | 1 + src/services/HomeServices.ts | 3 + 18 files changed, 1187 insertions(+), 73 deletions(-) create mode 100644 src/configs/adminDepConfig.ts create mode 100644 src/configs/adminGrpConfig.ts create mode 100644 src/pages/Staff/Grp/components/AdminGrpEditModal.tsx create mode 100644 src/pages/Staff/Grp/components/AdminGrpSelect.tsx create mode 100644 src/pages/Staff/Grp/index.tsx create mode 100644 src/pages/Staff/dep/components/AdminDepEditModal.tsx create mode 100644 src/pages/Staff/dep/components/AdminDepSelect.tsx delete mode 100644 src/pages/Staff/group/index.tsx create mode 100644 src/services/HomeServices.ts diff --git a/src/configs/adminDepConfig.ts b/src/configs/adminDepConfig.ts new file mode 100644 index 0000000..d9c6e89 --- /dev/null +++ b/src/configs/adminDepConfig.ts @@ -0,0 +1,12 @@ +/** + * 部门状态 + */ +export const stateObj: any = { + 1: '正常', + 2: '禁用', +}; + +export const stateOptions = [ + { label: '正常', value: '1' }, + { label: '禁用', value: '2' }, +]; diff --git a/src/configs/adminGrpConfig.ts b/src/configs/adminGrpConfig.ts new file mode 100644 index 0000000..9b7c81b --- /dev/null +++ b/src/configs/adminGrpConfig.ts @@ -0,0 +1,12 @@ +/** + * 角色状态 + */ +export const statusObj: any = { + 1: '正常', + 2: '禁用', +}; + +export const statusOptions = [ + { label: '正常', value: '1' }, + { label: '禁用', value: '2' }, +]; diff --git a/src/configs/routes.ts b/src/configs/routes.ts index 672dc52..8cdb669 100644 --- a/src/configs/routes.ts +++ b/src/configs/routes.ts @@ -6,8 +6,8 @@ import ErrorPage from '@/pages/Error'; import Index from '@/pages/Index'; import Login from '@/pages/Record/Login'; import Sys from '@/pages/Record/Sys'; -import Dep from '@/pages/Staff/dep'; -import Group from '@/pages/Staff/group'; +import Dep from '@/pages/Staff/Dep'; +import Grp from '@/pages/Staff/Grp'; import StaffList from '@/pages/Staff/List'; import UserList from '@/pages/User/List'; import type { IRouteItem } from '@/router/types'; @@ -44,7 +44,7 @@ export const routes: IRouteItem[] = [ children: [ { path: '/list', Component: StaffList }, { path: '/dep', Component: Dep }, - { path: '/group', Component: Group }, + { path: '/group', Component: Grp }, { path: '/login', Component: Login }, { path: '/sys', Component: Sys }, ], diff --git a/src/pages/Index/index.tsx b/src/pages/Index/index.tsx index e0d2c80..08fb2a6 100644 --- a/src/pages/Index/index.tsx +++ b/src/pages/Index/index.tsx @@ -1,32 +1,99 @@ -const Index = () => { +import { Card, Col, Descriptions, Row, Tooltip } from 'antd'; +import { useEffect, useState } from 'react'; +import { DefaultERPName } from '@/configs/config'; +import { HomeServices } from '@/services/HomeServices'; +import { useRequest } from '@/utils/useRequest'; + +const Index: React.FC = () => { + const [projectInfo, setProjectInfo] = useState([]); // 项目信息 + const [serverInfo, setServerInfo] = useState([]); // 服务器信息 + const [admin, setAdminInfo] = useState([]); // 登录信息 + const { loading: listLoading, request: listRequest } = useRequest(HomeServices.index, { + onSuccessCodeZero: (res) => { + setProjectInfo(res?.data?.projectInfo || {}); + setServerInfo(res?.data?.serverInfo || {}); + setAdminInfo(res?.data?.admin || {}); + }, + }); + + useEffect(() => { + if (!listLoading) { + listRequest(); + } + }, []); + return ( -
- 开发中... - {/* Index */} - {/* - - - login */} - {/* {undefined.map()} */} +
+ {/* 上面登录信息 */} + + + {admin?.username} + {admin?.nickname} + {admin?.create_date} + + + + {/* 下面两列:左服务器,右项目 */} + + + + + {serverInfo?.os} + {serverInfo?.php} + {serverInfo?.web} + {serverInfo?.mysql} + {serverInfo?.host} + {serverInfo?.memory_limit} + {serverInfo?.max_execution_time} + {serverInfo?.upload_max_filesize} + {String(serverInfo?.ssl)} + + + + + + + {DefaultERPName} + {projectInfo?.framework} + {projectInfo?.timezone} + {String(projectInfo?.debug)} + {String(projectInfo?.storage_writable)} + {String(projectInfo?.cache_writable)} + {projectInfo?.cache_driver} + {projectInfo?.session_driver} + + + {projectInfo?.dependencies} +
+ } + > + + {projectInfo?.dependencies} + + + + + + +
); }; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index 33d73f2..96c6404 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -18,7 +18,7 @@ const Login = () => { const { request, loading } = useRequest(AdminServices.login, { onSuccessCodeZero: (res) => { notificationEventBus.emit({ description: '登录成功' }); - user.updateUser(res.user_info); + user.updateUser(res.admin); auth.updateAuth(toObject(res.auth) as IAuth); location.href = '#/'; }, diff --git a/src/pages/Staff/Grp/components/AdminGrpEditModal.tsx b/src/pages/Staff/Grp/components/AdminGrpEditModal.tsx new file mode 100644 index 0000000..fffabca --- /dev/null +++ b/src/pages/Staff/Grp/components/AdminGrpEditModal.tsx @@ -0,0 +1,245 @@ +import { Button, Form, Input, notification, Select, Space, Tree } from 'antd'; +import TextArea from 'antd/lib/input/TextArea'; +import { stringify } from 'qs'; +import type React from 'react'; +import { useImperativeHandle, useState } from 'react'; +import ModalPlugin from '@/components/ModalPlugin'; +import { statusOptions } from '@/configs/adminGrpConfig'; +import { AdminGroupServices } from '@/services/AdminGroupServices'; +import type { IRef } from '@/utils/type'; +import { useRequest } from '@/utils/useRequest'; + +interface IProps extends IRef { + onCallback?: () => void; +} + +export type IAdminGrpEditModalType = { + show: (data?: any) => void; +}; + +export const AdminGrpEditModal: React.FC = (props) => { + const [open, setOpen] = useState(false); + const [title, setTitle] = useState(''); + const [form] = Form.useForm(); + const [data, setData] = useState(null); + + const [menuTree, setMenuTree] = useState([]); + const [checkedKeys, setCheckedKeys] = useState([]); + const [expandedKeys, setExpandedKeys] = useState([]); + + // 请求成功回调 + const success = (res: any) => { + if (res.err_code === 0) { + notification.success({ message: '保存成功' }); + props.onCallback?.(); + setOpen(false); + form.resetFields(); + setCheckedKeys([]); + } + }; + + const { loading: addLoading, request: addRequest } = useRequest(AdminGroupServices.add, { onSuccess: success }); + const { loading: editLoading, request: editRequest } = useRequest(AdminGroupServices.edit, { onSuccess: success }); + + // 获取菜单 + 功能树 + const { request: getMenuTreeRequest } = useRequest(AdminGroupServices.getGrpAjaxRights, { + onSuccessCodeZero: (res) => { + setMenuTree(transformToTreeNodes(res.data)); + }, + }); + + // 将后端数据转换为 Tree 节点 + const transformToTreeNodes = (menus: any[]): any[] => { + return menus.map((menu) => { + const childrenNodes: any[] = []; + + // 子菜单和功能节点 + if (menu.children && menu.children.length > 0) { + menu.children.forEach((child: any) => { + const childNodes: any[] = []; + + // 子菜单的功能节点 + if (child.children && child.children.length > 0) { + child.children.forEach((func: any) => { + childNodes.push({ + title: func.function_ch_name, + key: `func_${func.function_id}`, + isLeaf: true, + }); + }); + } + + // 子菜单自己的功能 + if (child.functions && child.functions.length > 0) { + child.functions.forEach((func: any) => { + childNodes.push({ + title: func.function_ch_name, + key: `func_${func.function_id}`, + isLeaf: true, + }); + }); + } + + childrenNodes.push({ + title: child.menu_ch_name, + key: `menu_${child.menu_id}`, + children: childNodes.length > 0 ? childNodes : undefined, + }); + }); + } + + // 菜单自己的功能节点 + if (menu.functions && menu.functions.length > 0) { + menu.functions.forEach((func: any) => { + childrenNodes.push({ + title: func.function_ch_name, + key: `func_${func.function_id}`, + isLeaf: true, + }); + }); + } + + return { + title: menu.menu_ch_name, + key: `menu_${menu.menu_id}`, + children: childrenNodes.length > 0 ? childrenNodes : undefined, + }; + }); + }; + + const save = async () => { + try { + const values = await form.validateFields(); + + // 只取功能节点 + const funcIds = checkedKeys + .filter((k) => typeof k === 'string' && k.toString().startsWith('func_')) + .map((k) => k.toString().replace('func_', '')); + + values.rules = funcIds.join(','); + + if (data?.group_id) { + values.group_id = data.group_id; + editRequest(stringify(values)); + } else { + addRequest(stringify(values)); + } + } catch (error) { + console.log('表单验证未通过', error); + } + }; + + useImperativeHandle(props.ref, () => ({ + show: async (data?: any) => { + setTitle(data ? `${data.name} 编辑` : '新增'); + setOpen(true); + setData(data); + + setExpandedKeys([]); + + form.resetFields(); + form.setFieldsValue({ + name: data?.name || '', + comments: data?.comments || '', + status: data ? String(data.status) : '1', + }); + + await getMenuTreeRequest(); + + if (data?.rules) { + const keys = data.rules.split(',').map((id: string) => `func_${id}`); + setCheckedKeys(keys); + } else { + setCheckedKeys([]); + } + }, + })); + + const selectAllFuncs = () => { + const allFuncKeys: React.Key[] = []; + const traverse = (nodes: any[]) => { + nodes.forEach((node) => { + if (node.isLeaf) allFuncKeys.push(node.key); + if (node.children) traverse(node.children); + }); + }; + traverse(menuTree); + setCheckedKeys(allFuncKeys); + }; + + const expandAll = () => { + const keys: React.Key[] = []; + + const traverse = (nodes: any[]) => { + nodes.forEach((node) => { + keys.push(node.key); + if (node.children) traverse(node.children); + }); + }; + + traverse(menuTree); + setExpandedKeys(keys); + }; + + const collapseAll = () => { + setExpandedKeys([]); + }; + + return ( + setOpen(false)} + title={title} + footer={[ + , + , + ]} + > +
+ + + + + +