第5章 前后端快速开发
学习目标
- 能够使用Element Plus组件改造项目的列表展示效果
- 能够使用若依框架的字典功能配合Element Plus组件展示状态数据
- 能够使用Element Plus组件改造项目的新增和修改的弹窗
- 能够独立集成OSS到项目中
- 能够独立完成功能的接口方法改造
数据字典
数据字典的价值:为企业提供了常量的统一管理。
应用场景:在如下拉框、单选按钮、复选框、树选择中的数据中,方便系统管理员维护。
- 状态的启用、禁用;
- 性别的男、女;
- 订单的已下单、支付中、已完成;
若依框架的字典管理
主要功能包括:字典分类管理、字典数据管理
点击字典类型进行字典详情编辑。
详细的操作步骤如下:
1、添加新的数据字典
2、添加字典数据
数据字典的表关系
在前端项目中引用数据字典
1、在Script标签中引用定义好的数据字典
//引用数据字典
const { nursing_project_status } = proxy.useDict("nursing_project_status");
2、在组件template标签中添加状态下拉框并使用字典数据
<el-form-item label="状态" prop="name">
<el-select v-model="queryParams.status" placeholder="请选择" clearable>
<el-option
v-for="item in nursing_project_status"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
文件上传到阿里云OSS
如何实现在若依框架中也将文件上传到阿里云OSS中呢?
目前使用的是若依提供的方案,对应的代码如下:
位置:zzyl-admin模块下,com.zzyl.web.controller.common.CommonController.uploadFile
/**
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称,保存到本地的目录中
String fileName = FileUploadUtils.upload(filePath, file);
String url = nursingrConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
集成OSS模块
推荐:单独创建一个模块,专门来管理OSS。
- 在父工程中创建子模块为:zzyl-oss,如下图所示:
- 在父工程的pom文件中进行版本管理
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zzyl</groupId>
<artifactId>zzyl</artifactId>
<version>3.8.8</version>
<name>zzyl</name>
<url>http://www.ruoyi.vip</url>
<description>中州养老后台管理系统</description>
<properties>
<aliyun.sdk.oss>3.17.4</aliyun.sdk.oss>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun.sdk.oss}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
在zzyl-oss模块中引入aliyun-sdk-oss依赖和zzyl-common依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zzyl</groupId>
<artifactId>zzyl</artifactId>
<version>3.8.8</version>
</parent>
<artifactId>zzyl-oss</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>com.zzyl</groupId>
<artifactId>zzyl-common</artifactId>
</dependency>
</dependencies>
</project>
- 创建oss配置类及客户端
上面的两个类如下:
AliyunOSSProperties:配置类,读取aliyun.oss为前缀的属性值(桶名称bucketName,域名站点endpoint)
package com.zzyl.oss; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "aliyun.oss") public class AliyunOSSProperties { private String endpoint; private String bucketName; }
AliyunOSSOperator:通过OSSClient对oss进行交互,提供了上传和删除两个方法
package com.zzyl.oss; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.common.auth.CredentialsProviderFactory; import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider; import com.aliyun.oss.model.DeleteObjectsRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Component public class AliyunOSSOperator { @Autowired private AliyunOSSProperties ossProperties; /** * 文件上传 * * @param content 文件内容 * @param originalFilename 文件名 * @return 文件访问路径url * @throws Exception */ public String upload(byte[] content, String originalFilename) throws Exception { String endpoint = ossProperties.getEndpoint(); String bucketName = ossProperties.getBucketName(); // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。 // 获取当前系统日期的字符串,格式为 yyyy/MM String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM")); // 根据原始文件名originalFilename, 生成一个新的不重复的文件名 String newFileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = dir + "/" + newFileName; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); // 文件上传 try { ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content)); } finally { if (ossClient != null) { ossClient.shutdown(); } } return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName; } }
注意:确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
- zzyl-admin模块引入并配置
先把zzyl-oss模块在父工程中声明:
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- 其他依赖配置省略...-->
<!-- OSS模块 -->
<dependency>
<groupId>com.zzyl</groupId>
<artifactId>zzyl-oss</artifactId>
<version>${zzyl.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
在zzyl-admin模块中引入zzyl-oss依赖
<dependency>
<groupId>com.zzyl</groupId>
<artifactId>zzyl-oss</artifactId>
</dependency>
在application.yml文件中添加对oss的配置
# 阿里云OSS相关配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: zznursing
注意:需要将bucketName改成自己的。
- 修改上传的接口
找到zzyl-admin模块中的com.zzyl.web.controller.common.CommonController类,修改单个文件上传的方法
// 先导入阿里云OSS工具
@Autowired
private AliyunOSSOperator aliyunOSSOperator;
/**
* 通用上传请求(单个)
*/
@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());
}
}
前端代码能自适应文件上传
为什么文件上传只需要修改后端代码?因为在前端代码中有识别url是否是本地文件存储的判断逻辑。
- 文件位置: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
在测试环境下:
# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'
测试是否能上传图片并展示
护理项目页面改造
跟据需求和页面原型进行前端页面改造
将模板生成的前端页面与原型进行比较,列出问题。
将不需要的部分删除(注释)掉,例如:删除无关按钮及其关联函数。
手动加上页面 Form 表单中缺少的 Select 选择器和Dialog 对话框中缺少的 Select 选择器
- 参考链接:https://element-plus.org/zh-CN/component/select.html
将页面 Table 表格的状态数字改为 Tag 标签包裹的状态显示
<el-table-column label="状态" align="center" > <template #default="scope"> <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">{{ scope.row.status === 1 ? '启用' : '禁用' }}</el-tag> </template> </el-table-column>
<template #default=“scope”> 这是一个Vue模板插槽的语法。
#default
表示默认插槽,scope
是作用域参数,通过scope
可以访问到父组件传递给插槽的任何数据scope.row 代表的是这一行数据
:type=success | danger 表示显示不同的样式 success:成功 danger:危险
更改页面 Table 表格的序号type、时间显示
{y}-{m}-{d} {h}:{i}:{s}
添加禁用和启用按钮(包含图标)
- 图标组件链接:https://element-plus.org/zh-CN/component/icon.html
固定操作列和调整列宽width
- 参考链接:https://element-plus.org/zh-CN/component/table.html
状态管理用数据字典
- 添加数据字典并编辑字典数据
- 修改数据状态不回显问题
- 把返回的状态字段的数据类型改为字符串类型,数据字典是字符串类型的。
护理计划功能开发
第5章-前后端快速开发 - 飞书云文档
护理等级功能开发
数据传输对象DTO
DTO即Data Transfer Object 数据传输对象。
用于封装前端给后端传递的数据。
是一种开发规范,有利于团队开发。
值对象Vo
Vo即Value Object 值对象。
用于封装后端给前端传递的数据。
是一种开发规范,有利于团队开发。
属性拷贝工具BeanUtils
用于拷贝数据到相同属性和相同类型的对象中。
例如:BeanUtils.copyProperties(dto, nursingPlan);
功能开发分几步(CRUD)?
- 需求+原型分析
- 相应表结构关系分析
- 接口文档分析
- 功能实现(对模板生成代码进行改造)
- 如果是单表页面开发,则只需要在模板生成代码的基础上改造前端页面
- 如果是多表页面开发,要在模板生成代码的基础上再开发下面5个接口:
- 查询所有关联信息(手动添加接口代码)
- 新增信息(能够关联多表信息)
- 删除信息(能够关联多表信息)
- 跟据id查询信息(能够关联多表信息)
- 修改信息(能够关联多表信息)
后端接口开发分几步
- 整理实现思路
- 跟据思路编码