1.我们在列表数据展现定义columns数组时,预留了修改和查看的操作列代码,代码如下:
{title: '操作',dataIndex: 'option',valueType: 'option',render: (_, record) => [<akey="config"onClick={() => {handleUpdateModalVisible(true);setCurrentRow(record);}}>修改</a>,<aonClick={() => {setCurrentRow(record);setShowDetail(true);}}>查看</a>],},
这里点某一行数据的修改操作链接时会调用handleUpdateModalVisible(true)方法,从字面意义上看应该是有个UpdateModel组件,让其可见,然后调用setCurrentRow方法把当前行数据record存入state
const [currentRow, setCurrentRow] = useState();
2.我们先找UpdateModel组件
发现有个UpdateForm,而且src/pages/loginfo/index.jsx中确实有UpdateForm组件,而
handleUpdateModalVisible(true)只是个useState的设置,来设置UpdateForm组件的可见性
<UpdateFormonSubmit={async (value) => {const success = await handleUpdate(value, currentRow);if (success) {handleUpdateModalVisible(false);setCurrentRow(undefined);if (actionRef.current) {actionRef.current.reload();}}}}onCancel={() => {handleUpdateModalVisible(false);setCurrentRow(undefined);}}updateModalVisible={updateModalVisible}values={currentRow || {}}/>
updateModalVisible={updateModalVisible}
3.从以上代码我们可以分析出,修改模块的核心组件是UpdateForm,而UpdateForm是一个单独引入的JSX文件,文件位置在src/pages/loginfo/components/UpdateForm.jsx
4.我们打开UpdateForm.jsx,发现里面代码蛮多,而且还用了StepsForm
我们的表单没有这么复杂,我们把UpdateForm.jsx,全替换掉,替换后的的代码如下
import React from 'react';import { Modal } from 'antd';import ProForm, { ModalForm, ProFormText, ProFormDateTimePicker } from '@ant-design/pro-form';const UpdateForm = (props) => {return (<ModalFormlayout="horizontal"labelCol={{ span: 4 }}title="修改登录日志"width="600px"visible={props.updateModalVisible}modalProps={{destroyOnClose: true,onCancel: () => props.onCancel(),}}onFinish={props.onSubmit}initialValues={{infoId: props.values.infoId,ipaddr: props.values.ipaddr,loginLocation: props.values.loginLocation,browser: props.values.browser,loginTime: props.values.loginTime,msg: props.values.msg,}}><ProFormTextname="infoId"hidden="true"/><ProFormTextrules={[{required: true,message: '登录IP地址不能为空',},{pattern: new RegExp('^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$','g',),message: '登录IP地址格式错误',},]}width="md"name="ipaddr"label="登录IP地址"placeholder="请输入登录IP地址"/><ProFormTextrules={[{required: true,message: '登录地点为必填项',},]}width="md"label="登录地点"placeholder="请输入登录地点"name="loginLocation"/><ProFormTextrules={[{required: true,message: '浏览器类型为必填项',},]}width="md"label="浏览器类型"placeholder="请输入浏览器类型"name="browser"/><ProFormDateTimePickername="loginTime"label="访问时间"rules={[{required: true,message: '访问时间为必填项',},]}/><ProFormTextrules={[{required: true,message: '提示消息为必填项',},]}width="md"label="提示消息"placeholder="请输入提示消息"name="msg"/></ModalForm>);};export default UpdateForm;
这里的UpdateForm组件其实跟我们之前做新增时用的组件差不多,用的也是ModalForm,ModalForm里面用的组件和非空验证以及正则表达式验证也是一样的,其实之前在做新增登录日志时我们也说过,新增和修改其实可以共用一个jsx文件,有兴趣的朋友可以自行改造成共用一个jsx文件。
5.UpdateForm表单中有几段代码稍作说明
modalProps={{destroyOnClose: true,onCancel: () => props.onCancel(),}}
通过props公开onCancel方法
onFinish={props.onSubmit}
<UpdateFormonSubmit={async (value) => {const success = await handleUpdate(value, currentRow);if (success) {handleUpdateModalVisible(false);setCurrentRow(undefined);if (actionRef.current) {actionRef.current.reload();}}}}
通过props公开onSubmit方法,即更新表单后,点确定时会触发onSubmit方法,onSubmit中会调用handleUpdate更新数据,更新成功后会隐藏更新表单,然后重新加载表格。
initialValues={{infoId: props.values.infoId,ipaddr: props.values.ipaddr,loginLocation: props.values.loginLocation,browser: props.values.browser,loginTime: props.values.loginTime,msg: props.values.msg,}}
initialValues设置编辑表单上各个组件的初始值,updateForm中有属性values,values的值即为当前行的数据对象,values会通过props传递给UpdateForm,我们可以在initialValues方法中拿到props.values,并且给各个组件设置初始值,如infoId:props.values.infoId,
<ProFormTextname="infoId"hidden="true"/>
让主键字段infoId文本框隐藏,即实现效果,这里踩了好久的坑,在Antd Pro官网的ProFormText并未找到如何实现隐藏域的效果,官网地址:
https://procomponents.ant.design/components/field-set#proformtext,在Antd 的Input组件属性中也未找到,官网地址:
https://ant.design/components/input-cn/,最后自己反复猜测尝试,才发现可以用hidden=”true”实现隐藏域效果
6.保存UpdateForm.jsx后,等编译后,打开登录日志列表页面,选择我们刚才录入的哪条数据,发现数据可以正常显示在更新页面上,且主键字段值不会显示出来,如下图:
7.下一步是写后台方法,之前在做新增时也说过,若依的登录日志的Contoller中是没有新增、修改的方法的,我们先加一下修改的后台方法,代码如下
@PostMapping(value="edit")public AjaxResult edit(@Validated @RequestBody SysLogininfor sysLogininfor){sysLogininfor.setUpdateBy(getUsername());sysLogininfor.setUserName(getUsername());sysLogininfor.setStatus("0");return toAjax(logininforService.updateSysLogininfor(sysLogininfor));}
这是一个Post接口,传入参数为一个sysLoginfor实体对象的JSON数据,接口调用的url地址为/api/monitor/logininfor/edit,这里有个问题,若依的servcie中连updateSysLogininfor方法也未提供,我们需要手动增加updateSysLogininfor方法,若依后台使用的是mybatis,我们需要先从mapper文件开始进行修改
8.我们先在mapper文件中增加更新logininfo的xml代码,找到ruoyi-system模块(若依是一个多模块的项目)下的resources/mapper/system/SysLogininforMapper.xml,找到insert代码
<insert id="insertLogininfor" parameterType="SysLogininfor">insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time)values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate())</insert>
我们在insert后面增加update的mybatis xml代码如下:
<update id="updateSysLogininfor" parameterType="SysLogininfor">update sys_logininfor<trim prefix="SET" suffixOverrides=","><if test="userName != null">user_name = #{userName},</if><if test="ipaddr != null">ipaddr = #{ipaddr},</if><if test="loginLocation != null">login_location = #{loginLocation},</if><if test="browser != null">browser = #{browser},</if><if test="os != null">os = #{os},</if><if test="status != null">status = #{status},</if><if test="msg != null">msg = #{msg},</if><if test="loginTime != null">login_time = #{loginTime},</if></trim>where info_id = #{infoId}</update>
然后保存xml文件
9.找到ruoyi-system模块下的src/java/com/ruoyi/system/mapper/SysLogininforMapper.java,在
public void insertLogininfor(SysLogininfor logininfor);后面加一行更新方法的代码如下
public int updateSysLogininfor(SysLogininfor sysLogininfor);

10.找到ruoyi-system模块下的src/java/com/ruoyi/system/service/ISysLogininforService.java,在
public void insertLogininfor(SysLogininfor logininfor);后面加一行更新方法的代码如下
public int updateSysLogininfor(SysLogininfor sysLogininfor);
11.找到ruoyi-system模块下的src/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java,在
@Overridepublic void insertLogininfor(SysLogininfor logininfor){logininforMapper.insertLogininfor(logininfor);}
后面加更新方法的代码如下
@Overridepublic int updateSysLogininfor(SysLogininfor sysLogininfor){return logininforMapper.updateSysLogininfor(sysLogininfor);}
这一步做完后contoller中的edit部分的代码应该不会报错了,我们重新maven reload一下
然后Rebuild Project
稍等几分钟,Rebuild 成功后,重启后台
12.后台方法写好后,我们就应该修改前台调用的接口了,找到src/pages/loginfo/service.js,找到updateRule方法,代码如下:
export async function updateRule(data, options) {return request('/api/rule', {data,method: 'PUT',...(options || {}),});}
修改为以下代码,主要修改了方法名和请求url地址,method改成后台对应的POST
export async function updateLoginfo(data, options) {return request('/api/monitor/logininfor/edit', {data,method: 'POST',...(options || {}),});}
13.回到src/pages/loginfo/index.jsx,修改引入service的代码
import { loginfo, addLoginfo, updateRule, removeRule } from './service';
将updateRule替换成updateLoginfo,替换后代码如下
import { loginfo, addLoginfo, updateLoginfo, removeRule } from './service';
14.找到handleUpdate方法,代码如下:
const handleUpdate = async (fields, currentRow) => {const hide = message.loading('正在配置');try {await updateRule({ ...currentRow, ...fields });hide();message.success('配置成功');return true;} catch (error) {hide();message.error('配置失败请重试!');return false;}};
这是更新调用后台接口的主方法,查询表格里面已做好代码封装,我们只需将updateRule方法改为updateLoginfo即可,修改后代码如下:
const handleUpdate = async (fields, currentRow) => {const hide = message.loading('正在更新');try {await updateLoginfo({ ...currentRow, ...fields });hide();message.success('更新成功');return true;} catch (error) {hide();message.error('更新失败请重试!');return false;}};/**
15.保存前台代码,前台编译完成后,确保后台已启动,我们重新登录前台,打开登录日志,编辑我们之前录入的那条数据
修改成功后表格会刷新,会绑定更新后的数据,如下图所示
