当前位置: 首页 > article >正文

react后台管理系统(三)

​🌈个人主页:前端青山
🔥系列专栏:React篇
🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来React篇专栏内容:react后台管理系统(三)

前言

本文档将通过一系列实际案例,详细介绍如何使用 React 和 Ant Design 组件库来构建一个完整的管理员管理页面。我们将涵盖从环境配置、API 调用到表单处理和数据渲染的各个方面,帮助开发者快速掌握相关技能

目录

前言

13.axios的封装

14.添加轮播图

15.渲染轮播图的数据

16.渲染商品列表数据

17.价格/销量/库存排序

18.分类的筛选

19.推荐/秒杀

20.首页数据展示

21.显示中文文案 - i18n - 国际化

22.筛选商品

23.管理员列表

24.添加管理员 - 抽屉

25.管理员编辑

总结

13.axios的封装

axios中文文档|axios中文网 | axios

cnpm i axios -S

Utils/request.js

import axios from 'axios'
​
// 判断用户当前运行的环境 开发环境 生产环境
// 访问不同的环境 ,请求不同的地址
// 开发环境  npm run start  ---- development
// 生产环境  npm run build  ---- production
// process.env.NODE_ENV 
const isDev = process.env.NODE_ENV === 'development'
​
// http://121.89.205.189/admin/banner/add
// 请求是请求 /banner/add
const request = axios.create({ // 自定义axios
  // baseURL: 'http://121.89.205.189/admin'
  // baseURL: isDev ? 'http://localhost:3000/admin' : 'http://182.44.11.110/admin'
  baseURL: isDev ? http://182.44.11.110//admin' : 'http://182.44.11.110/admin'
})
​
// axios 拦截器
// 请求拦截器
​
// 响应拦截器
export default request
// api/banner.js 封装数据请求

import request from '../utils/request'
​
// 添加轮播图
export function add (params) {
  return request.post('/banner/add', params)
}
​
// 删除轮播图数据
export function deleteItem (params) {
  return request.get('/banner/delete', { params })
}
​
// 删除所有的轮播图
export function removeAll (params) {
  return request.get('/banner/removeAll', { params })
}
​
// 查询轮播图的数据
export function getBannerList (params) {
  return request.get('/banner/list', { params })
}

14.添加轮播图

构建添加轮播图页面

import React from 'react'
import { Input, Space, Button, Image } from 'antd';
const width = { width: '300px'}
function Index() {
  return (
    <Space direction="vertical">
      {/* 点击图片链接 */}
      <Input placeholder="link" style={ width }/>
      {/* 图片alt属性 */}
      <Input placeholder="alt" style={ width }/>
      {/* 用来存放图片的base64地址 */}
      <Input style={ width }/>
      {/* 原始的上传控件,太丑 */}
      <Input type="file" hidden></Input>
      {/* 点击时相当于要去点击 type="file" */}
      <Button>点击选择上传文件</Button>
      {/* 预览效果 */}
      <Image
        height={300}
        src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
      />
    
      <Button type="primary">提交</Button>
    </Space>
  )
}
​
export default Index
 

获取各自的参数

import React, { useRef, useState } from 'react'
import { Input, Space, Button, Image } from 'antd';
const width = { width: '300px'}
function Index() {
  // 使用了 hooks
  const [link, setLink] = useState('')
  const [alt, setAlt] = useState('')
  const [img, setImg] = useState('')
​
  const fileRef = useRef()
​
  // 点击打开选择文件窗口
  const selectBanner = () => {
    console.log(fileRef.current.input)
    // DOM  document.getElementById().click()
    fileRef.current.input.click()
  }
  // 获取用户选择的文件信息
  const getBanenrInfo = (e) => {
    // 获取文件信息
    const file = fileRef.current.input.files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = function () {
      // 这里的this不是函数值组件中的this
      setImg(this.result)
    }
  }
  // 改变 link
  const changeLink = (e) => {
    console.log(e.target)
    setLink(e.target.value)
  }
  // 改变 alt
  const changeAlt = (e) => {
    console.log(e.target)
    setAlt(e.target.value)
  }
  // 提交信息
  const submitBanner = () => {
    const params = { img, link, alt }
    console.log(params)
  }
  return (
    <Space direction="vertical">
      {/* 受控组件 value 配合 onChange */}
      <Input placeholder="link" style={ width } value = { link } onChange = { changeLink }/>
      {/* 受控组件 value 配合 onChange */}
      <Input placeholder="alt" style={ width } value = { alt } onChange = { changeAlt }/>
      <Input style={ width } hidden value = { img }/>
      {/* 非受控组件 ref 配合 onChange */}
      <Input type="file" hidden ref = { fileRef } onChange = { getBanenrInfo }></Input>
      <Button onClick = { selectBanner }>点击选择上传文件</Button>
      {/* 如果没有上传图,默认图片
      实际上,没有图不可以上传 */}
      <Image
        height={300}
        src={
          img === '' ? 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' : img
        }
      />
      {/* 有图片才可以上传 */}
      <Button type="primary" disabled = { img === '' } onClick = { submitBanner }>提交</Button>
    </Space>
  )
}
​
export default Index

上传数据到服务器

import React, { useRef, useState } from 'react'
import { Input, Space, Button, Image } from 'antd';
import { useHistory } from 'react-router-dom'
// 引入添加轮播图接口
import { add } from './../../api/banner'
const width = { width: '300px'}
function Index() {
  const [link, setLink] = useState('')
  const [alt, setAlt] = useState('')
  const [img, setImg] = useState('')
  // 编程式导航
  const history = useHistory()
​
  const fileRef = useRef()
​
  const selectBanner = () => {
    console.log(fileRef.current.input)
    fileRef.current.input.click()
  }
  const getBanenrInfo = (e) => {
    const file = fileRef.current.input.files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = function () {
      setImg(this.result)
    }
  }
  const changeLink = (e) => {
    console.log(e.target)
    setLink(e.target.value)
  }
  const changeAlt = (e) => {
    console.log(e.target)
    setAlt(e.target.value)
  }
  const submitBanner = () => {
    const params = { img, link, alt }
    console.log(params)
    // 调用接口
    add(params).then(res => {
      history.push('/banner/list')
    })
  }
  return (
    <Space direction="vertical">
      <Input placeholder="link" style={ width } value = { link } onChange = { changeLink }/>
      <Input placeholder="alt" style={ width } value = { alt } onChange = { changeAlt }/>
      <Input style={ width } hidden value = { img }/>
      <Input type="file" hidden ref = { fileRef } onChange = { getBanenrInfo }></Input>
      <Button onClick = { selectBanner }>点击选择上传文件</Button>
      <Image
        height={300}
        src={
          img === '' ? 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' : img
        }
      />
      <Button type="primary" disabled = { img === '' } onClick = { submitBanner }>提交</Button>
    </Space>
  )
}
​
export default Index
​

15.渲染轮播图的数据

import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button } from 'antd'
import { getBannerList } from '../../api/banner'
function Index() {
  const [bannerList, setBannerList] = useState([])
​
  useEffect(() => {
    getBannerList().then(res => {
      setBannerList(res.data.data)
    })
  }, [])
    // 设置表格
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '图片',
      dataIndex: 'img',
      // text 相当于上面的 img 字段
      // record 相当于每一条数据的对象
      // index 索引值
      render: (text, record, index) => {
        return (
          <Image src = { text } width = { 200 } height = { 100 } />
        )
      }
    },
    {
      title: '链接',
      dataIndex: 'link'
    },
    {
      title: '提示',
      dataIndex: 'alt'
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <Space>
            <Button type="danger">删除</Button>
          </Space>
        )
      }
    }
  ]
  return (
    <div>
      <Table
        rowKey = { record => record.bannerid }
        dataSource = { bannerList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index
​

删除轮播图单条数据

import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm } from 'antd'
import { getBannerList, deleteItem, removeAll } from '../../api/banner'
function Index() {
  const [bannerList, setBannerList] = useState([])
​
  useEffect(() => {
    getBannerList().then(res => {
      setBannerList(res.data.data)
    })
  }, [])
  const deleteBannerItem = (bannerid) => {
    deleteItem({ bannerid }).then(res => {
      // 删除之后重新请求数据
      getBannerList().then(res => {
        setBannerList(res.data.data)
      })
    })
  }
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '图片',
      dataIndex: 'img',
      // text 相当于上面的 img 字段
      // record 相当于每一条数据的对象
      // index 索引值
      render: (text, record, index) => {
        return (
          <Image src = { text } width = { 200 } height = { 100 } />
        )
      }
    },
    {
      title: '链接',
      dataIndex: 'link'
    },
    {
      title: '提示',
      dataIndex: 'alt'
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <Space>
            <Popconfirm
            title="确定删除吗?"
            onConfirm={() => {
              deleteBannerItem(record.bannerid)
            }}
            okText="确定"
            cancelText="取消">
              <Button type="danger">删除</Button>
            </Popconfirm>
          </Space>
        )
      }
    }
  ]
  const removeAllBanner = () => { // 删除全部的数据
    removeAll().then(res => {
      // 删除全部数据,只需要再把列表置为空
      setBannerList([])
    })
  }
  return (
    <div>
      <Button onClick = { removeAllBanner }>全部删除</Button>
      <Table
        rowKey = { record => record.bannerid }
        dataSource = { bannerList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index
​

16.渲染商品列表数据

// api/pro.js
import request from '../utils/request'
​
export function getProList (params) {
  return request.get('/pro/list', { params })
}
import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm, Tooltip,Switch } from 'antd'
import { getProList } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([]) 
  useEffect(() => {
    // 该项目共有150,测试Table组件的自动分页,写了 200
    getProList({ limitNum: 200 }).then(res => {
      setProList(res.data.data)
    })
  }, [])
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category' },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice' },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales' },
  { title: '库存', width: 100,  dataIndex: 'stock' },
  { title: '上架状态', width: 110,  fixed: 'right', dataIndex: 'issale', render: (text) => <Switch checked = { text }/> }, 
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', render: (text) => <Switch checked = { text }/> },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', render: (text) => <Switch checked = { text }/> },
  { title: '操作', width: 180,  fixed: 'right', render: (text, record, index) => {
    return (
      <Space>
        <Tooltip title="功能正在开发中">
          <Button type="dashed" >编辑</Button>
        </Tooltip>
        <Popconfirm
        title="确定删除吗?"
        onConfirm={() => {
        }}
        okText="确定"
        cancelText="取消">
          <Button type="danger">删除</Button>
        </Popconfirm>
      </Space>
    )
  } },
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500 }}
      ></Table>
    </div>
  )
}
​
export default Index
​

17.价格/销量/库存排序

import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm, Tooltip,Switch } from 'antd'
import { getProList } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([]) 
  useEffect(() => {
    // 该项目共有150,测试Table组件的自动分页,写了 200
    getProList({ limitNum: 200 }).then(res => {
      setProList(res.data.data)
    })
  }, [])
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category' },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice',
    sorter: (a, b) => a.originprice - b.originprice, // 按照价格排序
  },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales',
    sorter: (a, b) => a.sales - b.sales,// 按照销量排序
  },
  { title: '库存', width: 100,  dataIndex: 'stock',
    sorter: (a, b) => a.stock - b.stock, // 按照库存排序
  },
  { title: '上架状态', width: 110,  fixed: 'right', dataIndex: 'issale', render: (text) => <Switch checked = { text }/> }, 
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', render: (text) => <Switch checked = { text }/> },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', render: (text) => <Switch checked = { text }/> },
  { title: '操作', width: 180,  fixed: 'right', render: (text, record, index) => {
    return (
      <Space>
        <Tooltip title="功能正在开发中">
          <Button type="dashed" >编辑</Button>
        </Tooltip>
        <Popconfirm
        title="确定删除吗?"
        onConfirm={() => {
        }}
        okText="确定"
        cancelText="取消">
          <Button type="danger">删除</Button>
        </Popconfirm>
      </Space>
    )
  } },
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

18.分类的筛选

// api/pro.js
import request from '../utils/request'
​
export function getProList (params) {
  return request.get('/pro/list', { params })
}
​
export function getCategory (params) {
  return request.get('/pro/getCategory', { params })
}
import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm, Tooltip,Switch } from 'antd'
import { getProList, getCategory } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([]) 
  const [ categoryList, setCategoryList ] = useState([]) 
  useEffect(() => {
    // 该项目共有150,测试Table组件的自动分页,写了 200
    getProList({ limitNum: 200 }).then(res => {
      setProList(res.data.data)
    })
    getCategory().then(res => { // 获取分类的数据
      const arr = []
      res.data.data.forEach(item => { // 处理分类数据
        arr.push({ text: item, value: item })
      })
      setCategoryList(arr)
    })
  }, [])
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category',
    filters: categoryList, // 分类过滤数组
    onFilter: (value, record) => record.category.indexOf(value) !== -1 // 返回匹配项
  },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice',
    sorter: (a, b) => a.originprice - b.originprice,
  },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales',
    sorter: (a, b) => a.sales - b.sales,
  },
  { title: '库存', width: 100,  dataIndex: 'stock',
    sorter: (a, b) => a.stock - b.stock,
  },
  { title: '上架状态', width: 110,  fixed: 'right', dataIndex: 'issale', render: (text) => <Switch checked = { text }/> }, 
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', render: (text) => <Switch checked = { text }/> },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', render: (text) => <Switch checked = { text }/> },
  { title: '操作', width: 180,  fixed: 'right', render: (text, record, index) => {
    return (
      <Space>
        <Tooltip title="功能正在开发中">
          <Button type="dashed" >编辑</Button>
        </Tooltip>
        <Popconfirm
        title="确定删除吗?"
        onConfirm={() => {
        }}
        okText="确定"
        cancelText="取消">
          <Button type="danger">删除</Button>
        </Popconfirm>
      </Space>
    )
  } },
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

19.推荐/秒杀

// api/pro.js
import request from '../utils/request'
​
export function getProList (params) {
  return request.get('/pro/list', { params })
}
​
export function getCategory (params) {
  return request.get('/pro/getCategory', { params })
}
​
export function updateFlag (params) {
  return request.post('/pro/updateFlag', params)
}

import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm, Tooltip,Switch } from 'antd'
import { getProList, getCategory, updateFlag } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([]) 
  const [ categoryList, setCategoryList ] = useState([]) 
  useEffect(() => {
    // 该项目共有150,测试Table组件的自动分页,写了 200
    getProList({ limitNum: 200 }).then(res => {
      setProList(res.data.data)
    })
    getCategory().then(res => {
      const arr = []
      res.data.data.forEach(item => {
        arr.push({ text: item, value: item })
      })
      setCategoryList(arr)
    })
  }, [])
  // 修改推荐状态
  const changeRecommendFlag = (proid, text) => {
    updateFlag({ proid, type: 'isrecommend', flag: text === 1 ? false : true })
      .then(() => {
        // 重新获取数据
        getProList({ limitNum: 200 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  // 修改秒杀状态
  const changeSeckillFlag = (proid, text) => {
    // text 拿到的上一次的状态,如果上一次的值为1, 代表用户点击完后要变为0
    updateFlag({ proid, type: 'isseckill', flag: text === 1 ? false : true })
      .then(() => {
        // 重新获取数据
        getProList({ limitNum: 200 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category',
    filters: categoryList,
    onFilter: (value, record) => record.category.indexOf(value) !== -1
  },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice',
    sorter: (a, b) => a.originprice - b.originprice,
  },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales',
    sorter: (a, b) => a.sales - b.sales,
  },
  { title: '库存', width: 100,  dataIndex: 'stock',
    sorter: (a, b) => a.stock - b.stock,
  },
  { title: '上架状态', width: 110,  fixed: 'right', dataIndex: 'issale', render: (text) => <Switch checked = { text }/> }, 
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', 
    render: (text,record) => <Switch checked = { text } onChange = { () => { // 改变推荐状态
      changeRecommendFlag(record.proid, text)
    }}/> },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', 
    render: (text,record) => <Switch checked = { text } onChange = { () => { // 改变秒杀状态
      changeSeckillFlag(record.proid, text)
    }}/> },
  { title: '操作', width: 180,  fixed: 'right', render: (text, record, index) => {
    return (
      <Space>
        <Tooltip title="功能正在开发中">
          <Button type="dashed" >编辑</Button>
        </Tooltip>
        <Popconfirm
        title="确定删除吗?"
        onConfirm={() => {
        }}
        okText="确定"
        cancelText="取消">
          <Button type="danger">删除</Button>
        </Popconfirm>
      </Space>
    )
  } },
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

20.首页数据展示

推荐

复制商品列表的代码至 推荐页面

import request from '../utils/request'
​
export function getProList (params) {
  return request.get('/pro/list', { params })
}
​
export function getCategory (params) {
  return request.get('/pro/getCategory', { params })
}
​
export function updateFlag (params) {
  return request.post('/pro/updateFlag', params)
}
export function showdata (params) {
  return request.post('/pro/showdata', params)
}
import React, { useState, useEffect } from 'react'
import { Table, Image, Switch } from 'antd'
import { showdata, updateFlag } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([])  
  useEffect(() => {
    // 请求的是 被推荐的数据
    showdata({ type: 'isrecommend', flag: 1 }).then(res => {
      setProList(res.data.data)
    })
  }, [])
  const changeRecommendFlag = (proid, text) => {
    updateFlag({ proid, type: 'isrecommend', flag: text === 1 ? false : true })
      .then(() => {
        // 重新请求数据
        showdata({ type: 'isrecommend', flag: 1 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  // 删除了排序以及筛选,只保留 推荐列表的状态
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category' },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice' },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales' },
  { title: '库存', width: 100,  dataIndex: 'stock' },
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', 
    render: (text,record) => <Switch checked = { text } onChange = { () => {
      changeRecommendFlag(record.proid, text)
    }}/> },
  
  
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

秒杀

import React, { useState, useEffect } from 'react'
import { Table, Image, Switch } from 'antd'
import { showdata, updateFlag } from '../../api/pro'
function Index() {
  const [ proList, setProList ] = useState([]) 
 
  useEffect(() => {
    showdata({ type: 'isseckill', flag: 1 }).then(res => {
      setProList(res.data.data)
    })
    
  }, [])
  
  const changeSeckillFlag = (proid, text) => {
    updateFlag({ proid, type: 'isseckill', flag: text === 1 ? false : true })
      .then(() => {
        showdata({ type: 'isseckill', flag: 1 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category' },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice' },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales' },
  { title: '库存', width: 100,  dataIndex: 'stock' },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', 
    render: (text,record) => <Switch checked = { text } onChange = { () => {
      changeSeckillFlag(record.proid, text)
    }}/> },
  
  ]
  return (
    <div>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

21.显示中文文案 - i18n - 国际化

语言包 - 国际化

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App.jsx';
import { ConfigProvider } from 'antd';
// 由于 antd 组件的默认文案是英文,所以需要修改为中文
import zhCN from 'antd/lib/locale/zh_CN';
​
ReactDOM.render(
  <ConfigProvider locale = { zhCN }>
    <App />
  </ConfigProvider>,
  document.getElementById('root')
);

22.筛选商品

import request from '../utils/request'
​
export function getProList (params) {
  return request.get('/pro/list', { params })
}
​
export function getCategory (params) {
  return request.get('/pro/getCategory', { params })
}
​
export function updateFlag (params) {
  return request.post('/pro/updateFlag', params)
}
export function showdata (params) {
  return request.post('/pro/showdata', params)
}
​
export function searchPro (params) {
  return request.post('/pro/searchPro', params)
}
import React, { useState, useEffect } from 'react'
import { Table, Image, Space, Button, Popconfirm, Tooltip,Switch, Select, Input } from 'antd'
import { getProList, getCategory, updateFlag, searchPro } from '../../api/pro'
const { Option } = Select
function Index() {
  const [ proList, setProList ] = useState([]) 
  const [ categoryList, setCategoryList ] = useState([]) 
  // 设置需要的字段的参数两个 category / search
  const [ category, setCategory ] = useState('')
  const [ search, setSearch ] = useState('')
  useEffect(() => {
    // 该项目共有150,测试Table组件的自动分页,写了 200
    getProList({ limitNum: 200 }).then(res => {
      setProList(res.data.data)
    })
    getCategory().then(res => {
      // 无需重置分类数据
      setCategoryList(res.data.data)
    })
  }, [])
  const changeRecommendFlag = (proid, text) => {
    updateFlag({ proid, type: 'isrecommend', flag: text === 1 ? false : true })
      .then(() => {
        getProList({ limitNum: 200 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  const changeSeckillFlag = (proid, text) => {
    updateFlag({ proid, type: 'isseckill', flag: text === 1 ? false : true })
      .then(() => {
        getProList({ limitNum: 200 }).then(res => {
          setProList(res.data.data)
        })
      })
  }
  const columns = [
  { title: '序号', width: 100, fixed: 'left', render: (text, record, index) => <span>{index + 1}</span>},
  { title: '名称', width: 260, fixed: 'left', dataIndex: 'proname' },
  { title: '分类', width: 100,  dataIndex: 'category' },
  { title: '品牌', width: 100,  dataIndex: 'brand' },
  { title: '图片', width: 200,  dataIndex: 'img1', render: (text) => <Image src={text} width={80} height={80}/> },
  { title: '原价', width: 100,  dataIndex: 'originprice' },
  { title: '折扣', width: 100,  dataIndex: 'discount' },
  { title: '销量', width: 100,  dataIndex: 'sales' },
  { title: '库存', width: 100,  dataIndex: 'stock' },
  { title: '上架状态', width: 110,  fixed: 'right', dataIndex: 'issale', render: (text) => <Switch checked = { text }/> }, 
  { title: '是否推荐', width: 110,  fixed: 'right', dataIndex: 'isrecommend', 
    render: (text,record) => <Switch checked = { text } onChange = { () => {
      changeRecommendFlag(record.proid, text)
    }}/> },
  { title: '是否秒杀', width: 100,  fixed: 'right', dataIndex: 'isseckill', 
    render: (text,record) => <Switch checked = { text } onChange = { () => {
      changeSeckillFlag(record.proid, text)
    }}/> },
  { title: '操作', width: 180,  fixed: 'right', render: (text, record, index) => {
    return (
      <Space>
        <Tooltip title="功能正在开发中">
          <Button type="dashed" >编辑</Button>
        </Tooltip>
        <Popconfirm
        title="确定删除吗?"
        onConfirm={() => {
        }}
        okText="确定"
        cancelText="取消">
          <Button type="danger">删除</Button>
        </Popconfirm>
      </Space>
    )
  } },
  ]
  // 改变分类
  const changeCategory = (value) => {
    setCategory(value)
  }
  // 改变关键词的数据
  const changeSearch = (e) => {
    setSearch(e.target.value)
  }
  // 搜索
  const searchFn = () => {
    searchPro({
      category, search
    }).then(res => {
      setProList(res.data.data)
    })
  }
  return (
    <div>
      <Select style={{ width: 120 }} value={ category } onChange = { changeCategory }>
        <Option value="">全部</Option>
        {
          categoryList && categoryList.map(item => {
            return <Option key = { item } value = { item }>
              { item }
            </Option>
          })
        }
      </Select>
      <Input style={{width:200}} placeholder = '请输入关键词' value={ search } onChange = { changeSearch }></Input>
      <Button type="primary" onClick = { searchFn }>搜索</Button>
      <Table 
      columns = { columns } 
      dataSource = { proList } 
      rowKey = { record => record.proid }  
      scroll={{ x: 1500, y: 740 }}
      ></Table>
    </div>
  )
}
​
export default Index

23.管理员列表

// api/users.js
import request from './../utils/request'
​
export function getAdminList (params) {
  return request.get('/admin/list', { params })
}
import React, { useState, useEffect } from 'react'
import { Table, Tooltip, Space, Button, Popconfirm } from 'antd'
import { getAdminList } from '../../api/users'
function Index() {
  const [adminList, setAdminList] = useState([])
​
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
​
  
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              <Tooltip title="功能正在开发中">
                <Button type="dashed" >编辑</Button>
              </Tooltip>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  
  return (
    <div>
     
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index

24.添加管理员 - 抽屉

搭建页面的架构

import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm } from 'antd'
import { getAdminList } from '../../api/users'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              <Button type="dashed" >编辑</Button>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  // 2.添加管理员
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <p>Some contents...</p>
        <p>Some contents...</p>
        <p>Some contents...</p>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index

添加表单

import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm, Input, Select, Tree } from 'antd'
import { getAdminList } from '../../api/users'
import menus from './../../router/menus'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              <Button type="dashed" >编辑</Button>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  // 2.添加管理员 - 控制抽屉的显示
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  // 2.添加管理员 - 需要的组件状态
  const [adminname, setAdminname] = useState('')
  const [password, setPasssword] = useState('')
  const [role, setRole] = useState('1')
  const [checkedKeys, setCheckedKeys] = useState([]) // 用来记录哪些被选中
  const changeRole = (value) => {
    setRole(value)
  }
  const onCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setCheckedKeys(checkedKeys)
  }
  const addAdminFn = () => {
    const obj = { adminname, password, role, checkedKeys }
    console.log(obj)
  }
  // const expandedKeys = ['0-2']
  const expandedKeys = []
  menus.forEach(item => {
    expandedKeys.push(item.key)
  })
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <Space direction = "vertical">
          <Input placeholder = "请输入账户名" value = { adminname } onChange = { (e) => {
            setAdminname(e.target.value)
          }} />
          <Input type="password" placeholder = "请输入密码" value = { password } onChange = { (e) => {
            setPasssword(e.target.value)
          }} />
          <Select value={ role } onChange = { changeRole }>
            <Select.Option value="2">超级管理员</Select.Option>
            <Select.Option value="1">管理员</Select.Option>
          </Select>
          <Tree
            checkable // 前面添加复选框
            expandedKeys={expandedKeys} // 自动展开哪些二级菜单
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            treeData={menus}
          />
          <Button type="primary" onClick = { addAdminFn }>添加</Button>
        </Space>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index

提交数据

import request from './../utils/request'
​
export function getAdminList (params) {
  return request.get('/admin/list', { params })
}
​
export function addAdmin (params) {
  return request.post('/admin/add', params)
}
import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm, Input, Select, Tree } from 'antd'
import { getAdminList, addAdmin } from '../../api/users'
import menus from './../../router/menus'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              <Button type="dashed" >编辑</Button>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  // 2.添加管理员 - 控制抽屉的显示
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  // 2.添加管理员 - 需要的组件状态
  const [adminname, setAdminname] = useState('')
  const [password, setPasssword] = useState('')
  const [role, setRole] = useState('1')
  const [checkedKeys, setCheckedKeys] = useState([]) // 用来记录哪些被选中
  const changeRole = (value) => {
    setRole(value)
  }
  const onCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setCheckedKeys(checkedKeys)
  }
  const addAdminFn = () => {
    const obj = { adminname, password, role, checkedKeys }
    console.log(obj)
    addAdmin(obj).then(() => { // 提交表单信息 ************************
      // 抽屉消失,表单回归初始状态
      setVisible(false)
      setAdminname('')
      setPasssword('')
      setRole('1')
      setCheckedKeys([])
      // 重新渲染一次页面
      getAdminList().then(res => {
        setAdminList(res.data.data)
      })
    })
  }
  // const expandedKeys = ['0-2']
  const expandedKeys = []
  menus.forEach(item => {
    expandedKeys.push(item.key)
  })
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <Space direction = "vertical">
          <Input placeholder = "请输入账户名" value = { adminname } onChange = { (e) => {
            setAdminname(e.target.value)
          }} />
          <Input type="password" placeholder = "请输入密码" value = { password } onChange = { (e) => {
            setPasssword(e.target.value)
          }} />
          <Select value={ role } onChange = { changeRole }>
            <Select.Option value="2">超级管理员</Select.Option>
            <Select.Option value="1">管理员</Select.Option>
          </Select>
          <Tree
            checkable // 前面添加复选框
            expandedKeys={expandedKeys} // 自动展开哪些二级菜单
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            treeData={menus}
          />
          <Button type="primary" onClick = { addAdminFn }>添加</Button>
        </Space>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
    </div>
  )
}
​
export default Index

25.管理员编辑

主界面

import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm, Input, Select, Tree, Modal } from 'antd'
import { getAdminList, addAdmin } from '../../api/users'
import menus from './../../router/menus'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              {/* 3.编辑管理员数据 */}
              <Button type="dashed" onClick = { () => {
                setIsModalVisible(true)
              }}>编辑</Button>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  // 2.添加管理员 - 控制抽屉的显示
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  // 2.添加管理员 - 需要的组件状态
  const [adminname, setAdminname] = useState('')
  const [password, setPasssword] = useState('')
  const [role, setRole] = useState('1')
  const [checkedKeys, setCheckedKeys] = useState([]) // 用来记录哪些被选中
  const changeRole = (value) => {
    setRole(value)
  }
  const onCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setCheckedKeys(checkedKeys)
  }
  const addAdminFn = () => {
    const obj = { adminname, password, role, checkedKeys }
    console.log(obj)
    addAdmin(obj).then(() => {
      // 抽屉消失,表单回归初始状态
      setVisible(false)
      setAdminname('')
      setPasssword('')
      setRole('1')
      setCheckedKeys([])
      // 重新渲染一次页面
      getAdminList().then(res => {
        setAdminList(res.data.data)
      })
    })
  }
  // const expandedKeys = ['0-2']
  const expandedKeys = []
  menus.forEach(item => {
    expandedKeys.push(item.key)
  })
​
  // 3.编辑管理员数据 - 控制对话框的展示
  const [isModalVisible, setIsModalVisible] = useState(false);
​
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <Space direction = "vertical">
          <Input placeholder = "请输入账户名" value = { adminname } onChange = { (e) => {
            setAdminname(e.target.value)
          }} />
          <Input type="password" placeholder = "请输入密码" value = { password } onChange = { (e) => {
            setPasssword(e.target.value)
          }} />
          <Select value={ role } onChange = { changeRole }>
            <Select.Option value="2">超级管理员</Select.Option>
            <Select.Option value="1">管理员</Select.Option>
          </Select>
          <Tree
            checkable // 前面添加复选框
            expandedKeys={expandedKeys} // 自动展开哪些二级菜单
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            treeData={menus}
          />
          <Button type="primary" onClick = { addAdminFn }>添加</Button>
        </Space>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
      {/* 3.编辑管理员数据 */}
      <Modal 
        title="更新管理员信息" 
        visible={isModalVisible} 
        onOk={ () => {
          console.log('更新数据')
        }} 
        onCancel={ () => { setIsModalVisible(false) }}>
        <p>Some contents...</p>
        <p>Some contents...</p>
        <p>Some contents...</p>
      </Modal>
    </div>
  )
}
​
export default Index
​
​
import request from './../utils/request'
​
export function getAdminList (params) {
  return request.get('/admin/list', { params })
}
​
export function addAdmin (params) {
  return request.post('/admin/add', params)
}
​
export function updateAdmin (params) {
  return request.post('/admin/update', params)
}
import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm, Input, Select, Tree, Modal } from 'antd'
import { getAdminList, addAdmin, updateAdmin } from '../../api/users'
import menus from './../../router/menus'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (
          <>
            {
              index === 0 ? null : <Space>
              {/* 3.编辑管理员数据 */}
              <Button type="dashed" onClick = { () => {
                setIsModalVisible(true)
                // 3.修改表单的数据状态
                setUadminname(record.adminname)
                setUrole(record.role + '')
                setUcheckedKeys(record.checkedKeys)
              }}>编辑</Button>
              <Popconfirm
              title="确定删除吗?"
              onConfirm={() => {}}
              okText="确定"
              cancelText="取消">
                <Button type="danger">删除</Button>
              </Popconfirm>
            </Space>
            }
          </>
          
        )
      }
    }
  ]
  // 2.添加管理员 - 控制抽屉的显示
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  // 2.添加管理员 - 需要的组件状态
  const [adminname, setAdminname] = useState('')
  const [password, setPasssword] = useState('')
  const [role, setRole] = useState('1')
  const [checkedKeys, setCheckedKeys] = useState([]) // 用来记录哪些被选中
  const changeRole = (value) => {
    setRole(value)
  }
  const onCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setCheckedKeys(checkedKeys)
  }
  const addAdminFn = () => {
    const obj = { adminname, password, role, checkedKeys }
    console.log(obj)
    addAdmin(obj).then(() => {
      // 抽屉消失,表单回归初始状态
      setVisible(false)
      setAdminname('')
      setPasssword('')
      setRole('1')
      setCheckedKeys([])
      // 重新渲染一次页面
      getAdminList().then(res => {
        setAdminList(res.data.data)
      })
    })
  }
  // const expandedKeys = ['0-2']
  const expandedKeys = []
  menus.forEach(item => {
    expandedKeys.push(item.key)
  })
​
  // 3.编辑管理员数据 - 控制对话框的展示
  const [isModalVisible, setIsModalVisible] = useState(false);
  // 3.编辑管理员数据 - 输入框的值
  const [ uadminname, setUadminname] = useState('')
  const [ urole, setUrole] = useState('1')
  const [ ucheckedKeys, setUcheckedKeys] = useState([])
  const changeURole = (value) => {
    setUrole(value)
  }
  const onUCheck = (checkedKeys) => {
    setUcheckedKeys(checkedKeys)
  }
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <Space direction = "vertical">
          <Input placeholder = "请输入账户名" value = { adminname } onChange = { (e) => {
            setAdminname(e.target.value)
          }} />
          <Input type="password" placeholder = "请输入密码" value = { password } onChange = { (e) => {
            setPasssword(e.target.value)
          }} />
          <Select value={ role } onChange = { changeRole }>
            <Select.Option value="2">超级管理员</Select.Option>
            <Select.Option value="1">管理员</Select.Option>
          </Select>
          <Tree
            checkable // 前面添加复选框
            expandedKeys={expandedKeys} // 自动展开哪些二级菜单
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            treeData={menus}
          />
          <Button type="primary" onClick = { addAdminFn }>添加</Button>
        </Space>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
      {/* 3.编辑管理员数据 */}
      <Modal 
        title="更新管理员信息" 
        visible={isModalVisible} 
        onOk={ () => {
          const obj = { adminname: uadminname, role: urole, checkedKeys: ucheckedKeys}
          console.log('更新数据', obj)
          
          // updateAdmin(obj).then(() => {
          //   setIsModalVisible(false)
          // })
        }} 
        onCancel={ () => { setIsModalVisible(false) }}>
          <Space direction = "vertical">
            <Input placeholder = "请输入账户名" value = { uadminname } readOnly />
            <Select value={ urole } onChange = { changeURole }>
              <Select.Option value="2">超级管理员</Select.Option>
              <Select.Option value="1">管理员</Select.Option>
            </Select>
            <Tree
              checkable // 前面添加复选框
              expandedKeys={expandedKeys} // 自动展开哪些二级菜单
              onCheck={onUCheck}
              checkedKeys={ucheckedKeys}
              treeData={menus}
            />
          </Space>
      </Modal>
    </div>
  )
}
​
export default Index

编辑以及删除

import React, { useState, useEffect } from 'react'
import { Table, Drawer, Space, Button, Popconfirm, Input, Select, Tree, Modal, notification } from 'antd'
import { getAdminList, addAdmin, updateAdmin, deleteAdmin } from '../../api/users'
import menus from './../../router/menus'
function Index() {
  // 1.管理员列表
  const [adminList, setAdminList] = useState([])
  useEffect(() => {
    getAdminList().then(res => {
      setAdminList(res.data.data)
    })
  }, [])
  const columns = [
    {
      title: '序号',
      render: (text, record, index) => <span>{ index + 1 }</span>
    },
    {
      title: '账户',
      dataIndex: 'adminname'
    },
    {
      title: '权限',
      dataIndex: 'role',
      render: (text) => {
        return (
          text === 2 ? '超级管理员' : '管理员'
        )
      }
    },
    {
      title: '操作',
      render: (text, record, index) => {
        return (<Space>
          {/* 3.编辑管理员数据 */}
          <Button type="dashed" onClick = { () => {
            setIsModalVisible(true)
            // 3.修改表单的数据状态
            setUadminname(record.adminname)
            setUrole(record.role + '')
            setUcheckedKeys(record.checkedKeys)
          }}>编辑</Button>
          <Popconfirm
          title="确定删除吗?"
          onConfirm={() => {
            deleteAdmin({ adminid: record.adminid}).then(() => {
              getAdminList().then(res => setAdminList(res.data.data))
            })
          }}
          okText="确定"
          cancelText="取消">
            <Button type="danger">删除</Button>
          </Popconfirm>
        </Space>
        )
      }
    }
  ]
  // 2.添加管理员 - 控制抽屉的显示
  const [visible, setVisible] = useState(false)
  const showDrawer = () => {
    setVisible(true)
  }
  // 2.添加管理员 - 需要的组件状态
  const [adminname, setAdminname] = useState('')
  const [password, setPasssword] = useState('')
  const [role, setRole] = useState('1')
  const [checkedKeys, setCheckedKeys] = useState([]) // 用来记录哪些被选中
  const changeRole = (value) => {
    setRole(value)
  }
  const onCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setCheckedKeys(checkedKeys)
  }
  const addAdminFn = () => {
    const obj = { adminname, password, role, checkedKeys }
    console.log(obj)
    addAdmin(obj).then((res) => {
      if (res.data.code === '10004') {
        notification.warning({
          duration: 2,
          message: '消息提醒',
          description:
            '该管理员已存在',
          onClick: () => {
          },
        });
      } else {
        // 抽屉消失,表单回归初始状态
        setVisible(false)
        setAdminname('')
        setPasssword('')
        setRole('1')
        setCheckedKeys([])
        // 重新渲染一次页面
        getAdminList().then(res => {
          setAdminList(res.data.data)
        })
      }
    })
  }
  // const expandedKeys = ['0-2']
  const expandedKeys = []
  menus.forEach(item => {
    expandedKeys.push(item.key)
  })
​
  // 3.编辑管理员数据 - 控制对话框的展示
  const [isModalVisible, setIsModalVisible] = useState(false);
  // 3.编辑管理员数据 - 输入框的值
  const [ uadminname, setUadminname] = useState('')
  const [ urole, setUrole] = useState('1')
  const [ ucheckedKeys, setUcheckedKeys] = useState([])
  const changeURole = (value) => {
    setUrole(value)
  }
  const onUCheck = (checkedKeys) => {
    console.log(checkedKeys)
    setUcheckedKeys(checkedKeys)
  }
  return (
    <div>
      {/* 2.添加管理员 */}
      <Button type="primary" onClick = { showDrawer }>添加管理员</Button>
      <Drawer
        width={ 500 }
        title="添加管理员"
        placement="right"
        closable={true}
        onClose={ () => { setVisible(false) }}
        visible={visible}
      >
        <Space direction = "vertical">
          <Input placeholder = "请输入账户名" value = { adminname } onChange = { (e) => {
            setAdminname(e.target.value)
          }} />
          <Input type="password" placeholder = "请输入密码" value = { password } onChange = { (e) => {
            setPasssword(e.target.value)
          }} />
          <Select value={ role } onChange = { changeRole }>
            <Select.Option value="2">超级管理员</Select.Option>
            <Select.Option value="1">管理员</Select.Option>
          </Select>
          <Tree
            checkable // 前面添加复选框
            expandedKeys={expandedKeys} // 自动展开哪些二级菜单
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            treeData={menus}
          />
          <Button type="primary" onClick = { addAdminFn }>添加</Button>
        </Space>
      </Drawer>
      {/* 1.管理员列表 */}
      <Table
        rowKey = { record => record.adminid }
        dataSource = { adminList } 
        columns = { columns } />
      {/* 3.编辑管理员数据 */}
      <Modal 
        title="更新管理员信息" 
        visible={isModalVisible} 
        onOk={ () => {
          const obj = { adminname: uadminname, role: urole, checkedKeys: ucheckedKeys}
          console.log('更新数据', obj)
          
          updateAdmin(obj).then(() => {
            setIsModalVisible(false)
            getAdminList().then(res => setAdminList(res.data.data))
          })
        }} 
        onCancel={ () => { setIsModalVisible(false) }}>
          <Space direction = "vertical">
            <Input placeholder = "请输入账户名" value = { uadminname } readOnly />
            <Select value={ urole } onChange = { changeURole }>
              <Select.Option value="2">超级管理员</Select.Option>
              <Select.Option value="1">管理员</Select.Option>
            </Select>
            <Tree
              checkable // 前面添加复选框
              expandedKeys={expandedKeys} // 自动展开哪些二级菜单
              onCheck={onUCheck}
              checkedKeys={ucheckedKeys}
              treeData={menus}
            />
          </Space>
      </Modal>
    </div>
  )
}
​
export default Index

总结

通过本文档的学习,我们掌握了以下几点:

  1. 环境配置

    • 如何根据不同的环境配置不同的 API 地址。
    • 如何创建自定义的 axios 实例并设置请求和响应拦截器。
  2. 表单页面构建

    • 如何构建一个添加管理员的表单页面,包括输入框、选择框和树形选择组件的使用。
    • 如何实现表单数据的提交和验证。
  3. 数据管理和操作

    • 如何从后端获取管理员列表数据并使用 Table 组件进行渲染。
    • 如何实现管理员数据的删除功能,并使用 Popconfirm 组件进行确认提示。
    • 如何实现管理员数据的编辑功能,包括模态对话框的显示和数据更新。
  4. 组件库使用

    • 如何使用 antd 组件库中的 InputSelectTreeTableModal 和 Button 等组件构建复杂的用户界面。
    • 如何利用 antd 的样式和布局功能提升用户体验。

通过这些实际案例,我们可以看到 axios 在处理 HTTP 请求方面的强大功能,以及 antd 组件库在构建复杂用户界面时的便捷性和灵活性。希望本文档能为读者在实际项目开发中提供有价值的参考。


http://www.kler.cn/a/409896.html

相关文章:

  • 下载并安装Visual Studio 2017过程
  • Vue.observable 全解析:Observable 是什么及使用场景剖析
  • React 前端框架深度剖析
  • Macos远程连接Linux桌面教程;Ubuntu配置远程桌面;Mac端远程登陆Linux桌面;可能出现的问题
  • RT-DETR:替代YOLO的更快实时目标检测模型及其Pytorch实现【附源码】
  • VirtIO实现原理之数据结构与数据传输演示(1)
  • python小课堂(一)
  • 二进制 分析工具:Radare2、r2frida、Binutils、file、string、as、nm、ldd、objdump、readelf、strip
  • pywinauto常见用法详解
  • 【linux】基础-Git使用
  • Redis 在实际业务中的高效应用
  • 递推进阶与入门递归
  • [Java]微服务体系下的用户身份认证方案
  • 【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析
  • C++:用红黑树封装map与set-2
  • 数据结构每日一题|判断链表环形结构并返回环的起始节点
  • QT6 android生成release版本注意事项
  • 【VRChat 改模】着色器(shader)简介、预制体(prefab)简介
  • 日志抽取工具——flume的安装与使用教程
  • 学习路之压力测试--jmeter安装教程