首先要使用antd,要先下载
yarn add antd
登录页面关键代码
import React from 'react'
/*
1、如果要在react中完成样式隔离,需要如下操作
1)命名一个xx.module.scss webpack要求
2) 在需要的组件中通过ES6方式进行导入,导入的格式如下
import 模块名 from 'xx.module.scss的路径'
3) 在页面的标签中引用,引用的格式<标签名 className={模块名.类样式名称}/>或者className={模块名['类样式名称']}/>
*/
/*
2.antd中Form组件的使用
2.1 触发Form中的onFinish事件的回调函数它的的条件
1)必须让
import React,{useState,useEffect} from 'react'
import homeStyle from '../assets/css/home.module.scss'
import {Layout,Menu} from 'antd'
import {WindowsOutlined,TrademarkCircleOutlined,UserOutlined} from '@ant-design/icons'
import {useNavigate,Outlet} from 'react-router-dom'
const {Header,Sider,Content,Footer}=Layout
export default function Home() {
const [menuList,setMenuList]=useState([])
const nav=useNavigate()
useEffect(()=>{
const list=[
{
key:'sub1',
label:'日常业务',
icon: ,
children:[
{
label:'学员管理',
key:'/home/students'
},
{
label:'班级管理',
key:'/home/classes'
}
]
},
{
key:'sub2',
label:'校区管理',
icon: ,
children:[
{
label:'班主任管理',
key:'/home/directors'
},
{
label:'专业管理',
key:'/home/subjects'
}
]
},
{
key:'sub3',
label:'系统管理',
icon: ,
children:[
{
key:'/home/users',
label:'用户管理'
}
]
}
]
setMenuList(list)
},[])
const go=(item)=>{
nav(item.key)
}
return (
<>
蜗牛BOSS管理系统
{/* 设置子路由出口 */}
>
)
}
import React, { useState, useEffect } from 'react'
import { Card, Table, Avatar, Button, Space, Popconfirm } from 'antd';
import api from '../api'
export default function Users() {
const [list, setList] = useState([])
const columns = [
{
title: '用户名',
dataIndex: 'username'
},
{
title: '邮箱',
dataIndex: 'email'
},
{
title: '手机',
dataIndex: 'phone'
},
{
title: '角色',
dataIndex: 'auth',
render: (item) => {
return item == 1 ? '超级管理员' : item == 2 ? '普通管理员' : '暂无'
}
},
{
title: '头像',
dataIndex: 'image',
render: (item) => {
return
}
},
{
title: '操作',
key: 'action',
render: (arg1) => {
return (
查看
{deleteUser(arg1._id)}}
okText="确认"
cancelText="取消">
删除
)
}
}
]
useEffect(() => {
getUsers()
}, [])
const getUsers = async () => {
const result = await api.users.getUsers()
setList(result.data.result)
}
const deleteUser = (_id) => {
console.log('_id', _id);
}
return (
)
}
在api/modules/users下编写获取权限菜单的接口
import request from '../../utils/request'
export default{
getAuthMenus:()=>request.get('/menus/getAuthMenus')
}
在SysMenus.jsx中调用getAuthMenus接口来完成权限菜单数据的获取
useEffect(()=>{
getAuthMenus()
},[])
const getAuthMenus=async()=>{
const result=await api.users.getAuthMenus()
console.log(result.data);
const rlist=transformDataToMenus(result.data)
console.log('转换后的结果',rlist);
setMenuList(rlist)
}
将后台的权限菜单数据转成antd格式的菜单数据
/**
* 将后台的权限菜单数据转成antd格式的菜单数据
*/
const transformDataToMenus=(list)=>{
return list.map(item=>{
let menuItem={label:item.title,key:item.path,icon:React.createElement(icons[item.icon])}
if(item.children){
menuItem.children=transformDataToMenus(item.children)
}
return menuItem
})
}
渲染导航列表
在components文件夹下创建函数Auth组件
在router/index.js的路由配置中使用
将
包裹起来
关键代码如下
import React,{useEffect} from 'react'
import {Navigate,useNavigate} from 'react-router-dom'
import api from '../api'
import {message} from 'antd'
export default function Auth({children}) {
//从localStorage获取token
//如何将结果转成boolean类型
const nav=useNavigate()
const isAuth=!!localStorage.getItem('token')
useEffect(()=>{
getUserInfo()
},[])
const getUserInfo=async()=>{
try {
await api.users.getUserInfo()
} catch (error) {
message.warning('您的token已失效,请重新登录')
nav('/login')
}
}
if(isAuth){
return (
<>
{children}
>
)
}else{
message.warning('您还没有登录请登录')
return (<>
>)
}
}
注意:需要在request.js的响应拦截器中完成Promise.reject()
axios.interceptors.response.use(response=>{
return response.data
},error=>{
return Promise.reject(error)
})
import React, { useState, useEffect } from 'react'
import { Card, Table, Avatar, Button, Space, Popconfirm,Pagination } from 'antd';
import api from '../../api'
export default function Users() {
const [list, setList] = useState([])
const [total,setTotal]=useState(0)
const [pageSize,setPageSize]=useState(10)
const [current,setCurrent]=useState(1)
const columns = [
{
title: '用户名',
dataIndex: 'username'
},
{
title: '邮箱',
dataIndex: 'email'
},
{
title: '手机',
dataIndex: 'phone'
},
{
title: '角色',
dataIndex: 'auth',
render: (item) => {
return item == 1 ? '超级管理员' : item == 2 ? '普通管理员' : '暂无'
}
},
{
title: '头像',
dataIndex: 'image',
render: (item) => {
return
}
},
{
title: '操作',
key: 'action',
render: (arg1) => {
return (
查看
{deleteUser(arg1._id)}}
okText="确认"
cancelText="取消">
删除
)
}
}
]
useEffect(() => {
getUsers()
}, [])
const getUsers = async (params={pageSize:10,currentPage:1}) => {
const result = await api.users.getUsers(params)
setList(result.data.result)
setTotal(result.data.total)
}
const deleteUser = (_id) => {
console.log('_id', _id);
}
const onChange=(page,pageSize)=>{
let params={pageSize,currentPage:page}
getUsers(params)
setCurrent(page)
setPageSize(pageSize)
}
const onSizeChange=(current,pageSize)=>{
console.log('pageSize',pageSize);
console.log('current',current);
let params={pageSize,currentPage:current}
getUsers(params)
}
return (
)
}
import React,{useMemo,useEffect,useState} from 'react'
import { Breadcrumb } from 'antd';
import {useLocation} from 'react-router-dom'
import api from '../api'
export default function MyBreadcrumb() {
const location=useLocation()
let pathname=location.pathname
const [breadcrumbAry,setBreadcrumbAry]=useState([])
useEffect(()=>{
getAuthMenu()
},[])
const getAuthMenu=async()=>{
const result=await api.users.getAuthMenus()
transformAry(result.data)
}
const transformAry=(list)=>{
let breadcrumbData={}
list.forEach(item=>{
if(item.children){
item.children.forEach(subItem=>{
breadcrumbData[subItem.path]=[item,subItem]
})
}
})
setBreadcrumbAry(breadcrumbData[pathname])
}
return (
<>
{
!breadcrumbAry?[].map((item,index)=>{item.title} ):breadcrumbAry.map((item,index)=>{item.title} )
}
>
)
}
import React,{useEffect,useState} from 'react'
import MyBreadcrumb from '../../components/MyBreadcrumb';
import {Button,Card,Modal,Form, Input, Select,Upload,Radio} from 'antd'
import { PlusOutlined,LoadingOutlined } from '@ant-design/icons';
import api from '../../api'
export default function StudentList() {
const [addForm]=Form.useForm()
const [classesOptions,setClassesOptions]=useState([])
const [subjectsOptions,setSubjectsOptions]=useState([])
const [loading, setLoading] = useState(false);
const [imageUrl, setImageUrl] = useState();
useEffect(()=>{
getAllSubjects()
},[])
const getAllSubjects=async()=>{
const result=await api.subjects.getSubjects()
setSubjectsOptions(result.data.result)
}
const changeSubject=async(arg)=>{
const result=await api.classes.getClassesBySubjectsId(arg)
setClassesOptions(result.data.result)
}
const handleChange = (info) => {
if (info.file.status === 'uploading') {
setLoading(true);
return;
}
if (info.file.status === 'done') {
setLoading(false);
setImageUrl(`http://www.zhaijizhe.cn:3005/${info.file.response.data[0]}`)
}
}
const uploadButton = (
{loading ? : }
上传头像
);
const [isModalOpen, setIsModalOpen] = useState(false);
const showModal = () => {
setIsModalOpen(true);
};
const handleOk = () => {
setIsModalOpen(false);
const params={
name:addForm.getFieldValue(['name']),
age:addForm.getFieldValue(['age']),
gender:addForm.getFieldValue(['gender'])?addForm.getFieldValue(['gender']):"男",
subjectsId:addForm.getFieldValue(['subjectsId']),
classesId:addForm.getFieldValue(['classesId']),
}
if(addForm.getFieldValue(['imagePath']).file.response){
params.imageUrl=`http://www.zhaijizhe.cn:3005${addForm.getFieldValue(['imagePath']).file.response.data[0]}`
}
console.log('params',params);
};
const handleCancel = () => {
setIsModalOpen(false);
};
return (
添加学生
男
女
{imageUrl ? (
) : (
uploadButton
)}
)
}