├── src ├── pages │ ├── System │ │ ├── RoleAdmin │ │ │ ├── index.less │ │ │ ├── index.type.ts │ │ │ └── index.tsx │ │ ├── UserAdmin │ │ │ ├── index.less │ │ │ ├── index.type.ts │ │ │ └── index.tsx │ │ ├── MenuAdmin │ │ │ ├── index.less │ │ │ ├── index.type.ts │ │ │ └── index.tsx │ │ └── PowerAdmin │ │ │ ├── index.less │ │ │ ├── index.type.ts │ │ │ └── index.tsx │ ├── Home │ │ ├── index.less │ │ └── index.tsx │ ├── ErrorPages │ │ ├── index.less │ │ ├── 404.tsx │ │ └── 401.tsx │ └── Login │ │ ├── index.less │ │ └── index.tsx ├── vite-env.d.ts ├── assets │ ├── logo.png │ ├── snow.gif │ ├── error.gif │ ├── loading.gif │ ├── nothing.png │ ├── react-logo.jpg │ └── styles │ │ ├── default.less │ │ └── global.less ├── layouts │ ├── UserLayout.less │ ├── BasicLayout.less │ ├── UserLayout.tsx │ └── BasicLayout.tsx ├── config │ └── index.ts ├── components │ ├── Bread │ │ ├── index.less │ │ └── index.tsx │ ├── Loading │ │ ├── index.less │ │ └── index.tsx │ ├── ErrorBoundary │ │ ├── index.less │ │ └── index.tsx │ ├── Footer │ │ ├── index.less │ │ └── index.tsx │ ├── CanvasBack │ │ ├── index.less │ │ └── index.tsx │ ├── Icon │ │ └── index.tsx │ ├── Menu │ │ ├── index.less │ │ └── index.tsx │ ├── Header │ │ ├── index.less │ │ └── index.tsx │ └── TreeChose │ │ ├── RoleTree.tsx │ │ └── PowerTreeTable.tsx ├── store │ └── index.ts ├── main.tsx ├── util │ ├── json.ts │ ├── axios.ts │ └── tools.ts ├── router │ ├── AuthProvider.tsx │ └── index.tsx └── models │ ├── index.type.ts │ ├── app.ts │ └── sys.ts ├── .eslintignore ├── public └── favicon.ico ├── postcss.config.js ├── .prettierrc.json ├── tsconfig.node.json ├── .gitignore ├── index.html ├── tsconfig.json ├── .eslintrc.cjs ├── vite.config.ts ├── README.md ├── README.en.md ├── package.json ├── LICENSE └── mock └── app-data.js /src/pages/System/RoleAdmin/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/System/UserAdmin/index.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | scripts 4 | src/assets 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/snow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/snow.gif -------------------------------------------------------------------------------- /src/assets/error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/error.gif -------------------------------------------------------------------------------- /src/layouts/UserLayout.less: -------------------------------------------------------------------------------- 1 | .page-user { 2 | width: 100%; 3 | min-height: 100vh; 4 | } 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /src/assets/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/loading.gif -------------------------------------------------------------------------------- /src/assets/nothing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/nothing.png -------------------------------------------------------------------------------- /src/assets/react-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-admin/HEAD/src/assets/react-logo.jpg -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": false 6 | } 7 | -------------------------------------------------------------------------------- /src/config/index.ts: -------------------------------------------------------------------------------- 1 | // const env = process.env.NODE_ENV; // development / production 2 | 3 | export const baseUrl = `${location.protocol}//${location.host}`; 4 | -------------------------------------------------------------------------------- /src/components/Bread/index.less: -------------------------------------------------------------------------------- 1 | .bread { 2 | padding: 16px; 3 | display: flex; 4 | align-items: center; 5 | .icon { 6 | flex: none; 7 | color: #22cc22; 8 | margin-right: 8px; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /src/components/Loading/index.less: -------------------------------------------------------------------------------- 1 | .loading { 2 | text-align: center; 3 | padding: 50px; 4 | font-size: 14px; 5 | position: relative; 6 | margin: 0 auto; 7 | color: #888; 8 | img { 9 | margin-bottom: 20px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout.less: -------------------------------------------------------------------------------- 1 | .page-basic { 2 | width: 100%; 3 | min-height: 100vh; 4 | .content { 5 | margin: 0 16px 16px 16px; 6 | padding: 16px; 7 | background: #fff; 8 | height: 100%; 9 | min-height: 280px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/components/ErrorBoundary/index.less: -------------------------------------------------------------------------------- 1 | .error-boundary { 2 | text-align: center; 3 | padding: 50px; 4 | font-size: 14px; 5 | position: relative; 6 | margin: 0 auto; 7 | color: #aaa; 8 | .error-icon { 9 | font-size: 60px; 10 | margin-bottom: 20px; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/components/Footer/index.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | text-align: center; 3 | padding: 0 16px 16px 16px; 4 | flex: none; 5 | a:hover { 6 | text-decoration: underline; 7 | } 8 | &.user-layout { 9 | width: 100%; 10 | background-color: transparent; 11 | color: #ddd; 12 | font-size: 12px; 13 | z-index: 2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/components/CanvasBack/index.less: -------------------------------------------------------------------------------- 1 | .canvas-back { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | overflow: hidden; 8 | canvas { 9 | position: absolute; 10 | display: block; 11 | top: 50%; 12 | left: 50%; 13 | height: 100%; 14 | width: 100%; 15 | transform: translate(-50%, -50%); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | pnpm-lock.yaml 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /src/components/Loading/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Loading组件 3 | * 用于按需加载时过渡显示等 4 | */ 5 | import React from "react"; 6 | import "./index.less"; 7 | import ImgLoading from "@/assets/loading.gif"; 8 | 9 | export default function LoadingComponent(): JSX.Element { 10 | return ( 11 |
12 | 13 |
加载中...
14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Admin 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/Icon/index.tsx: -------------------------------------------------------------------------------- 1 | /* 用于菜单的自定义图标 */ 2 | import React from "react"; 3 | import { createFromIconfontCN } from "@ant-design/icons"; 4 | 5 | const IconFont = createFromIconfontCN({ 6 | scriptUrl: "//at.alicdn.com/t/font_1688075_vwak21i2wxj.js", 7 | }); 8 | 9 | interface Props { 10 | type: string; 11 | } 12 | 13 | export default function Icon(props: Props): JSX.Element { 14 | return ; 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/Home/index.less: -------------------------------------------------------------------------------- 1 | .page-home { 2 | padding: 50px 0 0 0; 3 | height: 100%; 4 | .box { 5 | margin: 0 auto; 6 | text-align: center; 7 | .title { 8 | font-size: 24px; 9 | } 10 | .info { 11 | margin-top: 10px; 12 | color: #888; 13 | } 14 | .link { 15 | margin-top: 40px; 16 | font-size: 12px; 17 | color: #888; 18 | a { 19 | color: #888; 20 | text-decoration: none; 21 | &:hover { 22 | text-decoration: underline; 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | /** 全局唯一数据中心 **/ 2 | 3 | import { init, Models, RematchDispatch, RematchRootState } from "@rematch/core"; 4 | 5 | import app from "@/models/app"; 6 | import sys from "@/models/sys"; 7 | 8 | export interface RootModel extends Models { 9 | app: typeof app; 10 | sys: typeof sys; 11 | } 12 | 13 | const rootModel: RootModel = { app, sys }; 14 | const store = init({ 15 | models: rootModel, 16 | }); 17 | 18 | export type Store = typeof store; 19 | export type Dispatch = RematchDispatch; 20 | export type RootState = RematchRootState; 21 | 22 | export default store; 23 | -------------------------------------------------------------------------------- /src/pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | /* 主页 */ 2 | 3 | import React from "react"; 4 | import ImgLogo from "@/assets/react-logo.jpg"; 5 | 6 | import "./index.less"; 7 | 8 | export default function HomePageContainer(): JSX.Element { 9 | return ( 10 |
11 |
12 | 13 |
React-admin
14 |
15 | 标准后台管理系统解决方案,react18、router6、rematch、antd4、vite4、ES6+ 16 |
17 |
动态菜单配置,权限精确到按钮
18 |
19 |
20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { HashRouter } from "react-router-dom"; 4 | import { Provider } from "react-redux"; 5 | import store from "./store"; 6 | import Router from "./router"; 7 | 8 | import "normalize.css"; 9 | import "@/assets/styles/default.less"; 10 | import "@/assets/styles/global.less"; 11 | 12 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /src/components/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | /* Footer 页面底部 */ 2 | import React from "react"; 3 | import { Layout } from "antd"; 4 | import "./index.less"; 5 | 6 | const { Footer } = Layout; 7 | 8 | interface Props { 9 | className?: string; 10 | } 11 | 12 | export default function FooterCom(props: Props) { 13 | return ( 14 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "baseUrl": "./", 19 | "paths": { 20 | "@/*": ["src/*"] 21 | } 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /src/pages/ErrorPages/index.less: -------------------------------------------------------------------------------- 1 | .page-error { 2 | position: relative; 3 | height: 100%; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | background-color: #fff; 8 | letter-spacing: 1px; 9 | .title { 10 | font-size: 100px; 11 | font-weight: bold; 12 | color: #888; 13 | @supports (-webkit-background-clip: text) { 14 | -webkit-background-clip: text; 15 | -webkit-text-fill-color: transparent; 16 | background-image: url(../../assets/snow.gif); 17 | background-repeat: repeat; 18 | opacity: 0.5; 19 | } 20 | } 21 | .info { 22 | font-size: 20px; 23 | color: #888; 24 | } 25 | .backBtn { 26 | margin-top: 10px; 27 | } 28 | img { 29 | margin-left: 100px; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/pages/System/MenuAdmin/index.less: -------------------------------------------------------------------------------- 1 | .page-menu-admin { 2 | display: flex; 3 | .l { 4 | width: 256px; 5 | border: solid 1px #f0f0f0; 6 | flex: none; 7 | .title { 8 | height: 44px; 9 | line-height: 44px; 10 | box-sizing: border-box; 11 | font-size: 14px; 12 | padding: 0 10px; 13 | border-bottom: 1px solid #f0f0f0; 14 | } 15 | } 16 | .r { 17 | border: solid 1px #f0f0f0; 18 | margin-left: 16px; 19 | flex: auto; 20 | .searchBox { 21 | padding: 8px; 22 | & > ul { 23 | display: flex; 24 | & > li + li { 25 | margin-left: 4px; 26 | flex: none; 27 | } 28 | } 29 | } 30 | .ant-table-pagination.ant-pagination { 31 | margin-right: 10px; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/pages/System/PowerAdmin/index.less: -------------------------------------------------------------------------------- 1 | .page-power-admin { 2 | display: flex; 3 | .l { 4 | width: 256px; 5 | border: solid 1px #f0f0f0; 6 | flex: none; 7 | .title { 8 | height: 44px; 9 | line-height: 44px; 10 | box-sizing: border-box; 11 | font-size: 14px; 12 | padding: 0 10px; 13 | border-bottom: 1px solid #f0f0f0; 14 | } 15 | } 16 | .r { 17 | border: solid 1px #f0f0f0; 18 | margin-left: 16px; 19 | flex: auto; 20 | .searchBox { 21 | padding: 8px; 22 | & > ul { 23 | display: flex; 24 | & > li + li { 25 | margin-left: 4px; 26 | flex: none; 27 | } 28 | } 29 | } 30 | .ant-table-pagination.ant-pagination { 31 | margin-right: 10px; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/components/Menu/index.less: -------------------------------------------------------------------------------- 1 | .sider { 2 | box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35); 3 | min-height: 100vh; 4 | .menuLogo { 5 | height: 64px; 6 | background-color: #001529; 7 | &.hide { 8 | a { 9 | justify-content: center; 10 | div { 11 | overflow: hidden; 12 | opacity: 0; 13 | width: 0; 14 | } 15 | } 16 | } 17 | a { 18 | display: flex; 19 | height: 100%; 20 | align-items: center; 21 | img { 22 | width: 40px; 23 | flex: none; 24 | margin-left: 12px; 25 | } 26 | div { 27 | color: #fff; 28 | width: 100%; 29 | font-size: 24px; 30 | padding-left: 10px; 31 | white-space: nowrap; 32 | transition: all 0.3s; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/layouts/UserLayout.tsx: -------------------------------------------------------------------------------- 1 | /** 基础页面结构 - 有头部,有底部,有侧边导航 **/ 2 | 3 | // ================== 4 | // 所需的第三方库 5 | // ================== 6 | import React from "react"; 7 | import { Outlet } from "react-router-dom"; 8 | import { Layout } from "antd"; 9 | 10 | // ================== 11 | // 自定义的东西 12 | // ================== 13 | import "./UserLayout.less"; 14 | 15 | // ================== 16 | // 组件 17 | // ================== 18 | 19 | import Footer from "../components/Footer"; 20 | 21 | const { Content } = Layout; 22 | 23 | // ================== 24 | // 本组件 25 | // ================== 26 | export default function AppContainer(): JSX.Element { 27 | return ( 28 | 29 | 30 | 31 | 32 |