目录
数据字典:
字典管理用来维护字典类型的数据,例如:状态的启用、禁用;性别的男、女;订单的已下单、支付中、已完成;通常用在如下拉框、单选按钮、复选框、树选择中的数据中,方便系统管理员维护。
原代码是在前端文件当中定义写死options数组进行遍历,这样不利于维护,所以我们采用数据字典:


首先我们要在图示内容下创建新的数据字典,在字典管理页面下点击新增创建字典项,然后点击字典类型下的蓝色超链接进入字典数据,在其中进行修改编辑,这里注意一下显示排序,数值越小排在越前
我们将前端声明options数组的语句换成以下代码:
const {nursing_project_status} = proxy.useDict('nursing_project_status')
然后把表单项绑定的options数组换成我们定义好的 nursing_project_status 即可
前端新增页面改造:

我们进行代码的更改如下:

这里提及一个问题,我们最早把代码复制过来进行调试的时候发现打开护理项目时加载时间很久,开始以为是前端或后端或者虚拟机死掉了,尝试重启前后端项目发现问题并未解决;打开别的菜单栏发现正常运行,F12打开调试器发现前端报错,内容是路由有问题(实际上我们并未修改路由有关内容),将我们这部分修改的内容复原后问题消失,经过研究分析发现:代码复制过来的时候格式不对,出现了报错以及黄色的方框(其中并无内容只是占用一个空格,将其删除之后保存调试问题解决)
解决修改时状态没有回显的问题:

该问题是由于从数据库拿到的数据是int类型,而字典需要的是字符串类型,我们添加以下内容即可:

集成OSS:

新建OSS模块:

将封装好的AliyunOSSOperator、AliyunOSSProperties文件放到OSS模块下,然后到admin模块下的application.yml文件下配置断点和bucketName:
# 阿里云OSS相关配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: zznursing-le1yu
然后查看自己的KeyId和KeySecret是否已在环境变量中配置,接下来修改后端代码,我们仅需要修改admin模块下CommonController文件下uploadFile方法即可:
/**
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称
// String fileName = FileUploadUtils.upload(filePath, file);
String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename());
// String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", url);
ajax.put("newFileName", FileUtils.getName(url));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
这样我们封装好的AliyunOSSOperator当中的方法就会帮我们上传文件到阿里云当中
接下来我们阅读一下相关的前端代码:
//文件位置:src/components/imageUpload/index.vue
watch(() => props.modelValue, val => {
if (val) {
// 首先将值转为数组
const list = Array.isArray(val) ? val : props.modelValue.split(",")
// 然后将数组转为对象数组
fileList.value = list.map(item => {
if (typeof item === "string") {
if (item.indexOf(baseUrl) === -1 && !isExternal(item)) {
item = { name: baseUrl + item, url: baseUrl + item }
} else {
item = { name: item, url: item }
}
}
return item
})
} else {
fileList.value = []
return []
}
},{ deep: true, immediate: true })
//baseUrl的定义:
const baseUrl = import.meta.env.VITE_APP_BASE_API
效果展示:

代码提交:


护理计划功能开发:
修改若依生成的前端文件:
将资料中的代码覆盖掉若依生成的代码,并在src/assets/styles/variables.mudule.scss文件中添加一个颜色引用:
$--color-main: #00b8a0;
添加一个查询所有方法:在@/api/nursing/project.js中新增一个接口,查询所有的护理项目;由于后端并未开发对应接口,此时肯定会报错:

这里遇到了一个问题,现象是打开护理计划时加载时间很久,打开控制台发现是import报错,原来是不小心将查询所有的接口写在了plan.js文件当中,而不是project.js,这样就导致index.vue当中导入方法的时候找不到该方法,更改后正确显示以上图片内容
导入后端代码:
在若依系统代码生成当中导入nursing_project_plan表,然后将生成的NursingProjectPlan实体类、Mapper接口及其xml文件导入到项目当中:

创建数据字典:
新建字典nursing_plan_status(护理计划状态)再点入字典类型添加两个状态:

编写后端查询所有方法:
现在我们要解决刚才接口报错问题,由于我们要查询所有的护理项目,所以要在NursingProjectController当中编写查询所有方法,这里介绍一下VO类,VO即Value Object,是后端返回给前端所封装的一个类(这里我们创建该类并根据接口文档封装属性):
package com.zzyl.nursing.vo;
import lombok.Data;
@Data
public class NursingProjectVo {
/**
* 项目名称
*/
private String label;
/**
* 项目ID
*/
private String value;
}
然后逐层编写方法一直到Mapper层,由于sql语句较为简单所有直接用@Select注解写出:
select name label, id value from nursing_project where status = 1
新增护理计划功能:
这里我们用到了DTO类,DTO即Data Transfer Object,用于封装前端传递给后端的数据:
package com.zzyl.nursing.dto;
import com.zzyl.nursing.domain.NursingProjectPlan;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class NursingPlanDto {
private Long id;
/**
* 排序号
*/
@ApiModelProperty(value = "排序号")
private Integer sortNo;
/**
* 计划名称
*/
@ApiModelProperty(value = "计划名称")
private String planName;
/**
* 状态(0:禁用,1:启用)
*/
@ApiModelProperty(value = "状态(0:禁用,1:启用)")
private Integer status;
/**
* 护理计划关联项目列表
*/
List<NursingProjectPlan> projectPlans;
}
然后我们自己在Service层编写方法,方法中操作两张表,分别是护理计划表和计划项目关联表,因此需要在方法上加上@Transactional(rollbackFor = Exception.class)注解来保证原子性:
/**
* 新增护理计划
*
* @param dto 护理计划
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertNursingPlan(NursingPlanDto dto) {
//1.保存护理计划
NursingPlan nursingPlan = new NursingPlan();
BeanUtils.copyBeanProp(nursingPlan, dto);
nursingPlan.setCreateTime(DateUtils.getNowDate());
nursingPlanMapper.insert(nursingPlan);
//2.批量保存护理计划和护理项目的对应关系
int count = nursingProjectPlanMapper.batchInsert(dto.getProjectPlans(), nursingPlan.getId());
return count == 0 ? 0 : 1;
}
然后第一个insert方法是MP当中写好的方法,而下面的batchInsert是我们自己编写的,下面介绍一下batchInsert的逻辑:首先我们在声明方法的时候用@Param注解重新命名了参数的名称:
int batchInsert(@Param("list") List<NursingProjectPlan> projectPlans,@Param("planId") Long planId);
然后在xml文件中写sql逻辑:
<insert id="batchInsert">
insert into nursing_project_plan (plan_id, project_id, execute_time, execute_cycle, execute_frequency, create_time, remark) values
<foreach item="item" collection="list" separator=",">
(#{planId}, #{item.projectId}, #{item.executeTime}, #{item.executeCycle}, #{item.executeFrequency},sysdate(),#{item.remark})
</foreach>
</insert>
可以看到,我们命名的list、planId在这里都有用到
接下来谈谈其中遇到的问题:
①刚编写完测试的时候发现报错,进入到后台查看报错内容如下:
### Error updating database. Cause: java.lang.UnsupportedOperationException
经过调查发现,这是由于我们在Mapper层alt+enter快捷键生成xml代码的时候,想当然地以为会选中insert,结果选中了默认的update,所有变成了update标签,当Mybatis来执行sql的时候发现我们要执行的是update语句,sql写的却是insert,因此报错。
②将刚才的问题更正之后发现了另一个问题:在前端页面新增护理计划的时候,护理名称没有显示并且状态居然为禁用(我们设置为启用),经过断点排查发现,执行insert语句的时候,参数是空的,这是由于前面进行参数拷贝的时候从哪拷贝到哪弄反了,导致把空的参数给到了insert方法,因此加入数据库的内容都为null,更正过后进行测试问题得以解决
效果展示:

数据回显(根据id查询护理计划):
由于我们之前编写若依的代码生成模板的使用用的MP,MP只能操作单表,所以生成的代码只查询回了基本信息(即护理计划表中的内容)
首先分析了一下接口文档发现,现有的类无法满足返回参数的需要,因此要再新创两个VO类:
package com.zzyl.nursing.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(description = "护理计划")
public class NursingPlanVo {
/**
* 护理计划id
*/
private Long id;
/**
* 排序号
*/
@ApiModelProperty(value = "护理计划排序号")
private Integer sortNo;
@ApiModelProperty(value = "护理计划名称")
private String planName;
@ApiModelProperty(value = "状态(0:禁用,1:启用)")
private Integer status;
@ApiModelProperty(value = "护理计划项目列表")
List<NursingProjectPlanVo> projectPlans;
}
package com.zzyl.nursing.vo;
import com.zzyl.common.annotation.Excel;
import lombok.Data;
@Data
public class NursingProjectPlanVo {
/** 项目id */
private String projectId;
/** $column.columnComment */
private Long id;
/** 计划id */
@Excel(name = "计划id")
private Long planId;
/** 计划执行时间 */
@Excel(name = "计划执行时间")
private String executeTime;
/** 执行周期 0 天 1 周 2月 */
@Excel(name = "执行周期 0 天 1 周 2月")
private String executeCycle;
/** 执行频次 */
@Excel(name = "执行频次")
private Long executeFrequency;
}
PlanVO表示要返回的整个护理计划(包括基础信息和护理项目数组),而ProjectPlanVO则是封装护理项目用的,创建好两个VO类后开始从Controller层开始修改,把泛型换成VO类,然后逐层修改泛型,到实现类当中我们要分步实现我们的功能:
/**
* 查询护理计划
*
* @param id 护理计划主键
* @return 护理计划
*/
@Override
public NursingPlanVo selectNursingPlanById(Long id) {
//查询护理计划基本信息
NursingPlan nursingPlan = nursingPlanMapper.selectById(id);
//查询护理计划关联的项目集合
List<NursingProjectPlanVo> projectPlans =nursingProjectPlanMapper.selectByNursingPlanId(id);
//将两部分信息封装到一个对象中返回
NursingPlanVo nursingPlanVo = new NursingPlanVo();
BeanUtils.copyProperties(nursingPlan, nursingPlanVo);
nursingPlanVo.setProjectPlans(projectPlans);
return nursingPlanVo;
}
首先通过MP方法快速查询基本信息,然后调用我们自己写的selectByNursingPlanId方法,最后把查询到的信息拷贝到nursingPlanVo对象当中,再单独set查询到的护理项目数组,封装到nursingPlanVo当中并返回
接下来就是我们自己编写的方法selectByNursingPlanId的具体实现了:
/**
* 根据计划id查询计划项目
* @param planId 护理计划id
* @return
*/
List<NursingProjectPlanVo> selectByNursingPlanId(@Param("planId") Long planId);
和刚才一样,先用@Param注解重命名我们的参数,然后到xml文件中写sql逻辑:
<select id="selectByNursingPlanId" resultType="com.zzyl.nursing.vo.NursingProjectPlanVo">
select id,
plan_id,
project_id,
execute_time,
execute_cycle,
execute_frequency,
create_time,
create_by
from nursing_project_plan
where plan_id = #{planId}
</select>
这里就是根据返回参数看看需要什么样的字段
效果展示:

这里被我发现了一个问题,点击查看进来居然还是修改护理计划,不过老师的也是这样的,后面应该会有更正
修改护理计划功能:
没有什么特别的,大致说说实现类和sql的逻辑吧:
/**
* 修改护理计划
*
* @param dto 护理计划
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int updateNursingPlan(NursingPlanDto dto) {
//判断dto中的护理项目是否为空,如果不为空,先删除护理计划关联的所有护理项目,再重新批量保存最新的关联
if (dto.getProjectPlans() != null && !dto.getProjectPlans().isEmpty()) {
//删除护理计划对应的护理项目列表
nursingProjectPlanMapper.deleteByNursingPlanId(dto.getId());
//批量保存护理计划关联的护理项目
nursingProjectPlanMapper.batchInsert(dto.getProjectPlans(), dto.getId());
}
NursingPlan nursingPlan = new NursingPlan();
BeanUtils.copyProperties(dto, nursingPlan);
//修改护理计划
return nursingPlanMapper.updateById(nursingPlan);
}
@Delete("delete from nursing_project_plan where plan_id = #{planId}")
void deleteByNursingPlanId(@Param("planId") Long planId);
删除护理计划功能:
由于只有单条删除,所以把批量删除改成根据单个id删除单条数据(但是要操作两张表),记得加Transational注解
代码commit:
过于简单不再赘述
微实战:
自主完成护理等级部分:
我先设定了数据字典然后发现状态栏下拉框没东西,原来是声明变量时调用方法引错了:
//原来的
const {nursing_level_status} = proxy.useDict('nursing_project_status')
//更改后
const {nursing_level_status} = proxy.useDict('nursing_level_status')
接下来就是写查询所有护理计划的接口以及页面的正确展示:
效果展示:


未完待续......
972

被折叠的 条评论
为什么被折叠?



