React笔记(七)Antd

一、登录功能

  • 首先要使用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)必须让<Button>的类型是submit,具体的做法是<Button htmlType="submit">2) 如何获取表单中文本框或者密码中的数据,需要在<Form.Item>设置name属性
*/
import loginStyle from '../assets/css/login.module.scss'
import {Form,Input,Button,message} from 'antd'
import {useNavigate} from 'react-router-dom'
import api from '../api'
export default function Login() {const [messageApi,contextHolder]=message.useMessage()const nav=useNavigate()const login=async values=>{const {code,message,token}=await api.users.login(values)if(code){messageApi.open({type:'success',content:message})//保存token到localStorage中localStorage.setItem('token',token)//跳转到后台首页nav('/home')}else{messageApi.open({type: 'error',content: '用户名或者密码有误',});}}return (
​<div>{contextHolder}<div className={loginStyle.container}><div className={loginStyle['login-box']}><Form onFinish={login}><Form.Item name="username"rules={[{required:true,message:'账号不能为空'}]}className={loginStyle.item}><Input className={loginStyle.txt}></Input></Form.Item><Form.Item name="password"rules={[{required:true,message:'密码不能为空'}]}><Input.Password></Input.Password></Form.Item><Form.Item className={loginStyle.item}><Button type='primary' htmlType='submit' className={loginStyle.loginBtn}>登录</Button></Form.Item></Form></div></div></div>)
}

二、后台页面设计

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:<WindowsOutlined />,children:[{label:'学员管理',key:'/home/students'},{label:'班级管理',key:'/home/classes'}]},{key:'sub2',label:'校区管理',icon:<TrademarkCircleOutlined />,children:[{label:'班主任管理',key:'/home/directors'},{label:'专业管理',key:'/home/subjects'}]},{key:'sub3',label:'系统管理',icon:<UserOutlined />,children:[{key:'/home/users',label:'用户管理'}]}]setMenuList(list)},[])const go=(item)=>{nav(item.key)}return (<><Layout><Header><div className={homeStyle.logo}>蜗牛BOSS管理系统</div></Header>  <Layout style={{height:'750px'}}><Sider><Menu items={menuList} onClick={go}mode="inline"theme="dark"defaultOpenKeys={['sub1','sub2']}defaultSelectedKeys={['/home/students']}></Menu></Sider><Content>{/* 设置子路由出口 */}<Outlet></Outlet></Content></Layout><Footer style={{ textAlign: 'center'}}>Ant Design ©2023 Created by Ant UED</Footer></Layout> </>)
}

三、用户列表

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 <Avatar shape="square" size={64} src={item} />}},{title: '操作',key: 'action',render: (arg1) => {return (<Space><Button type='primary'>查看</Button><Popconfirmplacement="top"title="提示"description="您确定要删除吗?"onConfirm={()=>{deleteUser(arg1._id)}}okText="确认"cancelText="取消"><Button type='primary' danger>删除</Button></Popconfirm></Space>)}}
​]useEffect(() => {getUsers()}, [])const getUsers = async () => {const result = await api.users.getUsers()setList(result.data.result)}
​const deleteUser = (_id) => {console.log('_id', _id);}return (<div style={{ display: 'flex', justifyContent: 'center' }}><Card bordered={true} style={{ width: '98%', marginTop: '10px' }}><Table dataSource={list} columns={columns} rowKey="_id"></Table></Card></div>)
}

四、动态菜单

  • 在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})}
  • 渲染导航列表

<Menuitems={menuList}mode="inline"theme="dark"onClick={goNav}></Menu>

五、路由鉴权

  • 在components文件夹下创建函数Auth组件

  • 在router/index.js的路由配置中使用<Auth><Home>包裹起来

  • 关键代码如下

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 (<><Navigate to={"/login"}></Navigate></>)}
}

注意:需要在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 <Avatar shape="square" size={64} src={item} />}},{title: '操作',key: 'action',render: (arg1) => {return (<Space><Button type='primary'>查看</Button><Popconfirmplacement="top"title="提示"description="您确定要删除吗?"onConfirm={()=>{deleteUser(arg1._id)}}okText="确认"cancelText="取消"><Button type='primary' danger>删除</Button></Popconfirm></Space>)}}]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 (<div style={{ display: 'flex', justifyContent: 'center' }}><Card bordered={true} style={{ width: '98%', marginTop: '10px' }}><Table dataSource={list} columns={columns} rowKey="_id"pagination={false}></Table><Pagination style={{marginTop:'20px'}}total={total}pageSize={pageSize}current={current}showSizeChanger={true}pageSizeOptions={[3,5,10,15,20]}onChange={onChange}onShowSizeChange={onSizeChange}></Pagination></Card></div>)
}

七、面包屑

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.pathnameconst [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 (<><Breadcrumb>{!breadcrumbAry?[].map((item,index)=><Breadcrumb.Item key={index}>{item.title}</Breadcrumb.Item>):breadcrumbAry.map((item,index)=><Breadcrumb.Item key={index}>{item.title}</Breadcrumb.Item>)}</Breadcrumb></>)
}

八、增加操作

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 = (<div>{loading ? <LoadingOutlined /> : <PlusOutlined />}<divstyle={{marginTop: 8,}}>上传头像</div></div>);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 (<div> <MyBreadcrumb></MyBreadcrumb><Card><Button type="primary" onClick={showModal}>添加学生</Button><Modal title="添加学生" open={isModalOpen} onOk={handleOk} onCancel={handleCancel} cancelText="取消" okText="确定"><Form form={addForm}><Form.Item label="姓名" name="name"><Input></Input></Form.Item><Form.Item label="年龄" name="age"><Input></Input></Form.Item><Form.Item label="性别" name="gender"><Radio.Group name="radiogroup" defaultValue={"男"}><Radio value={"男"}>男</Radio><Radio value={"女"}>女</Radio></Radio.Group></Form.Item><Form.Item label="专业" name="subjectsId"><Select options={subjectsOptions} fieldNames={{label:'name',value:'_id'}}onChange={changeSubject}></Select></Form.Item><Form.Item label="专业" name="classesId"><Select options={classesOptions} fieldNames={{label:'name',value:'_id'}}></Select></Form.Item><Form.Item label="头像" name="imagePath"><Uploadname="file"listType="picture-card"showUploadList={false}onChange={handleChange}action="http://www.zhaijizhe.cn:3005/images/uploadImages">{imageUrl ? (<imgsrc={imageUrl}alt="avatar"style={{width: '100%',}}/>) : (uploadButton)}</Upload></Form.Item></Form></Modal></Card></div>)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/68590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科技驱动产业升级:浅谈制造型企业对MES系统的应用

在科技不断进步的背景下&#xff0c;制造型行业也在持续发展&#xff0c;但随之而来的挑战也不断增加。传统的管理方式已经无法满足企业的需求&#xff0c;因此许多制造型企业开始寻找新的管理模式。制造执行系统&#xff08;MES&#xff09;作为先进的制造信息技术之一&#x…

Harmony网络请求工具类

使用的网络请求框架是axios 1、安装axios ohpm install @ohos/axios2、封装 import axios, { FormData } from "@ohos/axios" import fs from @ohos.file.fs import ArrayList from @ohos.util.ArrayList/*** 网络请求工具类*/ class HttpManager {baseUrl:string…

学会这几步,教你1分钟辨出B站优质UP主!

品牌想要投放某UP主&#xff0c;该如何判断UP主是否优质并且同品牌相匹配呢&#xff1f;运用这一套多维度的UP主评估方法 &#xff0c;帮助你高效判断&#xff0c;快来看看具体怎么操作吧&#xff01; 一、up主粉丝涨跌 有些广告主在判断UP主是否值得投放时&#xff0c;会陷入…

9.3.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-车道线检测

目录 前言1. 车道线检测总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-车道…

工服穿戴检测联动门禁开关算法

工服穿戴检测联动门禁开关算法通过yolov8深度学习框架模型&#xff0c;工服穿戴检测联动门禁开关算法能够准确识别和检测作业人员是否按照规定进行工服着装&#xff0c;只有当人员合规着装时&#xff0c;算法会发送开关量信号给门禁设备&#xff0c;使门禁自动打开。YOLO的结构…

港陆证券:五日线破位怎么看?

在股票交易中&#xff0c;五日线是个重要的技术指标之一&#xff0c;它能够反映出最近的商场趋势。假如五日线破位&#xff0c;这意味着商场呈现了趋势反转&#xff0c;出资者需求注重趋势改动&#xff0c;并采取相应的出资战略。 首先&#xff0c;咱们来看看五日线破位的原因…

【算法与数据结构】654、LeetCode最大二叉树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树这两道题有些类似&#xff0c;相关代…

OLED透明屏原彩优势和特点解析:开创显示技术新时代

OLED透明屏 原彩作为一项领先的显示技术&#xff0c;正以其卓越的性能和创新的设计特点引起广泛关注。 本文将通过深入探讨OLED透明屏 原彩的优势和特点、应用领域、技术发展以及未来前景等方面内容&#xff0c;并结合具体数据、报告和行业动态&#xff0c;为读者提供专业可信…

解决DNS服务器未响应错误的方法

​当你将设备连接到家庭网络或具有互联网接入功能的Wi-Fi热点时,由于各种原因,互联网连接可能无法正常工作。本文中的说明适用于Windows 10、Windows 8和Windows 7。 无法连接到DNS服务器的原因 故障的一类与域名系统有关,域名系统是世界各地互联网提供商使用的分布式名称…

W5500-EVB-PICO进行MQTT连接订阅发布教程(十二)

前言 上一章我们用开发板通过SNTP协议获取网络协议&#xff0c;本章我们介绍一下开发板通过配置MQTT连接到服务器上&#xff0c;并且订阅和发布消息。 什么是MQTT&#xff1f; MQTT是一种轻量级的消息传输协议&#xff0c;旨在物联网&#xff08;IoT&#xff09;应用中实现设备…

架构师成长之路|MVCC多版本并发控制机制

InnoDB 多版本控制 官网: https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存…

仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法

文章目录 仿gRPC功能实现像调用本地方法一样调用其他服务器方法 简介单体架构微服务架构RPCgPRC gRPC交互逻辑服务端逻辑客户端逻辑示例图 原生实现仿gRPC框架编写客户端方法编写服务端方法综合演示 仿 gRPC功能实现像调用本地方法一样调用其他服务器方法 简介 在介绍gRPC简介…

【OpenCV入门】第五部分——图像运算

文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模 当计算机处理图像时&#xff0c;有些内容需要处理&#xff0c;有些内容不需要处理。能够覆盖原始图像&#xff0c;仅暴露原始图像“感兴趣区域…

Myvatis关联关系映射与表对象之间的关系

目录 一、关联关系映射 1.1 一对一 1.2 一对多 1.3 多对多 二、处理关联关系的方式 2.1 嵌套查询 2.2 嵌套结果 三、一对一关联映射 3.1 建表 ​编辑 3.2 配置文件 3.3 代码生成 3.4 编写测试 四、一对多关联映射 五、多对多关联映射 六、小结 一、关联关系映射 …

javafx Dialog无法关闭

// 生成二维码图片String qrCodeText "https://example.com";DialogPane grid new DialogPane();grid.setPadding(new Insets(5));VBox vBox new VBox();vBox.setAlignment(Pos.CENTER);Image qrCodeImage generateQRCodeImage(qrCodeText);ImageView customImag…

kind搭建k8s集群用于测试

安装kind 需要先安装go kind基于go开发 #第一种安装方式#修改go源加快下载速度 go env -w GOPROXYhttps://goproxy.cn,direct #直接下载安装kind最新版本 go install sigs.k8s.io/kindlatest #进入GOPATH目录找到bin目录下kind执行程序 移动到环境变量里 mv ./kind /usr/local…

一文学会K8s集群搭建

环境准备 节点数量&#xff1a;2台虚拟机 centos7硬件配置&#xff1a;master节点内存至少3G&#xff08;2G后面在master节点初始化集群时会报错&#xff0c;内存不够&#xff09;&#xff0c;node节点可以2G&#xff0c;CPU至少2个&#xff0c;硬盘至少30G网络要求&#xff1…

Ant-Design-Pro-V5: ProTable前端导出excel表格。

Prtable表格中根据搜索条件实现excel表格导出。 代码展示&#xff1a; index.jsx import React, { useRef, useState, Fragment, useEffect } from react; import { getLecturerList, lecturerExportExcel } from /services/train/personnel; import { getOrgList, getSelec…

服务器性能指什么如何优化

服务器性能指什么如何优化 性能最通俗的衡量指标就是“时间”&#xff0c;CPU的使用率指的是CPU用于计算的时间占比&#xff0c;磁盘使用率指的是磁盘操作的时间占比。 当CPU使用率100%时&#xff0c;意味着有部分请求来不及计算&#xff0c;响应时间增加或者超时&#xff1b…

Navicat Premium 16.2.7 for Mac

Navicat Premium 16是一款功能强大的跨平台数据库管理工具&#xff0c;支持多种数据库类型&#xff0c;如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等等。它提供了丰富的数据库管理功能和工具&#xff0c;可以帮助开发人员和数据库管理员快速地创建、管理和维护数据库。 Nav…