1.我们在列表数据展现定义columns数组时,预留了修改和查看的操作列代码,代码如下:
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<a
key="config"
onClick={() => {
handleUpdateModalVisible(true);
setCurrentRow(record);
}}
>
修改
</a>,
<a
onClick={() => {
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组件的可见性
<UpdateForm
onSubmit={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 (
<ModalForm
layout="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,
}}
>
<ProFormText
name="infoId"
hidden="true"
/>
<ProFormText
rules={[
{
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地址"
/>
<ProFormText
rules={[
{
required: true,
message: '登录地点为必填项',
},
]}
width="md"
label="登录地点"
placeholder="请输入登录地点"
name="loginLocation"
/>
<ProFormText
rules={[
{
required: true,
message: '浏览器类型为必填项',
},
]}
width="md"
label="浏览器类型"
placeholder="请输入浏览器类型"
name="browser"
/>
<ProFormDateTimePicker
name="loginTime"
label="访问时间"
rules={[
{
required: true,
message: '访问时间为必填项',
},
]}
/>
<ProFormText
rules={[
{
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}
<UpdateForm
onSubmit={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,
<ProFormText
name="infoId"
hidden="true"
/>
让主键字段infoId文本框隐藏,即实现input type='hidden'效果,这里踩了好久的坑,在Antd Pro官网的ProFormText并未找到如何实现隐藏域的效果,官网地址: procomponents.ant.design/components/…,在Antd 的Input组件属性中也未找到,官网地址: ant.design/components/…,最后自己反复猜测尝试,才发现可以用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,在
@Override
public void insertLogininfor(SysLogininfor logininfor)
{
logininforMapper.insertLogininfor(logininfor);
}
后面加更新方法的代码如下
@Override
public 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.保存前台代码,前台编译完成后,确保后台已启动,我们重新登录前台,打开登录日志,编辑我们之前录入的那条数据
修改成功后表格会刷新,会绑定更新后的数据,如下图所示
最近做了个小API应用,希望大家关注支持下: www.yuque.com/docs/share/…