用户列表想要实现这样的效果:
渲染数据:
import React,{useState,useEffect} from 'react';
import { Button,Table, Tag,Modal,Popover, Switch } from 'antd';
import { EditOutlined,DeleteOutlined,ExclamationCircleOutlined } from '@ant-design/icons';
import axios from 'axios';
import { data } from 'react-router-dom';
import Item from 'antd/es/list/Item';
const { confirm } = Modal;function UserList() {const [dataSource,setdataSource]=useState([])useEffect(()=>{axios.get("http://localhost:3000/users?_expand=role").then(res=>{console.log(res.data);const list = res.datasetdataSource(list)})},[])const columns = [{title: '区域',dataIndex: 'region',render:(region)=>{return <b>{region===""?'全球':region}</b>}},{title: '角色名称',dataIndex: 'role',render:(role)=>{return role?.roleName}},{title: '用户名',dataIndex: 'username',},{title:"用户状态",dataIndex:"roleState",render:(roleState,item)=>{return <Switch checked={roleState} disabled={item.default}></Switch>}},{title: '操作',render:(record)=>{return <div><Button type="primary" shape="circle" icon={<EditOutlined />} disabled={record.default} /><Button danger type="primary" shape="circle" icon={<DeleteOutlined />} disabled={record.default}/></div>}},];const deleteMethod = (record) => {console.log(record);}return (<div><Button></Button><Table dataSource={dataSource} columns={columns}pagination={{pageSize:5 }}>rowKey = {item => item.id}</Table></div>)
}export default UserList;
接下来我逐步完成增删改查的功能
增
增数据需要用到弹出型的新增表单:
还需要从后端拿取数据,所以定义新的状态:
import React,{useState,useEffect,useRef} from 'react';
import { Button,Table, Tag,Modal,Popover, Switch,Form,Input,Radio,Select } from 'antd';
import { EditOutlined,DeleteOutlined,ExclamationCircleOutlined } from '@ant-design/icons';
import axios from 'axios';
import { data } from 'react-router-dom';
import Item from 'antd/es/list/Item';
import UserForm from '../../../components/user-manage/UserForm';const { confirm } = Modal;
function UserList() {const [dataSource,setdataSource]=useState([])const [isAddVisible,setisAddVisible]=useState(false)const [roleList,setroleList]=useState([])const [regionList,setregionList]=useState([])const addForm = useRef(null)useEffect(()=>{axios.get("http://localhost:3000/users?_expand=role").then(res=>{// console.log(res.data);const list = res.datasetdataSource(list)})},[])useEffect(()=>{axios.get("http://localhost:3000/regions").then(res=>{// console.log(res.data);const list = res.datasetregionList(list)})},[])useEffect(()=>{axios.get("http://localhost:3000/roles").then(res=>{// console.log(res.data);const list = res.datasetroleList(list)})
},[])const columns = [{title: '区域',dataIndex: 'region',render:(region)=>{return <b>{region===""?'全球':region}</b>}},{title: '角色名称',dataIndex: 'role',render:(role)=>{return role?.roleName}},{title: '用户名',dataIndex: 'username',},{title:"用户状态",dataIndex:"roleState",render:(roleState,item)=>{return <Switch checked={roleState} disabled={item.default}></Switch>}},{title: '操作',render:(record)=>{return <div><Button type="primary" shape="circle" icon={<EditOutlined />} disabled={record.default} /><Button danger type="primary" shape="circle" icon={<DeleteOutlined />} disabled={record.default}/></div>}},];const deleteMethod = (record) => {// console.log(record);}const [open, setOpen] = useState(false);return (<div><Button type='primary' onClick={() => setOpen(true)}>添加用户</Button><Table dataSource={dataSource} columns={columns}pagination={{pageSize:5 }}>rowKey = {item => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={()=>{addForm.current.validateFields().then((value)=>{console.log(value);}).catch((errInfo)=>{console.log(errInfo);})}}destroyOnClosemodalRender={(dom) => (<Formlayout="vertical">{dom}</Form>)}><UserForm regionList={regionList} roleList={roleList}ref={addForm}></UserForm></Modal></div>)
}export default UserList;
把Form单独抽象成组件:
import React, { forwardRef, useImperativeHandle } from 'react';
import { Form, Input, Select } from 'antd';const UserForm = forwardRef((props, ref) => {const [form] = Form.useForm();// 让外部 ref 访问 form 的方法useImperativeHandle(ref, () => ({validateFields: () => form.validateFields(),resetFields: () => form.resetFields(),}));// 选择框事件const onChange = (value) => {console.log(`selected ${value}`);};return (<Form form={form} layout="vertical"> {/* 用户名 */}<Form.Itemname="username"label="用户名"rules={[{ required: true, message: '请输入用户名' }]}><Input placeholder="请输入用户名" /></Form.Item>{/* 密码 */}<Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item>{/* 区域选择 */}<Form.Itemname="region"label="区域"rules={[{ required: true, message: '请选择区域' }]}><SelectshowSearchplaceholder="请选择区域"optionFilterProp="label"onChange={onChange}options={props.regionList.map(item => ({value: item.id,label: item.value,}))}/></Form.Item>{/* 角色选择 */}<Form.Itemname="roleId"label="角色"rules={[{ required: true, message: '请选择角色' }]}><SelectshowSearchplaceholder="请选择角色"optionFilterProp="label"onChange={onChange}options={props.roleList.map(item => ({value: item.id,label: item.roleName,}))}/></Form.Item></Form>);
});export default UserForm;
这个UserForm组件需要使用forwardRef,这样才可以把ref传递出去,以及遇到的bug:穿出去值了但是打印出结果是空数组:
修改后就是暴露方法,把之前的div去掉,以及useForm()绑定Form组件
接下来实现超级管理员禁用地区的功能,定义状态禁用
介绍一下Form组件,在 antd
中,我们可以使用 Form.useForm()
来创建一个受控的表单实例:
import { Form, Input, Button } from 'antd';const MyForm = () => {const [form] = Form.useForm(); // 创建表单实例const handleSubmit = () => {form.validateFields().then(values => {console.log('提交的数据:', values);}).catch(error => {console.log('表单验证失败:', error);});};return (<Form form={form} layout="vertical"><Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}><Input placeholder="请输入用户名" /></Form.Item><Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item><Button type="primary" onClick={handleSubmit}>提交</Button></Form>);
};
Form的一些常用方法:
加上处理的逻辑,角色和区域的事件应该分开写,改变区域设定的规则,如果是超级管理员的话不能选择区域也可以使表单成功的提交
import React, { useState,forwardRef, useImperativeHandle } from 'react';
import { Form, Input, Select } from 'antd';// 封装一下
const UserForm = forwardRef((props, ref) => {// 使用forwardRef 可以让子组件获取父组件的方法const [form] = Form.useForm();// 让外部 ref 访问 form 的方法useImperativeHandle(ref, () => ({validateFields: () => form.validateFields(),resetFields: () => form.resetFields(),}));const [isDisabled, setIsDisabled] = useState(false);// 选择框事件// 角色选择事件
const handleRoleChange = (value) => {if (value === 1) { setIsDisabled(true);form.setFieldsValue({ region: "" }); // 清空区域} else {setIsDisabled(false);}};// 区域选择事件 (不影响角色逻辑)const handleRegionChange = (value) => {console.log("区域选择:", value);};return (<Form form={form} layout="vertical"> {/* 用户名 */}<Form.Itemname="username"label="用户名"rules={[{ required: true, message: '请输入用户名' }]}><Input placeholder="请输入用户名" /></Form.Item>{/* 密码 */}<Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item>{/* 区域选择 */}<Form.Itemname="region"label="区域"rules={isDisabled?[]:[{ required: true, message: '请选择区域' }]}><Selectdisabled={isDisabled}showSearchplaceholder="请选择区域"optionFilterProp="label"onChange={handleRegionChange}options={props.regionList.map(item => ({value: item.id,label: item.value,}))}/></Form.Item>{/* 角色选择 */}<Form.Itemname="roleId"label="角色"rules={[{ required: true, message: '请选择角色' }]}><SelectshowSearchplaceholder="请选择角色"optionFilterProp="label"onChange={handleRoleChange}options={props.roleList.map(item => ({value: item.id,label: item.roleName,}))}/></Form.Item></Form>);
});export default UserForm;
现在想要将改动同步到页面上:
import React, { useState, useEffect, useRef } from 'react'
import {Button,Table,Tag,Modal,Popover,Switch,Form,Input,Radio,Select,
} from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import { data } from 'react-router-dom'
import Item from 'antd/es/list/Item'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return <Switch checked={roleState} disabled={item.default}></Switch>},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}/></div>)},},]const deleteMethod = (record) => {// console.log(record);}const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 idconst selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 获取所选角色的名称const selectedRole = roleList.find(item => item.id === value.roleId)?.roleName || "";axios.post(`http://localhost:3000/users`,{...value,"roleState": true,"default": false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource, res.data])})}).catch((errInfo) => {console.log(errInfo)})}const [open, setOpen] = useState(false)return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal></div>)
}export default UserList
同步确实是同步了,可是这个角色的名称总是不显示,只有刷新一次才会正常的显示。。
这下就又要修改代码了:
import React, { useState, useEffect, useRef } from 'react'
import {Button,Table,Tag,Modal,Popover,Switch,Form,Input,Radio,Select,
} from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import { data } from 'react-router-dom'
import Item from 'antd/es/list/Item'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return <Switch checked={roleState} disabled={item.default}></Switch>},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}/></div>)},},]const deleteMethod = (record) => {// console.log(record);}const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 idconst selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 获取所选角色的名称const selectedRole = roleList.find(item => item.id === value.roleId)?.roleName || "";axios.post(`http://localhost:3000/users`,{...value,"roleState": true,"default": false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource, {...res.data,role:roleList.filter(item => item.id === value.roleId)[0],}])})}).catch((errInfo) => {console.log(errInfo)})}const [open, setOpen] = useState(false)return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal></div>)
}export default UserList
更新了dataSource的装填,就可以更新并渲染了
分为:扩展现有数据、添加新用户数据、更新状态
至此添加部分的功能都完毕了,来写删除
删
进行删除的判定确认,同步后端数据:
import React, { useState, useEffect, useRef } from 'react'
import {Button,Table,Tag,Modal,Popover,Switch,Form,Input,Radio,Select,
} from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import { data } from 'react-router-dom'
import Item from 'antd/es/list/Item'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const confirmMethod = (record) => {confirm({title: '确定要删除这个角色吗?',icon: <ExclamationCircleOutlined />,onOk() {deleteMethod(record)},onCancel() {console.log('取消删除')},})}const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return <Switch checked={roleState} disabled={item.default}></Switch>},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}onClick={()=>confirmMethod(record)}/></div>)},},]const deleteMethod = (record) => {// console.log(record);//页面状态+后端setdataSource(dataSource.filter((item) => item.id !== record.id))axios.delete(`http://localhost:3000/users/${record.id}`)}const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 idconst selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 获取所选角色的名称const selectedRole = roleList.find(item => item.id === value.roleId)?.roleName || "";axios.post(`http://localhost:3000/users`,{...value,"roleState": true,"default": false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource, {...res.data,role:roleList.filter(item => item.id === value.roleId)[0],}])})}).catch((errInfo) => {console.log(errInfo)})}const [open, setOpen] = useState(false)return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal></div>)
}export default UserList
改
改就是更改状态和更改信息 ,这是更改选择并同步到后端:
import React, { useState, useEffect, useRef } from 'react'
import {Button,Table,Tag,Modal,Popover,Switch,Form,Input,Radio,Select,
} from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import { data } from 'react-router-dom'
import Item from 'antd/es/list/Item'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const deleteMethod = (record) => {// console.log(record);//页面状态+后端setdataSource(dataSource.filter((item) => item.id !== record.id))axios.delete(`http://localhost:3000/users/${record.id}`)}const confirmMethod = (record) => {confirm({title: '确定要删除这个角色吗?',icon: <ExclamationCircleOutlined />,onOk() {deleteMethod(record)},onCancel() {console.log('取消删除')},})}const handleChange = (item)=>{// console.log(item)item.roleState = !item.roleStatesetdataSource([...dataSource])axios.patch(`http://localhost:3000/users/${item.id}`,{roleState:item.roleState})}const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return <Switch checked={roleState} disabled={item.default}onChange={()=>handleChange(item)}></Switch>},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}onClick={()=>confirmMethod(record)}/></div>)},},]const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 idconst selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 获取所选角色的名称const selectedRole = roleList.find(item => item.id === value.roleId)?.roleName || "";axios.post(`http://localhost:3000/users`,{...value,"roleState": true,"default": false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource, {...res.data,role:roleList.filter(item => item.id === value.roleId)[0],}])})}).catch((errInfo) => {console.log(errInfo)})}const [open, setOpen] = useState(false)return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal></div>)
}export default UserList
接下来实现点击编辑按钮弹出框可以修改信息的功能
在实现这个功能的时候遇到了问题,我觉得是事件绑定和useEffect的依赖项的问题,现在修改完可以成功的显示旧的数据了:
import React, {useState,forwardRef,useImperativeHandle,useEffect,
} from 'react'
import { Form, Input, Select } from 'antd'const UserForm = forwardRef((props, ref) => {const [form] = Form.useForm()const internalForm = props.form || form // 使用外部传递的 form 实例const [isDisabled, setIsDisabled] = useState(false)// useEffect(() => {// if (props.form) {// props.form.setFieldValue(props.initialValues)// }// // setIsDisabled(props.isUpdateDisabled);// }, [props.isUpdateDisabled, props.form]) // 修复 useEffect 的语法useEffect(() => {if (props.form && props.initialValues) {props.form.setFieldsValue(props.initialValues);}setIsDisabled(props.isUpdateDisabled);}, [props.isUpdateDisabled, props.form, props.initialValues]); // 确保依赖项正确useImperativeHandle(ref, () => ({validateFields: () => internalForm.validateFields(),resetFields: () => internalForm.resetFields(),setFieldsValue: (values) => internalForm.setFieldsValue(values),}))// const handleRoleChange = (value) => {// if (value === 1) {// setIsDisabled(true);// form.setFieldsValue({ region: "" });// } else {// setIsDisabled(false);// }// };// UserForm 组件中的角色切换逻辑const handleRoleChange = (value) => {const isSuperAdmin = value === 1 // 假设角色ID=1是超级管理员setIsDisabled(isSuperAdmin)if (isSuperAdmin) {internalForm.setFieldsValue({ region: '' }) // 清空区域选择}}const handleRegionChange = (value) => {console.log('区域选择:', value)}return (<Form form={internalForm} layout="vertical"><Form.Itemname="username"label="用户名"rules={[{ required: true, message: '请输入用户名' }]}><Input placeholder="请输入用户名" /></Form.Item>{/* <Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item> */}<Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item><Form.Itemname="region"label="区域"rules={isDisabled ? [] : [{ required: true, message: '请选择区域' }]}><Selectdisabled={isDisabled}showSearchplaceholder="请选择区域"optionFilterProp="label"onChange={handleRegionChange}options={props.regionList.map((item) => ({value: item.id,label: item.value,}))}/></Form.Item><Form.Itemname="roleId"label="角色"rules={[{ required: true, message: '请选择角色' }]}><SelectshowSearchplaceholder="请选择角色"optionFilterProp="label"onChange={handleRoleChange}options={props.roleList.map((item) => ({value: item.id,label: item.roleName,}))}/></Form.Item></Form>)
})export default UserForm
import React, { useState, useEffect, useRef } from 'react'
import { Button, Table, Modal, Switch, Form, Menu } from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const [isUpdateVisible, setisUpdateVisible] = useState(false)const [isUpdateDisabled, setisUpdateDisabled] = useState(false)const [form] = Form.useForm() //创建antd的form实例const updateForm = useRef(null)const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const deleteMethod = (record) => {// console.log(record);//页面状态+后端setdataSource(dataSource.filter((item) => item.id !== record.id))axios.delete(`http://localhost:3000/users/${record.id}`)}const confirmMethod = (record) => {confirm({title: '确定要删除这个角色吗?',icon: <ExclamationCircleOutlined />,onOk() {deleteMethod(record)},onCancel() {console.log('取消删除')},})}const handleChange = (item) => {// console.log(item)item.roleState = !item.roleStatesetdataSource([...dataSource])axios.patch(`http://localhost:3000/users/${item.id}`, {roleState: item.roleState,})}const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return (<Switchchecked={roleState}disabled={item.default}onChange={() => handleChange(item)}></Switch>)},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}onClick={() => handleUpdate(record)}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}onClick={() => confirmMethod(record)}/></div>)},},]const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 id// const selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 添加用户的代码逻辑const selectedRegion =regionList.find((item) => item.id === value.region)?.value || ''axios.post(`http://localhost:3000/users`, {...value,region: selectedRegion, // 存储的是区域的名称(如"华东")})// 获取所选角色的名称const selectedRole =roleList.find((item) => item.id === value.roleId)?.roleName || ''axios.post(`http://localhost:3000/users`, {...value,roleState: true,default: false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource,{...res.data,role: roleList.filter((item) => item.id === value.roleId)[0],},])})}).catch((errInfo) => {console.log(errInfo)})}const [isUpdate, setisUpdate] = useState(false)const [updateform] = Form.useForm() //创建antd的updateform实例// const handleUpdate = (item) => {// setisUpdateVisible(true)// setisUpdateDisabled(item.default)// if(item.roleId === 1){// //禁用// setisUpdateDisabled(true)// }// else{// setisUpdateDisabled(false) // 启用更新表单的编辑// }// setTimeout(() => {// updateform.setFieldsValue({// username: item.username,// region: item.region,// roleId: item.role?.id,// })// }, 100) // 增加一定的延迟确保 Modal 已渲染// // //更新要想办法让已有数据展示出来// // // setisUpdate(true)// // updateform.setFieldsValue({ // 填充表单数据// // username: item.username,// // region: item.region,// // roleId: item.role?.id// // });// }// const handleUpdate = (item) => {// setisUpdateVisible(true);// setisUpdateDisabled(item.default);// if (item.roleId === 1) {// setisUpdateDisabled(true);// } else {// setisUpdateDisabled(false);// }// setTimeout(() => {// updateform.setFieldsValue({// username: item.username,// region: item.region,// roleId: item.role?.id,// password: item.password, // 确保密码字段被正确设置// });// }, 100);// }const handleUpdate = (item) => {setisUpdateVisible(true);setisUpdateDisabled(item.default);setTimeout(() => {updateform.setFieldsValue({username: item.username,password: item.password, // 确保密码字段被正确设置region: item.region,roleId: item.role?.id,});}, 100); // 增加一定的延迟确保 Modal 已渲染}const [open, setOpen] = useState(false)const updateFormOk = () => {}return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal>{/* 更新 */}<Modalopen={isUpdateVisible}title="更新用户"okText="更新"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => {setisUpdateVisible(false)setisUpdateDisabled(!isUpdateDisabled)}}onOk={() => updateFormOk()}destroyOnClosemodalRender={(dom) => (<Form layout="vertical" form={updateform}>{/* //将form实例传递给Form组件 */}{dom}</Form>)}><UserFormregionList={regionList}roleList={roleList}form={updateform}isUpdateDisabled={isUpdateDisabled}></UserForm></Modal></div>)
}export default UserList
更改并且同步了后端的数据:
import React, { useState, useEffect, useRef } from 'react'
import { Button, Table, Modal, Switch, Form, Menu } from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const [isUpdateVisible, setisUpdateVisible] = useState(false)const [isUpdateDisabled, setisUpdateDisabled] = useState(false)const [form] = Form.useForm() //创建antd的form实例const [current,setCurrent] = useState(null)const updateForm = useRef(null)const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const deleteMethod = (record) => {// console.log(record);//页面状态+后端setdataSource(dataSource.filter((item) => item.id !== record.id))axios.delete(`http://localhost:3000/users/${record.id}`)}const confirmMethod = (record) => {confirm({title: '确定要删除这个角色吗?',icon: <ExclamationCircleOutlined />,onOk() {deleteMethod(record)},onCancel() {console.log('取消删除')},})}const handleChange = (item) => {// console.log(item)item.roleState = !item.roleStatesetdataSource([...dataSource])axios.patch(`http://localhost:3000/users/${item.id}`, {roleState: item.roleState,})}const columns = [{title: '区域',dataIndex: 'region',render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return (<Switchchecked={roleState}disabled={item.default}onChange={() => handleChange(item)}></Switch>)},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}onClick={() => handleUpdate(record)}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}onClick={() => confirmMethod(record)}/></div>)},},]const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 id// const selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 添加用户的代码逻辑const selectedRegion =regionList.find((item) => item.id === value.region)?.value || ''axios.post(`http://localhost:3000/users`, {...value,region: selectedRegion, // 存储的是区域的名称(如"华东")})// 获取所选角色的名称const selectedRole =roleList.find((item) => item.id === value.roleId)?.roleName || ''axios.post(`http://localhost:3000/users`, {...value,roleState: true,default: false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource,{...res.data,role: roleList.filter((item) => item.id === value.roleId)[0],},])})}).catch((errInfo) => {console.log(errInfo)})}const [isUpdate, setisUpdate] = useState(false)const [updateform] = Form.useForm() //创建antd的updateform实例const handleUpdate = (item) => {setisUpdateVisible(true);setisUpdateDisabled(item.default);setTimeout(() => {//保证超级管理员的区域禁用if(item.roleId === 1) {setisUpdateDisabled(true)} else {setisUpdateDisabled(false)}updateform.setFieldsValue({username: item.username,password: item.password, // 确保密码字段被正确设置region: item.region,roleId: item.role?.id,});}, 100); // 增加一定的延迟确保 Modal 已渲染setCurrent(item)}const [open, setOpen] = useState(false)const updateFormOk = () => {updateform.validateFields().then((value) => {setisUpdateVisible(false);const selectedRegion = regionList.find(region => region.id === value.region)?.value || '';setdataSource(dataSource.map((item) => {if (item.id === current.id) {return {...item,...value,region: selectedRegion, // 将区域 ID 转换为区域名称role: roleList.filter((data) => data.id === value.roleId)[0],}}return item;}));// 同步后端数据axios.patch(`http://localhost:3000/users/${current.id}`, {...value,region: selectedRegion, // 确保后端也存储区域名称});});}return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal>{/* 更新 */}<Modalopen={isUpdateVisible}title="更新用户"okText="更新"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => {setisUpdateVisible(false)setisUpdateDisabled(!isUpdateDisabled)}}onOk={() => updateFormOk()}destroyOnClosemodalRender={(dom) => (<Form layout="vertical" form={updateform}>{/* //将form实例传递给Form组件 */}{dom}</Form>)}><UserFormregionList={regionList}roleList={roleList}form={updateform}isUpdateDisabled={isUpdateDisabled}></UserForm></Modal></div>)
}export default UserList
import React, {useState,forwardRef,useImperativeHandle,useEffect,
} from 'react'
import { Form, Input, Select } from 'antd'const UserForm = forwardRef((props, ref) => {const [form] = Form.useForm()const internalForm = props.form || form // 使用外部传递的 form 实例const [isDisabled, setIsDisabled] = useState(false)// useEffect(() => {// if (props.form) {// props.form.setFieldValue(props.initialValues)// }// // setIsDisabled(props.isUpdateDisabled);// }, [props.isUpdateDisabled, props.form]) // 修复 useEffect 的语法useEffect(() => {if (props.form && props.initialValues) {props.form.setFieldsValue(props.initialValues);}setIsDisabled(props.isUpdateDisabled);}, [props.isUpdateDisabled, props.form, props.initialValues]); // 确保依赖项正确useImperativeHandle(ref, () => ({validateFields: () => internalForm.validateFields(),resetFields: () => internalForm.resetFields(),setFieldsValue: (values) => internalForm.setFieldsValue(values),}))// const handleRoleChange = (value) => {// if (value === 1) {// setIsDisabled(true);// form.setFieldsValue({ region: "" });// } else {// setIsDisabled(false);// }// };// UserForm 组件中的角色切换逻辑const handleRoleChange = (value) => {const isSuperAdmin = value === 1 // 假设角色ID=1是超级管理员setIsDisabled(isSuperAdmin)if (isSuperAdmin) {internalForm.setFieldsValue({ region: '' }) // 清空区域选择}}const handleRegionChange = (value) => {console.log('区域选择:', value)}return (<Form form={internalForm} layout="vertical"><Form.Itemname="username"label="用户名"rules={[{ required: true, message: '请输入用户名' }]}><Input placeholder="请输入用户名" /></Form.Item>{/* <Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item> */}<Form.Itemname="password"label="密码"rules={[{ required: true, message: '请输入密码' }]}><Input.Password placeholder="请输入密码" /></Form.Item><Form.Itemname="region"label="区域"rules={isDisabled ? [] : [{ required: true, message: '请选择区域' }]}><Selectdisabled={isDisabled}showSearchplaceholder="请选择区域"optionFilterProp="label"onChange={handleRegionChange}options={props.regionList.map((item) => ({value: item.id,label: item.value,}))}/></Form.Item><Form.Itemname="roleId"label="角色"rules={[{ required: true, message: '请选择角色' }]}><SelectshowSearchplaceholder="请选择角色"optionFilterProp="label"onChange={handleRoleChange}options={props.roleList.map((item) => ({value: item.id,label: item.roleName,}))}/></Form.Item></Form>)
})export default UserForm
查
实现一个过滤地区的功能
这个过滤是table组件自带的功能
筛选主要控制的是onFilter属性
import React, { useState, useEffect, useRef } from 'react'
import { Button, Table, Modal, Switch, Form, Menu } from 'antd'
import {EditOutlined,DeleteOutlined,ExclamationCircleOutlined,
} from '@ant-design/icons'
import axios from 'axios'
import UserForm from '../../../components/user-manage/UserForm'const { confirm } = Modal
function UserList() {const [dataSource, setdataSource] = useState([])const [isAddVisible, setisAddVisible] = useState(false)const [roleList, setroleList] = useState([])const [regionList, setregionList] = useState([])const [isUpdateVisible, setisUpdateVisible] = useState(false)const [isUpdateDisabled, setisUpdateDisabled] = useState(false)const [form] = Form.useForm() //创建antd的form实例const [current,setCurrent] = useState(null)const updateForm = useRef(null)const addForm = useRef(null)useEffect(() => {axios.get('http://localhost:3000/users?_expand=role').then((res) => {// console.log(res.data);const list = res.datasetdataSource(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/regions').then((res) => {// console.log(res.data);const list = res.datasetregionList(list)})}, [])useEffect(() => {axios.get('http://localhost:3000/roles').then((res) => {// console.log(res.data);const list = res.datasetroleList(list)})}, [])const deleteMethod = (record) => {// console.log(record);//页面状态+后端setdataSource(dataSource.filter((item) => item.id !== record.id))axios.delete(`http://localhost:3000/users/${record.id}`)}const confirmMethod = (record) => {confirm({title: '确定要删除这个角色吗?',icon: <ExclamationCircleOutlined />,onOk() {deleteMethod(record)},onCancel() {console.log('取消删除')},})}const handleChange = (item) => {// console.log(item)item.roleState = !item.roleStatesetdataSource([...dataSource])axios.patch(`http://localhost:3000/users/${item.id}`, {roleState: item.roleState,})}const columns = [{title: '区域',dataIndex: 'region',filters:[...regionList.map((item) => ({text: item.value,value: item.value,})),{text: '全球',value: '全球',}],onFilter: (value, item) =>{if(value === '全球') {return item.region === ""}return item.region===value}, render: (region) => {return <b>{region === '' ? '全球' : region}</b>},},{title: '角色名称',dataIndex: 'role',render: (role) => {return role?.roleName},},{title: '用户名',dataIndex: 'username',},{title: '用户状态',dataIndex: 'roleState',render: (roleState, item) => {return (<Switchchecked={roleState}disabled={item.default}onChange={() => handleChange(item)}></Switch>)},},{title: '操作',render: (record) => {return (<div><Buttontype="primary"shape="circle"icon={<EditOutlined />}disabled={record.default}onClick={() => handleUpdate(record)}/><Buttondangertype="primary"shape="circle"icon={<DeleteOutlined />}disabled={record.default}onClick={() => confirmMethod(record)}/></div>)},},]const addFormOk = () => {addForm.current.validateFields().then((value) => {// console.log(value)setOpen(false)addForm.current.resetFields()//post到后端生成id,再设置dataSource,方便删除和更新// 修正: 确保 `region` 存储的是字符串,而不是 id// const selectedRegion = regionList.find(item => item.id === value.region)?.value || "";// 添加用户的代码逻辑const selectedRegion =regionList.find((item) => item.id === value.region)?.value || ''axios.post(`http://localhost:3000/users`, {...value,region: selectedRegion, // 存储的是区域的名称(如"华东")})// 获取所选角色的名称const selectedRole =roleList.find((item) => item.id === value.roleId)?.roleName || ''axios.post(`http://localhost:3000/users`, {...value,roleState: true,default: false,region: selectedRegion, // 修正 `region` 的值roleName: selectedRole, // 修正 `roleName` 的值}).then((res) => {console.log(res.data)setdataSource([...dataSource,{...res.data,role: roleList.filter((item) => item.id === value.roleId)[0],},])})}).catch((errInfo) => {console.log(errInfo)})}const [isUpdate, setisUpdate] = useState(false)const [updateform] = Form.useForm() //创建antd的updateform实例const handleUpdate = (item) => {setisUpdateVisible(true);setisUpdateDisabled(item.default);setTimeout(() => {//保证超级管理员的区域禁用if(item.roleId === 1) {setisUpdateDisabled(true)} else {setisUpdateDisabled(false)}updateform.setFieldsValue({username: item.username,password: item.password, // 确保密码字段被正确设置region: item.region,roleId: item.role?.id,});}, 100); // 增加一定的延迟确保 Modal 已渲染setCurrent(item)}const [open, setOpen] = useState(false)const updateFormOk = () => {updateform.validateFields().then((value) => {setisUpdateVisible(false);const selectedRegion = regionList.find(region => region.id === value.region)?.value || '';setdataSource(dataSource.map((item) => {if (item.id === current.id) {return {...item,...value,region: selectedRegion, // 将区域 ID 转换为区域名称role: roleList.filter((data) => data.id === value.roleId)[0],}}return item;}));// 同步后端数据axios.patch(`http://localhost:3000/users/${current.id}`, {...value,region: selectedRegion, // 确保后端也存储区域名称});});}return (<div><Button type="primary" onClick={() => setOpen(true)}>添加用户</Button><TabledataSource={dataSource}columns={columns}pagination={{pageSize: 5,}}>rowKey = {(item) => item.id}</Table><Modalopen={open}title="添加用户"okText="确定"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => setOpen(false)}onOk={() => addFormOk()}destroyOnClosemodalRender={(dom) => <Form layout="vertical">{dom}</Form>}><UserFormregionList={regionList}roleList={roleList}ref={addForm}></UserForm></Modal>{/* 更新 */}<Modalopen={isUpdateVisible}title="更新用户"okText="更新"cancelText="取消"okButtonProps={{ autoFocus: true, htmlType: 'submit' }}onCancel={() => {setisUpdateVisible(false)setisUpdateDisabled(!isUpdateDisabled)}}onOk={() => updateFormOk()}destroyOnClosemodalRender={(dom) => (<Form layout="vertical" form={updateform}>{/* //将form实例传递给Form组件 */}{dom}</Form>)}><UserFormregionList={regionList}roleList={roleList}form={updateform}isUpdateDisabled={isUpdateDisabled}></UserForm></Modal></div>)
}export default UserList
至此用户阶段的增删改查全部完成