【若依管理系统】前后端分离单机版开发必备小技巧
该文主要总结本人在使用若依管理系统时的开发小技巧,涵盖前后端。例如如何写单元测试,如何使用分页查询,如何设置日志等级,如何替换系统图标……
若依教程
https://doc.ruoyi.vip/ruoyi/other/faq.html
https://doc.ruoyi.vip/ruoyi/
后端
修改端口
在admin模块下的配置文件中修改

Security设置部分请求无需登录即可访问



Swagger访问地址
http://localhost:6010/swagger-ui/index.html
使用的是swagger3,注解如下:

本地文件读取问题

虽然打包进去了,但是还是会出错,因为文件的路径已经变了



package com.ruoyi.common.utils.txt;
import java.io.*;
import java.nio.charset.Charset;
public class TxtFileUtils {
public static String read(InputStream fstream, String charset) throws Exception {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(fstream, Charset.forName(charset)));
String s = br.readLine();
return s;
} finally {
try {
fstream.close();
} catch (Exception e) {
}
}
}
public static String read(File f, String charset) throws Exception {
FileInputStream fstream = new FileInputStream(f);
try {
int fileSize = (int) f.length();
// if (fileSize > 1024 * 512) {
// throw new Exception("File too large to read! size=" + fileSize);
// }
byte[] buffer = new byte[fileSize];
fstream.read(buffer);
return new String(buffer, charset);
} finally {
try {
fstream.close();
} catch (Exception e) {
}
}
}
public static void write(File f, String text, String charset) throws Exception {
FileOutputStream fstream = new FileOutputStream(f);
try {
fstream.write(text.getBytes(charset));
} finally {
fstream.close();
}
}
}
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("data/layout/hahahhahahah.txt");
Resource resource = resources[0];
//获得文件流,因为在jar文件中,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
InputStream inputStream = resource.getInputStream();
String json = TxtFileUtils.read(inputStream, "GBK");
创建新模块
在admin模块的pom.xml中引入所创建的新模块依赖

在项目根模块pom.xml中管理模块依赖版本

在application上方添加注解,如果新创建模块的代码包名不是com.ruoyi,可以尝试如下方式来扫描新模块的包
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }, scanBasePackages = { "com.ruoyi", "com.shm" })
@MapperScan("com.shm.mapper")
如果访问controller中定义的接口还是失败,清理缓存

整合mybatis-plus
https://blog.csdn.net/laodanqiu/article/details/132174457
热部署
系统已经整合了热部署模块,直接ctrl+shift+F9编译就行
定制自己的抛异常方法
创建属于自己的ErrorCode类

package com.ruoyi.common.enums;
/**
* 错误码
*
* @author yupi
*/
public enum ErrorCode {
SUCCESS(200, "操作成功"),
PARAMS_ERROR(40000, "请求参数错误"),
NOT_LOGIN_ERROR(40100, "未登录"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),
FORBIDDEN_ERROR(40300, "禁止访问"),
SYSTEM_ERROR(50000, "系统内部异常"),
OPERATION_ERROR(50001, "操作失败");
/**
* 状态码
*/
private final int code;
/**
* 信息
*/
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
修改原有的业务异常类

加上这段代码
public ServiceException(ErrorCode errorCode) {
this.message = errorCode.getMessage();
this.code = errorCode.getCode();
}
使用

启动出错,报日志路径找不到

直接修改为相对路径就行

运行之后,日志会被放在项目目录中
打包运行之后,日志会被放在jar包同级目录中,如下图所示

单元测试
在admin模块创建test包

在admin模块的pom.xml文件中引入如下依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
写测试类
package hahah;
import com.alibaba.fastjson2.JSON;
import com.dam.RuoYiApplication;
import com.dam.common.core.domain.entity.packing.cimsJson.CIMSTask;
import com.dam.common.utils.TxtUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
/**
* @Author dam
* @create 2024/8/19 16:34
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {RuoYiApplication.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class InstanceInputTest {
@Test
public void dashidas() throws Exception {
String read = TxtUtil.read(new File("D:\\Projects\\irregular-packing-system\\ips-server\\data\\instance_import\\intsance1.json"), "utf-8");
CIMSTask cimsTask = JSON.parseObject(read, CIMSTask.class);
int temp = 0;
}
}
分页查询
若依已经帮我们实现好分页了,只需要在查询之前调用startPage()方法

就算是查vo,也不自己需要在sql中写limit,调用startPage()方法即可
看完这里,还需要看一下前端部分需要怎么样传递参数
日志等级设置

初始等级为debug,每段SQL的执行都会输出日志到控制台,可以将日志级别调整为更高的级别,比如info、warn或error。这样会过滤掉调试级别的日志输出
图片上传与回显
回显原理
为什么若依管理系统在上传图片之后,可以直接通过如下方式进行回显

起初我还以为是专门有一个controller来处理这个图片回显请求,后面通过代码调试,发现是拦截/profile,然后映射到本地图片路径中,这样就可以让 Spring Boot 应用能够将这些文件作为静态资源提供给前端访问


修改成相对路径
设置图片的上传地址


这样子图片就会被保留在项目目录下面

开启注册功能
首先修改参数,将是否开启注册功能改为true

该值是存储在MySQL里面的,直接在数据库里面修改也可以

不然无法通过校验

通过/register访问注册页面,默认的注册只需要输入账号、密码、验证码即可。如果需要自己定制注册功能的话,可以在RegisterBody类补充字段,然后完善registerService.register方法

缓存key前缀设置
若依管理系统使用Redis来存储系统的一些参数,如果我们同时有多个项目使用若依搭建,并使用同一个Redis中间件,这样很容易出现配置错乱,因此建议设置好key前缀

前端
修改前端访问的后端域名端口

打包
使用prod生产环境配置来打包,在打包之前,需要修改.env.production

部署之后刷新页面报404
如果是宝塔部署
在宝塔面板添加这个配置

try_files $uri $uri/ /index.html;
如果是nginx挂载

使用generator生成的前端代码要做如下修改
:visible.sync要改成v-model

按钮使用

没有mini,最小是small
slot-scope=“scope” 修改为 #default=“scope”

全局组件挂载

分页查询
前端发请求的时候需要拼接上pageNum和pageSize
// 查询用户和自己最近的聊天信息
export function listChat(toUsername, page) {
return httpRequest.request({
url: `/market/chat/listChat/${toUsername}?pageNum=${page.pageNum}&pageSize=${page.pageSize}`,
method: 'get'
})
}
回到上一个页面

可以去阿里巴巴矢量图标库中下载一个svg图片


<el-tooltip content="回到上一个页面" effect="dark" placement="bottom">
<div class="right-menu-item hover-effect">
<svg-icon :icon-class="'back'" @click="goBack" style="width: 21px;height: 21px;"/>
</div>
</el-tooltip>
返回上一页的方法,调用router的back方法
goBack() {
this.$router.back();
}
报错:找不到模块

修改如下两个文件
component: (resolve) => require(['@/views/system/user/authRole'],resolve),

return (resolve) => require([`@/views/${view}`], resolve)

菜单使用阿里巴巴图标
怎么把这里的图标替换成自己想要的

首先看菜单添加或修改的时候可以选择一些图标


经过层层追踪,发现这些图标来源于这个目录

找到了家在哪里,问题就简单了,把阿里巴巴图标下载成svg图标塞进来就行

把刚刚下载的图标丢进来

这下在菜单的图标选择界面就可以看到了

首页的图标不能直接在上面替换,因为它已经写死在router的index.js里面了


替换Logo

换一个图片把这个覆盖掉就行

Navbar上面增加图标


首先将下载好的图标svg放到如下文件夹


store存储变量
要实现的功能:App.vue页面收到WebSocket通知之后,主动发生请求获取正在计算的任务数据,其他页面通过store来共享该变量的值
创建calculate.js

const calculate = {
state: {
// 存储投递计算的任务数组
calculatingInstance: [],
// 计算完成的任务数量
finishInstanceNum: 0,
},
mutations: {
setCalculatingInstance: (state, calculatingInstance) => {
state.calculatingInstance = calculatingInstance
},
setFinishInstanceNum: (state, finishInstanceNum) => {
state.finishInstanceNum = finishInstanceNum
},
},
actions: {
/**
* 更新投递计算的任务数组
* @param commit
* @param data
*/
updateCalculatingInstance({commit}, data) {
commit('setCalculatingInstance', data);
},
/**
* 更新完成计算的任务数
* @param commit
* @param data
*/
updateFinishInstanceNum({commit}, data) {
commit('setFinishInstanceNum', data);
}
},
getters: {
listCalculatingInstance(state) {
return state.calculatingInstance;
},
getFinishInstanceNum(state) {
return state.finishInstanceNum;
},
}
}
export default calculate
在index.js中使用

在App.vue页面中设置值
listCalculatingInstance() {
listCalculatingInstance().then(res => {
this.$store.dispatch('updateCalculatingInstance', res.data);
})
},
/**
* 完成计算的任务数量++
*/
finishInstanceNumPlus() {
this.$store.dispatch('updateFinishInstanceNum', this.$store.getters.getFinishInstanceNum + 1);
}
在Navbar.vue页面的计算属性中使用
computed: {
calculatingInstanceList() {
return this.$store.getters.listCalculatingInstance;
},
finishInstanceNum() {
return this.$store.getters.getFinishInstanceNum;
}
},
在组件中直接使用值
<div class="right-menu-item hover-effect position-relative" @click="listCalculatingInstance">
<svg-icon :icon-class="'calculate'" style="width: 21px;height: 21px;"/>
<div class="badge position-absolute" v-if="finishInstanceNum>0">{{ finishInstanceNum }}</div>
</div>
在store中管理的用户信息保存用户名信息
例如要在store中存储用户名


获取缓存中的name

【使用】
在需要使用name属性的页面中添加如下代码:
export default {
computed: {
...mapGetters([
'name',
'token'
]),
},
使用,直接this.name使用即可。注意,如果name值被设置,这里获取出来的name值也会同步更新
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐




所有评论(0)