diff --git a/package.json b/package.json index 9b0d6c27c4d4763209dfd376ad1cb4cd31223d58..00311f5de5c446ebc7e83961e4603afd99892b0c 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@ainiteam/quick-react-ui": "0.0.0-alpha.5", + "@ainiteam/quick-react-ui": "0.0.0-alpha.6", "@ant-design/icons": "^5.2.6", "@reduxjs/toolkit": "^2.0.1", "@types/crypto-js": "^4.2.1", diff --git a/src/views/auth/role/components/DialogProgress/index.tsx b/src/views/auth/role/components/DialogProgress/index.tsx index 6c9940d136ebb8edb41477390894e5f3f1367768..43eff0f15a9d1c447954b1c1a2234f1c2c575057 100644 --- a/src/views/auth/role/components/DialogProgress/index.tsx +++ b/src/views/auth/role/components/DialogProgress/index.tsx @@ -1,7 +1,242 @@ -const DialogProgress: React.FC = () => { - return ( -
DialogProgress
- ); +import { getApiPermission, getMenuPermission } from "@/api/auth"; +import { getApiList } from "@/api/system/api"; +import { getMenuList } from "@/api/system/menu"; +import { IMenuTree } from "@/types"; +import { listToTableTree, listToTree } from "@/utils"; +import { Steps, Tree } from "antd"; +import { useEffect, useState } from "react"; + +type RoleProp = { + role: any; +}; + +const DialogProgress: React.FC = (props: RoleProp) => { + const { role } = props; + const [current, setCurrent] = useState(0); + const [menuTreeData, setMenuTreeData] = useState([]); + const [menuTreeList, setMenuTreeList] = useState([]); + const [apiTreeList, setApiTreeList] = useState([]); + const [apiTreeData, setApiTreeData] = useState([]); + + const treeData = [ + { + title: "0-0", + key: "0-0", + children: [ + { + title: "0-0-0", + key: "0-0-0", + children: [ + { + title: "0-0-0-0", + key: "0-0-0-0", + }, + { + title: "0-0-0-1", + key: "0-0-0-1", + }, + { + title: "0-0-0-2", + key: "0-0-0-2", + }, + ], + }, + { + title: "0-0-1", + key: "0-0-1", + children: [ + { + title: "0-0-1-0", + key: "0-0-1-0", + }, + { + title: "0-0-1-1", + key: "0-0-1-1", + }, + { + title: "0-0-1-2", + key: "0-0-1-2", + }, + ], + }, + { + title: "0-0-2", + key: "0-0-2", + }, + ], + }, + { + title: "0-1", + key: "0-1", + children: [ + { + title: "0-1-0-0", + key: "0-1-0-0", + }, + { + title: "0-1-0-1", + key: "0-1-0-1", + }, + { + title: "0-1-0-2", + key: "0-1-0-2", + }, + ], + }, + { + title: "0-2", + key: "0-2", + }, + ]; + const [expandedKeys, setExpandedKeys] = useState(["0-0-0", "0-0-1"]); + const [checkedKeys, setCheckedKeys] = useState(["0-0-0"]); + const [selectedKeys, setSelectedKeys] = useState([]); + const [autoExpandParent, setAutoExpandParent] = useState(true); + const [currentTreeData, setCurrentTreeData] = useState({ + key: "", + title: "", + children: [], + }); + + const onExpand = (expandedKeysValue: any) => { + setExpandedKeys(expandedKeysValue); + setAutoExpandParent(false); + }; + const onCheck = (checkedKeysValue: any) => { + console.log("onCheck", checkedKeysValue); + setCheckedKeys(checkedKeysValue); + }; + const onSelect = (selectedKeysValue: any, info: any) => { + console.log("onSelect", info); + setSelectedKeys(selectedKeysValue); + }; + + const onChange = (value: any) => { + setCurrent(value); + }; + /** + * 加载接口数据 + */ + const apiLoad = () => { + getApiList().then((res) => { + const { data: apiList } = res; + setApiTreeList([...apiList]); + getApiPermission1(role.id!.toString()); + }); + }; + + const getApiPermission1 = (id: string) => { + getApiPermission(id).then((res) => { + const { data: keys } = res; + setSelectedKeys(keys); + setApiTreeData([...apiTreeList]); + // nextTick(() => { + // if (apiTreeRef.value) { + // apiTreeRef.value.setCheckedKeys(keys, false); + // } + // }); + }); + }; + /** + * 加载菜单数据 + */ + const menuLoad = () => { + getMenuList().then((res) => { + const { data: menuList } = res; + const menuTree = listToTree(menuList, 0, { + pId: "pId", + label: "menuName", + }); + console.log("menuTree", menuTree); + setMenuTreeList([...menuTree]); + getMenuPermission1(role.id!.toString()); + }); + }; + const getMenuPermission1 = (id: string) => { + getMenuPermission(id).then((res) => { + const { data: keys } = res; + setSelectedKeys(keys); + setMenuTreeData([...menuTreeList]); + // nextTick(() => { + // if (menuTreeRef.value) { + // menuTreeRef.value.setCheckedKeys(keys, false); + // } + // }); + }); + }; + const FirstTree = () => { + if (current == 0) { + return ( + + ); + } else if (current == 1) { + return ; + } else if (current == 2) { + return
待开发
; + } + }; + useEffect(() => { + menuLoad(); + apiLoad(); + }, []); + return ( + <> +
+ + + {/*
+ +
+
+ +
*/} + {/*
待开发
*/} +
+ + ); }; -export default DialogProgress; \ No newline at end of file +export default DialogProgress; diff --git a/src/views/auth/role/index.tsx b/src/views/auth/role/index.tsx index abd7e6406e76485557e4885732325fcdf049ff7f..d458b7f44d72ef63584a89bbaa41de7de3ae6611 100644 --- a/src/views/auth/role/index.tsx +++ b/src/views/auth/role/index.tsx @@ -1,7 +1,250 @@ +import { + addRole, + deleteRole, + getRoleList, + updateRole, +} from "@/api/system/role"; +import { AppDispatch, RootState } from "@/store"; +import { getPermissionBtns } from "@/store/modules/user"; +import { IRole, IRolePermissionButton } from "@/types"; +import { validatePermission } from "@/utils"; +import { + Crud, + IActionbar, + IColumn, + IFormItem, + // IPage, + IToolbar, +} from "@ainiteam/quick-react-ui"; +import { ExclamationCircleFilled } from "@ant-design/icons"; +import { Modal, message, Button } from "antd"; +import { useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import DialogProgress from "./components/DialogProgress"; + const Role: React.FC = () => { - return ( -
Role
- ); + /** + * 属性 + */ + const { confirm } = Modal; + + const [dataList, setDataList] = useState([]); + const [loading, setLoading] = useState(false); + const dispatch: AppDispatch = useDispatch(); + const { activeTab } = useSelector((state: RootState) => state.tab); + const { permissionBtn }: { permissionBtn: IRolePermissionButton } = + useSelector((state: RootState) => state.user); + const [dialogVisible, setDialogVisible] = useState(false); + const [role, setRole] = useState({}); + const handleAuth = (item: IRole) => { + setDialogVisible(true); + setRole({ ...item }); + }; + + /** + * 工具栏 + */ + const tableToolbar: IToolbar = { + hiddenBatchDeleteButton: true, + hiddenImportButton: true, + hiddenExportButton: true, + hiddenPrintButton: true, + hiddenAddButton: !validatePermission(permissionBtn?.add), + }; + /** + * 操作栏 + */ + + const tableActionbar: IActionbar = { + width: 300, + hiddenEditButton: true, + hiddenDeleteButton: true, + hiddenDetailButton: true, + btns: [ + { + name: "配置权限", + click(item: IRole) { + handleAuth(item); + }, + render() { + return true; + }, + }, + ], + }; + /** + * 表格 + */ + const tableColumns: IColumn[] = [ + { + width: "50", + type: "selection", + }, + { + label: "角色编号", + prop: "roleId", + width: "200", + }, + { + label: "角色名称", + prop: "roleName", + }, + ]; + const handleDelete = (item: IRole, done: any) => { + confirm({ + title: "警告", + icon: , + content: `你真的删除【${item.roleName}】的字典吗?`, + onOk() { + if (!item.id) { + return; + } + deleteRole(item.id).then(() => { + message.success("角色删除成功"); + done(); + }); + }, + }); + }; + /** + * 加载数据 + */ + const load = () => { + setLoading(true); + getRoleList().then((res) => { + setLoading(false); + + const { data: roleList } = res; + setDataList([...roleList]); + }); + }; + /** + * 表单 + */ + const dialogTitle = { + add: "新增角色", + edit: "编辑角色", + detail: "角色详情", + }; + const formModel: IRole = { + id: undefined, + roleId: "", + roleName: "", + }; + const formItems: IFormItem[] = [ + { + label: "角色编号", + labelWidth: "80px", + vModel: "roleId", + placeholder: "角色编号", + editReadonly: true, + prop: "roleId", + rules: [ + { + required: true, + message: "角色编号不能为空", + trigger: "blur", + }, + ], + }, + { + label: "角色名称", + labelWidth: "80px", + vModel: "roleName", + placeholder: "角色名称", + prop: "roleName", + rules: [ + { + required: true, + message: "角色名称不能为空", + trigger: "blur", + }, + ], + }, + ]; + const handleFormSubmit = (form: IRole, done: any) => { + const row = { ...form }; + if (row.id) { + console.log("updateRole", row); + updateRole(row).then(() => { + message.success("角色修改成功"); + done(); + }); + } else { + row.id = undefined; + console.log("addRole", row); + addRole(row).then(() => { + message.success("角色创建成功"); + done(); + }); + } + }; + /** + * 弹窗 + */ + const handleOk = () => { + setDialogVisible(false); + }; + + const handleCancel = () => { + setDialogVisible(false); + }; + const prev = () => { + // dialogProgressRef?.prev(); + }; + const next = () => { + // dialogProgressRef?.next(); + }; + const save = () => { + // dialogProgressRef?.save(() => { + // setDialogVisible(false); + // }); + }; + useEffect(() => { + dispatch(getPermissionBtns(activeTab)); + load(); + }, []); + + return ( + <> + + + 上一步 + , + , + , + ]} + > +
+ +
+
+ + ); }; -export default Role; \ No newline at end of file +export default Role; diff --git a/src/views/help/productIntroduction/index.less b/src/views/help/productIntroduction/index.less new file mode 100644 index 0000000000000000000000000000000000000000..4ec73eec54b7c59e4d774cf9e927cb976ac868bb --- /dev/null +++ b/src/views/help/productIntroduction/index.less @@ -0,0 +1,30 @@ +.product { + .description { + font-size: 24px; + color: gray; + } + + .quick-row { + margin-bottom: 15px; + } + + .quick-card { + height: 400px; + } + .card4 { + margin-right: 15px; + } + .card2 { + margin-right: 15px; + } + p { + font-size: 14px; + color: gray; + } + .quick-button { + margin-left: 10px; + } + .card-header { + font-size: 16px; + } +} diff --git a/src/views/help/productIntroduction/index.tsx b/src/views/help/productIntroduction/index.tsx index 5d36c997c2b6b02a549d4573ea1732f7a0b7838e..e3e1722e2a8cfed1127e78d4b0be6f504576b25d 100644 --- a/src/views/help/productIntroduction/index.tsx +++ b/src/views/help/productIntroduction/index.tsx @@ -1,7 +1,245 @@ +import React from "react"; +import { Button, Card, Col, Row } from "antd"; +import "./index.less"; const ProductIntroduction: React.FC = () => { - return ( -
ProductIntroduction
- ); + const yanshi = () => { + window.open("https://react.quick.ainiteam.com/"); + }; + const kaiyuan = () => { + window.open("https://gitee.com/zhanglp520/quick-react-admin.git"); + }; + return ( + <> +
+ + + +
+
+ 产品名称:quick中后台开发者系统平台 +
+
+
+ quick-react-admin + 是一款免费开源快速搭建中后台系统框架。本框架基于 + vite5、react、antd、@reduxjs/toolkit 以及 react-router-dom + 等最新主流技术并封装了通用的组件方便开发者提高工作效率。后期也会通过版本升级的方式来维护并更新,使开发者拥有一款长期并且稳定的脚手架。本团队还提供了基于 + quick 框架开发的各类业务项目,比如: + 订单管理系统、调度管理系统、聊天系统、音视系统 + 、监控系统、商城系统、物联网平台、外卖系统、ERP 系统、CMR + 系统、OA 系统、物流管理系统、CRM + 管理系统等等常用的业务系统,如有相关需求联系管理员。 +
+

+ 开源地址: + +
+ 演示地址: + +
+ 账号密码:admin/123456 +
+ 如果对你有帮助,帮忙点个star吧! + 也可以fork项目并对项目做出贡献! +
+ 如果想加入项目,请联系管理员! +

+
+
+ + +
+
+ +
+ + + +
+
+ 特色 +
+
+ + +

+ 1.使用 + vite5、react8、redux、@reduxjs/toolkit、react-router-dom、antd + 和 typescript 等前言技术 +
+ 2.封装了通用的组件 +
+ 3.提供了系统管理常用功能模块
+ 4.提供权限管理模块
+ 5.动态菜单技术 +
+ 6.动态路由技术
+ 7.使用 JWT 鉴权 +
+ 8.使用中间件异常处理 +
+ 9.前后端分离 +
+ 10.后端使用 nestjs 框架 +
+ 11.使用 restful 接口规范 +
+ 12.k8s 分布式 +
+

+ + +

+ 13.模块化管理 +
+ 14.使用 mvc 架构及多层设计思想 +
+ 15.token 鉴权 +
+ 16.个人资料修改及密码修改功能 +
+ 17.支持支付功能 +
+ 18.docker 容器化 +
+ 19.jenkins 自动化部署技术 +
+ 20.使用 typeorm 框架,可活支持数据库及多种类型的数据库 +
+

+ +
+
+ + + +
+
+ 升级 +
+
+

+ 发布版本1.0.1 +
+ 1.菜单优化; +
+ 2.路由缓存; +
+ 3.修复bug +
+
+ 发布版本1.1.0 +
+ 1.增加:资源管理模块 +
+ 2.增加:产品介绍页面 +
+ 3.优化:选项卡 +
+ 4.优化:面包屑 +
+ 5.优化:菜单滚动条; +
+ 6.修复bug +
+

+
+ +
+ + + +
+
+ 服务 +
+
+

+ 1.开发文档: + +
+ 2.接口文档: + +
+ 4.码云地址: + +
+ 5.github地址: + +
+ 6.gitlab地址: + +
+ 7.gitee中发起 Issue +
+ 8.qq群帮助:558795174 +
+

+
+ + + +
+
+ 合作 +
+
+

+ 1.承接quick产品的定制化开发 +
+ 2.承接quick产品的业务项目 +
+ 3.组件定制化开发 +
+ 4.其他项目可以联系咨询 +
+ qq:1841031740 +
+

+
+ +
+
+ + ); }; -export default ProductIntroduction; \ No newline at end of file +export default ProductIntroduction; diff --git a/src/views/system/dept/index.tsx b/src/views/system/dept/index.tsx index 9e8ac460f5bf2eff8a28d3c85bda6a1857b31536..8f189eba4cb34551b3463c4cf65304bce2bffba8 100644 --- a/src/views/system/dept/index.tsx +++ b/src/views/system/dept/index.tsx @@ -256,6 +256,7 @@ const Dept: React.FC = () => { leftTree={leftTree} leftTreeRefresh={true} loading={loading} + displayNumber={false} onTreeLoad={treeLoad} onTreeClick={handleTreeClick} onFormSubmit={handleFormSubmit} diff --git a/src/views/system/menu/index.tsx b/src/views/system/menu/index.tsx index 641a86269e6c4da15e39076679248d01069beef3..d3e0a7d4c698d33b612c0e0afd76e85cf1c8a8be 100644 --- a/src/views/system/menu/index.tsx +++ b/src/views/system/menu/index.tsx @@ -164,7 +164,7 @@ const Menu: React.FC = () => { { required: true, message: "请选择菜单类型", - trigger: "change", + // trigger: "change", }, ], },